@rubytech/create-realagent-code 0.1.30 → 0.1.32
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/index.js +37 -39
- package/package.json +1 -1
- package/payload/platform/lib/graph-trash/dist/index.d.ts +1 -1
- package/payload/platform/lib/graph-trash/dist/index.d.ts.map +1 -1
- package/payload/platform/lib/graph-trash/dist/index.js +1 -2
- package/payload/platform/lib/graph-trash/dist/index.js.map +1 -1
- package/payload/platform/lib/graph-trash/src/index.ts +1 -2
- package/payload/platform/lib/persistent-components/dist/index.d.ts +11 -12
- package/payload/platform/lib/persistent-components/dist/index.d.ts.map +1 -1
- package/payload/platform/lib/persistent-components/dist/index.js +11 -12
- package/payload/platform/lib/persistent-components/dist/index.js.map +1 -1
- package/payload/platform/lib/persistent-components/src/index.ts +11 -12
- package/payload/platform/neo4j/schema.cypher +10 -19
- package/payload/platform/plugins/admin/.claude-plugin/plugin.json +1 -1
- package/payload/platform/plugins/admin/PLUGIN.md +1 -7
- package/payload/platform/plugins/admin/mcp/dist/index.js +15 -582
- package/payload/platform/plugins/admin/mcp/dist/index.js.map +1 -1
- package/payload/platform/plugins/admin/skills/access-manager/references/operations.md +7 -7
- package/payload/platform/plugins/admin/skills/public-agent-manager/SKILL.md +1 -1
- package/payload/platform/plugins/admin/skills/stream-log-review/references/analysis-patterns.md +2 -2
- package/payload/platform/plugins/anthropic/skills/get-api-key/SKILL.md +2 -4
- package/payload/platform/plugins/cloudflare/scripts/setup-tunnel.sh +0 -47
- package/payload/platform/plugins/docs/references/cloudflare.md +0 -1
- package/payload/platform/plugins/docs/references/deployment.md +9 -18
- package/payload/platform/plugins/docs/references/internals.md +4 -4
- package/payload/platform/plugins/docs/references/platform.md +5 -1
- package/payload/platform/plugins/docs/references/troubleshooting.md +11 -7
- package/payload/platform/plugins/email/references/email-reference.md +3 -7
- package/payload/platform/plugins/memory/PLUGIN.md +1 -1
- package/payload/platform/plugins/memory/mcp/dist/index.js +1 -1
- package/payload/platform/plugins/memory/mcp/dist/index.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/lib/graph-prune.d.ts +2 -3
- package/payload/platform/plugins/memory/mcp/dist/lib/graph-prune.d.ts.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/lib/graph-prune.js +2 -3
- package/payload/platform/plugins/memory/mcp/dist/lib/graph-prune.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-restore.d.ts +1 -1
- package/payload/platform/plugins/memory/references/graph-primitives.md +5 -5
- package/payload/platform/plugins/teaching/PLUGIN.md +2 -1
- package/payload/platform/plugins/whatsapp/mcp/dist/index.js +1 -1
- package/payload/platform/plugins/whatsapp/mcp/dist/index.js.map +1 -1
- package/payload/platform/plugins/whatsapp/skills/connect-whatsapp/SKILL.md +1 -1
- package/payload/platform/plugins/whatsapp/skills/manage-whatsapp-config/SKILL.md +2 -8
- package/payload/platform/plugins/writer-craft/PLUGIN.md +2 -1
- package/payload/platform/scripts/component-knowledgedoc-backfill.ts +1 -1
- package/payload/platform/scripts/seed-neo4j.sh +9 -38
- package/payload/platform/services/claude-session-manager/dist/http-server.d.ts +1 -1
- package/payload/platform/services/claude-session-manager/dist/http-server.d.ts.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/http-server.js +45 -44
- package/payload/platform/services/claude-session-manager/dist/http-server.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/index.js +11 -0
- package/payload/platform/services/claude-session-manager/dist/index.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/jsonl-observer.d.ts +30 -0
- package/payload/platform/services/claude-session-manager/dist/jsonl-observer.d.ts.map +1 -0
- package/payload/platform/services/claude-session-manager/dist/jsonl-observer.js +175 -0
- package/payload/platform/services/claude-session-manager/dist/jsonl-observer.js.map +1 -0
- package/payload/platform/services/claude-session-manager/dist/jsonl-path.d.ts +4 -2
- package/payload/platform/services/claude-session-manager/dist/jsonl-path.d.ts.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/jsonl-path.js +15 -22
- package/payload/platform/services/claude-session-manager/dist/jsonl-path.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/pty-spawner.d.ts +13 -14
- package/payload/platform/services/claude-session-manager/dist/pty-spawner.d.ts.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/pty-spawner.js +28 -13
- package/payload/platform/services/claude-session-manager/dist/pty-spawner.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/session-store.d.ts +9 -0
- package/payload/platform/services/claude-session-manager/dist/session-store.d.ts.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/session-store.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/system-prompt.d.ts +1 -25
- package/payload/platform/services/claude-session-manager/dist/system-prompt.d.ts.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/system-prompt.js +3 -54
- package/payload/platform/services/claude-session-manager/dist/system-prompt.js.map +1 -1
- package/payload/platform/templates/agents/admin/IDENTITY.md +2 -0
- package/payload/platform/templates/agents/public/IDENTITY.md +1 -1
- package/payload/platform/templates/specialists/agents/content-producer.md +3 -3
- package/payload/platform/templates/specialists/agents/personal-assistant.md +2 -2
- package/payload/premium-plugins/teaching/PLUGIN.md +2 -1
- package/payload/premium-plugins/writer-craft/PLUGIN.md +2 -1
- package/payload/server/{chunk-NL7QLVAD.js → chunk-KVGTWNKQ.js} +1 -70
- package/payload/server/{chunk-2MRZBQMH.js → chunk-RZQMYJVY.js} +1 -1
- package/payload/server/{chunk-YPZFYTYP.js → chunk-ZGJ6CUU2.js} +1 -1
- package/payload/server/{cloudflare-task-tracker-QVOGHKWV.js → cloudflare-task-tracker-4PKOLE4H.js} +2 -2
- package/payload/server/maxy-edge.js +2 -2
- package/payload/server/public/assets/{Checkbox-YIF0payo.js → Checkbox-C6zXApx_.js} +1 -1
- package/payload/server/public/assets/admin-Cuu1QdAA.js +216 -0
- package/payload/server/public/assets/{architectureDiagram-Q4EWVU46-Bz8mlxZZ.js → architectureDiagram-Q4EWVU46-BYXgFii5.js} +1 -1
- package/payload/server/public/assets/{blockDiagram-DXYQGD6D-DwV8Z8-i.js → blockDiagram-DXYQGD6D-GIQ0eO13.js} +1 -1
- package/payload/server/public/assets/{brand-Bm671owU.js → brand-B-bNrpwc.js} +1 -1
- package/payload/server/public/assets/{brand-DqiRNMlu.css → brand-DdhkC994.css} +1 -1
- package/payload/server/public/assets/{c4Diagram-AHTNJAMY-DiUTejMp.js → c4Diagram-AHTNJAMY-BmyWfG-l.js} +1 -1
- package/payload/server/public/assets/channel-C76knBRO.js +1 -0
- package/payload/server/public/assets/{chunk-336JU56O-4mHZpBXe.js → chunk-336JU56O-DcWl0MQo.js} +2 -2
- package/payload/server/public/assets/{chunk-426QAEUC-Cbv0vrN9.js → chunk-426QAEUC-BIW6kq6y.js} +1 -1
- package/payload/server/public/assets/{chunk-4TB4RGXK-BvLhId_2.js → chunk-4TB4RGXK-CdoHpV4X.js} +1 -1
- package/payload/server/public/assets/{chunk-5FUZZQ4R-bBafOTkw.js → chunk-5FUZZQ4R-bn_a4sfU.js} +1 -1
- package/payload/server/public/assets/{chunk-5PVQY5BW-B0NqBKVy.js → chunk-5PVQY5BW-C_Rq8j_M.js} +1 -1
- package/payload/server/public/assets/{chunk-EDXVE4YY-CFd4SqI6.js → chunk-EDXVE4YY-CWQvoVKV.js} +1 -1
- package/payload/server/public/assets/{chunk-ENJZ2VHE-ajf2sb6c.js → chunk-ENJZ2VHE-DBHn1kSk.js} +1 -1
- package/payload/server/public/assets/{chunk-ICPOFSXX-pWg6bug7.js → chunk-ICPOFSXX-SW2Qx11O.js} +1 -1
- package/payload/server/public/assets/{chunk-OYMX7WX6-OjEd-17c.js → chunk-OYMX7WX6-BvIG7tVW.js} +1 -1
- package/payload/server/public/assets/{chunk-U2HBQHQK-DbEFSPoh.js → chunk-U2HBQHQK-BiBUb0cF.js} +1 -1
- package/payload/server/public/assets/{chunk-X2U36JSP-COdNwrBb.js → chunk-X2U36JSP-Y0MKZCCh.js} +1 -1
- package/payload/server/public/assets/{chunk-YZCP3GAM-CHMWuY9B.js → chunk-YZCP3GAM-DKPh06GH.js} +1 -1
- package/payload/server/public/assets/{chunk-ZZ45TVLE-B-uDLQOB.js → chunk-ZZ45TVLE-C2WNo-fK.js} +1 -1
- package/payload/server/public/assets/classDiagram-6PBFFD2Q-Bohexn7P.js +1 -0
- package/payload/server/public/assets/classDiagram-v2-HSJHXN6E-DVsmsAu7.js +1 -0
- package/payload/server/public/assets/clone-DUrXF4sO.js +1 -0
- package/payload/server/public/assets/{dagre-bhIG_KnW.js → dagre-CrK8E9ee.js} +1 -1
- package/payload/server/public/assets/{dagre-KV5264BT-CMEzmhIL.js → dagre-KV5264BT-_o6uXcH8.js} +1 -1
- package/payload/server/public/assets/data-j1WNhF8t.js +1 -0
- package/payload/server/public/assets/{device-url-actions-AcOyLSeF.js → device-url-actions-BcHerWqJ.js} +1 -1
- package/payload/server/public/assets/{diagram-5BDNPKRD-6RIoQhIL.js → diagram-5BDNPKRD-FFP9DKhc.js} +1 -1
- package/payload/server/public/assets/{diagram-G4DWMVQ6-BSp36TVv.js → diagram-G4DWMVQ6-DpwD1jBP.js} +1 -1
- package/payload/server/public/assets/{diagram-MMDJMWI5-D54fo52D.js → diagram-MMDJMWI5-C3K5agdK.js} +1 -1
- package/payload/server/public/assets/{diagram-TYMM5635-CWL8z-Pq.js → diagram-TYMM5635-CbeDipbC.js} +1 -1
- package/payload/server/public/assets/{erDiagram-SMLLAGMA-AnnHBo3z.js → erDiagram-SMLLAGMA-XBIFndNy.js} +1 -1
- package/payload/server/public/assets/{flowDiagram-DWJPFMVM-laWmBl5o.js → flowDiagram-DWJPFMVM-BvEgySyn.js} +1 -1
- package/payload/server/public/assets/{ganttDiagram-T4ZO3ILL-B94ko8ie.js → ganttDiagram-T4ZO3ILL-D7gIRKJf.js} +1 -1
- package/payload/server/public/assets/{gitGraphDiagram-UUTBAWPF-DxzL1fxZ.js → gitGraphDiagram-UUTBAWPF-vJu_hcri.js} +1 -1
- package/payload/server/public/assets/graph-C_f_9L_7.js +1 -0
- package/payload/server/public/assets/graph-labels-BSQJHlgf.js +1 -0
- package/payload/server/public/assets/{graphlib-CY-zIElM.js → graphlib-Dp0mN6JW.js} +1 -1
- package/payload/server/public/assets/{infoDiagram-42DDH7IO-BMTajIIr.js → infoDiagram-42DDH7IO-g4Dlc5Cr.js} +1 -1
- package/payload/server/public/assets/{ishikawaDiagram-UXIWVN3A-B_QauE5O.js → ishikawaDiagram-UXIWVN3A-D_45LXOe.js} +1 -1
- package/payload/server/public/assets/{journeyDiagram-VCZTEJTY-DmlqSIih.js → journeyDiagram-VCZTEJTY-CggbHl6N.js} +1 -1
- package/payload/server/public/assets/{kanban-definition-6JOO6SKY-ZGDQT7xB.js → kanban-definition-6JOO6SKY-CysAe-Ab.js} +1 -1
- package/payload/server/public/assets/{line-D13opgep.js → line-BAxq_DSY.js} +1 -1
- package/payload/server/public/assets/{mermaid-parser.core-C650Sual.js → mermaid-parser.core-DbFuvkjL.js} +1 -1
- package/payload/server/public/assets/{mermaid.core-BqnQoXTp.js → mermaid.core-CehvJn5b.js} +3 -3
- package/payload/server/public/assets/{mindmap-definition-QFDTVHPH-BS_8y-tY.js → mindmap-definition-QFDTVHPH-DbPbBJ9h.js} +1 -1
- package/payload/server/public/assets/page-B0BPrSE3.js +1 -0
- package/payload/server/public/assets/{page-qSH972X0.js → page-Co7KCRV8.js} +2 -2
- package/payload/server/public/assets/{pieDiagram-DEJITSTG-B5OmNvBO.js → pieDiagram-DEJITSTG-cagLL9ng.js} +1 -1
- package/payload/server/public/assets/{public-DDsYgotk.js → public-B6TEcDLx.js} +5 -5
- package/payload/server/public/assets/{quadrantDiagram-34T5L4WZ-DTYITdNo.js → quadrantDiagram-34T5L4WZ-Keaa1jDh.js} +1 -1
- package/payload/server/public/assets/{requirementDiagram-MS252O5E-CRZWxH06.js → requirementDiagram-MS252O5E-BcYRyn5z.js} +1 -1
- package/payload/server/public/assets/{sankeyDiagram-XADWPNL6-DazRENhe.js → sankeyDiagram-XADWPNL6--fKoG9NR.js} +1 -1
- package/payload/server/public/assets/{sequenceDiagram-FGHM5R23-BcHTxmPy.js → sequenceDiagram-FGHM5R23-lKG36-Di.js} +1 -1
- package/payload/server/public/assets/{stateDiagram-FHFEXIEX-DYU7nbqg.js → stateDiagram-FHFEXIEX-BuVsrlig.js} +1 -1
- package/payload/server/public/assets/stateDiagram-v2-QKLJ7IA2-DSt88_xL.js +1 -0
- package/payload/server/public/assets/{timeline-definition-GMOUNBTQ-BKGmqkST.js → timeline-definition-GMOUNBTQ-D6X6uq17.js} +1 -1
- package/payload/server/public/assets/{vennDiagram-DHZGUBPP-BXvLPmX7.js → vennDiagram-DHZGUBPP-BgvcfRVf.js} +1 -1
- package/payload/server/public/assets/{wardleyDiagram-NUSXRM2D-BCclUa3Z.js → wardleyDiagram-NUSXRM2D-Cpd1xsrt.js} +1 -1
- package/payload/server/public/assets/{xychartDiagram-5P7HB3ND-C-Xp-Eoc.js → xychartDiagram-5P7HB3ND-CDF5ZVFv.js} +1 -1
- package/payload/server/public/data.html +5 -5
- package/payload/server/public/graph.html +6 -6
- package/payload/server/public/index.html +8 -8
- package/payload/server/public/public.html +5 -5
- package/payload/server/server.js +142 -278
- package/payload/platform/plugins/admin/hooks/onboarding-skill-drift.sh +0 -102
- package/payload/platform/plugins/admin/references/contextual-ui.md +0 -109
- package/payload/platform/plugins/admin/skills/onboarding/SKILL.md +0 -240
- package/payload/platform/scripts/__tests__/admin-persist-audit.test.ts +0 -182
- package/payload/server/public/assets/admin-CDvF5de6.js +0 -216
- package/payload/server/public/assets/channel-PtVtoBEL.js +0 -1
- package/payload/server/public/assets/classDiagram-6PBFFD2Q-RVH_SEhY.js +0 -1
- package/payload/server/public/assets/classDiagram-v2-HSJHXN6E-Cm3rAb93.js +0 -1
- package/payload/server/public/assets/clone-BjY0Wzht.js +0 -1
- package/payload/server/public/assets/data-K_kS__sL.js +0 -1
- package/payload/server/public/assets/graph-DeEigyO_.js +0 -1
- package/payload/server/public/assets/graph-labels-C7I5QvNv.js +0 -1
- package/payload/server/public/assets/page-B_rpjIRr.js +0 -1
- package/payload/server/public/assets/stateDiagram-v2-QKLJ7IA2-BgljVtlp.js +0 -1
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
// Observe (do not predict) the JSONL file Claude Code writes for a session.
|
|
2
|
+
//
|
|
3
|
+
// Task 065 — the manager used to derive `jsonlPath` from the captured
|
|
4
|
+
// `/remote-control` URL at spawn time. That id is the *bridge* sessionId
|
|
5
|
+
// (the suffix after `session_` in the URL), which is NOT the same as the
|
|
6
|
+
// *intrinsic* sessionId that Claude Code uses for the JSONL filename.
|
|
7
|
+
// `GET /list` then merged the live store (keyed by bridge id) with the
|
|
8
|
+
// on-disk enumerator (keyed by intrinsic id) and the dedup never matched,
|
|
9
|
+
// producing one phantom row per spawn.
|
|
10
|
+
//
|
|
11
|
+
// The fix: never predict. Watch the project dir; when a new JSONL appears,
|
|
12
|
+
// read its head bytes and bind it to the spawn whose URL bridge-suffix
|
|
13
|
+
// appears verbatim somewhere in those bytes. Claude Code writes a
|
|
14
|
+
// `bridgeSessionId=cse_<suffix>` record in the JSONL head; the suffix is
|
|
15
|
+
// also the part after `session_` in the URL we captured. Substring match
|
|
16
|
+
// over the head bytes is the deterministic link, schema-agnostic and
|
|
17
|
+
// concurrency-safe — two spawns never share a random URL suffix.
|
|
18
|
+
//
|
|
19
|
+
// One shared `fs.watch` on the project dir. Each spawn calls `observe()`
|
|
20
|
+
// to register a pending observation; the call does a one-shot scan first
|
|
21
|
+
// (closes the snapshot-vs-watch race) and otherwise resolves on the next
|
|
22
|
+
// `rename`/`change` event whose head bytes match. PTY exit before the
|
|
23
|
+
// JSONL appears calls `cancel()` to drop the pending registration.
|
|
24
|
+
import { existsSync, mkdirSync, openSync, closeSync, readSync, readdirSync, statSync, watch } from 'node:fs';
|
|
25
|
+
import { join } from 'node:path';
|
|
26
|
+
const HEAD_READ_BYTES = 4 * 1024;
|
|
27
|
+
/** Read the first HEAD_READ_BYTES of a file. Returns empty string on any
|
|
28
|
+
* IO error (ENOENT, EACCES, file truncated mid-read). The caller treats
|
|
29
|
+
* empty as "no match yet" and keeps the pending observation registered
|
|
30
|
+
* so a subsequent `change` event re-reads after Claude finishes writing. */
|
|
31
|
+
function readHead(path, logger) {
|
|
32
|
+
let fd = null;
|
|
33
|
+
try {
|
|
34
|
+
fd = openSync(path, 'r');
|
|
35
|
+
const stat = statSync(path);
|
|
36
|
+
const want = Math.min(stat.size, HEAD_READ_BYTES);
|
|
37
|
+
if (want === 0)
|
|
38
|
+
return '';
|
|
39
|
+
const buf = Buffer.alloc(want);
|
|
40
|
+
const got = readSync(fd, buf, 0, want, 0);
|
|
41
|
+
return buf.toString('utf8', 0, got);
|
|
42
|
+
}
|
|
43
|
+
catch (err) {
|
|
44
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
45
|
+
logger(`jsonl-observer head-read-failed path=${path} message=${msg}`);
|
|
46
|
+
return '';
|
|
47
|
+
}
|
|
48
|
+
finally {
|
|
49
|
+
if (fd !== null) {
|
|
50
|
+
try {
|
|
51
|
+
closeSync(fd);
|
|
52
|
+
}
|
|
53
|
+
catch { /* ignore */ }
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
/** Try to bind the given JSONL to any pending observation. Returns the
|
|
58
|
+
* observation that matched (already resolved) or null if no match. */
|
|
59
|
+
function tryBindFile(jsonlPath, pendings, logger) {
|
|
60
|
+
if (pendings.size === 0)
|
|
61
|
+
return null;
|
|
62
|
+
const head = readHead(jsonlPath, logger);
|
|
63
|
+
if (!head)
|
|
64
|
+
return null;
|
|
65
|
+
for (const p of pendings) {
|
|
66
|
+
if (p.settled)
|
|
67
|
+
continue;
|
|
68
|
+
if (head.includes(p.bridgeSuffix)) {
|
|
69
|
+
const claudeSessionId = jsonlPath.endsWith('.jsonl')
|
|
70
|
+
? jsonlPath.slice(jsonlPath.lastIndexOf('/') + 1, -'.jsonl'.length)
|
|
71
|
+
: jsonlPath.slice(jsonlPath.lastIndexOf('/') + 1);
|
|
72
|
+
p.settled = true;
|
|
73
|
+
p.resolve({ jsonlPath, claudeSessionId });
|
|
74
|
+
pendings.delete(p);
|
|
75
|
+
return p;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
return null;
|
|
79
|
+
}
|
|
80
|
+
export function createJsonlObserver(opts) {
|
|
81
|
+
const { projectsDir, logger } = opts;
|
|
82
|
+
// Claude Code only creates this dir on its first spawn; the manager may
|
|
83
|
+
// start before then. mkdir -p so fs.watch has something to bind to.
|
|
84
|
+
mkdirSync(projectsDir, { recursive: true });
|
|
85
|
+
const pendings = new Set();
|
|
86
|
+
let watcher = null;
|
|
87
|
+
function onWatchEvent(eventType, filename) {
|
|
88
|
+
if (!filename || !filename.endsWith('.jsonl'))
|
|
89
|
+
return;
|
|
90
|
+
const full = join(projectsDir, filename);
|
|
91
|
+
if (!existsSync(full))
|
|
92
|
+
return;
|
|
93
|
+
const bound = tryBindFile(full, pendings, logger);
|
|
94
|
+
if (bound) {
|
|
95
|
+
logger(`jsonl-observer matched event=${eventType} path=${full} bridgeSuffix=${bound.bridgeSuffix}`);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
try {
|
|
99
|
+
watcher = watch(projectsDir, { persistent: false }, onWatchEvent);
|
|
100
|
+
watcher.on('error', (err) => {
|
|
101
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
102
|
+
logger(`jsonl-observer watch-error dir=${projectsDir} message=${msg}`);
|
|
103
|
+
});
|
|
104
|
+
logger(`jsonl-observer armed dir=${projectsDir}`);
|
|
105
|
+
}
|
|
106
|
+
catch (err) {
|
|
107
|
+
// mkdir succeeded but watch failed — extremely unlikely. Log loudly;
|
|
108
|
+
// observations registered later will resolve only via the on-arm scan
|
|
109
|
+
// unless the operator restarts the manager.
|
|
110
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
111
|
+
logger(`jsonl-observer watch-init-failed dir=${projectsDir} message=${msg}`);
|
|
112
|
+
}
|
|
113
|
+
function observe(args) {
|
|
114
|
+
const { bridgeSuffix } = args;
|
|
115
|
+
let resolveFn;
|
|
116
|
+
const promise = new Promise((resolve) => {
|
|
117
|
+
resolveFn = resolve;
|
|
118
|
+
});
|
|
119
|
+
const pending = {
|
|
120
|
+
bridgeSuffix,
|
|
121
|
+
resolve: resolveFn,
|
|
122
|
+
settled: false,
|
|
123
|
+
};
|
|
124
|
+
// On-arm scan — close the race between this call and the fs.watch
|
|
125
|
+
// event firing for a JSONL Claude already wrote.
|
|
126
|
+
pendings.add(pending);
|
|
127
|
+
let scannedHit = false;
|
|
128
|
+
try {
|
|
129
|
+
for (const entry of readdirSync(projectsDir, { withFileTypes: true })) {
|
|
130
|
+
if (!entry.isFile() || !entry.name.endsWith('.jsonl'))
|
|
131
|
+
continue;
|
|
132
|
+
const full = join(projectsDir, entry.name);
|
|
133
|
+
const bound = tryBindFile(full, pendings, logger);
|
|
134
|
+
if (bound === pending) {
|
|
135
|
+
scannedHit = true;
|
|
136
|
+
logger(`jsonl-observer on-arm-scan-matched path=${full} bridgeSuffix=${bridgeSuffix}`);
|
|
137
|
+
break;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
catch (err) {
|
|
142
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
143
|
+
logger(`jsonl-observer on-arm-scan-failed dir=${projectsDir} message=${msg}`);
|
|
144
|
+
}
|
|
145
|
+
if (!scannedHit) {
|
|
146
|
+
logger(`jsonl-observer pending bridgeSuffix=${bridgeSuffix}`);
|
|
147
|
+
}
|
|
148
|
+
return {
|
|
149
|
+
promise,
|
|
150
|
+
cancel: () => {
|
|
151
|
+
if (pending.settled)
|
|
152
|
+
return;
|
|
153
|
+
pending.settled = true;
|
|
154
|
+
pendings.delete(pending);
|
|
155
|
+
pending.resolve(null);
|
|
156
|
+
logger(`jsonl-observer cancelled bridgeSuffix=${bridgeSuffix}`);
|
|
157
|
+
},
|
|
158
|
+
};
|
|
159
|
+
}
|
|
160
|
+
function close() {
|
|
161
|
+
if (watcher) {
|
|
162
|
+
watcher.close();
|
|
163
|
+
watcher = null;
|
|
164
|
+
}
|
|
165
|
+
for (const p of pendings) {
|
|
166
|
+
if (p.settled)
|
|
167
|
+
continue;
|
|
168
|
+
p.settled = true;
|
|
169
|
+
p.resolve(null);
|
|
170
|
+
}
|
|
171
|
+
pendings.clear();
|
|
172
|
+
}
|
|
173
|
+
return { observe, close };
|
|
174
|
+
}
|
|
175
|
+
//# sourceMappingURL=jsonl-observer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"jsonl-observer.js","sourceRoot":"","sources":["../src/jsonl-observer.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
export declare function claudeStateRoot(env?: NodeJS.ProcessEnv): string;
|
|
2
2
|
export declare function projectSlugForCwd(cwd: string): string;
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
/** Extract the bridge-session suffix from a `/remote-control` URL. This is
|
|
4
|
+
* the part after `session_`, not the intrinsic JSONL filename. Returns
|
|
5
|
+
* null if the URL has no `session_<...>` component. */
|
|
6
|
+
export declare function bridgeSuffixFromUrl(url: string): string | null;
|
|
5
7
|
//# sourceMappingURL=jsonl-path.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"jsonl-path.d.ts","sourceRoot":"","sources":["../src/jsonl-path.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"jsonl-path.d.ts","sourceRoot":"","sources":["../src/jsonl-path.ts"],"names":[],"mappings":"AAqBA,wBAAgB,eAAe,CAAC,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,MAAM,CAE5E;AAED,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAErD;AAED;;wDAEwD;AACxD,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAG9D"}
|
|
@@ -1,23 +1,20 @@
|
|
|
1
|
-
//
|
|
1
|
+
// Helpers for locating claude's per-session JSONL transcripts on disk.
|
|
2
2
|
//
|
|
3
3
|
// Claude Code writes one JSONL file per session at
|
|
4
4
|
//
|
|
5
5
|
// ${CLAUDE_CONFIG_DIR or ~/.claude}/projects/<project-slug>/<claude-session-id>.jsonl
|
|
6
6
|
//
|
|
7
|
-
// where <project-slug> is the cwd at spawn time with every '/' replaced
|
|
8
|
-
//
|
|
9
|
-
//
|
|
10
|
-
//
|
|
7
|
+
// where <project-slug> is the cwd at spawn time with every '/' replaced by '-'
|
|
8
|
+
// (leading slash included, so /home/foo becomes -home-foo). Task 019 set
|
|
9
|
+
// CLAUDE_CONFIG_DIR on the manager unit so brand isolation holds for
|
|
10
|
+
// credentials and JSONL transcripts.
|
|
11
11
|
//
|
|
12
|
-
// Task
|
|
13
|
-
//
|
|
14
|
-
//
|
|
15
|
-
//
|
|
16
|
-
//
|
|
17
|
-
//
|
|
18
|
-
// The PRD names this file as the canonical per-session forensic surface;
|
|
19
|
-
// the manager records the path on every spawn so the operator can
|
|
20
|
-
// `tail -f` it directly.
|
|
12
|
+
// Task 065 removed `deriveJsonlPath` and `claudeSessionIdFromUrl`. The
|
|
13
|
+
// `/remote-control` URL contains the bridge sessionId (the suffix after
|
|
14
|
+
// `session_`), which is NOT the JSONL filename. The intrinsic JSONL
|
|
15
|
+
// filename is only knowable by observing what Claude Code actually writes
|
|
16
|
+
// on disk (see `jsonl-observer.ts`). The only URL helper still needed is
|
|
17
|
+
// `bridgeSuffixFromUrl`, used by pty-spawner to register the observation.
|
|
21
18
|
import { homedir } from 'node:os';
|
|
22
19
|
import { join } from 'node:path';
|
|
23
20
|
export function claudeStateRoot(env = process.env) {
|
|
@@ -26,15 +23,11 @@ export function claudeStateRoot(env = process.env) {
|
|
|
26
23
|
export function projectSlugForCwd(cwd) {
|
|
27
24
|
return cwd.replace(/\//g, '-');
|
|
28
25
|
}
|
|
29
|
-
|
|
26
|
+
/** Extract the bridge-session suffix from a `/remote-control` URL. This is
|
|
27
|
+
* the part after `session_`, not the intrinsic JSONL filename. Returns
|
|
28
|
+
* null if the URL has no `session_<...>` component. */
|
|
29
|
+
export function bridgeSuffixFromUrl(url) {
|
|
30
30
|
const match = url.match(/session_([A-Za-z0-9_-]+)/);
|
|
31
31
|
return match ? match[1] : null;
|
|
32
32
|
}
|
|
33
|
-
export function deriveJsonlPath(cwd, url) {
|
|
34
|
-
const claudeId = claudeSessionIdFromUrl(url);
|
|
35
|
-
if (!claudeId)
|
|
36
|
-
return null;
|
|
37
|
-
const slug = projectSlugForCwd(cwd);
|
|
38
|
-
return join(claudeStateRoot(), 'projects', slug, `${claudeId}.jsonl`);
|
|
39
|
-
}
|
|
40
33
|
//# sourceMappingURL=jsonl-path.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"jsonl-path.js","sourceRoot":"","sources":["../src/jsonl-path.ts"],"names":[],"mappings":"AAAA,
|
|
1
|
+
{"version":3,"file":"jsonl-path.js","sourceRoot":"","sources":["../src/jsonl-path.ts"],"names":[],"mappings":"AAAA,uEAAuE;AACvE,EAAE;AACF,mDAAmD;AACnD,EAAE;AACF,0FAA0F;AAC1F,EAAE;AACF,+EAA+E;AAC/E,yEAAyE;AACzE,qEAAqE;AACrE,qCAAqC;AACrC,EAAE;AACF,uEAAuE;AACvE,wEAAwE;AACxE,oEAAoE;AACpE,0EAA0E;AAC1E,yEAAyE;AACzE,0EAA0E;AAE1E,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAA;AACjC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AAEhC,MAAM,UAAU,eAAe,CAAC,MAAyB,OAAO,CAAC,GAAG;IAClE,OAAO,GAAG,CAAC,iBAAiB,IAAI,IAAI,CAAC,OAAO,EAAE,EAAE,SAAS,CAAC,CAAA;AAC5D,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,GAAW;IAC3C,OAAO,GAAG,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAA;AAChC,CAAC;AAED;;wDAEwD;AACxD,MAAM,UAAU,mBAAmB,CAAC,GAAW;IAC7C,MAAM,KAAK,GAAG,GAAG,CAAC,KAAK,CAAC,0BAA0B,CAAC,CAAA;IACnD,OAAO,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAA;AAChC,CAAC"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { Logger, PtyHandle, Role, Channel } from './types.js';
|
|
2
2
|
import { SessionStore, type StoredSession } from './session-store.js';
|
|
3
|
-
import {
|
|
3
|
+
import type { JsonlObserver } from './jsonl-observer.js';
|
|
4
4
|
import type { HostResolution } from './config.js';
|
|
5
5
|
import type { ToolSurface } from './tool-surface.js';
|
|
6
6
|
export type SpawnResult = {
|
|
@@ -31,6 +31,18 @@ export interface SpawnDeps {
|
|
|
31
31
|
* publicAllowlist field, so by the time pty-spawner sees this struct, the
|
|
32
32
|
* per-tool decisions are guaranteed complete. */
|
|
33
33
|
toolSurface: ToolSurface;
|
|
34
|
+
/** Task 065 — observer for the JSONL file Claude Code writes. The spawn
|
|
35
|
+
* registers a pending observation keyed on the URL's bridge suffix; the
|
|
36
|
+
* observer resolves when the matching JSONL appears on disk. Tests
|
|
37
|
+
* inject a noop observer whose `observe()` returns a never-resolving
|
|
38
|
+
* promise and a no-op cancel. */
|
|
39
|
+
observer: JsonlObserver;
|
|
40
|
+
/** Task 065 — fires once after the observer matches a JSONL to the
|
|
41
|
+
* session. The closure has already mutated `session.jsonlPath` and
|
|
42
|
+
* `session.claudeSessionId` by the time this is invoked. http-server
|
|
43
|
+
* uses this to defer public-tool audit attachment until the JSONL
|
|
44
|
+
* exists. Tests may omit this. */
|
|
45
|
+
onJsonlObserved?: (session: StoredSession) => void;
|
|
34
46
|
}
|
|
35
47
|
export interface SpawnArgs {
|
|
36
48
|
senderId: string;
|
|
@@ -46,19 +58,6 @@ export interface SpawnArgs {
|
|
|
46
58
|
* When omitted or empty, argv is byte-identical to today — existing
|
|
47
59
|
* Maxy installs with no channel plugins pay nothing for the addition. */
|
|
48
60
|
channels?: string[];
|
|
49
|
-
/** Task 043 — admin onboarding directive. When provided, the manager
|
|
50
|
-
* appends a third sentinel-wrapped section (`<onboarding-state>`) to the
|
|
51
|
-
* --append-system-prompt block at PTY spawn time. The operator's first
|
|
52
|
-
* /input therefore carries only their raw text; the directive is part
|
|
53
|
-
* of the system prompt, not the user transcript. Resumed sessions and
|
|
54
|
-
* step-9 (complete) sessions never receive this payload. */
|
|
55
|
-
onboarding?: OnboardingPayload;
|
|
56
|
-
/** Task 043 — for observability log line only. The admin UI wrapper
|
|
57
|
-
* resolves accountId server-side; the manager echoes the first 8 chars
|
|
58
|
-
* in `[onboarding-prompt]` so a tail can correlate the spawn with the
|
|
59
|
-
* source account without persisting the full id. Public/non-admin
|
|
60
|
-
* spawns omit this. */
|
|
61
|
-
accountId?: string;
|
|
62
61
|
/** Task 010 — operator-selected permission mode. When set to anything
|
|
63
62
|
* other than `default`, the manager appends `--permission-mode <mode>`
|
|
64
63
|
* to the spawn argv so the claude CLI starts the session in that mode.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pty-spawner.d.ts","sourceRoot":"","sources":["../src/pty-spawner.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,YAAY,CAAA;AAElE,OAAO,EAAE,YAAY,EAAE,KAAK,aAAa,EAAE,MAAM,oBAAoB,CAAA;AAErE,OAAO,
|
|
1
|
+
{"version":3,"file":"pty-spawner.d.ts","sourceRoot":"","sources":["../src/pty-spawner.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,YAAY,CAAA;AAElE,OAAO,EAAE,YAAY,EAAE,KAAK,aAAa,EAAE,MAAM,oBAAoB,CAAA;AAErE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAA;AAExD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAA;AACjD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAA;AAEpD,MAAM,MAAM,WAAW,GACnB;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,OAAO,EAAE,aAAa,CAAA;CAAE,GACpC;IACE,EAAE,EAAE,KAAK,CAAA;IACT,MAAM,EACF,wBAAwB,GACxB,kBAAkB,GAClB,qBAAqB,GACrB,yBAAyB,CAAA;IAC7B,UAAU,EAAE,MAAM,CAAA;CACnB,CAAA;AAEL,MAAM,WAAW,SAAS;IACxB,QAAQ,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,GAAG,EAAE,MAAM,CAAC,UAAU,KAAK,SAAS,CAAA;IAC5E,QAAQ,EAAE,MAAM,CAAA;IAChB,SAAS,EAAE,MAAM,CAAA;IACjB,mBAAmB,EAAE,MAAM,CAAA;IAC3B,MAAM,EAAE,MAAM,CAAA;IACd,KAAK,EAAE,YAAY,CAAA;IACnB;;;;;uCAKmC;IACnC,IAAI,EAAE,cAAc,CAAA;IACpB;;;;sDAIkD;IAClD,WAAW,EAAE,WAAW,CAAA;IACxB;;;;sCAIkC;IAClC,QAAQ,EAAE,aAAa,CAAA;IACvB;;;;uCAImC;IACnC,eAAe,CAAC,EAAE,CAAC,OAAO,EAAE,aAAa,KAAK,IAAI,CAAA;CACnD;AAED,MAAM,WAAW,SAAS;IACxB,QAAQ,EAAE,MAAM,CAAA;IAChB,IAAI,EAAE,IAAI,CAAA;IACV,OAAO,EAAE,OAAO,CAAA;IAChB;;gCAE4B;IAC5B,qBAAqB,CAAC,EAAE,MAAM,CAAA;IAC9B;;;;8EAI0E;IAC1E,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAA;IACnB;;;sEAGkE;IAClE,cAAc,CAAC,EAAE,cAAc,CAAA;IAC/B;;;;;;iEAM6D;IAC7D,aAAa,CAAC,EAAE,MAAM,CAAA;CACvB;AAED,MAAM,MAAM,cAAc,GAAG,SAAS,GAAG,aAAa,GAAG,MAAM,GAAG,MAAM,CAAA;AACxE,eAAO,MAAM,gBAAgB,EAAE,SAAS,cAAc,EAA+C,CAAA;AAErG,wBAAsB,kBAAkB,CAAC,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,SAAS,GAAG,OAAO,CAAC,WAAW,CAAC,CAsI/F;AAED,MAAM,WAAW,UAAU;IACzB,KAAK,EAAE,YAAY,CAAA;IACnB,WAAW,EAAE,MAAM,CAAA;IACnB,MAAM,EAAE,MAAM,CAAA;CACf;AAED,wBAAsB,aAAa,CACjC,IAAI,EAAE,UAAU,EAChB,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,OAAO,EAAE,OAAO,CAAA;CAAE,CAAC,CAqBzC"}
|
|
@@ -11,14 +11,14 @@
|
|
|
11
11
|
import { randomUUID } from 'node:crypto';
|
|
12
12
|
import { mkdirSync } from 'node:fs';
|
|
13
13
|
import { startUrlCapture } from './url-capture.js';
|
|
14
|
-
import {
|
|
15
|
-
import { composeAppendSystemPrompt
|
|
14
|
+
import { bridgeSuffixFromUrl } from './jsonl-path.js';
|
|
15
|
+
import { composeAppendSystemPrompt } from './system-prompt.js';
|
|
16
16
|
export const PERMISSION_MODES = ['default', 'acceptEdits', 'plan', 'auto'];
|
|
17
17
|
export async function spawnClaudeSession(deps, args) {
|
|
18
18
|
const sessionId = randomUUID();
|
|
19
19
|
const startedAt = new Date().toISOString();
|
|
20
20
|
const start = Date.now();
|
|
21
|
-
const appendSystemPrompt = composeAppendSystemPrompt(deps.host
|
|
21
|
+
const appendSystemPrompt = composeAppendSystemPrompt(deps.host);
|
|
22
22
|
if (!appendSystemPrompt) {
|
|
23
23
|
const stderrTail = deps.host.lanIPv4Diagnostic ?? 'append-system-prompt unresolved';
|
|
24
24
|
deps.logger(`spawn-failed reason=host-context-unresolved stderr-tail=${JSON.stringify(stderrTail)}`);
|
|
@@ -87,7 +87,10 @@ export async function spawnClaudeSession(deps, args) {
|
|
|
87
87
|
timeoutMs: deps.urlCaptureTimeoutMs,
|
|
88
88
|
logger: deps.logger,
|
|
89
89
|
onUrl: (url) => {
|
|
90
|
-
|
|
90
|
+
// Task 065 — never predict the JSONL path. Store the session with
|
|
91
|
+
// null observation fields; the observer mutates them once Claude
|
|
92
|
+
// Code's file appears on disk and the head bytes match this
|
|
93
|
+
// spawn's bridge suffix.
|
|
91
94
|
const session = {
|
|
92
95
|
sessionId,
|
|
93
96
|
pid: pty.pid,
|
|
@@ -96,24 +99,36 @@ export async function spawnClaudeSession(deps, args) {
|
|
|
96
99
|
senderId: args.senderId,
|
|
97
100
|
role: args.role,
|
|
98
101
|
channel: args.channel,
|
|
99
|
-
jsonlPath,
|
|
102
|
+
jsonlPath: null,
|
|
103
|
+
claudeSessionId: null,
|
|
100
104
|
pty,
|
|
101
105
|
exited: false,
|
|
102
106
|
};
|
|
103
107
|
deps.store.add(session);
|
|
108
|
+
const bridgeSuffix = bridgeSuffixFromUrl(url);
|
|
109
|
+
let observation = null;
|
|
110
|
+
if (bridgeSuffix) {
|
|
111
|
+
observation = deps.observer.observe({ bridgeSuffix });
|
|
112
|
+
observation.promise.then((observed) => {
|
|
113
|
+
if (!observed)
|
|
114
|
+
return;
|
|
115
|
+
session.jsonlPath = observed.jsonlPath;
|
|
116
|
+
session.claudeSessionId = observed.claudeSessionId;
|
|
117
|
+
deps.logger(`jsonl-observed pid=${pty.pid} sessionId=${observed.claudeSessionId} path=${observed.jsonlPath}`);
|
|
118
|
+
deps.onJsonlObserved?.(session);
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
else {
|
|
122
|
+
deps.logger(`jsonl-observe-skipped pid=${pty.pid} reason=bridge-suffix-unparseable url=${url}`);
|
|
123
|
+
}
|
|
104
124
|
pty.onExit(() => {
|
|
105
125
|
session.exited = true;
|
|
126
|
+
if (observation)
|
|
127
|
+
observation.cancel();
|
|
106
128
|
deps.logger(`kill pid=${pty.pid} reason=process-exited exit-code=0`);
|
|
107
129
|
});
|
|
108
|
-
deps.logger(`spawn pid=${pty.pid} sessionUrl=${url}
|
|
130
|
+
deps.logger(`spawn pid=${pty.pid} sessionUrl=${url} senderId=${args.senderId} role=${args.role} channel=${args.channel} permissionMode=${args.permissionMode ?? 'default'} latency-ms=${Date.now() - start}`);
|
|
109
131
|
deps.logger(`[pty-spawn] sessionId=${sessionId} appendSystemPromptBytes=${Buffer.byteLength(appendSystemPrompt, 'utf8')} hostname=${deps.host.hostname} lanIPv4=${deps.host.lanIPv4} adminUrl=${deps.host.adminUrl} tunnelUrl=${deps.host.tunnelUrl ?? 'none'}`);
|
|
110
|
-
if (args.onboarding) {
|
|
111
|
-
const rendered = renderOnboardingBlock(args.onboarding.step);
|
|
112
|
-
if (rendered) {
|
|
113
|
-
const accountIdShort = args.accountId ? args.accountId.slice(0, 8) : '';
|
|
114
|
-
deps.logger(`[onboarding-prompt] step=${rendered.label} bytes=${Buffer.byteLength(rendered.block, 'utf8')} sessionId=${sessionId.slice(0, 8)} accountId=${accountIdShort}`);
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
132
|
resolve({ ok: true, session });
|
|
118
133
|
},
|
|
119
134
|
onTimeout: () => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pty-spawner.js","sourceRoot":"","sources":["../src/pty-spawner.ts"],"names":[],"mappings":"AAAA,yEAAyE;AACzE,yEAAyE;AACzE,0DAA0D;AAC1D,0EAA0E;AAC1E,2EAA2E;AAC3E,eAAe;AACf,EAAE;AACF,0EAA0E;AAC1E,0EAA0E;AAC1E,iEAAiE;AAEjE,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AACxC,OAAO,EAAE,SAAS,EAAE,MAAM,SAAS,CAAA;AAEnC,OAAO,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAA;AAElD,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"pty-spawner.js","sourceRoot":"","sources":["../src/pty-spawner.ts"],"names":[],"mappings":"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"}
|
|
@@ -7,7 +7,16 @@ export interface StoredSession {
|
|
|
7
7
|
senderId: string;
|
|
8
8
|
role: Role;
|
|
9
9
|
channel: Channel;
|
|
10
|
+
/** Path to the JSONL Claude Code wrote, observed from disk (see
|
|
11
|
+
* jsonl-observer.ts). Null until the observer matches the JSONL to
|
|
12
|
+
* this session's bridge suffix. Task 065 — replaces the predicted
|
|
13
|
+
* path that produced phantom /list rows. */
|
|
10
14
|
jsonlPath: string | null;
|
|
15
|
+
/** Intrinsic claude session id (the JSONL basename, without `.jsonl`),
|
|
16
|
+
* observed via jsonl-observer. Distinct from the URL bridge suffix.
|
|
17
|
+
* Used by /list dedup against the on-disk enumerator. Null until the
|
|
18
|
+
* observer fires. Task 065. */
|
|
19
|
+
claudeSessionId: string | null;
|
|
11
20
|
pty: PtyHandle;
|
|
12
21
|
exited: boolean;
|
|
13
22
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"session-store.d.ts","sourceRoot":"","sources":["../src/session-store.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,YAAY,CAAA;AAE1D,MAAM,WAAW,aAAa;IAC5B,SAAS,EAAE,MAAM,CAAA;IACjB,GAAG,EAAE,MAAM,CAAA;IACX,GAAG,EAAE,MAAM,CAAA;IACX,SAAS,EAAE,MAAM,CAAA;IACjB,QAAQ,EAAE,MAAM,CAAA;IAChB,IAAI,EAAE,IAAI,CAAA;IACV,OAAO,EAAE,OAAO,CAAA;IAChB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;IACxB,GAAG,EAAE,SAAS,CAAA;IACd,MAAM,EAAE,OAAO,CAAA;CAChB;AAED,qBAAa,YAAY;IACvB,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAmC;IAE5D,GAAG,CAAC,CAAC,EAAE,aAAa,GAAG,IAAI;IAI3B,GAAG,CAAC,EAAE,EAAE,MAAM,GAAG,aAAa,GAAG,SAAS;IAI1C,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,aAAa,GAAG,SAAS;IAM7C,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,aAAa,EAAE;IAQ/C,GAAG,IAAI,aAAa,EAAE;IAItB,IAAI,IAAI,MAAM;CAGf"}
|
|
1
|
+
{"version":3,"file":"session-store.d.ts","sourceRoot":"","sources":["../src/session-store.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,YAAY,CAAA;AAE1D,MAAM,WAAW,aAAa;IAC5B,SAAS,EAAE,MAAM,CAAA;IACjB,GAAG,EAAE,MAAM,CAAA;IACX,GAAG,EAAE,MAAM,CAAA;IACX,SAAS,EAAE,MAAM,CAAA;IACjB,QAAQ,EAAE,MAAM,CAAA;IAChB,IAAI,EAAE,IAAI,CAAA;IACV,OAAO,EAAE,OAAO,CAAA;IAChB;;;iDAG6C;IAC7C,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;IACxB;;;oCAGgC;IAChC,eAAe,EAAE,MAAM,GAAG,IAAI,CAAA;IAC9B,GAAG,EAAE,SAAS,CAAA;IACd,MAAM,EAAE,OAAO,CAAA;CAChB;AAED,qBAAa,YAAY;IACvB,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAmC;IAE5D,GAAG,CAAC,CAAC,EAAE,aAAa,GAAG,IAAI;IAI3B,GAAG,CAAC,EAAE,EAAE,MAAM,GAAG,aAAa,GAAG,SAAS;IAI1C,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,aAAa,GAAG,SAAS;IAM7C,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,aAAa,EAAE;IAQ/C,GAAG,IAAI,aAAa,EAAE;IAItB,IAAI,IAAI,MAAM;CAGf"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"session-store.js","sourceRoot":"","sources":["../src/session-store.ts"],"names":[],"mappings":"AAAA,6EAA6E;
|
|
1
|
+
{"version":3,"file":"session-store.js","sourceRoot":"","sources":["../src/session-store.ts"],"names":[],"mappings":"AAAA,6EAA6E;AA0B7E,MAAM,OAAO,YAAY;IACN,QAAQ,GAAG,IAAI,GAAG,EAAyB,CAAA;IAE5D,GAAG,CAAC,CAAgB;QAClB,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,SAAS,EAAE,CAAC,CAAC,CAAA;IACnC,CAAC;IAED,GAAG,CAAC,EAAU;QACZ,OAAO,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC,CAAA;IAC9B,CAAC;IAED,MAAM,CAAC,EAAU;QACf,MAAM,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC,CAAA;QAC/B,IAAI,CAAC;YAAE,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC,CAAA;QAC/B,OAAO,CAAC,CAAA;IACV,CAAC;IAED,YAAY,CAAC,QAAgB;QAC3B,MAAM,GAAG,GAAoB,EAAE,CAAA;QAC/B,KAAK,MAAM,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE,EAAE,CAAC;YACvC,IAAI,CAAC,CAAC,QAAQ,KAAK,QAAQ;gBAAE,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;QAC1C,CAAC;QACD,OAAO,GAAG,CAAA;IACZ,CAAC;IAED,GAAG;QACD,OAAO,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAA;IACpC,CAAC;IAED,IAAI;QACF,OAAO,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAA;IAC3B,CAAC;CACF"}
|
|
@@ -4,30 +4,6 @@ export interface HostContext {
|
|
|
4
4
|
adminUrl: string;
|
|
5
5
|
tunnelUrl: string | null;
|
|
6
6
|
}
|
|
7
|
-
/** Onboarding state forwarded by the admin UI wrapper to the manager.
|
|
8
|
-
* `step` is the raw value returned by `loadOnboardingStep(accountId)` —
|
|
9
|
-
* 0..8 = in-progress, 9 = complete, -1 = no node (defensive), null =
|
|
10
|
-
* Neo4j unreachable. Task 043 moves the onboarding directive from PTY
|
|
11
|
-
* keystrokes (where the Claude CLI's Ink TextInput interpreted each
|
|
12
|
-
* `\n` in a multi-line block as Enter, dropping the bytes before they
|
|
13
|
-
* reached the agent) into the spawn-time append-system-prompt block. */
|
|
14
|
-
export interface OnboardingPayload {
|
|
15
|
-
step: number | null;
|
|
16
|
-
}
|
|
17
7
|
export declare const ATTACHMENT_CEILING_BYTES = 31457280;
|
|
18
|
-
export declare function composeAppendSystemPrompt(host: HostContext
|
|
19
|
-
export interface RenderedOnboardingBlock {
|
|
20
|
-
/** Block body without a leading newline; callers join with `\n`. */
|
|
21
|
-
block: string;
|
|
22
|
-
/** Label for observability: `<n>` for in-progress steps, `missing` for
|
|
23
|
-
* step === -1, `graph-unreachable` for step === null. Never emitted
|
|
24
|
-
* for the complete (step === 9) case — that returns null. */
|
|
25
|
-
label: string;
|
|
26
|
-
}
|
|
27
|
-
/** Render the onboarding-state section for a given step. Returns null when
|
|
28
|
-
* the agent should see no onboarding block (step === 9 = complete). The
|
|
29
|
-
* prose contract — declarative two-tool sequence, forbidden preamble
|
|
30
|
-
* phrasings — is pinned by tests in `__tests__/system-prompt.test.ts`
|
|
31
|
-
* and `platform/ui/app/lib/__tests__/onboarding-prompt-complete-onboarding.test.ts`. */
|
|
32
|
-
export declare function renderOnboardingBlock(step: number | null): RenderedOnboardingBlock | null;
|
|
8
|
+
export declare function composeAppendSystemPrompt(host: HostContext): string | null;
|
|
33
9
|
//# sourceMappingURL=system-prompt.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"system-prompt.d.ts","sourceRoot":"","sources":["../src/system-prompt.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"system-prompt.d.ts","sourceRoot":"","sources":["../src/system-prompt.ts"],"names":[],"mappings":"AAkBA,MAAM,WAAW,WAAW;IAC1B,QAAQ,EAAE,MAAM,CAAA;IAChB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;IACtB,QAAQ,EAAE,MAAM,CAAA;IAChB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;CACzB;AAED,eAAO,MAAM,wBAAwB,WAAa,CAAA;AAElD,wBAAgB,yBAAyB,CAAC,IAAI,EAAE,WAAW,GAAG,MAAM,GAAG,IAAI,CAc1E"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// Composes the `--append-system-prompt` block injected into every spawned
|
|
2
|
-
// `claude --verbose --remote-control` PTY.
|
|
2
|
+
// `claude --verbose --remote-control` PTY. Two sentinel-wrapped sections:
|
|
3
3
|
//
|
|
4
4
|
// <host> ... </host> — hostname, LAN IPv4, admin URL,
|
|
5
5
|
// tunnel URL (or "none")
|
|
@@ -7,12 +7,6 @@
|
|
|
7
7
|
// — 30 MiB SendUserFile ceiling and
|
|
8
8
|
// the tunnel-link workaround for
|
|
9
9
|
// oversize files
|
|
10
|
-
// <onboarding-state> ... </onboarding-state>
|
|
11
|
-
// — optional. Present only when the
|
|
12
|
-
// caller supplies an `onboarding`
|
|
13
|
-
// payload AND the resolved step
|
|
14
|
-
// is anything other than 9
|
|
15
|
-
// (complete). Task 043.
|
|
16
10
|
//
|
|
17
11
|
// The block is the only doctrine surface that survives Claude Code SDK
|
|
18
12
|
// upgrades. Per Task 037, no skill carries a copy; one edit here changes the
|
|
@@ -22,11 +16,11 @@
|
|
|
22
16
|
// caller passes that case as `null` to indicate the spawner should reject
|
|
23
17
|
// with `host-context-unresolved` rather than emit a malformed block.
|
|
24
18
|
export const ATTACHMENT_CEILING_BYTES = 31_457_280; // 30 MiB, mirrors the SDK uploader
|
|
25
|
-
export function composeAppendSystemPrompt(host
|
|
19
|
+
export function composeAppendSystemPrompt(host) {
|
|
26
20
|
if (!host.lanIPv4)
|
|
27
21
|
return null;
|
|
28
22
|
const tunnelLine = host.tunnelUrl ? host.tunnelUrl : 'none';
|
|
29
|
-
|
|
23
|
+
return [
|
|
30
24
|
'<host>',
|
|
31
25
|
`hostname: ${host.hostname}`,
|
|
32
26
|
`lan-ipv4: ${host.lanIPv4}`,
|
|
@@ -36,51 +30,6 @@ export function composeAppendSystemPrompt(host, onboarding) {
|
|
|
36
30
|
'<attachment-ceiling>',
|
|
37
31
|
'SendUserFile and any inline attachment surface accept at most 30 MiB per file. Over that ceiling, write the file under <spawn-cwd>/output/ and send the operator the public URL at <tunnel-url>/files/<relative-path>; never call SendUserFile with a file whose on-disk size exceeds 30 MiB. The tool returns "N files delivered to user" even when the byte upload silently fails, so the response is not evidence of delivery.',
|
|
38
32
|
'</attachment-ceiling>',
|
|
39
|
-
];
|
|
40
|
-
if (onboarding) {
|
|
41
|
-
const rendered = renderOnboardingBlock(onboarding.step);
|
|
42
|
-
if (rendered)
|
|
43
|
-
sections.push(rendered.block);
|
|
44
|
-
}
|
|
45
|
-
return sections.join('\n');
|
|
46
|
-
}
|
|
47
|
-
/** Render the onboarding-state section for a given step. Returns null when
|
|
48
|
-
* the agent should see no onboarding block (step === 9 = complete). The
|
|
49
|
-
* prose contract — declarative two-tool sequence, forbidden preamble
|
|
50
|
-
* phrasings — is pinned by tests in `__tests__/system-prompt.test.ts`
|
|
51
|
-
* and `platform/ui/app/lib/__tests__/onboarding-prompt-complete-onboarding.test.ts`. */
|
|
52
|
-
export function renderOnboardingBlock(step) {
|
|
53
|
-
if (step === 9)
|
|
54
|
-
return null;
|
|
55
|
-
if (step === null) {
|
|
56
|
-
return { block: renderUnreachableBlock(), label: 'graph-unreachable' };
|
|
57
|
-
}
|
|
58
|
-
if (step < 0) {
|
|
59
|
-
return { block: renderIncompleteBlock(-1), label: 'missing' };
|
|
60
|
-
}
|
|
61
|
-
return { block: renderIncompleteBlock(step), label: String(step) };
|
|
62
|
-
}
|
|
63
|
-
function renderIncompleteBlock(currentStep) {
|
|
64
|
-
const stepAttr = currentStep < 0 ? 'missing' : String(currentStep);
|
|
65
|
-
const resumeStep = currentStep < 0 ? 0 : currentStep + 1;
|
|
66
|
-
// Task 038 Outcome E1 — declarative, no menu phrasing, no pre-skill preamble.
|
|
67
|
-
// Two-tool contract: first `skill-load(name=onboarding)`, then
|
|
68
|
-
// `render-component` for the next step. Operator-visible drift (any "let
|
|
69
|
-
// me check", "let me figure out", "let me list" preamble) is the
|
|
70
|
-
// failure mode the precision-check rule `onboarding-skill-drift` watches
|
|
71
|
-
// for; the prose below names it so the agent treats the constraint as
|
|
72
|
-
// structural rather than stylistic.
|
|
73
|
-
return [
|
|
74
|
-
`<onboarding-state currentStep="${stepAttr}" resumeStep="${resumeStep}">`,
|
|
75
|
-
`Onboarding is incomplete. Your first tool call this turn is \`skill-load\` with \`skillName=onboarding\`. Your second tool call is \`render-component\` for step ${resumeStep}, exactly as the skill body directs. Do not greet, do not summarise, do not write a preamble (\`let me check\`, \`let me figure out\`, \`let me list\` and similar phrasings are forbidden). The skill body is the only authority for what the operator sees next.`,
|
|
76
|
-
`</onboarding-state>`,
|
|
77
|
-
].join('\n');
|
|
78
|
-
}
|
|
79
|
-
function renderUnreachableBlock() {
|
|
80
|
-
return [
|
|
81
|
-
`<onboarding-state currentStep="unknown" graphUnreachable="true">`,
|
|
82
|
-
`Neo4j is unreachable, so onboarding state cannot be read. Do not assume onboarding is complete. Tell the operator the graph is unreachable, name the symptom in one line, and stop — do not improvise an onboarding flow without state, and do not silently skip the step the operator was on.`,
|
|
83
|
-
`</onboarding-state>`,
|
|
84
33
|
].join('\n');
|
|
85
34
|
}
|
|
86
35
|
//# sourceMappingURL=system-prompt.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"system-prompt.js","sourceRoot":"","sources":["../src/system-prompt.ts"],"names":[],"mappings":"AAAA,0EAA0E;AAC1E,
|
|
1
|
+
{"version":3,"file":"system-prompt.js","sourceRoot":"","sources":["../src/system-prompt.ts"],"names":[],"mappings":"AAAA,0EAA0E;AAC1E,0EAA0E;AAC1E,EAAE;AACF,2EAA2E;AAC3E,oEAAoE;AACpE,mDAAmD;AACnD,6EAA6E;AAC7E,4EAA4E;AAC5E,4DAA4D;AAC5D,EAAE;AACF,uEAAuE;AACvE,6EAA6E;AAC7E,0DAA0D;AAC1D,EAAE;AACF,yEAAyE;AACzE,0EAA0E;AAC1E,qEAAqE;AASrE,MAAM,CAAC,MAAM,wBAAwB,GAAG,UAAU,CAAA,CAAC,mCAAmC;AAEtF,MAAM,UAAU,yBAAyB,CAAC,IAAiB;IACzD,IAAI,CAAC,IAAI,CAAC,OAAO;QAAE,OAAO,IAAI,CAAA;IAC9B,MAAM,UAAU,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM,CAAA;IAC3D,OAAO;QACL,QAAQ;QACR,aAAa,IAAI,CAAC,QAAQ,EAAE;QAC5B,aAAa,IAAI,CAAC,OAAO,EAAE;QAC3B,cAAc,IAAI,CAAC,QAAQ,EAAE;QAC7B,eAAe,UAAU,EAAE;QAC3B,SAAS;QACT,sBAAsB;QACtB,maAAma;QACna,uBAAuB;KACxB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;AACd,CAAC"}
|
|
@@ -14,6 +14,8 @@ The Neo4j graph is where this account stores everything it knows. Before you wri
|
|
|
14
14
|
|
|
15
15
|
Every node has a parent. The canonical hierarchy is LocalBusiness, then Project, then Task or Person or Organisation or KnowledgeDocument. A node with no upward edge to its hierarchy parent is a write defect, not a graph state. The wrapped writers refuse it; the graph-write shim rolls back any raw cypher that produces one. Cross-hierarchy edges (one Person linked to several Projects, one KnowledgeDocument about several Organisations) are normal; the rule governs containment, not exclusivity.
|
|
16
16
|
|
|
17
|
+
When the owner declines an offer, record the decline as a property on `Person` (e.g. `preferences.declinedRemoteAccess: true`) so you do not re-ask. The `## About the Owner` Coverage signal will keep surfacing missing fields; honour `notApplicable: true` on any field the owner has explicitly opted out of.
|
|
18
|
+
|
|
17
19
|
## Before you act
|
|
18
20
|
|
|
19
21
|
You may not act on a request until you know three things: what is being asked, what is in scope and what is out of scope, and what rules apply for this specific task. When the owner's words are precise, all three are obvious. Act. When any of the three needs a guess, stop and ask one question. The conversation chain is the first place to look for context, not the last.
|