agentix-cli 0.151.0 → 0.152.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{App-WAWZFD66.js → App-NCB3Y5DS.js} +2 -2
- package/dist/{ChatApp-TRJIS3O4.js → ChatApp-HOWN5H7Y.js} +2 -2
- package/dist/{absorb-eval-CFWLHUTB.js → absorb-eval-JXRNSZII.js} +2 -2
- package/dist/agent-DMXUUMEU.js +2 -0
- package/dist/{board-dashboard-5V6RHW3E.js → board-dashboard-POWARL34.js} +402 -241
- package/dist/board-dashboard-POWARL34.js.map +1 -0
- package/dist/{chunk-X6C6U4GL.js → chunk-24QMHUU2.js} +5 -5
- package/dist/{chunk-X6C6U4GL.js.map → chunk-24QMHUU2.js.map} +1 -1
- package/dist/{chunk-ALE354ZC.js → chunk-7UH3DXAG.js} +2 -2
- package/dist/chunk-ADG6NBZY.js +862 -0
- package/dist/chunk-ADG6NBZY.js.map +1 -0
- package/dist/{chunk-IMITYHBT.js → chunk-CZEBLLZQ.js} +2 -2
- package/dist/{chunk-XD7HTMOP.js → chunk-DZUJP6L7.js} +2 -2
- package/dist/{chunk-TZZBGWLX.js → chunk-E4V5EADX.js} +6 -6
- package/dist/{chunk-XVJXXELY.js → chunk-GI5CY27P.js} +2 -2
- package/dist/{chunk-LVS5ESTS.js → chunk-HS7ATV4Z.js} +2 -2
- package/dist/{chunk-RGJZV5RY.js → chunk-ILZRO6SN.js} +2 -2
- package/dist/{chunk-UG2OF2EI.js → chunk-IVBCCSDR.js} +2 -2
- package/dist/{chunk-V3VWYIJ3.js → chunk-JDX7AYIB.js} +2 -2
- package/dist/{chunk-PUSBK2OQ.js → chunk-JHAQE46R.js} +46 -46
- package/dist/chunk-JHAQE46R.js.map +1 -0
- package/dist/chunk-JJOLZPUY.js +35 -0
- package/dist/chunk-JJOLZPUY.js.map +1 -0
- package/dist/{chunk-2PJKGZWP.js → chunk-JNG3P5V2.js} +2 -2
- package/dist/chunk-JNG3P5V2.js.map +1 -0
- package/dist/{chunk-2GJQDJBF.js → chunk-LDLRDBAD.js} +2 -2
- package/dist/{chunk-DJQIJF4R.js → chunk-LOTCKF22.js} +2 -2
- package/dist/{chunk-O7SYQXKS.js → chunk-MTBY46CL.js} +8 -8
- package/dist/{chunk-FGJNSYHM.js → chunk-P25TJ4XN.js} +3 -3
- package/dist/{chunk-6LFOX6Q5.js → chunk-P4EZJIQ4.js} +257 -256
- package/dist/chunk-P4EZJIQ4.js.map +1 -0
- package/dist/{chunk-X3T2GCSI.js → chunk-PC24JMEH.js} +2 -2
- package/dist/{chunk-EJTKLVIW.js → chunk-PGLTBNGZ.js} +2 -2
- package/dist/{chunk-4GXJMHSA.js → chunk-QSNKF5VD.js} +2 -2
- package/dist/{chunk-DFGANY25.js → chunk-R4R7EYY3.js} +2 -2
- package/dist/{chunk-Q5NLNLD5.js → chunk-RNAKP7WY.js} +2 -2
- package/dist/{chunk-L6IW6HWE.js → chunk-SQUTRMKH.js} +23 -20
- package/dist/chunk-SQUTRMKH.js.map +1 -0
- package/dist/{chunk-C5UTFHPB.js → chunk-TNZBQAUR.js} +2 -2
- package/dist/{chunk-Y5MFVVTM.js → chunk-U23LVMMZ.js} +2 -2
- package/dist/{chunk-YGDJV4ZZ.js → chunk-UFYKUC4E.js} +2 -2
- package/dist/{chunk-CTQ25CUL.js → chunk-VIZVF6KH.js} +2 -2
- package/dist/{chunk-ETBDN5WX.js → chunk-XE3CGJV4.js} +2 -2
- package/dist/{chunk-UALK4F3W.js → chunk-YBUCVI45.js} +2 -2
- package/dist/{chunk-DWXCZRBJ.js → chunk-YJZQRFET.js} +2 -2
- package/dist/cli.js +1 -1
- package/dist/{client-VT7GT3SK.js → client-6IOWB5AT.js} +2 -2
- package/dist/{compaction-FS6XNRLM.js → compaction-PFXWL4H7.js} +3 -3
- package/dist/{config-NZS2UTHI.js → config-SHIT5WJE.js} +2 -2
- package/dist/{config-mutate-LINLC354.js → config-mutate-6ACI5COM.js} +2 -2
- package/dist/config-mutator-LAEX6HOH.js +2 -0
- package/dist/{context-planner-3JDA7FNR.js → context-planner-DJB6CKY6.js} +2 -2
- package/dist/{contributions-67B3BYLV.js → contributions-N7K6LNL7.js} +2 -2
- package/dist/{doctor-FOKX4K2G.js → doctor-T7QAQRCJ.js} +2 -2
- package/dist/{follow-up-tool-JOIOYOON.js → follow-up-tool-HQ2GWF4K.js} +2 -2
- package/dist/{grants-QXF7N6SS.js → grants-HSLB62EG.js} +2 -2
- package/dist/heal-RGM7X2ZG.js +2 -0
- package/dist/hub-53IMEYGX.js +2 -0
- package/dist/index.d.ts +125 -6
- package/dist/index.js +1 -1
- package/dist/memory-extract-GHLBXV4H.js +2 -0
- package/dist/{program-XFZBG3EI.js → program-LSXONKPW.js} +225 -219
- package/dist/program-LSXONKPW.js.map +1 -0
- package/dist/{promote-WNYNTGKC.js → promote-626PE5VM.js} +2 -2
- package/dist/{providers-55NC2SFN.js → providers-BDJXGHEY.js} +2 -2
- package/dist/{query-ZU2DDCEH.js → query-GR3SOD6A.js} +2 -2
- package/dist/{query-settings-BXRIJWWO.js → query-settings-6XZHNFXE.js} +2 -2
- package/dist/{registry-7BITIEQ2.js → registry-SAY7ROZV.js} +2 -2
- package/dist/{request-planner-DLQP2NV6.js → request-planner-DWYXUVF4.js} +2 -2
- package/dist/{review-candidates-3BMHLIBW.js → review-candidates-GXWMKZKA.js} +2 -2
- package/dist/routing-TB6BBRH4.js +2 -0
- package/dist/schedule-tool-EI2SRMZM.js +2 -0
- package/dist/{scheduler-SYI5MZ3H.js → scheduler-VOZIMG5F.js} +2 -2
- package/dist/{seat-6JF7BYM7.js → seat-H6F6H55Y.js} +2 -2
- package/dist/{select-JT4I3JOH.js → select-OUBL6EMZ.js} +2 -2
- package/dist/{set-enabled-JRGFKA3S.js → set-enabled-NYJHFXHY.js} +2 -2
- package/dist/tool-FWATXW5Q.js +6 -0
- package/dist/tool-FWATXW5Q.js.map +1 -0
- package/dist/{tool-P6GVYNDO.js → tool-HXFGNBLS.js} +2 -2
- package/dist/wiki-PG5ZBOMH.js +2 -0
- package/dist/wiki-enrich-BIQZWJRB.js +2 -0
- package/package.json +1 -1
- package/dist/agent-6KCTPI7E.js +0 -2
- package/dist/board-dashboard-5V6RHW3E.js.map +0 -1
- package/dist/chunk-2PJKGZWP.js.map +0 -1
- package/dist/chunk-5I7NJMK6.js +0 -35
- package/dist/chunk-5I7NJMK6.js.map +0 -1
- package/dist/chunk-6LFOX6Q5.js.map +0 -1
- package/dist/chunk-CBML7UCP.js +0 -861
- package/dist/chunk-CBML7UCP.js.map +0 -1
- package/dist/chunk-L6IW6HWE.js.map +0 -1
- package/dist/chunk-PUSBK2OQ.js.map +0 -1
- package/dist/config-mutator-FUMSW5HD.js +0 -2
- package/dist/heal-U67X6NIN.js +0 -2
- package/dist/hub-QETWDYPD.js +0 -2
- package/dist/memory-extract-ATD6YLRK.js +0 -2
- package/dist/program-XFZBG3EI.js.map +0 -1
- package/dist/routing-FVZCQJ6T.js +0 -2
- package/dist/schedule-tool-TDVJHRQX.js +0 -2
- package/dist/tool-UDOUNWQT.js +0 -6
- package/dist/tool-UDOUNWQT.js.map +0 -1
- package/dist/wiki-MTZHDFHK.js +0 -2
- package/dist/wiki-enrich-CHR4RCRE.js +0 -2
- /package/dist/{App-WAWZFD66.js.map → App-NCB3Y5DS.js.map} +0 -0
- /package/dist/{ChatApp-TRJIS3O4.js.map → ChatApp-HOWN5H7Y.js.map} +0 -0
- /package/dist/{absorb-eval-CFWLHUTB.js.map → absorb-eval-JXRNSZII.js.map} +0 -0
- /package/dist/{agent-6KCTPI7E.js.map → agent-DMXUUMEU.js.map} +0 -0
- /package/dist/{chunk-ALE354ZC.js.map → chunk-7UH3DXAG.js.map} +0 -0
- /package/dist/{chunk-IMITYHBT.js.map → chunk-CZEBLLZQ.js.map} +0 -0
- /package/dist/{chunk-XD7HTMOP.js.map → chunk-DZUJP6L7.js.map} +0 -0
- /package/dist/{chunk-TZZBGWLX.js.map → chunk-E4V5EADX.js.map} +0 -0
- /package/dist/{chunk-XVJXXELY.js.map → chunk-GI5CY27P.js.map} +0 -0
- /package/dist/{chunk-LVS5ESTS.js.map → chunk-HS7ATV4Z.js.map} +0 -0
- /package/dist/{chunk-RGJZV5RY.js.map → chunk-ILZRO6SN.js.map} +0 -0
- /package/dist/{chunk-UG2OF2EI.js.map → chunk-IVBCCSDR.js.map} +0 -0
- /package/dist/{chunk-V3VWYIJ3.js.map → chunk-JDX7AYIB.js.map} +0 -0
- /package/dist/{chunk-2GJQDJBF.js.map → chunk-LDLRDBAD.js.map} +0 -0
- /package/dist/{chunk-DJQIJF4R.js.map → chunk-LOTCKF22.js.map} +0 -0
- /package/dist/{chunk-O7SYQXKS.js.map → chunk-MTBY46CL.js.map} +0 -0
- /package/dist/{chunk-FGJNSYHM.js.map → chunk-P25TJ4XN.js.map} +0 -0
- /package/dist/{chunk-X3T2GCSI.js.map → chunk-PC24JMEH.js.map} +0 -0
- /package/dist/{chunk-EJTKLVIW.js.map → chunk-PGLTBNGZ.js.map} +0 -0
- /package/dist/{chunk-4GXJMHSA.js.map → chunk-QSNKF5VD.js.map} +0 -0
- /package/dist/{chunk-DFGANY25.js.map → chunk-R4R7EYY3.js.map} +0 -0
- /package/dist/{chunk-Q5NLNLD5.js.map → chunk-RNAKP7WY.js.map} +0 -0
- /package/dist/{chunk-C5UTFHPB.js.map → chunk-TNZBQAUR.js.map} +0 -0
- /package/dist/{chunk-Y5MFVVTM.js.map → chunk-U23LVMMZ.js.map} +0 -0
- /package/dist/{chunk-YGDJV4ZZ.js.map → chunk-UFYKUC4E.js.map} +0 -0
- /package/dist/{chunk-CTQ25CUL.js.map → chunk-VIZVF6KH.js.map} +0 -0
- /package/dist/{chunk-ETBDN5WX.js.map → chunk-XE3CGJV4.js.map} +0 -0
- /package/dist/{chunk-UALK4F3W.js.map → chunk-YBUCVI45.js.map} +0 -0
- /package/dist/{chunk-DWXCZRBJ.js.map → chunk-YJZQRFET.js.map} +0 -0
- /package/dist/{client-VT7GT3SK.js.map → client-6IOWB5AT.js.map} +0 -0
- /package/dist/{compaction-FS6XNRLM.js.map → compaction-PFXWL4H7.js.map} +0 -0
- /package/dist/{config-NZS2UTHI.js.map → config-SHIT5WJE.js.map} +0 -0
- /package/dist/{config-mutate-LINLC354.js.map → config-mutate-6ACI5COM.js.map} +0 -0
- /package/dist/{config-mutator-FUMSW5HD.js.map → config-mutator-LAEX6HOH.js.map} +0 -0
- /package/dist/{context-planner-3JDA7FNR.js.map → context-planner-DJB6CKY6.js.map} +0 -0
- /package/dist/{contributions-67B3BYLV.js.map → contributions-N7K6LNL7.js.map} +0 -0
- /package/dist/{doctor-FOKX4K2G.js.map → doctor-T7QAQRCJ.js.map} +0 -0
- /package/dist/{follow-up-tool-JOIOYOON.js.map → follow-up-tool-HQ2GWF4K.js.map} +0 -0
- /package/dist/{grants-QXF7N6SS.js.map → grants-HSLB62EG.js.map} +0 -0
- /package/dist/{heal-U67X6NIN.js.map → heal-RGM7X2ZG.js.map} +0 -0
- /package/dist/{hub-QETWDYPD.js.map → hub-53IMEYGX.js.map} +0 -0
- /package/dist/{memory-extract-ATD6YLRK.js.map → memory-extract-GHLBXV4H.js.map} +0 -0
- /package/dist/{promote-WNYNTGKC.js.map → promote-626PE5VM.js.map} +0 -0
- /package/dist/{providers-55NC2SFN.js.map → providers-BDJXGHEY.js.map} +0 -0
- /package/dist/{query-ZU2DDCEH.js.map → query-GR3SOD6A.js.map} +0 -0
- /package/dist/{query-settings-BXRIJWWO.js.map → query-settings-6XZHNFXE.js.map} +0 -0
- /package/dist/{registry-7BITIEQ2.js.map → registry-SAY7ROZV.js.map} +0 -0
- /package/dist/{request-planner-DLQP2NV6.js.map → request-planner-DWYXUVF4.js.map} +0 -0
- /package/dist/{review-candidates-3BMHLIBW.js.map → review-candidates-GXWMKZKA.js.map} +0 -0
- /package/dist/{routing-FVZCQJ6T.js.map → routing-TB6BBRH4.js.map} +0 -0
- /package/dist/{schedule-tool-TDVJHRQX.js.map → schedule-tool-EI2SRMZM.js.map} +0 -0
- /package/dist/{scheduler-SYI5MZ3H.js.map → scheduler-VOZIMG5F.js.map} +0 -0
- /package/dist/{seat-6JF7BYM7.js.map → seat-H6F6H55Y.js.map} +0 -0
- /package/dist/{select-JT4I3JOH.js.map → select-OUBL6EMZ.js.map} +0 -0
- /package/dist/{set-enabled-JRGFKA3S.js.map → set-enabled-NYJHFXHY.js.map} +0 -0
- /package/dist/{tool-P6GVYNDO.js.map → tool-HXFGNBLS.js.map} +0 -0
- /package/dist/{wiki-MTZHDFHK.js.map → wiki-PG5ZBOMH.js.map} +0 -0
- /package/dist/{wiki-enrich-CHR4RCRE.js.map → wiki-enrich-BIQZWJRB.js.map} +0 -0
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/desktop/install.ts","../src/native/macos/index.ts","../src/native/macos/run.ts","../src/native/macos/banner.ts","../src/native/macos/notes.ts","../src/native/macos/sound.ts","../src/native/macos/tasks.ts","../src/native/none.ts","../src/native/index.ts","../src/notify/local.ts","../src/approvals/mirror.ts","../src/requests/card-view.ts","../src/requests/loops.ts"],"sourcesContent":["import { existsSync, readFileSync } from 'node:fs'\nimport { dirname, join } from 'node:path'\nimport { fileURLToPath } from 'node:url'\nimport { homedir } from 'node:os'\n\nexport const DESKTOP_LABEL = 'tn.acme.agentx.voice'\nexport const DESKTOP_APP = 'AgentX Desktop.app'\nexport const HELPER_APP = 'AgentX Helper.app'\nexport function desktopPlatformError(platform: string, arch: string, release: string): string | null {\n if (platform !== 'darwin' || arch !== 'arm64' || Number(release.split('.')[0]) < 23)\n return 'AgentX Desktop currently requires Apple Silicon and macOS 14 or newer.'\n return null\n}\nexport function selectDesktopAgent(agents: Record<string, unknown>, requested?: string): string {\n if (requested && !Object.hasOwn(agents, requested)) throw new Error(`Unknown agent: ${requested}. Run agentx agent list.`)\n const id = requested || Object.keys(agents)[0]\n if (!id) throw new Error('No agents configured. Run agentx setup first.')\n return id\n}\nexport function shellQuote(value: string): string { return `'${value.replace(/'/g, \"'\\\\''\")}'` }\n/** launchd's default PATH, which is all a login item gets unless the plist sets one. */\nexport const LAUNCHD_PATH = '/usr/bin:/bin:/usr/sbin:/sbin'\n/** PATH for the login item: AGENTX_VOICE_PATH when set, else the folder of\n * the ffmpeg found at install time (mlx_whisper needs it) ahead of launchd's default. */\nexport function desktopPath(ffmpeg: string | null, override?: string): string {\n if (override) return override\n return [...new Set([...(ffmpeg ? [dirname(ffmpeg)] : []), ...LAUNCHD_PATH.split(':')])].join(':')\n}\nfunction unxml(s: string): string {\n const ents: Record<string, string> = { amp: '&', lt: '<', gt: '>', quot: '\"', apos: \"'\" }\n return s.replace(/&(amp|lt|gt|quot|apos);/g, (_, e) => ents[e])\n}\n/** The PATH a login item plist sets, or launchd's default when it sets none. */\nexport function plistPathEnv(plist: string): string {\n const m = plist.match(/<key>PATH<\\/key>\\s*<string>([^<]*)<\\/string>/)\n return m ? unxml(m[1]) : LAUNCHD_PATH\n}\n/** Login item files the voice app may have been installed under. */\nexport const isVoiceLoginItemFile = (name: string) => /agentx\\.voice.*\\.plist$/.test(name)\nexport type LoginItem = { file: string; label: string }\n/** One login item per Mac. The label was renamed once and\n * apps/mac-voice/install.sh writes its own, so adopt the first existing\n * `*agentx.voice*` item that runs the voice app (any bundle name) and\n * retire the others; with none, use DESKTOP_LABEL. Plists are XML text. */\nexport function adoptLoginItem(dir: string, items: { file: string; plist: string }[]): { keep: LoginItem; remove: LoginItem[] } {\n let keep: LoginItem | null = null\n const remove: LoginItem[] = []\n for (const { file, plist } of [...items].sort((a, b) => (a.file < b.file ? -1 : 1))) {\n const label = plist.match(/<key>Label<\\/key>\\s*<string>([^<]*)<\\/string>/)?.[1]\n const program = plist.match(/<key>ProgramArguments<\\/key>\\s*<array>\\s*<string>([^<]*)<\\/string>/)?.[1]\n if (!label || !program || !unxml(program).endsWith('/Contents/MacOS/AgentXVoice')) continue\n if (keep) remove.push({ file, label: unxml(label) })\n else keep = { file, label: unxml(label) }\n }\n return { keep: keep ?? { file: join(dir, `${DESKTOP_LABEL}.plist`), label: DESKTOP_LABEL }, remove }\n}\n/** The file that a process with this PATH would run, or null. */\nexport function findOnPath(bin: string, path: string, isExecutable: (file: string) => boolean): string | null {\n for (const dir of path.split(':')) if (dir && isExecutable(join(dir, bin))) return join(dir, bin)\n return null\n}\n/** Without `agent` the app talks to the agent picked in its menu-bar\n * icon; with it, that agent is pinned and the menu cannot switch. */\nexport function desktopPlist(opts: { label?: string; executable: string; cwd: string; agent?: string; url: string; helper: string; cli: string; node: string; log: string; path: string }): string {\n const xml = (s: string) => s.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/\"/g, '"').replace(/'/g, ''')\n const env = {\n PATH: opts.path,\n ...(opts.agent ? { AGENTX_VOICE_AGENT: opts.agent } : {}),\n AGENTX_DAEMON_URL: opts.url,\n AGENTX_MAC_HELPER: opts.helper,\n AGENTX_PASTE_COMMAND: `cd ${shellQuote(opts.cwd)} && ${shellQuote(opts.node)} ${shellQuote(opts.cli)} paste`,\n }\n return `<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\"><dict>\n<key>Label</key><string>${xml(opts.label ?? DESKTOP_LABEL)}</string>\n<key>ProgramArguments</key><array><string>${xml(opts.executable)}</string></array>\n<key>WorkingDirectory</key><string>${xml(opts.cwd)}</string>\n<key>EnvironmentVariables</key><dict>${Object.entries(env).map(([k,v]) => `<key>${k}</key><string>${xml(v)}</string>`).join('')}</dict>\n<key>RunAtLoad</key><true/><key>KeepAlive</key><true/>\n<key>ProcessType</key><string>Interactive</string>\n<key>StandardErrorPath</key><string>${xml(opts.log)}</string>\n</dict></plist>\\n`\n}\n/** build.sh arguments for the helper: the banner icon from\n * notifications.local.icon, or none for the bundled AgentX logo. */\nexport function helperBuildArgs(icon?: string): string[] {\n return icon ? ['--icon', icon] : []\n}\nexport function installedHelper(home: string): string {\n return join(home, 'Applications', HELPER_APP, 'Contents/MacOS/agentx-mac-helper')\n}\n/** The AgentX package folder, found by walking up from this file (dist/\n * when installed, src/ in a checkout) — never from the caller's cwd, so\n * `agentx notify` finds a repo-built helper from any folder. */\nexport function packageRoot(from = dirname(fileURLToPath(import.meta.url))): string | null {\n for (let dir = from; ; dir = dirname(dir)) {\n try {\n if (JSON.parse(readFileSync(join(dir, 'package.json'), 'utf8')).name === 'agentix-cli') return dir\n } catch { /* no package.json here — keep walking up */ }\n if (dirname(dir) === dir) return null\n }\n}\n/** The helper to run: an explicit path, else the one `agentx desktop\n * install` put in ~/Applications, else one built in the package. */\nexport function resolveHelper(root: string | null, home: string, override?: string): string {\n if (override) return override\n const installed = installedHelper(home)\n if (existsSync(installed) || !root) return installed\n return join(root, 'apps/mac-helper/build', HELPER_APP, 'Contents/MacOS/agentx-mac-helper')\n}\n/** The AgentX Helper binary when one is built or installed, else null.\n * AGENTX_MAC_HELPER points at a helper somewhere else. */\nexport function findHelper(): string | null {\n const path = resolveHelper(packageRoot(), homedir(), process.env.AGENTX_MAC_HELPER)\n return existsSync(path) ? path : null\n}\n","import { accessSync, constants } from \"fs\"\nimport { findOnPath } from \"@/desktop/install\"\nimport { readSystemFocus } from \"@/notify/focus\"\nimport type { NativeAdapter, NativeFocus } from \"../types\"\nimport { macosBanner } from \"./banner\"\nimport { macosNotes } from \"./notes\"\nimport type { Capture, Output, Run } from \"./run\"\nimport { macosSound } from \"./sound\"\nimport { macosTasks } from \"./tasks\"\n\n/** Programs the adapter runs, so tests can stand in for them. */\nexport interface MacosIo {\n run?: Run\n capture?: Capture\n output?: Output\n /** The AgentX Helper binary; null means none. Unset: looked up on use. */\n helper?: string | null\n /** Is this file an executable? Used to find remindctl. */\n isExecutable?: (file: string) => boolean\n}\n\nconst executable = (file: string): boolean => {\n try { accessSync(file, constants.X_OK); return true } catch { return false }\n}\n\n/** System Focus from the private Focus database (notify/focus.ts). That\n * reader answers \"not in Focus\" when it can't read the file, so here\n * anything but a clean answer is null: the OS could not tell. */\nconst focus: NativeFocus = {\n async active() {\n const s = readSystemFocus()\n if (s.active) return true\n return s.reason === \"no active Focus assertion\" ? false : null\n },\n}\n\nexport function macosAdapter(cfg: { reminders?: { command?: string } } = {}, io: MacosIo = {}): NativeAdapter {\n const command = cfg.reminders?.command || \"remindctl\"\n return {\n os: \"macos\",\n tasks: macosTasks(command, io.output),\n notes: macosNotes(io.output),\n banner: macosBanner(io),\n sound: macosSound(io),\n focus,\n async describe() {\n const problems: string[] = []\n const isExec = io.isExecutable ?? executable\n const found = command.includes(\"/\") ? isExec(command) : !!findOnPath(command, process.env.PATH || \"\", isExec)\n if (!found) problems.push(`Reminders: ${command} not found (brew install steipete/tap/remindctl, or set reminders.command).`)\n return { os: \"macos\", tasks: true, notes: true, banner: true, sound: true, focus: true, problems }\n },\n }\n}\n","import { execFile } from \"child_process\"\n\n/** Runs a program; resolves true when it exited 0. Never rejects. */\nexport type Run = (file: string, args: string[]) => Promise<boolean>\n\n/** Runs a program; resolves its stdout, or rejects with its stderr. */\nexport type Output = (file: string, args: string[]) => Promise<string>\n\n/** Runs a program; resolves its stdout, or null when it failed. */\nexport type Capture = (file: string, args: string[]) => Promise<string | null>\n\n/** A banner or a sound may not hold a caller hostage: afplay on a long\n * custom sound, or osascript stuck on a permission prompt, is cut off. */\nconst STEP_TIMEOUT_MS = 5_000\n\nexport const run: Run = (file, args) =>\n new Promise((done) => {\n try {\n execFile(file, args, { timeout: STEP_TIMEOUT_MS }, (err) => done(!err))\n } catch {\n done(false) // the program is not on this machine: not worth reporting\n }\n })\n\nexport const capture: Capture = (file, args) =>\n new Promise((done) => {\n try {\n execFile(file, args, { timeout: STEP_TIMEOUT_MS }, (err, stdout) => done(err ? null : String(stdout)))\n } catch {\n done(null)\n }\n })\n\nexport const output: Output = (file, args) =>\n new Promise((resolve, reject) => {\n execFile(file, args, { timeout: 30_000, maxBuffer: 8 * 1024 * 1024 }, (err, stdout, stderr) => {\n if (err) reject(new Error(`${file} ${args[0]}: ${(stderr || err.message).trim()}`))\n else resolve(stdout)\n })\n })\n","import { findHelper } from \"@/desktop/install\"\nimport type { BannerStatus, NativeBanner } from \"../types\"\nimport { capture as defaultCapture, run as defaultRun, type Capture, type Run } from \"./run\"\n\n// The banner is posted by the AgentX Helper app when it is installed, so it\n// carries the helper's icon (the AgentX logo by default). Without the\n// helper, or before macOS has allowed it to notify, osascript posts it, and\n// macOS shows it as coming from Script Editor.\n\nexport interface BannerIo {\n run?: Run\n capture?: Capture\n /** The helper binary; null means none. Unset: looked up on each use. */\n helper?: string | null\n}\n\nconst helperOf = (io: BannerIo): string | null => (io.helper === undefined ? findHelper() : io.helper)\n\n/** What the helper reports about its notification permission. Never shows\n * the macOS \"allow notifications\" prompt and never posts a banner. */\nexport async function helperBannerStatus(path: string | null, capture: Capture = defaultCapture): Promise<BannerStatus> {\n if (!path) return \"missing\"\n const out = await capture(path, [\"notify-status\"])\n let status: { authorization?: string; alertStyle?: string } | null = null\n try { status = out ? JSON.parse(out) : null } catch { status = null }\n if (!status) return \"outdated\"\n if (status.authorization === \"notDetermined\") return \"not-asked\"\n if (status.authorization === \"denied\") return \"not-allowed\"\n if (status.alertStyle === \"none\") return \"hidden\"\n return \"ready\"\n}\n\nexport function macosBanner(io: BannerIo = {}): NativeBanner {\n const exec = io.run ?? defaultRun\n return {\n async post({ title, message }) {\n const helper = helperOf(io)\n // A non-zero exit is usually \"not allowed to notify yet\" (the first\n // banner asks), so this one goes through osascript instead.\n if (helper && await exec(helper, [\"notify\", \"--title\", title, \"--message\", message])) return \"posted\"\n // Title and message travel as argv, never spliced into the script,\n // so a quote in either cannot turn into AppleScript.\n const ok = await exec(\"/usr/bin/osascript\", [\n \"-e\", \"on run argv\",\n \"-e\", \"display notification (item 2 of argv) with title (item 1 of argv)\",\n \"-e\", \"end run\",\n title, message,\n ])\n return ok ? \"posted\" : \"failed\"\n },\n status: () => helperBannerStatus(helperOf(io), io.capture),\n }\n}\n","import type { NativeNotes } from \"../types\"\nimport { output as defaultOutput, type Output } from \"./run\"\n\n// Apple Notes through JXA (osascript -l JavaScript). The folder, title\n// and body travel as argv and are read by the script, never spliced into\n// it, so nothing in them can run as code. Notes stores a body as HTML:\n// the script escapes the text and keeps its line breaks. The first call\n// from the daemon's process asks for the macOS Automation permission\n// (System Settings › Privacy & Security › Automation › Notes).\n\nexport const NOTES_SCRIPT = `\nfunction run(argv) {\n var folderName = argv[0], title = argv[1], body = argv[2]\n var Notes = Application(\"Notes\")\n var esc = function (s) { return s.replace(/&/g, \"&\").replace(/</g, \"<\").replace(/>/g, \">\") }\n var folder = Notes.folders.whose({ name: folderName })()[0]\n if (!folder) {\n folder = Notes.Folder({ name: folderName })\n Notes.folders.push(folder)\n folder = Notes.folders.whose({ name: folderName })()[0]\n }\n var lines = body.split(\"\\\\n\").map(function (l) { return \"<div>\" + (l ? esc(l) : \"<br>\") + \"</div>\" })\n // Notes takes the title from the first line: a name as well would show it twice.\n var note = Notes.Note({ body: \"<div><h1>\" + esc(title) + \"</h1></div>\" + lines.join(\"\") })\n folder.notes.push(note)\n return note.id()\n}\n`\n\nexport function macosNotes(exec: Output = defaultOutput): NativeNotes {\n return {\n async add({ folder, title, body }) {\n const raw = await exec(\"/usr/bin/osascript\", [\"-l\", \"JavaScript\", \"-e\", NOTES_SCRIPT, folder, title, body])\n const id = raw.trim()\n if (!id) throw new Error(\"Notes did not return the new note's id\")\n return { id }\n },\n }\n}\n","import { existsSync, readdirSync } from \"fs\"\nimport type { NativeSound } from \"../types\"\nimport { run as defaultRun, type Run } from \"./run\"\n\nconst SOUNDS = \"/System/Library/Sounds\"\n\n/** The system sound file for a name, or null when there is none. Names\n * only: a path in the config must not reach afplay. */\nexport function soundPath(name: string): string | null {\n if (!/^[\\w -]+$/.test(name)) return null\n const path = `${SOUNDS}/${name}.aiff`\n return existsSync(path) ? path : null\n}\n\nexport function macosSound(io: { run?: Run } = {}): NativeSound {\n const exec = io.run ?? defaultRun\n return {\n async play(name, volume) {\n const path = soundPath(name)\n if (!path) return\n await exec(\"/usr/bin/afplay\", [\"-v\", String(Math.min(1, Math.max(0, volume))), path])\n },\n has: (name) => soundPath(name) !== null,\n async names() {\n try {\n return readdirSync(SOUNDS).filter((f) => f.endsWith(\".aiff\")).map((f) => f.slice(0, -5)).sort()\n } catch {\n return []\n }\n },\n }\n}\n","import type { NativeTask, NativeTasks } from \"../types\"\nimport { output as defaultOutput, type Output } from \"./run\"\n\n// Apple Reminders through remindctl (Homebrew). It is the same tool the\n// mac-pim skill uses, so the daemon and the skill see the same lists. The\n// first call from the daemon's process triggers the macOS Reminders\n// permission prompt.\n//\n// Every value travels as its own argv entry, never through a shell, so\n// quotes and newlines arrive as typed. remindctl 0.1.1 reads any value\n// that starts with \"-\" as an option (and a value equal to --help or\n// --version runs that), and has no \"--opt=value\" form, so such a value\n// gets an invisible zero-width space in front. Reminders keeps that\n// character; listOpen takes it off again. A list name is a lookup key and\n// cannot carry it, so a list name that starts with \"-\" is refused.\n//\n// Reminders keeps a due time to the minute, in this Mac's time zone:\n// seconds are dropped.\n\nconst ZWSP = \"\\u200b\"\n\n/** A value remindctl takes literally. */\nexport function argValue(v: string): string {\n return v.startsWith(\"-\") ? ZWSP + v : v\n}\n\nconst unArg = (v: string | undefined): string | undefined => (v?.startsWith(ZWSP + \"-\") ? v.slice(1) : v)\n\nfunction listName(list: string): string {\n if (!list.trim() || list.startsWith(\"-\")) throw new Error(`Reminders list name \"${list}\" is not usable: it must not be empty or start with \"-\"`)\n return list\n}\n\n/** ISO to the minute, which is all Reminders keeps. */\nconst isoDue = (d: Date): string => new Date(Math.floor(d.getTime() / 60_000) * 60_000).toISOString().replace(/\\.\\d{3}Z$/, \"Z\")\n\nexport function macosTasks(command = \"remindctl\", exec: Output = defaultOutput): NativeTasks {\n return {\n async ensureList(list) {\n const raw = await exec(command, [\"list\", \"--json\", \"--no-input\"])\n const lists = JSON.parse(raw.trim() || \"[]\")\n if (!Array.isArray(lists)) throw new Error(`${command} list: expected a JSON array`)\n if (lists.some((l: { title?: string }) => l?.title === list)) return\n await exec(command, [\"list\", listName(list), \"--create\", \"--json\", \"--no-input\"])\n },\n async listOpen(list) {\n const raw = await exec(command, [\"show\", \"all\", \"--list\", listName(list), \"--json\", \"--no-input\"])\n const items = JSON.parse(raw.trim() || \"[]\")\n if (!Array.isArray(items)) throw new Error(`${command} show: expected a JSON array`)\n return items\n .filter((r: NativeTask) => r && typeof r.id === \"string\" && !r.isCompleted)\n .map((r: NativeTask) => ({ ...r, title: unArg(r.title) ?? \"\", ...(r.notes !== undefined ? { notes: unArg(r.notes) } : {}) }))\n },\n async add({ list, title, notes, due, priority }) {\n const args = [\"add\", \"--title\", argValue(title), \"--list\", listName(list), \"--notes\", argValue(notes)]\n if (due) args.push(\"--due\", isoDue(due))\n if (priority && priority !== \"none\") args.push(\"--priority\", priority)\n const raw = await exec(command, [...args, \"--json\", \"--no-input\"])\n let id: unknown\n try { id = JSON.parse(raw.trim())?.id } catch { id = undefined }\n if (typeof id !== \"string\" || !id) throw new Error(`${command} add: no reminder id in its answer`)\n return { id }\n },\n async update(id, patch) {\n const args = [\"edit\", id]\n if (patch.title !== undefined) args.push(\"--title\", argValue(patch.title))\n if (patch.notes !== undefined) args.push(\"--notes\", argValue(patch.notes))\n if (patch.due === null) args.push(\"--clear-due\")\n else if (patch.due) args.push(\"--due\", isoDue(patch.due))\n // remindctl refuses an edit that changes nothing; so does this.\n if (args.length === 2) return\n await exec(command, [...args, \"--json\", \"--no-input\"])\n },\n async complete(id) {\n await exec(command, [\"complete\", id, \"--json\", \"--no-input\"])\n },\n async remove(id) {\n await exec(command, [\"delete\", id, \"--force\", \"--json\", \"--no-input\"])\n },\n }\n}\n","import type { NativeAdapter } from \"./types\"\n\n/** The adapter for a machine AgentX has no OS layer for, or where the owner\n * turned it off. Every capability is absent; describe() says why. */\nexport function noneAdapter(reason: string): NativeAdapter {\n return {\n os: \"none\",\n async describe() {\n return { os: \"none\", tasks: false, notes: false, banner: false, sound: false, focus: false, problems: [reason] }\n },\n }\n}\n","import { macosAdapter, type MacosIo } from \"./macos\"\nimport { noneAdapter } from \"./none\"\nimport type { NativeAdapter } from \"./types\"\n\nexport * from \"./types\"\nexport { noneAdapter } from \"./none\"\n\nexport type NativeAdapterChoice = \"auto\" | \"none\"\n\nexport type NativeConfig = { native?: { adapter?: NativeAdapterChoice }; reminders?: { command?: string } }\n\n/** Programs an adapter runs, so tests can stand in for them. */\nexport type NativeIo = MacosIo\n\n/** Builds the adapter for one OS. Each OS adapter registers here. */\nexport type NativeAdapterFactory = (cfg: NativeConfig, io: NativeIo) => NativeAdapter\n\nconst FACTORIES: Partial<Record<NodeJS.Platform, NativeAdapterFactory>> = {\n darwin: macosAdapter,\n}\n\n/** The adapter for this machine. `native.adapter: \"none\"` forces none on\n * any OS; \"auto\" (the default) picks by platform. */\nexport function loadNativeAdapter(\n cfg: NativeConfig = {},\n opts: { platform?: NodeJS.Platform; factories?: Partial<Record<NodeJS.Platform, NativeAdapterFactory>>; io?: NativeIo } = {},\n): NativeAdapter {\n if (cfg.native?.adapter === \"none\") return noneAdapter(\"Turned off: native.adapter is \\\"none\\\".\")\n const platform = opts.platform ?? process.platform\n const make = (opts.factories ?? FACTORIES)[platform]\n return make ? make(cfg, opts.io ?? {}) : noneAdapter(`AgentX has no native adapter for ${platform} yet.`)\n}\n","import { existsSync } from \"fs\"\nimport { homedir } from \"os\"\nimport { isAbsolute } from \"path\"\nimport { loadNativeAdapter, type NativeConfig, type NativeIo } from \"@/native\"\n\nexport { findHelper } from \"@/desktop/install\"\n\n// What happens on THIS machine when a notification is delivered: a banner\n// on screen and a short sound. The push goes to the phone; these are for\n// the person sitting at the computer that raised the event. Both go\n// through the native adapter (src/native); a machine without one skips\n// them.\n//\n// Both are awaited rather than fired and forgotten. A caller that exits\n// straight after notifying — a `launchctl submit` job that removes itself,\n// a cron one-liner — used to take the sound down with it before it\n// played. Waiting costs about a second and makes the step reliable.\n//\n// Never fatal: a notification whose banner failed still arrived, and no\n// caller should have to handle an audio error to say a build finished.\n\nexport interface LocalSettings {\n /** Show a desktop banner (macOS only; other platforms skip it). */\n banner: boolean\n /** Play a sound (macOS only). */\n sound: boolean\n /** A system sound, by name (on a Mac, one of the sounds in System Settings › Sound). */\n soundName: string\n /** 0 (silent) … 1 (full). */\n volume: number\n /** Image for the helper's app icon, which macOS puts on its banners.\n * Unset: the AgentX logo. Applied when `agentx desktop install` builds\n * the helper, since macOS reads the icon from the app, not the banner. */\n icon?: string\n}\n\n/** Glass is the gentlest system sound that is still audible over a\n * keyboard — Basso and Sosumi are alerts, Funk and Frog are jokes, and\n * Ping is the one every other app already uses. */\nexport const DEFAULT_LOCAL: LocalSettings = { banner: true, sound: true, soundName: \"Glass\", volume: 0.4 }\n\n/** Shows the banner and plays the sound for one delivered notification. */\nexport type LocalAlert = (title: string, message: string) => Promise<void>\n\n/** Fill gaps in a partial `notifications.local` block with the defaults. */\nexport function localSettings(cfg: Partial<LocalSettings> | undefined): LocalSettings {\n return { ...DEFAULT_LOCAL, ...(cfg ?? {}) }\n}\n\nexport function localAlert(\n settings: LocalSettings,\n deps: { run?: NativeIo[\"run\"]; platform?: NodeJS.Platform; helper?: string | null; native?: NativeConfig[\"native\"] } = {},\n): LocalAlert {\n const native = loadNativeAdapter({ native: deps.native }, { platform: deps.platform, io: { run: deps.run, helper: deps.helper } })\n return async (title, message) => {\n const steps: Promise<unknown>[] = []\n if (settings.banner && native.banner) steps.push(native.banner.post({ title, message }))\n if (settings.sound && native.sound) steps.push(native.sound.play(settings.soundName, settings.volume))\n await Promise.all(steps)\n }\n}\n\n/**\n * Apply a change to a stored `notifications.local` block, the one rule\n * both the CLI and the dashboard write through. Returns the new block;\n * throws on a value that would not load. Only a machine with a native\n * adapter has sounds to check a name against; elsewhere the setting is\n * inert, so it need only be well-formed.\n */\nexport function patchLocal(\n current: Partial<LocalSettings> | undefined,\n patch: Record<string, unknown>,\n platform: NodeJS.Platform = process.platform,\n): Partial<LocalSettings> {\n const next = { ...(current ?? {}) }\n const native = loadNativeAdapter({}, { platform })\n if (\"banner\" in patch) next.banner = Boolean(patch.banner)\n if (\"sound\" in patch) next.sound = Boolean(patch.sound)\n if (\"soundName\" in patch) {\n const name = String(patch.soundName).trim()\n const ok = native.sound ? native.sound.has(name) : /^[\\w -]+$/.test(name)\n if (!ok) throw new Error(`no system sound named \"${name}\" on this machine`)\n next.soundName = name\n }\n if (\"icon\" in patch) {\n const icon = String(patch.icon ?? \"\").trim().replace(/^~(?=\\/)/, homedir())\n if (!icon) delete next.icon\n else {\n if (!isAbsolute(icon) || !/\\.(png|jpe?g|icns)$/i.test(icon)) throw new Error(\"icon must be the full path to a .png, .jpg or .icns file\")\n if (native.banner && !existsSync(icon)) throw new Error(`no icon file at ${icon}`)\n next.icon = icon\n }\n }\n if (\"volume\" in patch) {\n const v = Number(patch.volume)\n if (!Number.isFinite(v) || v < 0 || v > 1) throw new Error(\"volume must be between 0 and 1\")\n next.volume = v\n }\n return next\n}\n","import { existsSync, mkdirSync, readFileSync, renameSync, writeFileSync } from \"fs\"\nimport { dirname, resolve } from \"path\"\nimport type { NativePriority, NativeTasks } from \"@/native\"\nimport { summarize } from \"@/requests/card-view\"\nimport type { RequestRecord } from \"@/requests/store\"\nimport { CARD_LIMITS, type DecisionCard } from \"./cards\"\n\n// --- The Reminders mirror (#1062 step 5) ---\n//\n// Each pending decision card, and each request waiting on the owner,\n// becomes one task in the OS task app (Apple Reminders on a Mac) with a due\n// time. Calendar shows it, and the system alert comes back when it falls\n// due. Answering stays on the Desk, the Approvals page or the CLI: a task\n// cannot carry choices or a draft.\n//\n// Runs once a minute beside the approvals sweep, on the node that holds the\n// cards (forwarded cards live on the owner's node, so that is where they\n// are mirrored). Off by default.\n//\n// Rules:\n// - one task per card or request, created once;\n// - the card is answered, expires or is closed, or the request stops\n// waiting on the owner: the task is completed;\n// - the owner ticks the task off or deletes it while the item still\n// waits: the item stays on the Desk and is never mirrored again.\n// Ticking a task is not an answer;\n// - three failed adds for one item: the owner is told once and that\n// item is not tried again;\n// - every task ends with `agentx: card=<id>` or `agentx: request=<id>`,\n// which check-ins and the reminders hand-back skip, so a mirrored\n// task never turns back into a card or an agent's job.\n//\n// State lives in its own file, written only by the daemon, not in the card\n// files that the CLI and the dashboard also write.\n\nexport interface MirrorSettings {\n enabled: boolean\n list: string\n dueAfterMinutes: number\n include: (\"card\" | \"request\")[]\n /** Where the owner answers. Unset: the local dashboard's Approvals page. */\n answerUrl?: string\n}\n\nexport type MirrorState = \"open\" | \"completed\" | \"dismissed\" | \"failed\"\n\nexport interface MirrorEntry {\n /** The task's id in the OS task app, once added. */\n id?: string\n list: string\n state: MirrorState\n /** ISO time of the last change. */\n at: string\n failures: number\n lastError?: string\n}\n\nexport interface MirrorFile {\n /** Keyed `card:<id>` or `request:<id>`, the inbox's keys. */\n items: Record<string, MirrorEntry>\n /** ISO time of the last pass that read every list it needed. Stale\n * (the mirror was turned off, or the list can't be read) means the\n * mirror no longer covers anything, and the Mac popup is back. */\n checkedAt?: string\n /** That pass mirrored cards (include has \"card\"). */\n cards?: boolean\n /** ISO time the owner was last told adds are failing: once a day. */\n failureToldAt?: string\n /** The latest pass's last error, for doctor. */\n lastError?: { at: string; message: string }\n}\n\nexport const MAX_ADD_FAILURES = 3\n/** Closed entries are kept this long, then forgotten. */\nconst KEEP_CLOSED_MS = 30 * 24 * 3_600_000\n\nexport function mirrorPath(root: string): string {\n return resolve(root, \".agentx\", \"native-mirror.json\")\n}\n\nexport function readMirror(root: string): MirrorFile {\n try {\n const parsed = JSON.parse(readFileSync(mirrorPath(root), \"utf-8\"))\n return { ...parsed, items: parsed?.items && typeof parsed.items === \"object\" ? parsed.items : {} }\n } catch {\n return { items: {} }\n }\n}\n\nfunction writeMirror(root: string, file: MirrorFile): void {\n const path = mirrorPath(root)\n if (!existsSync(dirname(path))) mkdirSync(dirname(path), { recursive: true })\n const tmp = `${path}.${process.pid}.tmp`\n writeFileSync(tmp, JSON.stringify(file, null, 2) + \"\\n\")\n renameSync(tmp, path)\n}\n\n/** A pass older than this means the mirror is not running. */\nexport const MIRROR_FRESH_MS = 5 * 60_000\n\n/** True when the mirror is running and covers this card: it has a task,\n * or gets one on the next pass, or the owner ticked its task off. The Mac\n * popup then leaves it alone, so the owner is not alerted twice. A card\n * whose task could not be added is not covered. */\nexport function mirrorCovers(root: string, cardId: string, now = Date.now()): boolean {\n const file = readMirror(root)\n const checked = file.checkedAt ? Date.parse(file.checkedAt) : NaN\n if (!file.cards || !(now - checked <= MIRROR_FRESH_MS)) return false\n return file.items[`card:${cardId}`]?.state !== \"failed\"\n}\n\n/** What one task says. */\nexport interface MirrorItem {\n key: string\n title: string\n notes: string\n due: Date\n priority: NativePriority\n}\n\nconst DAY_MS = 24 * 3_600_000\n\nfunction dueFor(now: number, settings: MirrorSettings, limit?: number): Date {\n const due = now + settings.dueAfterMinutes * 60_000\n return new Date(limit !== undefined && Number.isFinite(limit) ? Math.max(now, Math.min(due, limit)) : due)\n}\n\nexport function cardItem(card: DecisionCard, settings: MirrorSettings, answerUrl: string, now: number): MirrorItem {\n const expires = Date.parse(card.expires)\n const lines = [summarize(card.ask, CARD_LIMITS.ask)]\n if (card.choices?.length) lines.push(...card.choices.map((c, i) => `${i + 1}. ${c}`))\n if (card.recommend) lines.push(`Recommended: ${summarize(card.recommend, CARD_LIMITS.recommend)}`)\n lines.push(`Answer: ${answerUrl}`, `agentx: card=${card.id}`)\n return {\n key: `card:${card.id}`,\n title: summarize(card.title, CARD_LIMITS.title),\n notes: lines.join(\"\\n\"),\n due: dueFor(now, settings, expires),\n priority: Number.isFinite(expires) && expires - now <= DAY_MS ? \"high\" : \"none\",\n }\n}\n\nexport function requestItem(r: RequestRecord, settings: MirrorSettings, answerUrl: string, now: number): MirrorItem {\n const lines = [summarize(r.question || r.text, CARD_LIMITS.ask), `Asked of ${r.agentId}.`, `Answer: ${answerUrl}`, `agentx: request=${r.id}`]\n const dueAt = r.dueAt ?? undefined\n return {\n key: `request:${r.id}`,\n title: summarize(r.text, CARD_LIMITS.title),\n notes: lines.join(\"\\n\"),\n due: dueFor(now, settings, dueAt),\n priority: dueAt !== undefined && dueAt - now <= DAY_MS ? \"high\" : \"none\",\n }\n}\n\nexport interface MirrorDeps {\n root: string\n settings: MirrorSettings\n tasks: NativeTasks\n /** Pending cards on this node. */\n cards: () => DecisionCard[]\n /** Requests in waiting_owner. */\n requests: () => RequestRecord[]\n answerUrl: string\n /** Tell the owner, through the usual notification. */\n notify: (title: string, message: string) => Promise<void>\n log: (msg: string) => void\n now?: number\n}\n\nexport interface MirrorResult {\n created: number\n completed: number\n dismissed: number\n failed: number\n}\n\n/** One pass of the mirror. Never throws. */\nexport async function runMirror(deps: MirrorDeps): Promise<MirrorResult> {\n const { root, settings, tasks, log } = deps\n const now = deps.now ?? Date.now()\n const at = new Date(now).toISOString()\n const result: MirrorResult = { created: 0, completed: 0, dismissed: 0, failed: 0 }\n const file = readMirror(root)\n // lastError says how the latest pass went: a clean pass clears it.\n delete file.lastError\n const fail = (message: string) => { file.lastError = { at, message } }\n\n const waiting = new Map<string, MirrorItem>()\n try {\n if (settings.include.includes(\"card\")) {\n for (const c of deps.cards()) if (c.status === \"pending\" && Date.parse(c.expires) > now) waiting.set(`card:${c.id}`, cardItem(c, settings, deps.answerUrl, now))\n }\n if (settings.include.includes(\"request\")) {\n for (const r of deps.requests()) if (r.state === \"waiting_owner\") waiting.set(`request:${r.id}`, requestItem(r, settings, deps.answerUrl, now))\n }\n } catch (e: any) {\n log(`[mirror] could not read what is waiting: ${e?.message ?? e}`)\n fail(String(e?.message ?? e))\n writeMirror(root, file)\n return result\n }\n\n // Close or notice dismissal for what is already mirrored. The open list\n // is read once per list; when it can't be read, nothing is closed or\n // dismissed this pass, so a hiccup never loses a task.\n let allRead = true\n const openIds = new Map<string, Set<string> | null>()\n const openIn = async (list: string): Promise<Set<string> | null> => {\n if (!openIds.has(list)) {\n try {\n openIds.set(list, new Set((await tasks.listOpen(list)).map((t) => t.id)))\n } catch (e: any) {\n log(`[mirror] could not read list \"${list}\": ${e?.message ?? e}`)\n fail(String(e?.message ?? e))\n openIds.set(list, null)\n allRead = false\n }\n }\n return openIds.get(list)!\n }\n\n for (const [key, entry] of Object.entries(file.items)) {\n if (entry.state !== \"open\" || !entry.id) continue\n const open = await openIn(entry.list)\n if (!open) continue\n if (!waiting.has(key)) {\n if (open.has(entry.id)) {\n try {\n await tasks.complete(entry.id)\n } catch (e: any) {\n log(`[mirror] ${key}: could not complete its task: ${e?.message ?? e}`)\n fail(String(e?.message ?? e))\n continue\n }\n }\n file.items[key] = { ...entry, state: \"completed\", at }\n result.completed++\n } else if (!open.has(entry.id)) {\n file.items[key] = { ...entry, state: \"dismissed\", at }\n result.dismissed++\n log(`[mirror] ${key}: its task was ticked off or deleted; it stays on the Desk and is not mirrored again`)\n }\n }\n\n let listReady: boolean | null = null\n const gaveUp: { title: string; message: string }[] = []\n for (const [key, item] of waiting) {\n const entry = file.items[key]\n if (entry && (entry.state === \"open\" || entry.state === \"dismissed\")) continue\n if (entry?.state === \"failed\" && entry.failures >= MAX_ADD_FAILURES) continue\n // The list is made on the first add of a pass, when it is missing.\n if (listReady === null) {\n try {\n await tasks.ensureList(settings.list)\n listReady = true\n } catch (e: any) {\n log(`[mirror] could not make list \"${settings.list}\": ${e?.message ?? e}`)\n fail(String(e?.message ?? e))\n listReady = false\n }\n }\n const failures = entry?.state === \"failed\" ? entry.failures : 0\n try {\n const { id } = await tasks.add({ list: settings.list, title: item.title, notes: item.notes, due: item.due, priority: item.priority })\n file.items[key] = { id, list: settings.list, state: \"open\", at, failures: 0 }\n result.created++\n } catch (e: any) {\n const message = String(e?.message ?? e)\n const n = failures + 1\n file.items[key] = { list: settings.list, state: \"failed\", at, failures: n, lastError: message }\n fail(message)\n result.failed++\n log(`[mirror] ${key}: could not add to Reminders (${n}/${MAX_ADD_FAILURES}): ${message}`)\n if (n === MAX_ADD_FAILURES) gaveUp.push({ title: item.title, message })\n }\n }\n\n // One notification a day at most, however many items gave up: a missing\n // permission fails every card the same way.\n const told = file.failureToldAt ? Date.parse(file.failureToldAt) : NaN\n if (gaveUp.length && !(now - told < DAY_MS)) {\n const first = gaveUp[0]\n const more = gaveUp.length > 1 ? ` (and ${gaveUp.length - 1} more)` : \"\"\n try {\n await deps.notify(\"Could not add to Reminders\", `${first.title}${more}: ${summarize(first.message, 200)}. Still on the Desk.`)\n file.failureToldAt = at\n } catch (err: any) {\n log(`[mirror] could not tell the owner: ${err?.message ?? err}`)\n }\n }\n\n if (allRead) {\n file.checkedAt = at\n file.cards = settings.include.includes(\"card\")\n }\n\n for (const [key, entry] of Object.entries(file.items)) {\n if (entry.state !== \"open\" && !waiting.has(key) && now - Date.parse(entry.at) > KEEP_CLOSED_MS) delete file.items[key]\n }\n writeMirror(root, file)\n return result\n}\n","import { markdownToHtml } from \"@/utils/markdown-html\"\nimport type { RequestRecord, RequestStore } from \"./store\"\nimport type { PlanState, PlanStore, StepState } from \"./plan-store\"\nimport { describeCloseWhen } from \"./checkers\"\nimport { activeStepAgentOf, stalledWhy, waitsOn, type StallGroup } from \"./loops\"\n\n// --- One open request as a card the owner can read in seconds (#459) ---\n//\n// The Approvals page shows each open request as a card: a short plain\n// summary, where it stands and why it is not finished, then the words the\n// owner used and the agent's last answer, both rendered. markdownToHtml\n// escapes before it marks up, so nothing an agent or a channel wrote\n// reaches the page as HTML. No model call: the summary is the start of the\n// request's own words, without the markdown marks.\n\nexport const SUMMARY_MAX = 200\n/** An answer of pages is cut: the card is for reading quickly. */\nexport const ANSWER_MAX = 4000\n\nexport interface RequestCard extends RequestRecord {\n summary: string\n /** The request in the owner's words (the transcript, when spoken). */\n textHtml: string\n /** Why it is not finished, or what is being asked. Null: work is under way. */\n why: string | null\n ownerNoteHtml: string | null\n lastAnswer: { agentId: string; at: number; html: string } | null\n /** The open loop (#1039): who it is owed to, when it is due, what\n * closes it. Null on a request with none of it. */\n loop: {\n owedTo: string | null\n promise: boolean\n dueAt: number | null\n /** What its check waits for, in words. */\n check: string | null\n verifyState: string | null\n verifyDetail: string | null\n } | null\n /** Stalled, and what it waits on. Null: not stalled, or not asked. */\n stall: { group: StallGroup; who: string; why: string } | null\n /** Its tracked plan (#788), step by step. Null: no plan. */\n plan: {\n state: PlanState\n steps: Array<{ idx: number; name: string; kind: string; agentId: string; state: StepState; approval: string | null; evidence: string | null; note: string | null; nudges: number }>\n } | null\n}\n\n/** Markdown to the words alone, on one line. */\nexport function plain(md: string): string {\n return md\n .replace(/```[\\s\\S]*?```/g, \" \")\n .replace(/!?\\[([^\\]]*)\\]\\([^)]*\\)/g, \"$1\")\n .replace(/^\\s{0,3}(#{1,6}|>|[-*+]|\\d+[.)])\\s+/gm, \"\")\n .replace(/[*_~`]+/g, \"\")\n .replace(/\\s+/g, \" \")\n .trim()\n}\n\n/** The start of the request, cut at a sentence when one ends in reach. */\nexport function summarize(md: string, max = SUMMARY_MAX): string {\n const text = plain(md)\n if (text.length <= max) return text\n const cut = text.slice(0, max)\n const end = Math.max(cut.lastIndexOf(\". \"), cut.lastIndexOf(\"? \"), cut.lastIndexOf(\"! \"))\n return end > max / 2 ? cut.slice(0, end + 1) : `${cut.slice(0, max - 1).trimEnd()}…`\n}\n\n/** What the stall view needs: the quiet time, the clock, and which ids are agents. */\nexport interface StallLookup { staleAfterHours: number; now: number; isAgent: (id: string) => boolean }\n\nexport function requestCard(\n r: RequestRecord,\n store: Pick<RequestStore, \"lastAnswer\">,\n plans?: Pick<PlanStore, \"get\" | \"steps\"> | null,\n stall?: StallLookup,\n): RequestCard {\n const plan = plans?.get(r.id)\n const why = stall ? stalledWhy(r, stall.staleAfterHours, stall.now) : null\n const answer = store.lastAnswer(r.id)\n const cutAnswer = answer && answer.text.length > ANSWER_MAX ? `${answer.text.slice(0, ANSWER_MAX)}\\n\\n…` : answer?.text\n return {\n ...r,\n summary: summarize(r.text),\n textHtml: markdownToHtml(r.text),\n why: r.state === \"waiting_owner\" ? r.question : r.state === \"needs_attention\" ? r.attentionReason : null,\n ownerNoteHtml: r.ownerNote ? markdownToHtml(r.ownerNote) : null,\n lastAnswer: answer ? { agentId: answer.agentId, at: answer.at, html: markdownToHtml(cutAnswer!) } : null,\n loop: r.promise || r.dueAt !== null || r.closeWhen ? {\n owedTo: r.owedTo, promise: r.promise, dueAt: r.dueAt, check: r.closeWhen ? describeCloseWhen(r.closeWhen) : null,\n verifyState: r.verifyState, verifyDetail: r.verifyDetail,\n } : null,\n stall: stall && why ? { ...waitsOn(r, { isAgent: stall.isAgent, activeStepAgent: activeStepAgentOf(plans) }), why } : null,\n plan: plan ? {\n state: plan.state,\n steps: plans!.steps(r.id).map((s) => ({\n idx: s.idx, name: s.name, kind: s.kind, agentId: s.agentId, state: s.state,\n approval: s.needsApproval ? s.approval : null, evidence: s.evidence, note: s.note, nudges: s.nudges,\n })),\n } : null,\n }\n}\n","import { OPEN_STATES, OWED_TO_OWNER, type RequestRecord, type RequestStore } from \"./store\"\nimport { runCheck, type CheckContext, type CheckResult, type CloseWhen } from \"./checkers\"\n\n// --- Open loops: who each one waits on, and when it is stalled (#1039) ---\n//\n// A loop is an open request: one the owner asked for, or one an agent\n// promised (action promise). It is stalled when it is past its due time,\n// or, without one, when nothing has happened for staleAfterHours. A loop\n// that needs attention is stalled too: nothing is retrying it.\n//\n// Stalled loops are grouped by what they wait on:\n// owner the owner's answer (waiting_owner), or the owner's decision\n// on one that needs attention\n// agent an agent: the one that has it, a plan step's agent, or the\n// agent it is owed to\n// person an outside person: a promise owed to a known person\n// The requests panel, `agentx requests --stalled` and the sweep's notice\n// all use this one grouping.\n\nexport const STALL_GROUPS = [\"owner\", \"agent\", \"person\"] as const\nexport type StallGroup = (typeof STALL_GROUPS)[number]\n\nexport interface StalledLoop {\n request: RequestRecord\n group: StallGroup\n /** Who it waits on: \"owner\", an agent id or a person id. */\n who: string\n /** Why it counts as stalled, in words. */\n why: string\n}\n\nexport interface LoopLookups {\n isAgent: (id: string) => boolean\n /** The agent of the active step of the request's plan, if it has one. */\n activeStepAgent?: (requestId: string) => string | null\n}\n\nconst HOUR = 3_600_000\nconst isOpen = (r: RequestRecord) => (OPEN_STATES as readonly string[]).includes(r.state)\n\n/** The agent of each request's active plan step, from the plan store. */\nexport function activeStepAgentOf(plans: { get(id: string): { state: string } | null; steps(id: string): Array<{ state: string; agentId: string }> } | null | undefined) {\n return (requestId: string): string | null => {\n if (!plans || plans.get(requestId)?.state !== \"active\") return null\n return plans.steps(requestId).find((s) => s.state === \"active\")?.agentId ?? null\n }\n}\n\n/** What an open loop waits on. */\nexport function waitsOn(r: RequestRecord, look: LoopLookups): { group: StallGroup; who: string } {\n if (r.state === \"waiting_owner\") return { group: \"owner\", who: OWED_TO_OWNER }\n if (r.promise && r.owedTo && r.owedTo !== OWED_TO_OWNER && !look.isAgent(r.owedTo)) return { group: \"person\", who: r.owedTo }\n if (r.state === \"needs_attention\") return { group: \"owner\", who: OWED_TO_OWNER }\n const step = look.activeStepAgent?.(r.id)\n return { group: \"agent\", who: step ?? r.agentId }\n}\n\n/** Why an open loop is stalled, or null when it is not. */\nexport function stalledWhy(r: RequestRecord, staleAfterHours: number, now: number): string | null {\n if (!isOpen(r)) return null\n if (r.state === \"needs_attention\") return r.attentionReason ?? \"needs attention\"\n if (r.dueAt !== null) return now > r.dueAt ? `past its due time (${when(r.dueAt)})` : null\n return now - r.updatedAt > staleAfterHours * HOUR ? `no activity for ${staleAfterHours} h or more` : null\n}\n\n/** Stalled loops among `items`, oldest first, grouped. */\nexport function stalledLoops(items: RequestRecord[], staleAfterHours: number, now: number, look: LoopLookups): Record<StallGroup, StalledLoop[]> {\n const out: Record<StallGroup, StalledLoop[]> = { owner: [], agent: [], person: [] }\n for (const r of items) {\n const why = stalledWhy(r, staleAfterHours, now)\n if (!why) continue\n const { group, who } = waitsOn(r, look)\n out[group].push({ request: r, group, who, why })\n }\n return out\n}\n\n/** The group, in words, for people. */\nexport function waitsOnWords(group: StallGroup, who: string): string {\n return group === \"owner\" ? \"you\" : group === \"agent\" ? `agent ${who}` : `${who} (outside person)`\n}\n\nexport const when = (ms: number) => new Date(ms).toISOString().slice(0, 16).replace(\"T\", \" \") + \" UTC\"\n\n/** A due time an agent or the owner gave: epoch ms, or an ISO date.\n * Undefined when absent, a string when it is not a time. */\nexport function parseDue(v: unknown): number | undefined | string {\n if (v === undefined || v === null || v === \"\") return undefined\n const at = typeof v === \"number\" ? v : typeof v === \"string\" ? Date.parse(v.trim()) : NaN\n if (!Number.isFinite(at) || at <= 0) return \"due must be an ISO date (2030-01-31T17:00:00Z) or epoch milliseconds\"\n return at\n}\n\n// ── Running the checkers from the requests check ─────────────────────────\n\n/** Runs a loop's checker. The daemon's own; tests give their own. */\nexport type LoopChecker = (spec: CloseWhen, request: RequestRecord) => Promise<CheckResult>\n\nexport function loopChecker(ctx: () => CheckContext): LoopChecker {\n return (spec) => runCheck(spec, ctx())\n}\n\n/** How many checkers run at once, and how many loops one check takes on. */\nconst CHECK_BATCH = 10\n\n/** Run the checker of every open loop whose last check is older than\n * `everyMinutes`. Met closes it as done with the checker's evidence;\n * unverifiable marks it unverified; not met leaves it as it is. */\nexport async function checkLoops(\n store: RequestStore,\n check: LoopChecker,\n opts: { everyMinutes: number; now: number; log: (msg: string) => void },\n): Promise<{ checked: number; closed: number }> {\n const due = store.dueForCheck(opts.now - opts.everyMinutes * 60_000, CHECK_BATCH)\n let closed = 0\n await Promise.all(due.map(async (r) => {\n // Marked before the call: a check that hangs is not started again\n // at the next minute.\n store.markChecked(r.id, r.verifyState, r.verifyDetail ?? \"\", opts.now)\n const res = await check(r.closeWhen!, r).catch((e: any): CheckResult => ({ verdict: \"unverifiable\", detail: String(e?.message ?? e) }))\n if (res.verdict === \"met\") {\n if (store.closeVerified(r.id, res.detail, opts.now)) {\n closed++\n opts.log(`[requests] ${r.id} closed by its check: ${res.detail}`)\n }\n return\n }\n // A refused done stays \"failed\" until the check says otherwise.\n store.markChecked(r.id, res.verdict === \"unverifiable\" ? \"unverified\" : r.verifyState === \"failed\" ? \"failed\" : null, res.detail, opts.now)\n }))\n return { checked: due.length, closed }\n}\n"],"mappings":"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","names":["existsSync","readFileSync","dirname","join","fileURLToPath","homedir","DESKTOP_LABEL","DESKTOP_APP","HELPER_APP","desktopPlatformError","platform","arch","release","selectDesktopAgent","agents","requested","id","shellQuote","value","LAUNCHD_PATH","desktopPath","ffmpeg","override","unxml","s","ents","_","e","plistPathEnv","plist","m","isVoiceLoginItemFile","name","adoptLoginItem","dir","items","keep","remove","file","a","b","label","program","findOnPath","bin","path","isExecutable","desktopPlist","opts","xml","env","k","v","helperBuildArgs","icon","installedHelper","home","packageRoot","from","resolveHelper","root","installed","findHelper","accessSync","constants","execFile","STEP_TIMEOUT_MS","run","file","args","done","err","capture","stdout","output","resolve","reject","stderr","helperOf","io","findHelper","helperBannerStatus","path","capture","out","status","macosBanner","exec","run","title","message","helper","NOTES_SCRIPT","macosNotes","exec","output","folder","title","body","id","existsSync","readdirSync","SOUNDS","soundPath","name","path","existsSync","macosSound","io","exec","run","volume","readdirSync","f","ZWSP","argValue","v","unArg","listName","list","isoDue","d","macosTasks","command","exec","output","raw","lists","l","items","r","title","notes","due","priority","args","id","patch","executable","file","accessSync","constants","focus","s","readSystemFocus","macosAdapter","cfg","io","command","macosTasks","macosNotes","macosBanner","macosSound","problems","isExec","findOnPath","noneAdapter","reason","FACTORIES","macosAdapter","loadNativeAdapter","cfg","opts","noneAdapter","platform","make","existsSync","homedir","isAbsolute","DEFAULT_LOCAL","localSettings","cfg","localAlert","settings","deps","native","loadNativeAdapter","title","message","steps","patchLocal","current","patch","platform","next","name","icon","homedir","isAbsolute","existsSync","v","existsSync","mkdirSync","readFileSync","renameSync","writeFileSync","dirname","resolve","init_checkers","init_store","init_checkers","STALL_GROUPS","HOUR","isOpen","r","OPEN_STATES","activeStepAgentOf","plans","requestId","s","waitsOn","look","OWED_TO_OWNER","stalledWhy","staleAfterHours","now","when","stalledLoops","items","out","why","group","who","waitsOnWords","ms","parseDue","v","at","loopChecker","ctx","spec","runCheck","CHECK_BATCH","checkLoops","store","check","opts","due","closed","res","e","SUMMARY_MAX","ANSWER_MAX","plain","md","summarize","max","text","cut","end","requestCard","r","store","plans","stall","plan","why","stalledWhy","answer","cutAnswer","markdownToHtml","describeCloseWhen","waitsOn","activeStepAgentOf","s","MAX_ADD_FAILURES","KEEP_CLOSED_MS","mirrorPath","root","resolve","readMirror","parsed","readFileSync","writeMirror","file","path","existsSync","dirname","mkdirSync","tmp","writeFileSync","renameSync","MIRROR_FRESH_MS","mirrorCovers","cardId","now","checked","DAY_MS","dueFor","settings","limit","due","cardItem","card","answerUrl","expires","lines","summarize","CARD_LIMITS","c","i","requestItem","r","dueAt","runMirror","deps","tasks","log","at","result","fail","message","waiting","e","allRead","openIds","openIn","list","t","key","entry","open","listReady","gaveUp","item","failures","id","n","told","first","more","err"]}
|