agentix-cli 0.65.0 → 0.67.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/apps/mac-voice/Sources/AgentXVoice/AgentClient.swift +29 -8
- package/apps/mac-voice/Sources/AgentXVoice/MiniOrbs.swift +219 -0
- package/apps/mac-voice/Sources/AgentXVoice/Panel.swift +32 -3
- package/apps/mac-voice/Sources/AgentXVoice/PillBusy.swift +126 -0
- package/apps/mac-voice/Sources/AgentXVoice/StatusMenu.swift +53 -12
- package/apps/mac-voice/Sources/AgentXVoice/main.swift +49 -3
- package/dist/{agent-HUKCS3AK.js → agent-LKL3XATA.js} +2 -2
- package/dist/{board-dashboard-S4V4WR2N.js → board-dashboard-ZE2A3ARS.js} +823 -371
- package/dist/board-dashboard-ZE2A3ARS.js.map +1 -0
- package/dist/{chunk-WWMFNLKD.js → chunk-2NYP4OQU.js} +3 -3
- package/dist/chunk-2NYP4OQU.js.map +1 -0
- package/dist/{chunk-HSJRI3NW.js → chunk-3DNBE7WD.js} +152 -152
- package/dist/chunk-3DNBE7WD.js.map +1 -0
- package/dist/{chunk-ECBKTFTL.js → chunk-6H3U3CII.js} +16 -16
- package/dist/chunk-6H3U3CII.js.map +1 -0
- package/dist/{chunk-EOKOGQZG.js → chunk-A5COMJRC.js} +2 -2
- package/dist/{chunk-AVDWFQZ5.js → chunk-F2LML4IL.js} +2 -2
- package/dist/chunk-JWDJMFU6.js +4 -0
- package/dist/chunk-JWDJMFU6.js.map +1 -0
- package/dist/{chunk-LEFRNHZF.js → chunk-PRHIW6SQ.js} +4 -4
- package/dist/{chunk-OTTAKMGC.js → chunk-UHUYGEXK.js} +5 -5
- package/dist/chunk-UHUYGEXK.js.map +1 -0
- package/dist/cli.js +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.js +1 -1
- package/dist/{program-DZCKFNHD.js → program-ZRGI76RT.js} +2 -2
- package/dist/push-announce-PM5FZJRW.js +3 -0
- package/dist/push-announce-PM5FZJRW.js.map +1 -0
- package/dist/push-prefs-YOJNTOJF.js +2 -0
- package/dist/push-store-5VJ4FNI4.js +2 -0
- package/dist/{registry-P7IAAFCX.js → registry-EUO2D6JT.js} +2 -2
- package/dist/registry-EUO2D6JT.js.map +1 -0
- package/dist/rotation-memo-5MTSJ4FH.js +15 -0
- package/dist/rotation-memo-5MTSJ4FH.js.map +1 -0
- package/dist/web/activity-graph.global.js +7 -7
- package/dist/web/activity-graph.global.js.map +1 -1
- package/package.json +1 -1
- package/dist/board-dashboard-S4V4WR2N.js.map +0 -1
- package/dist/chunk-ECBKTFTL.js.map +0 -1
- package/dist/chunk-HSJRI3NW.js.map +0 -1
- package/dist/chunk-OTTAKMGC.js.map +0 -1
- package/dist/chunk-WWMFNLKD.js.map +0 -1
- package/dist/push-store-LXTYULUF.js +0 -2
- package/dist/rotation-memo-453FXKHQ.js +0 -13
- package/dist/rotation-memo-453FXKHQ.js.map +0 -1
- /package/dist/{agent-HUKCS3AK.js.map → agent-LKL3XATA.js.map} +0 -0
- /package/dist/{chunk-EOKOGQZG.js.map → chunk-A5COMJRC.js.map} +0 -0
- /package/dist/{chunk-AVDWFQZ5.js.map → chunk-F2LML4IL.js.map} +0 -0
- /package/dist/{chunk-LEFRNHZF.js.map → chunk-PRHIW6SQ.js.map} +0 -0
- /package/dist/{program-DZCKFNHD.js.map → program-ZRGI76RT.js.map} +0 -0
- /package/dist/{push-store-LXTYULUF.js.map → push-prefs-YOJNTOJF.js.map} +0 -0
- /package/dist/{registry-P7IAAFCX.js.map → push-store-5VJ4FNI4.js.map} +0 -0
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/channels/push-store.ts"],"sourcesContent":["import type Database from \"better-sqlite3\"\n\n// --- Web Push subscriptions and recent pushes (SQLite) ---\n//\n// Shared by two processes on the node that hosts the phone app: the\n// dashboard writes subscriptions when a phone turns notifications on\n// (/api/app/push/*), and the daemon's PushAdapter reads them to deliver,\n// prunes the ones the push service reports gone, and logs what it sent for\n// the app's Alerts tab. Both open the same .agentx/db.sqlite; WAL lets one\n// write while the other reads.\n//\n// Tables are created here with IF NOT EXISTS rather than as a numbered\n// migration, so a branch that claims the same migration number elsewhere\n// can't make a database skip them.\n\nexport interface PushSubscriptionRow {\n endpoint: string\n p256dh: string\n auth: string\n /** Token id of the paired phone (TokenRecord.id). */\n deviceId: string\n deviceName: string\n /** VAPID public key the browser subscribed with. After\n * `agentx app push-keys --force` older rows can never be delivered. */\n publicKey: string\n createdAt: number\n}\n\nexport interface PushLogRow {\n id: number\n at: number\n title: string\n body: string\n url: string | null\n /** Phones the push service accepted it for. */\n delivered: number\n /** Set when the push was addressed to one phone; null for every phone. */\n deviceId: string | null\n}\n\nexport class PushStore {\n constructor(private db: Database.Database) {\n db.exec(`CREATE TABLE IF NOT EXISTS push_subscriptions (\n endpoint TEXT PRIMARY KEY, p256dh TEXT NOT NULL, auth TEXT NOT NULL,\n device_id TEXT NOT NULL, device_name TEXT NOT NULL, public_key TEXT NOT NULL,\n created_at INTEGER NOT NULL);\n CREATE INDEX IF NOT EXISTS push_subscriptions_device ON push_subscriptions(device_id);\n CREATE TABLE IF NOT EXISTS push_log (\n id INTEGER PRIMARY KEY AUTOINCREMENT, at INTEGER NOT NULL, title TEXT NOT NULL,\n body TEXT NOT NULL, url TEXT, delivered INTEGER NOT NULL, device_id TEXT);`)\n }\n\n /** Adds or refreshes a subscription. A browser that re-subscribes keeps\n * its endpoint, so the row is replaced, not duplicated. */\n subscribe(row: Omit<PushSubscriptionRow, \"createdAt\">, now = Date.now()): void {\n this.db.prepare(`INSERT OR REPLACE INTO push_subscriptions\n (endpoint, p256dh, auth, device_id, device_name, public_key, created_at) VALUES (?, ?, ?, ?, ?, ?, ?)`)\n .run(row.endpoint, row.p256dh, row.auth, row.deviceId, row.deviceName, row.publicKey, now)\n }\n\n /** Removes one subscription, only if it belongs to `deviceId` when given. */\n unsubscribe(endpoint: string, deviceId?: string): boolean {\n const r = deviceId === undefined\n ? this.db.prepare(\"DELETE FROM push_subscriptions WHERE endpoint = ?\").run(endpoint)\n : this.db.prepare(\"DELETE FROM push_subscriptions WHERE endpoint = ? AND device_id = ?\").run(endpoint, deviceId)\n return r.changes > 0\n }\n\n list(deviceId?: string): PushSubscriptionRow[] {\n const rows = (deviceId === undefined\n ? this.db.prepare(\"SELECT * FROM push_subscriptions ORDER BY created_at\").all()\n : this.db.prepare(\"SELECT * FROM push_subscriptions WHERE device_id = ? ORDER BY created_at\").all(deviceId)) as any[]\n return rows.map((r) => ({\n endpoint: r.endpoint, p256dh: r.p256dh, auth: r.auth,\n deviceId: r.device_id, deviceName: r.device_name, publicKey: r.public_key, createdAt: r.created_at,\n }))\n }\n\n /** Records a sent push and keeps only the newest `keep` rows. */\n log(entry: Omit<PushLogRow, \"id\" | \"at\">, keep: number, now = Date.now()): void {\n this.db.prepare(\"INSERT INTO push_log (at, title, body, url, delivered, device_id) VALUES (?, ?, ?, ?, ?, ?)\")\n .run(now, entry.title, entry.body, entry.url, entry.delivered, entry.deviceId)\n this.db.prepare(\"DELETE FROM push_log WHERE id NOT IN (SELECT id FROM push_log ORDER BY id DESC LIMIT ?)\").run(Math.max(0, keep))\n }\n\n /** Newest first. With `deviceId`, only pushes sent to every phone or to\n * that one, so one phone never sees another's messages. */\n recent(limit: number, deviceId?: string): PushLogRow[] {\n const cols = \"id, at, title, body, url, delivered, device_id AS deviceId\"\n return (deviceId === undefined\n ? this.db.prepare(`SELECT ${cols} FROM push_log ORDER BY id DESC LIMIT ?`).all(Math.max(0, limit))\n : this.db.prepare(`SELECT ${cols} FROM push_log WHERE device_id IS NULL OR device_id = ? ORDER BY id DESC LIMIT ?`)\n .all(deviceId, Math.max(0, limit))) as PushLogRow[]\n }\n}\n"],"mappings":"AAwCO,IAAMA,EAAN,KAAgB,CACrB,YAAoBC,EAAuB,CAAvB,QAAAA,EAClBA,EAAG,KAAK;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,iFAOqE,CAC/E,CAIA,UAAUC,EAA6CC,EAAM,KAAK,IAAI,EAAS,CAC7E,KAAK,GAAG,QAAQ;AAAA,4GACwF,EACrG,IAAID,EAAI,SAAUA,EAAI,OAAQA,EAAI,KAAMA,EAAI,SAAUA,EAAI,WAAYA,EAAI,UAAWC,CAAG,CAC7F,CAGA,YAAYC,EAAkBC,EAA4B,CAIxD,OAHUA,IAAa,OACnB,KAAK,GAAG,QAAQ,mDAAmD,EAAE,IAAID,CAAQ,EACjF,KAAK,GAAG,QAAQ,qEAAqE,EAAE,IAAIA,EAAUC,CAAQ,GACxG,QAAU,CACrB,CAEA,KAAKA,EAA0C,CAI7C,OAHcA,IAAa,OACvB,KAAK,GAAG,QAAQ,sDAAsD,EAAE,IAAI,EAC5E,KAAK,GAAG,QAAQ,0EAA0E,EAAE,IAAIA,CAAQ,GAChG,IAAKC,IAAO,CACtB,SAAUA,EAAE,SAAU,OAAQA,EAAE,OAAQ,KAAMA,EAAE,KAChD,SAAUA,EAAE,UAAW,WAAYA,EAAE,YAAa,UAAWA,EAAE,WAAY,UAAWA,EAAE,UAC1F,EAAE,CACJ,CAGA,IAAIC,EAAsCC,EAAcL,EAAM,KAAK,IAAI,EAAS,CAC9E,KAAK,GAAG,QAAQ,6FAA6F,EAC1G,IAAIA,EAAKI,EAAM,MAAOA,EAAM,KAAMA,EAAM,IAAKA,EAAM,UAAWA,EAAM,QAAQ,EAC/E,KAAK,GAAG,QAAQ,yFAAyF,EAAE,IAAI,KAAK,IAAI,EAAGC,CAAI,CAAC,CAClI,CAIA,OAAOC,EAAeJ,EAAiC,CACrD,IAAMK,EAAO,6DACb,OAAQL,IAAa,OACjB,KAAK,GAAG,QAAQ,UAAUK,0CAA6C,EAAE,IAAI,KAAK,IAAI,EAAGD,CAAK,CAAC,EAC/F,KAAK,GAAG,QAAQ,UAAUC,mFAAsF,EAC/G,IAAIL,EAAU,KAAK,IAAI,EAAGI,CAAK,CAAC,CACvC,CACF","names":["PushStore","db","row","now","endpoint","deviceId","r","entry","keep","limit","cols"]}
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import{a as u,c as m}from"./chunk-2GIDVZ4H.js";import"./chunk-QIJLFPWE.js";import{execFile as h}from"child_process";var g=3e4,w="haiku",M=`You are about to lose this working session due to context-size rotation. Before that happens, write a compact memo of what you should carry forward to your next session on the same conversation.
|
|
2
|
-
|
|
3
|
-
Include only durable facts a future turn would otherwise have to rediscover:
|
|
4
|
-
- Names, handles, agent ids, telegram/whatsapp/gitlab usernames
|
|
5
|
-
- File paths, URLs, project namespaces, ssh hosts, ports
|
|
6
|
-
- Decisions made and their reasoning
|
|
7
|
-
- Open tasks or commitments to follow up on
|
|
8
|
-
- Identifiers (issue numbers, PR numbers, ticket ids) the user referred to
|
|
9
|
-
|
|
10
|
-
Format: 3-12 short bullet points. Each \u2264120 chars. No prose, no preamble, no header. If the session was uninformative or just casual chat, reply with exactly the literal text "(no memo)".
|
|
11
|
-
|
|
12
|
-
Begin the memo now.`;async function E(n,r){let c=Date.now();if(!r)return{memo:null,reason:"no-resume",durationMs:0};let i=["-p",M,"--output-format","json","--resume",r,"--model",w];n.permissionMode==="bypassPermissions"&&i.push("--dangerously-skip-permissions");let p=m(u(n.workspace),n.billing);return new Promise(d=>{let a=!1,e=(t,s)=>{a||(a=!0,d({memo:t,reason:s,durationMs:Date.now()-c}))};h("claude",i,{cwd:n.workspace,env:p,timeout:g,maxBuffer:1024*1024},(t,s,b)=>{if(t)return t.killed?e(null,"timeout"):e(null,`error:${t.message.slice(0,80)}`);try{let l=JSON.parse(s||"{}"),o=typeof l.result=="string"?l.result.trim():"";if(!o||o==="(no memo)")return e(null,"empty");let f=o.length>4096?o.slice(0,4096)+"\u2026":o;return e(f,"ok")}catch{return e(null,"parse-error")}}).on("error",()=>e(null,"spawn-error"))})}export{E as extractRotationMemo};
|
|
13
|
-
//# sourceMappingURL=rotation-memo-453FXKHQ.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/agents/rotation-memo.ts"],"sourcesContent":["import { execFile } from \"child_process\"\nimport type { AgentDef } from \"@/daemon/config\"\nimport { buildAgentEnv, claudeBillingEnv } from \"@/utils/workspace-env\"\n\n// --- Pre-rotation memo extraction ---\n//\n// Just before agentx clears `claudeSessionId` (tier-2 / max-turns / stale\n// rotation), we ask the dying Claude session to dump the facts and\n// decisions it should carry forward. The agent has full working-memory\n// of its tool-use history at this moment — the only chance to capture\n// it before --resume is dropped and the next turn starts with a blank\n// session.\n//\n// The memo persists into MemoryStore, where the existing findRelevant\n// path injects it into future turns naturally. No new wiring on the\n// read side; one-shot LLM call on the write side.\n//\n// Hard rule: never block rotation. Timeout, errors, empty memos all\n// mean \"skip this round of memo capture\". Memory continuity is a\n// best-effort enhancement, not a correctness requirement.\n\nconst MEMO_TIMEOUT_MS = 30_000\nconst MEMO_MODEL = \"haiku\" // cheapest fast model — memo is summarisation, not reasoning\n\nconst MEMO_PROMPT =\n \"You are about to lose this working session due to context-size rotation. \" +\n \"Before that happens, write a compact memo of what you should carry forward \" +\n \"to your next session on the same conversation.\\n\\n\" +\n \"Include only durable facts a future turn would otherwise have to rediscover:\\n\" +\n \"- Names, handles, agent ids, telegram/whatsapp/gitlab usernames\\n\" +\n \"- File paths, URLs, project namespaces, ssh hosts, ports\\n\" +\n \"- Decisions made and their reasoning\\n\" +\n \"- Open tasks or commitments to follow up on\\n\" +\n \"- Identifiers (issue numbers, PR numbers, ticket ids) the user referred to\\n\\n\" +\n \"Format: 3-12 short bullet points. Each ≤120 chars. No prose, no preamble, \" +\n \"no header. If the session was uninformative or just casual chat, reply with \" +\n \"exactly the literal text \\\"(no memo)\\\".\\n\\n\" +\n \"Begin the memo now.\"\n\nexport interface RotationMemoResult {\n /** The extracted memo text, or null when extraction failed/skipped. */\n memo: string | null\n /** Why we skipped or what happened — \"ok\", \"timeout\", \"error\", \"empty\", \"no-resume\". */\n reason: string\n /** Wall-clock time spent in the extractor. */\n durationMs: number\n}\n\n/** Ask the dying Claude session for a carry-forward memo. Spawns one\n * short claude CLI call with --resume on the about-to-be-dropped\n * session id, asks for a compact memo, returns the text. Never throws\n * — every failure mode resolves with `memo=null` so the caller can\n * proceed with the rotation regardless. */\nexport async function extractRotationMemo(\n agent: AgentDef,\n resumeSessionId: string | undefined,\n): Promise<RotationMemoResult> {\n const start = Date.now()\n if (!resumeSessionId) {\n return { memo: null, reason: \"no-resume\", durationMs: 0 }\n }\n\n const args: string[] = [\n \"-p\", MEMO_PROMPT,\n \"--output-format\", \"json\",\n \"--resume\", resumeSessionId,\n \"--model\", MEMO_MODEL,\n ]\n if (agent.permissionMode === \"bypassPermissions\") {\n args.push(\"--dangerously-skip-permissions\")\n }\n\n const env = claudeBillingEnv(buildAgentEnv(agent.workspace), agent.billing)\n\n return new Promise<RotationMemoResult>((resolve) => {\n let settled = false\n const finish = (memo: string | null, reason: string) => {\n if (settled) return\n settled = true\n resolve({ memo, reason, durationMs: Date.now() - start })\n }\n\n const child = execFile(\n \"claude\",\n args,\n {\n cwd: agent.workspace,\n env,\n timeout: MEMO_TIMEOUT_MS,\n maxBuffer: 1024 * 1024, // 1 MB; the memo itself is tiny\n },\n (err, stdout, _stderr) => {\n if (err) {\n // execFile signals timeout via signal SIGTERM + err.killed\n if ((err as NodeJS.ErrnoException & { killed?: boolean }).killed) {\n return finish(null, \"timeout\")\n }\n return finish(null, `error:${err.message.slice(0, 80)}`)\n }\n try {\n const data = JSON.parse(stdout || \"{}\")\n // claude -p --output-format json yields { result, ... }\n const text = typeof data.result === \"string\" ? data.result.trim() : \"\"\n if (!text || text === \"(no memo)\") return finish(null, \"empty\")\n // Defensive cap: memos > 4 KB are almost certainly the LLM\n // ignoring instructions and dumping prose. Truncate.\n const capped = text.length > 4096 ? text.slice(0, 4096) + \"…\" : text\n return finish(capped, \"ok\")\n } catch {\n return finish(null, \"parse-error\")\n }\n },\n )\n child.on(\"error\", () => finish(null, \"spawn-error\"))\n })\n}\n"],"mappings":"2EAAA,OAAS,YAAAA,MAAgB,gBAqBzB,IAAMC,EAAkB,IAClBC,EAAa,QAEbC,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,qBA4BF,eAAsBC,EACpBC,EACAC,EAC6B,CAC7B,IAAMC,EAAQ,KAAK,IAAI,EACvB,GAAI,CAACD,EACH,MAAO,CAAE,KAAM,KAAM,OAAQ,YAAa,WAAY,CAAE,EAG1D,IAAME,EAAiB,CACrB,KAAML,EACN,kBAAmB,OACnB,WAAYG,EACZ,UAAWJ,CACb,EACIG,EAAM,iBAAmB,qBAC3BG,EAAK,KAAK,gCAAgC,EAG5C,IAAMC,EAAMC,EAAiBC,EAAcN,EAAM,SAAS,EAAGA,EAAM,OAAO,EAE1E,OAAO,IAAI,QAA6BO,GAAY,CAClD,IAAIC,EAAU,GACRC,EAAS,CAACC,EAAqBC,IAAmB,CAClDH,IACJA,EAAU,GACVD,EAAQ,CAAE,KAAAG,EAAM,OAAAC,EAAQ,WAAY,KAAK,IAAI,EAAIT,CAAM,CAAC,EAC1D,EAEcU,EACZ,SACAT,EACA,CACE,IAAKH,EAAM,UACX,IAAAI,EACA,QAASR,EACT,UAAW,KAAO,IACpB,EACA,CAACiB,EAAKC,EAAQC,IAAY,CACxB,GAAIF,EAEF,OAAKA,EAAqD,OACjDJ,EAAO,KAAM,SAAS,EAExBA,EAAO,KAAM,SAASI,EAAI,QAAQ,MAAM,EAAG,EAAE,GAAG,EAEzD,GAAI,CACF,IAAMG,EAAO,KAAK,MAAMF,GAAU,IAAI,EAEhCG,EAAO,OAAOD,EAAK,QAAW,SAAWA,EAAK,OAAO,KAAK,EAAI,GACpE,GAAI,CAACC,GAAQA,IAAS,YAAa,OAAOR,EAAO,KAAM,OAAO,EAG9D,IAAMS,EAASD,EAAK,OAAS,KAAOA,EAAK,MAAM,EAAG,IAAI,EAAI,SAAMA,EAChE,OAAOR,EAAOS,EAAQ,IAAI,CAC5B,MAAE,CACA,OAAOT,EAAO,KAAM,aAAa,CACnC,CACF,CACF,EACM,GAAG,QAAS,IAAMA,EAAO,KAAM,aAAa,CAAC,CACrD,CAAC,CACH","names":["execFile","MEMO_TIMEOUT_MS","MEMO_MODEL","MEMO_PROMPT","extractRotationMemo","agent","resumeSessionId","start","args","env","claudeBillingEnv","buildAgentEnv","resolve","settled","finish","memo","reason","execFile","err","stdout","_stderr","data","text","capped"]}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|