@decibelsystems/tools 2.1.2 → 2.1.4
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/README.md +144 -63
- package/dist/agentCommands.d.ts +11 -0
- package/dist/agentCommands.d.ts.map +1 -0
- package/dist/agentCommands.js +267 -0
- package/dist/agentCommands.js.map +1 -0
- package/dist/agentInbox.d.ts +37 -0
- package/dist/agentInbox.d.ts.map +1 -0
- package/dist/agentInbox.js +128 -0
- package/dist/agentInbox.js.map +1 -0
- package/dist/agentPresence.d.ts +36 -0
- package/dist/agentPresence.d.ts.map +1 -0
- package/dist/agentPresence.js +227 -0
- package/dist/agentPresence.js.map +1 -0
- package/dist/agenticJobs.d.ts +49 -0
- package/dist/agenticJobs.d.ts.map +1 -0
- package/dist/agenticJobs.js +190 -0
- package/dist/agenticJobs.js.map +1 -0
- package/dist/architectAdrs.d.ts +7 -0
- package/dist/architectAdrs.d.ts.map +1 -1
- package/dist/architectAdrs.js +91 -28
- package/dist/architectAdrs.js.map +1 -1
- package/dist/daemon.d.ts +6 -0
- package/dist/daemon.d.ts.map +1 -1
- package/dist/daemon.js +14 -0
- package/dist/daemon.js.map +1 -1
- package/dist/facades/definitions.d.ts.map +1 -1
- package/dist/facades/definitions.js +40 -6
- package/dist/facades/definitions.js.map +1 -1
- package/dist/hq/defineAgent.d.ts +11 -0
- package/dist/hq/defineAgent.d.ts.map +1 -0
- package/dist/hq/defineAgent.js +185 -0
- package/dist/hq/defineAgent.js.map +1 -0
- package/dist/hq/index.d.ts +3 -0
- package/dist/hq/index.d.ts.map +1 -0
- package/dist/hq/index.js +28 -0
- package/dist/hq/index.js.map +1 -0
- package/dist/hq/types.d.ts +59 -0
- package/dist/hq/types.d.ts.map +1 -0
- package/dist/hq/types.js +12 -0
- package/dist/hq/types.js.map +1 -0
- package/dist/httpServer.d.ts +1 -1
- package/dist/httpServer.d.ts.map +1 -1
- package/dist/httpServer.js +327 -19
- package/dist/httpServer.js.map +1 -1
- package/dist/kernel.d.ts +3 -1
- package/dist/kernel.d.ts.map +1 -1
- package/dist/kernel.js +40 -9
- package/dist/kernel.js.map +1 -1
- package/dist/projectRegistry.d.ts +27 -0
- package/dist/projectRegistry.d.ts.map +1 -1
- package/dist/projectRegistry.js +191 -5
- package/dist/projectRegistry.js.map +1 -1
- package/dist/sentinelIssues.d.ts +5 -0
- package/dist/sentinelIssues.d.ts.map +1 -1
- package/dist/sentinelIssues.js +1 -1
- package/dist/sentinelIssues.js.map +1 -1
- package/dist/server.js +12 -0
- package/dist/server.js.map +1 -1
- package/dist/store/fsStore.d.ts +6 -0
- package/dist/store/fsStore.d.ts.map +1 -0
- package/dist/store/fsStore.js +77 -0
- package/dist/store/fsStore.js.map +1 -0
- package/dist/store/index.d.ts +8 -0
- package/dist/store/index.d.ts.map +1 -0
- package/dist/store/index.js +23 -0
- package/dist/store/index.js.map +1 -0
- package/dist/store/markdown.d.ts +21 -0
- package/dist/store/markdown.d.ts.map +1 -0
- package/dist/store/markdown.js +175 -0
- package/dist/store/markdown.js.map +1 -0
- package/dist/store/supabaseStore.d.ts +6 -0
- package/dist/store/supabaseStore.d.ts.map +1 -0
- package/dist/store/supabaseStore.js +152 -0
- package/dist/store/supabaseStore.js.map +1 -0
- package/dist/store/types.d.ts +49 -0
- package/dist/store/types.d.ts.map +1 -0
- package/dist/store/types.js +11 -0
- package/dist/store/types.js.map +1 -0
- package/dist/supabaseRetry.d.ts +21 -0
- package/dist/supabaseRetry.d.ts.map +1 -0
- package/dist/supabaseRetry.js +72 -0
- package/dist/supabaseRetry.js.map +1 -0
- package/dist/toolConfig.d.ts +49 -0
- package/dist/toolConfig.d.ts.map +1 -0
- package/dist/toolConfig.js +309 -0
- package/dist/toolConfig.js.map +1 -0
- package/dist/tools/agentic/agentQueue.d.ts.map +1 -1
- package/dist/tools/agentic/agentQueue.js +7 -5
- package/dist/tools/agentic/agentQueue.js.map +1 -1
- package/dist/tools/agentic/index.d.ts +3 -0
- package/dist/tools/agentic/index.d.ts.map +1 -1
- package/dist/tools/agentic/index.js +158 -1
- package/dist/tools/agentic/index.js.map +1 -1
- package/dist/tools/codereview/index.d.ts +4 -0
- package/dist/tools/codereview/index.d.ts.map +1 -0
- package/dist/tools/codereview/index.js +93 -0
- package/dist/tools/codereview/index.js.map +1 -0
- package/dist/tools/codereview.d.ts +56 -0
- package/dist/tools/codereview.d.ts.map +1 -0
- package/dist/tools/codereview.js +304 -0
- package/dist/tools/codereview.js.map +1 -0
- package/dist/tools/concepts.d.ts +38 -0
- package/dist/tools/concepts.d.ts.map +1 -0
- package/dist/tools/concepts.js +283 -0
- package/dist/tools/concepts.js.map +1 -0
- package/dist/tools/corpus/index.d.ts +3 -0
- package/dist/tools/corpus/index.d.ts.map +1 -1
- package/dist/tools/corpus/index.js +183 -1
- package/dist/tools/corpus/index.js.map +1 -1
- package/dist/tools/corpus.d.ts +52 -0
- package/dist/tools/corpus.d.ts.map +1 -1
- package/dist/tools/corpus.js +207 -2
- package/dist/tools/corpus.js.map +1 -1
- package/dist/tools/dojo.d.ts.map +1 -1
- package/dist/tools/dojo.js +11 -1
- package/dist/tools/dojo.js.map +1 -1
- package/dist/tools/git-sentinel.d.ts.map +1 -1
- package/dist/tools/git-sentinel.js +24 -8
- package/dist/tools/git-sentinel.js.map +1 -1
- package/dist/tools/index.d.ts.map +1 -1
- package/dist/tools/index.js +6 -0
- package/dist/tools/index.js.map +1 -1
- package/dist/tools/oracle.d.ts +2 -0
- package/dist/tools/oracle.d.ts.map +1 -1
- package/dist/tools/oracle.js +146 -17
- package/dist/tools/oracle.js.map +1 -1
- package/dist/tools/peers.d.ts +15 -0
- package/dist/tools/peers.d.ts.map +1 -0
- package/dist/tools/peers.js +70 -0
- package/dist/tools/peers.js.map +1 -0
- package/dist/tools/registry/index.d.ts +4 -0
- package/dist/tools/registry/index.d.ts.map +1 -1
- package/dist/tools/registry/index.js +274 -1
- package/dist/tools/registry/index.js.map +1 -1
- package/dist/tools/roadmap.d.ts +4 -0
- package/dist/tools/roadmap.d.ts.map +1 -1
- package/dist/tools/roadmap.js.map +1 -1
- package/dist/tools/sentinel.d.ts +15 -1
- package/dist/tools/sentinel.d.ts.map +1 -1
- package/dist/tools/sentinel.js +198 -34
- package/dist/tools/sentinel.js.map +1 -1
- package/dist/tools/voice/index.d.ts.map +1 -1
- package/dist/tools/voice/index.js +2 -3
- package/dist/tools/voice/index.js.map +1 -1
- package/dist/tools/voice.d.ts +1 -1
- package/dist/tools/voice.js +2 -2
- package/dist/tools/voice.js.map +1 -1
- package/dist/tools/workflow.js +5 -5
- package/dist/tools/workflow.js.map +1 -1
- package/dist/transports/http.js +1 -1
- package/package.json +4 -2
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
export interface InboxCommand {
|
|
2
|
+
id: string;
|
|
3
|
+
org_id: string;
|
|
4
|
+
kind: string;
|
|
5
|
+
payload: Record<string, unknown>;
|
|
6
|
+
enqueued_at: number;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Enqueue a command for an SDK session to poll. Idempotent on command id. Also
|
|
10
|
+
* records the id→session ownership (for ack authorization). cmd.org_id is the
|
|
11
|
+
* owning org; drainCommands only returns commands whose org matches the caller's.
|
|
12
|
+
*/
|
|
13
|
+
export declare function enqueueCommand(sessionKey: string, cmd: InboxCommand): void;
|
|
14
|
+
/**
|
|
15
|
+
* Drain pending commands for a session (returns + removes them). Evicts stale
|
|
16
|
+
* first. Only returns commands belonging to `orgId` — a cross-org command (which
|
|
17
|
+
* should never be enqueued here given the dispatcher's org-first filter) is
|
|
18
|
+
* dropped, never delivered.
|
|
19
|
+
*/
|
|
20
|
+
export declare function drainCommands(sessionKey: string, orgId: string): InboxCommand[];
|
|
21
|
+
/** Is this session_key one the inbox is tracking? (has pending commands) */
|
|
22
|
+
export declare function hasInbox(sessionKey: string): boolean;
|
|
23
|
+
/** Store (or replace) the capability token for a session. */
|
|
24
|
+
export declare function setSessionToken(sessionKey: string, token: string): void;
|
|
25
|
+
/** The capability token for a session, or undefined if none is registered. */
|
|
26
|
+
export declare function getSessionToken(sessionKey: string): string | undefined;
|
|
27
|
+
/** Forget a session's token (on 'ended' lifecycle). */
|
|
28
|
+
export declare function dropSessionToken(sessionKey: string): void;
|
|
29
|
+
/** The session_key a command id was enqueued for (for ack authorization). */
|
|
30
|
+
export declare function ackOwnerOf(id: string): string | undefined;
|
|
31
|
+
/** Forget an id→session ownership once the command has been acked/settled. */
|
|
32
|
+
export declare function clearAckOwner(id: string): void;
|
|
33
|
+
/** Total queued commands across all sessions (for /health + tests). */
|
|
34
|
+
export declare function inboxDepth(): number;
|
|
35
|
+
/** Test/shutdown helper — resets inboxes, tokens, and ack-owners. */
|
|
36
|
+
export declare function clearInbox(): void;
|
|
37
|
+
//# sourceMappingURL=agentInbox.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agentInbox.d.ts","sourceRoot":"","sources":["../src/agentInbox.ts"],"names":[],"mappings":"AAyBA,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACjC,WAAW,EAAE,MAAM,CAAC;CACrB;AAyBD;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,UAAU,EAAE,MAAM,EAAE,GAAG,EAAE,YAAY,GAAG,IAAI,CAQ1E;AAED;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,YAAY,EAAE,CAK/E;AAED,4EAA4E;AAC5E,wBAAgB,QAAQ,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAGpD;AAMD,6DAA6D;AAC7D,wBAAgB,eAAe,CAAC,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAEvE;AAED,8EAA8E;AAC9E,wBAAgB,eAAe,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAEtE;AAED,uDAAuD;AACvD,wBAAgB,gBAAgB,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,CAEzD;AAED,6EAA6E;AAC7E,wBAAgB,UAAU,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAEzD;AAED,8EAA8E;AAC9E,wBAAgB,aAAa,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,CAE9C;AAeD,uEAAuE;AACvE,wBAAgB,UAAU,IAAI,MAAM,CAInC;AAED,qEAAqE;AACrE,wBAAgB,UAAU,IAAI,IAAI,CAIjC"}
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
// ============================================================================
|
|
2
|
+
// Agent command inbox — daemon-side delivery for SDK (non-broker) runtimes
|
|
3
|
+
// ============================================================================
|
|
4
|
+
// The HQ→agent command dispatcher (agentCommands.ts) delivers `message` to
|
|
5
|
+
// claude-peers sessions via the broker, and answers `request_status` from the
|
|
6
|
+
// broker's live registry. But SDK-registered runtimes (hermes/openclaw/codex/…
|
|
7
|
+
// from @decibelsystems/tools/hq) aren't in the broker — they have no transport.
|
|
8
|
+
//
|
|
9
|
+
// This module bridges that gap WITHOUT giving the SDK any Supabase creds (the
|
|
10
|
+
// "no service_role in untrusted hands" rule holds): the dispatcher ENQUEUES a
|
|
11
|
+
// command targeting a known SDK session here; the SDK polls GET /agents/commands
|
|
12
|
+
// + acks POST /agents/commands/ack (both localhost-only); the daemon settles the
|
|
13
|
+
// hq.agent_commands row in Core via service_role on ack.
|
|
14
|
+
//
|
|
15
|
+
// IDENTITY — capability token, NOT a bare label (security review 2026-06-15):
|
|
16
|
+
// session_key is a GUESSABLE label, so localhost-bind alone would let any
|
|
17
|
+
// co-resident local runtime drain/ack ANOTHER runtime's commands (the SDK's whole
|
|
18
|
+
// premise is several runtimes side-by-side). So the daemon mints a per-session
|
|
19
|
+
// SECRET token at /agents/register, returns it to that one SDK process, and
|
|
20
|
+
// requires it on poll + ack. session_key says "which inbox"; the token proves
|
|
21
|
+
// "I'm the process that registered it." The org-id-first cross-org invariant is
|
|
22
|
+
// preserved here too: InboxCommand carries org_id and drainCommands filters on it,
|
|
23
|
+
// so even a token-authenticated poll only ever receives its own org's commands.
|
|
24
|
+
// ============================================================================
|
|
25
|
+
// session_key → its pending commands. In-memory: the daemon is the single
|
|
26
|
+
// authority for sessions it hosts; a restart re-derives state from Core (pending
|
|
27
|
+
// rows get re-dispatched on the next tick).
|
|
28
|
+
const inboxes = new Map();
|
|
29
|
+
// session_key → its per-session capability token (the secret an SDK must present
|
|
30
|
+
// on poll/ack to prove it's the registrant). Minted by the HTTP register/heartbeat
|
|
31
|
+
// handler; verified there too (timing-safe). Wiped on a daemon restart — the SDK's
|
|
32
|
+
// next heartbeat re-mints, and it stores the fresh token from the response.
|
|
33
|
+
const sessionTokens = new Map();
|
|
34
|
+
// command id → the session_key it was enqueued for, with a timestamp for TTL
|
|
35
|
+
// eviction. The ack arrives AFTER drainCommands has already removed the command
|
|
36
|
+
// from the inbox, so the inbox itself can't tell us who owns an acked id — this
|
|
37
|
+
// map can. The ack handler maps id→session→token to authorize the settle.
|
|
38
|
+
const ackOwners = new Map();
|
|
39
|
+
// Drop inbox entries an SDK never polled, so a vanished runtime doesn't leak
|
|
40
|
+
// memory. Slightly longer than the command expiry (5min) so a slow poller still
|
|
41
|
+
// gets it; the dispatcher's expiry sweep settles the Core row regardless.
|
|
42
|
+
const INBOX_TTL_MS = 6 * 60_000;
|
|
43
|
+
const MAX_PER_SESSION = 100; // backstop against unbounded growth per session
|
|
44
|
+
/**
|
|
45
|
+
* Enqueue a command for an SDK session to poll. Idempotent on command id. Also
|
|
46
|
+
* records the id→session ownership (for ack authorization). cmd.org_id is the
|
|
47
|
+
* owning org; drainCommands only returns commands whose org matches the caller's.
|
|
48
|
+
*/
|
|
49
|
+
export function enqueueCommand(sessionKey, cmd) {
|
|
50
|
+
const list = inboxes.get(sessionKey) ?? [];
|
|
51
|
+
if (list.some((c) => c.id === cmd.id))
|
|
52
|
+
return; // already queued (keep first owner)
|
|
53
|
+
list.push(cmd);
|
|
54
|
+
// Trim oldest if a session somehow accumulates a flood (shouldn't happen).
|
|
55
|
+
while (list.length > MAX_PER_SESSION)
|
|
56
|
+
list.shift();
|
|
57
|
+
inboxes.set(sessionKey, list);
|
|
58
|
+
ackOwners.set(cmd.id, { sessionKey, at: cmd.enqueued_at });
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Drain pending commands for a session (returns + removes them). Evicts stale
|
|
62
|
+
* first. Only returns commands belonging to `orgId` — a cross-org command (which
|
|
63
|
+
* should never be enqueued here given the dispatcher's org-first filter) is
|
|
64
|
+
* dropped, never delivered.
|
|
65
|
+
*/
|
|
66
|
+
export function drainCommands(sessionKey, orgId) {
|
|
67
|
+
evictStale();
|
|
68
|
+
const list = inboxes.get(sessionKey) ?? [];
|
|
69
|
+
inboxes.delete(sessionKey);
|
|
70
|
+
return list.filter((c) => c.org_id === orgId);
|
|
71
|
+
}
|
|
72
|
+
/** Is this session_key one the inbox is tracking? (has pending commands) */
|
|
73
|
+
export function hasInbox(sessionKey) {
|
|
74
|
+
const list = inboxes.get(sessionKey);
|
|
75
|
+
return !!list && list.length > 0;
|
|
76
|
+
}
|
|
77
|
+
// ---------------------------------------------------------------------------
|
|
78
|
+
// Per-session capability tokens (proof-of-possession for poll/ack)
|
|
79
|
+
// ---------------------------------------------------------------------------
|
|
80
|
+
/** Store (or replace) the capability token for a session. */
|
|
81
|
+
export function setSessionToken(sessionKey, token) {
|
|
82
|
+
sessionTokens.set(sessionKey, token);
|
|
83
|
+
}
|
|
84
|
+
/** The capability token for a session, or undefined if none is registered. */
|
|
85
|
+
export function getSessionToken(sessionKey) {
|
|
86
|
+
return sessionTokens.get(sessionKey);
|
|
87
|
+
}
|
|
88
|
+
/** Forget a session's token (on 'ended' lifecycle). */
|
|
89
|
+
export function dropSessionToken(sessionKey) {
|
|
90
|
+
sessionTokens.delete(sessionKey);
|
|
91
|
+
}
|
|
92
|
+
/** The session_key a command id was enqueued for (for ack authorization). */
|
|
93
|
+
export function ackOwnerOf(id) {
|
|
94
|
+
return ackOwners.get(id)?.sessionKey;
|
|
95
|
+
}
|
|
96
|
+
/** Forget an id→session ownership once the command has been acked/settled. */
|
|
97
|
+
export function clearAckOwner(id) {
|
|
98
|
+
ackOwners.delete(id);
|
|
99
|
+
}
|
|
100
|
+
/** Evict commands + ack-owners older than the TTL (the dispatcher/DB sweep handles Core-side). */
|
|
101
|
+
function evictStale() {
|
|
102
|
+
const cutoff = Date.now() - INBOX_TTL_MS;
|
|
103
|
+
for (const [key, list] of inboxes) {
|
|
104
|
+
const kept = list.filter((c) => c.enqueued_at >= cutoff);
|
|
105
|
+
if (kept.length === 0)
|
|
106
|
+
inboxes.delete(key);
|
|
107
|
+
else if (kept.length !== list.length)
|
|
108
|
+
inboxes.set(key, kept);
|
|
109
|
+
}
|
|
110
|
+
for (const [id, owner] of ackOwners) {
|
|
111
|
+
if (owner.at < cutoff)
|
|
112
|
+
ackOwners.delete(id);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
/** Total queued commands across all sessions (for /health + tests). */
|
|
116
|
+
export function inboxDepth() {
|
|
117
|
+
let n = 0;
|
|
118
|
+
for (const list of inboxes.values())
|
|
119
|
+
n += list.length;
|
|
120
|
+
return n;
|
|
121
|
+
}
|
|
122
|
+
/** Test/shutdown helper — resets inboxes, tokens, and ack-owners. */
|
|
123
|
+
export function clearInbox() {
|
|
124
|
+
inboxes.clear();
|
|
125
|
+
sessionTokens.clear();
|
|
126
|
+
ackOwners.clear();
|
|
127
|
+
}
|
|
128
|
+
//# sourceMappingURL=agentInbox.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agentInbox.js","sourceRoot":"","sources":["../src/agentInbox.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The daemon's host identity for presence + command targeting. Defaults to
|
|
3
|
+
* os.hostname() but is overridable via DECIBEL_PRESENCE_HOST — needed where the
|
|
4
|
+
* OS hostname isn't a stable/unique daemon identity (containers with shared
|
|
5
|
+
* hostnames, or two daemons on one machine, e.g. a rolling restart or a test
|
|
6
|
+
* harness). target_host on hq.agent_commands matches this, so it must be the same
|
|
7
|
+
* value the presence writer stamps. Shared by the dispatcher (agentCommands.ts).
|
|
8
|
+
*/
|
|
9
|
+
export declare function resolveHost(): string;
|
|
10
|
+
export interface LocalAgentRegistration {
|
|
11
|
+
session_key: string;
|
|
12
|
+
runtime: string;
|
|
13
|
+
agent?: string | null;
|
|
14
|
+
cwd?: string | null;
|
|
15
|
+
summary?: string | null;
|
|
16
|
+
meta?: Record<string, unknown>;
|
|
17
|
+
status?: 'active' | 'ended';
|
|
18
|
+
}
|
|
19
|
+
/** Strip control chars/null bytes and cap length. Empty-after-clean → null. */
|
|
20
|
+
export declare function sanitizeText(s: string | null | undefined, maxLen: number): string | null;
|
|
21
|
+
/**
|
|
22
|
+
* Flatten meta to display-safe primitives: strings cleaned + capped, numbers/
|
|
23
|
+
* booleans/null kept, nested objects/arrays dropped (HQ typeof-guards numeric
|
|
24
|
+
* meta and renders strings as text). If the result still exceeds META_MAX_BYTES,
|
|
25
|
+
* drop it entirely — the caller re-adds the trusted last_action_at.
|
|
26
|
+
*/
|
|
27
|
+
export declare function sanitizeMeta(meta: Record<string, unknown> | undefined): Record<string, unknown>;
|
|
28
|
+
/**
|
|
29
|
+
* Upsert a local-runtime session into hq.agent_sessions (register or heartbeat).
|
|
30
|
+
* Returns true on success, false if Supabase is unconfigured or the write failed.
|
|
31
|
+
* Reuses the presence writer's org config + cwd→project resolution.
|
|
32
|
+
*/
|
|
33
|
+
export declare function writeLocalAgentSession(reg: LocalAgentRegistration): Promise<boolean>;
|
|
34
|
+
/** Start the presence writer loop. Returns a stop function. No-ops if Supabase unconfigured. */
|
|
35
|
+
export declare function startPresenceWriter(): () => void;
|
|
36
|
+
//# sourceMappingURL=agentPresence.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agentPresence.d.ts","sourceRoot":"","sources":["../src/agentPresence.ts"],"names":[],"mappings":"AAsBA;;;;;;;GAOG;AACH,wBAAgB,WAAW,IAAI,MAAM,CAEpC;AAwHD,MAAM,WAAW,sBAAsB;IACrC,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,GAAG,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAG/B,MAAM,CAAC,EAAE,QAAQ,GAAG,OAAO,CAAC;CAC7B;AAmBD,+EAA+E;AAC/E,wBAAgB,YAAY,CAAC,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAIxF;AAED;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAU/F;AAED;;;;GAIG;AACH,wBAAsB,sBAAsB,CAAC,GAAG,EAAE,sBAAsB,GAAG,OAAO,CAAC,OAAO,CAAC,CAuC1F;AAED,gGAAgG;AAChG,wBAAgB,mBAAmB,IAAI,MAAM,IAAI,CAchD"}
|
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
// ============================================================================
|
|
2
|
+
// Agent-presence writer — heartbeats live claude-peers sessions into Core
|
|
3
|
+
// ============================================================================
|
|
4
|
+
// Daemon-side telemetry writer for the Plan D agent-presence domain. On a 30s
|
|
5
|
+
// loop it:
|
|
6
|
+
// 1. reads live peers from the claude-peers broker (POST /list-peers),
|
|
7
|
+
// 2. upserts each into hq.agent_sessions via SERVICE_ROLE (deliberate scoped
|
|
8
|
+
// exception — presence is telemetry, peers carry no user JWT, v1 single-org),
|
|
9
|
+
// 3. stale-sweeps active rows that stopped heartbeating → idle (>90s) / ended (>5min).
|
|
10
|
+
// Never throws into the daemon; no-ops if Supabase isn't configured or the broker
|
|
11
|
+
// is down. Contract co-designed with decibel-hq (migration 20260524000005). EPIC-0033.
|
|
12
|
+
// ============================================================================
|
|
13
|
+
import os from 'os';
|
|
14
|
+
import path from 'path';
|
|
15
|
+
import { createClient } from '@supabase/supabase-js';
|
|
16
|
+
import { log } from './config.js';
|
|
17
|
+
import { withRetryResult } from './supabaseRetry.js';
|
|
18
|
+
const BROKER_URL = `http://127.0.0.1:${process.env.CLAUDE_PEERS_PORT ?? '7899'}`;
|
|
19
|
+
const ORG_ID = process.env.DECIBEL_ORG_ID || '1cb79e24-e06f-46c9-8a22-5ee025ffb0f4';
|
|
20
|
+
/**
|
|
21
|
+
* The daemon's host identity for presence + command targeting. Defaults to
|
|
22
|
+
* os.hostname() but is overridable via DECIBEL_PRESENCE_HOST — needed where the
|
|
23
|
+
* OS hostname isn't a stable/unique daemon identity (containers with shared
|
|
24
|
+
* hostnames, or two daemons on one machine, e.g. a rolling restart or a test
|
|
25
|
+
* harness). target_host on hq.agent_commands matches this, so it must be the same
|
|
26
|
+
* value the presence writer stamps. Shared by the dispatcher (agentCommands.ts).
|
|
27
|
+
*/
|
|
28
|
+
export function resolveHost() {
|
|
29
|
+
return process.env.DECIBEL_PRESENCE_HOST || os.hostname();
|
|
30
|
+
}
|
|
31
|
+
const HEARTBEAT_MS = 30_000;
|
|
32
|
+
const IDLE_AFTER_MS = 90_000;
|
|
33
|
+
const ENDED_AFTER_MS = 5 * 60_000;
|
|
34
|
+
function serviceClient() {
|
|
35
|
+
const url = process.env.SUPABASE_URL;
|
|
36
|
+
const key = process.env.SUPABASE_SERVICE_KEY;
|
|
37
|
+
if (!url || !key)
|
|
38
|
+
return null;
|
|
39
|
+
return createClient(url, key, {
|
|
40
|
+
auth: { persistSession: false, autoRefreshToken: false },
|
|
41
|
+
db: { schema: 'hq' },
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
async function fetchPeers() {
|
|
45
|
+
try {
|
|
46
|
+
const res = await fetch(`${BROKER_URL}/list-peers`, {
|
|
47
|
+
method: 'POST',
|
|
48
|
+
headers: { 'Content-Type': 'application/json' },
|
|
49
|
+
body: JSON.stringify({ requester_id: 'decibel-presence', scope: 'machine' }),
|
|
50
|
+
signal: AbortSignal.timeout(2000),
|
|
51
|
+
});
|
|
52
|
+
if (!res.ok)
|
|
53
|
+
return [];
|
|
54
|
+
return (await res.json());
|
|
55
|
+
}
|
|
56
|
+
catch {
|
|
57
|
+
return [];
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
// project label (repo dir basename) → hq.projects.id within the org. Cached;
|
|
61
|
+
// refreshed on a miss so newly-onboarded projects resolve.
|
|
62
|
+
let projectMap = null;
|
|
63
|
+
async function loadProjects(client) {
|
|
64
|
+
const { data, error } = await client.from('projects').select('id,key').eq('org_id', ORG_ID);
|
|
65
|
+
const m = new Map();
|
|
66
|
+
if (!error && data)
|
|
67
|
+
for (const r of data)
|
|
68
|
+
m.set(r.key, r.id);
|
|
69
|
+
return m;
|
|
70
|
+
}
|
|
71
|
+
async function resolveProjectId(client, cwd) {
|
|
72
|
+
const key = path.basename(cwd || '');
|
|
73
|
+
if (!key)
|
|
74
|
+
return null;
|
|
75
|
+
if (!projectMap)
|
|
76
|
+
projectMap = await loadProjects(client);
|
|
77
|
+
if (!projectMap.has(key))
|
|
78
|
+
projectMap = await loadProjects(client); // refresh once on miss
|
|
79
|
+
return projectMap.get(key) ?? null;
|
|
80
|
+
}
|
|
81
|
+
async function tick(client) {
|
|
82
|
+
const host = resolveHost();
|
|
83
|
+
const nowMs = Date.now();
|
|
84
|
+
const nowIso = new Date(nowMs).toISOString();
|
|
85
|
+
const peers = await fetchPeers();
|
|
86
|
+
for (const p of peers) {
|
|
87
|
+
if (!p.id)
|
|
88
|
+
continue;
|
|
89
|
+
const project_id = await resolveProjectId(client, p.cwd);
|
|
90
|
+
const row = {
|
|
91
|
+
org_id: ORG_ID,
|
|
92
|
+
host,
|
|
93
|
+
session_key: p.id,
|
|
94
|
+
agent: null,
|
|
95
|
+
// These are Claude Code sessions read from the claude-peers broker; tag the
|
|
96
|
+
// runtime so HQ's /agents board renders the runtime badge + filter (P1/P5).
|
|
97
|
+
runtime: 'claude-code',
|
|
98
|
+
summary: p.summary || null,
|
|
99
|
+
cwd: p.cwd || null,
|
|
100
|
+
project_id,
|
|
101
|
+
status: 'active',
|
|
102
|
+
started_at: p.registered_at || nowIso,
|
|
103
|
+
last_seen_at: nowIso,
|
|
104
|
+
ended_at: null,
|
|
105
|
+
// last_action_at = the broker's per-peer last_seen → HQ's ActivityLine renders
|
|
106
|
+
// a tool-call pulse from it. Richer self-report fields (tokens, current_file)
|
|
107
|
+
// are a follow-on (agent-side self-report; not daemon-observable).
|
|
108
|
+
meta: { last_action_at: p.last_seen || nowIso },
|
|
109
|
+
};
|
|
110
|
+
const { error } = await withRetryResult(() => client.from('agent_sessions').upsert(row, { onConflict: 'org_id,host,session_key' }), `presence.upsert ${p.id}`);
|
|
111
|
+
if (error)
|
|
112
|
+
log(`Presence: upsert ${p.id} failed: ${error.message}`);
|
|
113
|
+
}
|
|
114
|
+
// Stale-sweep: sessions that stopped heartbeating (broker dropped them, or daemon
|
|
115
|
+
// missed beats). idle first, then ended (ended uses status<>'ended' so it also
|
|
116
|
+
// catches idle rows past the longer cutoff).
|
|
117
|
+
const idleCut = new Date(nowMs - IDLE_AFTER_MS).toISOString();
|
|
118
|
+
const endedCut = new Date(nowMs - ENDED_AFTER_MS).toISOString();
|
|
119
|
+
await client.from('agent_sessions').update({ status: 'idle' })
|
|
120
|
+
.eq('org_id', ORG_ID).eq('status', 'active').lt('last_seen_at', idleCut);
|
|
121
|
+
await client.from('agent_sessions').update({ status: 'ended', ended_at: nowIso })
|
|
122
|
+
.eq('org_id', ORG_ID).neq('status', 'ended').lt('last_seen_at', endedCut);
|
|
123
|
+
}
|
|
124
|
+
// ---------------------------------------------------------------------------
|
|
125
|
+
// Write-time presence-field belt (NON-encoding) — co-designed with decibel-hq.
|
|
126
|
+
// ---------------------------------------------------------------------------
|
|
127
|
+
// HQ's /agents board already escapes these at render (React JSX text children),
|
|
128
|
+
// so the daemon MUST NOT HTML-encode here — that would double-escape and corrupt
|
|
129
|
+
// legitimate data (a real summary like "fix <Button> when a < b"). The correct
|
|
130
|
+
// write-time defense-in-depth is non-encoding: cap length + strip control chars /
|
|
131
|
+
// null bytes (preserving \t\n\r) so the stored value stays faithful but bounded.
|
|
132
|
+
// Also closes the review's "no validation on meta/result blobs" finding.
|
|
133
|
+
const FIELD_CAPS = { agent: 200, summary: 500, cwd: 1024 };
|
|
134
|
+
const META_VALUE_CAP = 1000;
|
|
135
|
+
const META_MAX_BYTES = 4096;
|
|
136
|
+
// C0 controls (U+0000..U+001F) + DEL (U+007F), EXCEPT tab/newline/carriage-return.
|
|
137
|
+
// eslint-disable-next-line no-control-regex
|
|
138
|
+
const CONTROL_CHARS = /[\u0000-\u0008\u000B\u000C\u000E-\u001F\u007F]/g;
|
|
139
|
+
/** Strip control chars/null bytes and cap length. Empty-after-clean → null. */
|
|
140
|
+
export function sanitizeText(s, maxLen) {
|
|
141
|
+
if (s == null)
|
|
142
|
+
return null;
|
|
143
|
+
const cleaned = String(s).replace(CONTROL_CHARS, '').slice(0, maxLen);
|
|
144
|
+
return cleaned.length ? cleaned : null;
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* Flatten meta to display-safe primitives: strings cleaned + capped, numbers/
|
|
148
|
+
* booleans/null kept, nested objects/arrays dropped (HQ typeof-guards numeric
|
|
149
|
+
* meta and renders strings as text). If the result still exceeds META_MAX_BYTES,
|
|
150
|
+
* drop it entirely — the caller re-adds the trusted last_action_at.
|
|
151
|
+
*/
|
|
152
|
+
export function sanitizeMeta(meta) {
|
|
153
|
+
if (!meta || typeof meta !== 'object')
|
|
154
|
+
return {};
|
|
155
|
+
const out = {};
|
|
156
|
+
for (const [k, v] of Object.entries(meta)) {
|
|
157
|
+
if (typeof v === 'string')
|
|
158
|
+
out[k] = v.replace(CONTROL_CHARS, '').slice(0, META_VALUE_CAP);
|
|
159
|
+
else if (typeof v === 'number' || typeof v === 'boolean' || v === null)
|
|
160
|
+
out[k] = v;
|
|
161
|
+
// nested objects/arrays intentionally dropped
|
|
162
|
+
}
|
|
163
|
+
if (Buffer.byteLength(JSON.stringify(out)) > META_MAX_BYTES)
|
|
164
|
+
return {};
|
|
165
|
+
return out;
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* Upsert a local-runtime session into hq.agent_sessions (register or heartbeat).
|
|
169
|
+
* Returns true on success, false if Supabase is unconfigured or the write failed.
|
|
170
|
+
* Reuses the presence writer's org config + cwd→project resolution.
|
|
171
|
+
*/
|
|
172
|
+
export async function writeLocalAgentSession(reg) {
|
|
173
|
+
const client = serviceClient();
|
|
174
|
+
if (!client)
|
|
175
|
+
return false;
|
|
176
|
+
if (!reg.session_key || !reg.runtime)
|
|
177
|
+
return false;
|
|
178
|
+
const host = resolveHost();
|
|
179
|
+
const nowIso = new Date().toISOString();
|
|
180
|
+
const project_id = await resolveProjectId(client, reg.cwd || '');
|
|
181
|
+
const ended = reg.status === 'ended';
|
|
182
|
+
const row = {
|
|
183
|
+
org_id: ORG_ID,
|
|
184
|
+
host,
|
|
185
|
+
session_key: reg.session_key,
|
|
186
|
+
runtime: reg.runtime,
|
|
187
|
+
// Non-encoding belt on caller-supplied display fields (store-raw / escape-at-
|
|
188
|
+
// render is HQ's job; we only cap length + strip control chars/null bytes).
|
|
189
|
+
agent: sanitizeText(reg.agent, FIELD_CAPS.agent),
|
|
190
|
+
summary: sanitizeText(reg.summary, FIELD_CAPS.summary),
|
|
191
|
+
cwd: sanitizeText(reg.cwd, FIELD_CAPS.cwd),
|
|
192
|
+
project_id,
|
|
193
|
+
status: ended ? 'ended' : 'active',
|
|
194
|
+
started_at: nowIso,
|
|
195
|
+
last_seen_at: nowIso,
|
|
196
|
+
ended_at: ended ? nowIso : null,
|
|
197
|
+
// Default last_action_at to now; a self-reporting SDK may override it via meta
|
|
198
|
+
// (intended richer signal — HQ reads last_seen_at, not this, for liveness).
|
|
199
|
+
meta: { last_action_at: nowIso, ...sanitizeMeta(reg.meta) },
|
|
200
|
+
};
|
|
201
|
+
// started_at only matters on first insert; onConflict updates the rest. We let it
|
|
202
|
+
// re-send started_at — harmless on heartbeat since HQ reads last_seen_at for liveness.
|
|
203
|
+
const { error } = await withRetryResult(() => client.from('agent_sessions').upsert(row, { onConflict: 'org_id,host,session_key' }), `presence.local-register ${reg.session_key}`);
|
|
204
|
+
if (error) {
|
|
205
|
+
log(`Presence: local register ${reg.session_key} (${reg.runtime}) failed: ${error.message}`);
|
|
206
|
+
return false;
|
|
207
|
+
}
|
|
208
|
+
return true;
|
|
209
|
+
}
|
|
210
|
+
/** Start the presence writer loop. Returns a stop function. No-ops if Supabase unconfigured. */
|
|
211
|
+
export function startPresenceWriter() {
|
|
212
|
+
const client = serviceClient();
|
|
213
|
+
if (!client) {
|
|
214
|
+
log('Presence: SUPABASE_URL/SERVICE_KEY not set — agent-presence writer disabled.');
|
|
215
|
+
return () => { };
|
|
216
|
+
}
|
|
217
|
+
log(`Presence: writer started (30s heartbeat → hq.agent_sessions, org ${ORG_ID}).`);
|
|
218
|
+
const run = () => {
|
|
219
|
+
tick(client).catch((e) => log(`Presence: tick error: ${e instanceof Error ? e.message : String(e)}`));
|
|
220
|
+
};
|
|
221
|
+
run();
|
|
222
|
+
const iv = setInterval(run, HEARTBEAT_MS);
|
|
223
|
+
if (typeof iv.unref === 'function')
|
|
224
|
+
iv.unref();
|
|
225
|
+
return () => clearInterval(iv);
|
|
226
|
+
}
|
|
227
|
+
//# sourceMappingURL=agentPresence.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agentPresence.js","sourceRoot":"","sources":["../src/agentPresence.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
export type JobStatus = 'queued' | 'claimed' | 'running' | 'done' | 'cancelled' | 'failed';
|
|
2
|
+
export interface AgenticJob {
|
|
3
|
+
id: string;
|
|
4
|
+
project_id: string;
|
|
5
|
+
prompt: string;
|
|
6
|
+
status: JobStatus;
|
|
7
|
+
claimed_by?: string;
|
|
8
|
+
claimed_at?: string;
|
|
9
|
+
completed_at?: string;
|
|
10
|
+
result?: {
|
|
11
|
+
output?: string;
|
|
12
|
+
files_changed?: string[];
|
|
13
|
+
};
|
|
14
|
+
created_at: string;
|
|
15
|
+
created_by?: string;
|
|
16
|
+
[key: string]: unknown;
|
|
17
|
+
}
|
|
18
|
+
export interface EnqueueJobInput {
|
|
19
|
+
projectId: string;
|
|
20
|
+
prompt: string;
|
|
21
|
+
createdBy?: string;
|
|
22
|
+
}
|
|
23
|
+
export interface EnqueueJobOutput {
|
|
24
|
+
jobId: string;
|
|
25
|
+
queuePosition: number;
|
|
26
|
+
filePath: string;
|
|
27
|
+
}
|
|
28
|
+
export interface CancelJobInput {
|
|
29
|
+
projectId: string;
|
|
30
|
+
jobId: string;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* List all jobs for a project. Returns oldest-first (creation order). Reads
|
|
34
|
+
* from both .decibel/ and decibel/ paths, deduplicating by id.
|
|
35
|
+
*/
|
|
36
|
+
export declare function listJobs(projectId: string): Promise<AgenticJob[]>;
|
|
37
|
+
/**
|
|
38
|
+
* Enqueue a new dispatch job. Allocates the next JOB-NNNN id, writes the
|
|
39
|
+
* YAML file, and returns the id + queue position (number of active jobs
|
|
40
|
+
* ahead of this one, inclusive).
|
|
41
|
+
*/
|
|
42
|
+
export declare function enqueueJob(input: EnqueueJobInput): Promise<EnqueueJobOutput>;
|
|
43
|
+
/**
|
|
44
|
+
* Cancel a queued / claimed job. No-op if the job is already terminal
|
|
45
|
+
* (done / cancelled / failed). Marks status: cancelled and stamps
|
|
46
|
+
* completed_at.
|
|
47
|
+
*/
|
|
48
|
+
export declare function cancelJob(input: CancelJobInput): Promise<AgenticJob>;
|
|
49
|
+
//# sourceMappingURL=agenticJobs.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agenticJobs.d.ts","sourceRoot":"","sources":["../src/agenticJobs.ts"],"names":[],"mappings":"AAqBA,MAAM,MAAM,SAAS,GACjB,QAAQ,GACR,SAAS,GACT,SAAS,GACT,MAAM,GACN,WAAW,GACX,QAAQ,CAAC;AAEb,MAAM,WAAW,UAAU;IACzB,EAAE,EAAE,MAAM,CAAC;IACX,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,SAAS,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,MAAM,CAAC,EAAE;QACP,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;KAC1B,CAAC;IACF,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;IAEpB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED,MAAM,WAAW,eAAe;IAC9B,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,MAAM,CAAC;IACd,aAAa,EAAE,MAAM,CAAC;IACtB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,cAAc;IAC7B,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;CACf;AA2FD;;;GAGG;AACH,wBAAsB,QAAQ,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC,CAoBvE;AAED;;;;GAIG;AACH,wBAAsB,UAAU,CAAC,KAAK,EAAE,eAAe,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAsClF;AAED;;;;GAIG;AACH,wBAAsB,SAAS,CAAC,KAAK,EAAE,cAAc,GAAG,OAAO,CAAC,UAAU,CAAC,CA6B1E"}
|