今日已更新 215 条资讯 | 累计 21081 条内容
关于我们

标签:#pens

找到 1396 篇相关文章

AI 资讯

Why modal.open() should return Promise , not Promise

How treating modals as typed async operations eliminates boolean state, callback chains, and runtime surprises in React apps. React applications often treat modals as UI details. A boolean flag. A conditional render. An onClose callback. That works fine for one dialog. But real products have modals that are actually business flows: confirm this destructive action rename this entity and return the new name pick a date range and apply it resolve a conflict before continuing complete a wizard step before the next one unlocks These flows need more than a boolean. They need typed input, typed output, and a way to await the result — just like any other async operation in your app. const result = await modal . open ( renameReportModal , { reportId : report . id , currentName : report . name , }); if ( result . status === " renamed " ) { await renameReport ({ id : report . id , name : result . name }); } That is the idea behind: npm install @okyrychenko-dev/react-modal-manager zustand A modal lifecycle manager. Not a component. Not a design system. A typed async contract between your app logic and your dialog UI. The problem with traditional modal state In most React apps, modal state starts locally: function ReportsPage () { const [ isRenameOpen , setIsRenameOpen ] = useState ( false ); return ( <> < button onClick = { () => setIsRenameOpen ( true ) } > Rename </ button > { isRenameOpen && ( < RenameModal onClose = { () => setIsRenameOpen ( false ) } /> ) } </> ); } And then real requirements arrive: const [ isRenameOpen , setIsRenameOpen ] = useState ( false ); const [ isDeleteOpen , setIsDeleteOpen ] = useState ( false ); const [ isShareOpen , setIsShareOpen ] = useState ( false ); const [ renameTarget , setRenameTarget ] = useState < Report | null > ( null ); const [ deleteTarget , setDeleteTarget ] = useState < Report | null > ( null ); const [ shareTarget , setShareTarget ] = useState < Report | null > ( null ); The UI is not the problem. The orchestration is: Where d

2026-06-12 原文 →
AI 资讯

Stop Hand-Editing Fragile APT Lines: Practical deb822 `.sources` Files for Debian and Ubuntu

If you still manage APT repositories as long one-line deb ... entries, you are working with a format APT now explicitly marks as deprecated. It still works, but it is harder to read, harder to automate safely, and easier to get wrong when you add options like arch= or signed-by= . The better option is deb822 style .sources files. This post shows how to: read the structure of a .sources file migrate a legacy .list entry safely use Signed-By without falling back to apt-key disable a repository cleanly without deleting it verify that APT accepts the new configuration I am focusing on practical host administration, not packaging theory. Why move to deb822 now? The sources.list(5) man page now says the traditional one-line .list format is deprecated and may eventually be removed, though not before 2029. More importantly, deb822 solves real operational annoyances: fields are explicit instead of positional one stanza can describe multiple suites or types Enabled: no is cleaner than commenting lines in and out machine parsing is much easier Signed-By is clearer and safer in structured form On a current Debian host, you may already be using it without noticing: find /etc/apt/sources.list.d -maxdepth 1 -type f -name '*.sources' On my test system, the default Debian repository is already stored as /etc/apt/sources.list.d/debian.sources . The old format vs the new format A traditional one-line entry looks like this: deb [arch=amd64 signed-by=/etc/apt/keyrings/example.gpg] https://packages.example.com/apt stable main The same source in deb822 format becomes: Types: deb URIs: https://packages.example.com/apt Suites: stable Components: main Architectures: amd64 Signed-By: /etc/apt/keyrings/example.gpg That is the core win. Instead of cramming everything into one line and hoping spacing stays correct, each field says exactly what it means. Example 1, a clean Debian .sources file Here is a practical example for Debian using separate stanzas for the main archive and the security arch

2026-06-12 原文 →
AI 资讯

How I Gave My AI Agent Persistent Memory Without Modifying Its Code

If you've ever worked with AI agents in production, you know the frustration: every new session starts from scratch. The agent has no memory of previous conversations, no context about ongoing projects, and you have to repeat yourself constantly. It's like Groundhog Day for your AI. I ran into this with a code assistant I was using for a multi-week refactoring project. It was great for one-off questions, but it couldn't remember what we discussed yesterday. I'd ask it about the architecture decisions we made last week, and it would stare at me blankly. I needed something that could carry context across sessions without forcing me to patch the agent's internals. I looked at the usual suspects: vector databases for RAG, ad-hoc session dumping, even fine-tuning. Each had a cost. RAG setups are powerful but often require custom tooling and tight integration. Session logs without structure are just noise. Fine-tuning is expensive and slow to iterate on. What I wanted was a self-contained system that worked with any agent, required no code changes to the agent, and actually understood what to keep and what to forget. That's when I found Memory Sidecar. It's an open-source project designed to run alongside any AI agent—Hermes, Claude Code, Cursor, Codex, or your own custom setup—as a separate process. It watches your agent's output, archives important conversations, builds a long-term knowledge base, and injects relevant context back before each new session. No patches, no invasive changes. How it works The architecture is simple on the surface but layered underneath. Agents write sessions to state.db and session files. The sidecar reads these, processes new content, and feeds through a three-tier retrieval system: Hot layer : Recent context with a small footprint (5 KB cap). This is the stuff the agent just talked about. Warm layer : Hindsight PostgreSQL database that stores summarised sessions and recent history. Cold layer : A knowledge graph (gbrain) combined with FTS5

2026-06-12 原文 →
AI 资讯

Shipping a Livewire 4 + Flux admin UI inside a package: four gotchas that 500'd on me

Bundling an admin UI inside a Laravel package is a different game from building one in an app. The app's conveniences — a compiled Vite manifest, a registered layout, your own Livewire components — aren't there. Today, getting the bundled admin UI in laravel-config-webhook to actually render meant walking through four separate 500s. Each one is a small, sharp lesson about the boundary between a package and its host app. 1. A Livewire 4 component name can't contain :: I registered the component with a namespaced-looking name and got a ComponentNotFoundException at runtime. The cause is subtle: under Livewire 4, a name containing :: triggers namespace resolution that ignores singly-registered components. So a "nice looking" name silently routes to a lookup that will never find it. The fix is to register a plain, dotted name: // ❌ looks tidy, but the "::" sends Livewire down a namespace path Livewire :: component ( 'config-webhook::webhooks' , Webhooks :: class ); // ✅ a flat dotted name resolves to the singly-registered component Livewire :: component ( 'config-webhook.webhooks' , Webhooks :: class ); Lesson: in a package, treat the component name as an identifier with framework-reserved characters — :: is not yours to use. 2. Flux ships Heroicons, not Pro/Lucide names The free tier of Flux ships Heroicons . Reach for a Pro-only or Lucide-style name and it throws at runtime. I'd used webhook , ellipsis , and list ; the free equivalents are bolt , ellipsis-horizontal , and queue-list . This is the same trap that bit my SSO package — which is exactly why I now guard it with a static test that reads the Blade and checks every icon against Flux's actual stub files. (Separate post on that.) If you ship a package UI with Flux, assume free-tier icons only unless you require Pro. 3. Don't @vite host assets that don't exist The bundled fallback layout @vite -d the host app's assets. In a fresh consumer (or the package's own workbench) there's no compiled manifest, so you get a

2026-06-12 原文 →