@jungjaehoon/mama-os 0.29.1 → 0.30.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/agent/agent-loop.d.ts +1 -12
- package/dist/agent/agent-loop.d.ts.map +1 -1
- package/dist/agent/agent-loop.js +6 -21
- package/dist/agent/agent-loop.js.map +1 -1
- package/dist/agent/code-act/constants.d.ts.map +1 -1
- package/dist/agent/code-act/constants.js +2 -4
- package/dist/agent/code-act/constants.js.map +1 -1
- package/dist/agent/code-act/host-bridge.d.ts.map +1 -1
- package/dist/agent/code-act/host-bridge.js +1 -290
- package/dist/agent/code-act/host-bridge.js.map +1 -1
- package/dist/agent/code-act/types.d.ts +1 -1
- package/dist/agent/code-act/types.d.ts.map +1 -1
- package/dist/agent/gateway-tool-executor.d.ts +1 -124
- package/dist/agent/gateway-tool-executor.d.ts.map +1 -1
- package/dist/agent/gateway-tool-executor.js +18 -1163
- package/dist/agent/gateway-tool-executor.js.map +1 -1
- package/dist/agent/gateway-tools.md +0 -38
- package/dist/agent/os-agent-capabilities.md +0 -14
- package/dist/agent/tool-registry.d.ts +1 -1
- package/dist/agent/tool-registry.d.ts.map +1 -1
- package/dist/agent/tool-registry.js +0 -183
- package/dist/agent/tool-registry.js.map +1 -1
- package/dist/agent/types.d.ts +2 -110
- package/dist/agent/types.d.ts.map +1 -1
- package/dist/agent/types.js.map +1 -1
- package/dist/api/graph-api-types.d.ts +0 -25
- package/dist/api/graph-api-types.d.ts.map +1 -1
- package/dist/api/graph-api.d.ts.map +1 -1
- package/dist/api/graph-api.js +0 -50
- package/dist/api/graph-api.js.map +1 -1
- package/dist/cli/commands/start.d.ts +18 -0
- package/dist/cli/commands/start.d.ts.map +1 -1
- package/dist/cli/commands/start.js +180 -42
- package/dist/cli/commands/start.js.map +1 -1
- package/dist/cli/config/types.d.ts +21 -0
- package/dist/cli/config/types.d.ts.map +1 -1
- package/dist/cli/config/types.js +7 -0
- package/dist/cli/config/types.js.map +1 -1
- package/dist/cli/runtime/api-routes-init.d.ts.map +1 -1
- package/dist/cli/runtime/api-routes-init.js +0 -3
- package/dist/cli/runtime/api-routes-init.js.map +1 -1
- package/dist/cli/runtime/gateway-wiring.d.ts +1 -1
- package/dist/cli/runtime/gateway-wiring.js +1 -1
- package/dist/gateways/discord.d.ts.map +1 -1
- package/dist/gateways/discord.js +0 -8
- package/dist/gateways/discord.js.map +1 -1
- package/dist/gateways/message-router.d.ts +13 -0
- package/dist/gateways/message-router.d.ts.map +1 -1
- package/dist/gateways/message-router.js +36 -0
- package/dist/gateways/message-router.js.map +1 -1
- package/dist/multi-agent/agent-process-manager.d.ts.map +1 -1
- package/dist/multi-agent/agent-process-manager.js +4 -3
- package/dist/multi-agent/agent-process-manager.js.map +1 -1
- package/dist/multi-agent/tool-permission-manager.d.ts +0 -5
- package/dist/multi-agent/tool-permission-manager.d.ts.map +1 -1
- package/dist/multi-agent/tool-permission-manager.js +0 -40
- package/dist/multi-agent/tool-permission-manager.js.map +1 -1
- package/dist/operator/board-reground.d.ts +19 -0
- package/dist/operator/board-reground.d.ts.map +1 -0
- package/dist/operator/board-reground.js +31 -0
- package/dist/operator/board-reground.js.map +1 -0
- package/dist/operator/conductor-inbox.d.ts +73 -0
- package/dist/operator/conductor-inbox.d.ts.map +1 -0
- package/dist/operator/conductor-inbox.js +184 -0
- package/dist/operator/conductor-inbox.js.map +1 -0
- package/dist/operator/conductor-session.d.ts +55 -0
- package/dist/operator/conductor-session.d.ts.map +1 -0
- package/dist/operator/conductor-session.js +110 -0
- package/dist/operator/conductor-session.js.map +1 -0
- package/dist/operator/conductor.d.ts +68 -0
- package/dist/operator/conductor.d.ts.map +1 -0
- package/dist/operator/conductor.js +84 -0
- package/dist/operator/conductor.js.map +1 -0
- package/dist/operator/operator-trigger-loop.d.ts +13 -0
- package/dist/operator/operator-trigger-loop.d.ts.map +1 -1
- package/dist/operator/operator-trigger-loop.js +39 -8
- package/dist/operator/operator-trigger-loop.js.map +1 -1
- package/dist/operator/report-run.d.ts +8 -2
- package/dist/operator/report-run.d.ts.map +1 -1
- package/dist/operator/report-run.js +9 -9
- package/dist/operator/report-run.js.map +1 -1
- package/dist/operator/trigger-author.d.ts +0 -1
- package/dist/operator/trigger-author.d.ts.map +1 -1
- package/dist/operator/trigger-author.js +24 -3
- package/dist/operator/trigger-author.js.map +1 -1
- package/dist/operator/workorder-consumer.d.ts +2 -0
- package/dist/operator/workorder-consumer.d.ts.map +1 -1
- package/dist/operator/workorder-consumer.js +57 -8
- package/dist/operator/workorder-consumer.js.map +1 -1
- package/package.json +1 -2
- package/public/viewer/src/utils/api.ts +0 -10
- package/scripts/backfill-channel-keys.ts +75 -17
- package/dist/multi-agent/conductor-persona.d.ts +0 -13
- package/dist/multi-agent/conductor-persona.d.ts.map +0 -1
- package/dist/multi-agent/conductor-persona.js +0 -157
- package/dist/multi-agent/conductor-persona.js.map +0 -1
- package/dist/tools/browser-tool.d.ts +0 -164
- package/dist/tools/browser-tool.d.ts.map +0 -1
- package/dist/tools/browser-tool.js +0 -315
- package/dist/tools/browser-tool.js.map +0 -1
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Durable conductor inbox.
|
|
3
|
+
*
|
|
4
|
+
* Written BEFORE the delta cursor commits (the trigger loop today commits the
|
|
5
|
+
* cursor and then invokes its callback, so a callback failure loses the batch
|
|
6
|
+
* forever - operator-trigger-loop.ts, "feed AFTER commit"). With this table
|
|
7
|
+
* the order inverts: enqueue -> commit. A crash between the two redelivers on
|
|
8
|
+
* the next drain, and per-event dedupe turns redelivery into a no-op.
|
|
9
|
+
*
|
|
10
|
+
* Claims are leases, not transfers: an acked row is done; an unacked claim
|
|
11
|
+
* older than the lease returns to pending via replayStale().
|
|
12
|
+
*
|
|
13
|
+
* `eventIds` and `lines` are INDEPENDENT fields, never zipped positionally:
|
|
14
|
+
* eventIds is the identity/cause set (the whole batch), lines is the bounded
|
|
15
|
+
* display excerpt - the same split the reconcile callback documents. Review
|
|
16
|
+
* caught the original positional pairing scrambling content for any batch
|
|
17
|
+
* larger than the display cap.
|
|
18
|
+
*/
|
|
19
|
+
import type { SQLiteDatabase } from '../sqlite.js';
|
|
20
|
+
export interface InboxBatch {
|
|
21
|
+
channelKey: string;
|
|
22
|
+
/** Identity + cause: EVERY event in the batch. */
|
|
23
|
+
eventIds: string[];
|
|
24
|
+
/** Bounded human-readable excerpt - display only, not paired with eventIds. */
|
|
25
|
+
lines: string[];
|
|
26
|
+
}
|
|
27
|
+
export interface InboxRow extends InboxBatch {
|
|
28
|
+
id: number;
|
|
29
|
+
status: 'pending' | 'claimed' | 'acked' | 'dead';
|
|
30
|
+
attempts: number;
|
|
31
|
+
}
|
|
32
|
+
export declare class ConductorInbox {
|
|
33
|
+
private readonly db;
|
|
34
|
+
private readonly stmtInsertEvent;
|
|
35
|
+
private readonly stmtInsertBatch;
|
|
36
|
+
private readonly stmtClaimSelect;
|
|
37
|
+
private readonly stmtClaimUpdate;
|
|
38
|
+
private readonly stmtAck;
|
|
39
|
+
private readonly stmtRetry;
|
|
40
|
+
private readonly stmtRetryStatus;
|
|
41
|
+
private readonly stmtPruneAcked;
|
|
42
|
+
private readonly stmtPrunePending;
|
|
43
|
+
private readonly stmtPruneEvents;
|
|
44
|
+
private readonly stmtReplay;
|
|
45
|
+
private readonly stmtDepth;
|
|
46
|
+
constructor(db: SQLiteDatabase);
|
|
47
|
+
private now;
|
|
48
|
+
/**
|
|
49
|
+
* Dedupe is PER EVENT, not per batch shape. A batch-boundary key fails on
|
|
50
|
+
* partial redelivery: [e1] enqueues, the cursor commit fails elsewhere, the
|
|
51
|
+
* next drain delivers [e1,e2] under a different boundary - and e1 runs
|
|
52
|
+
* twice. Seen event ids live in their own table; a batch with no unseen
|
|
53
|
+
* events is dropped, a batch with any unseen event is stored whole (its
|
|
54
|
+
* display lines may briefly re-show an already-seen event; identity never
|
|
55
|
+
* lies).
|
|
56
|
+
*/
|
|
57
|
+
enqueue(batch: InboxBatch): number | null;
|
|
58
|
+
claimNext(): InboxRow | null;
|
|
59
|
+
ack(id: number): void;
|
|
60
|
+
/**
|
|
61
|
+
* Return a claim to pending, or park it dead after MAX_ATTEMPTS. Returns
|
|
62
|
+
* the resulting status so the caller can be LOUD about a dead batch - a
|
|
63
|
+
* permanent loss must never be silent.
|
|
64
|
+
*/
|
|
65
|
+
retry(id: number, error: string): 'pending' | 'dead' | 'noop';
|
|
66
|
+
replayStale(olderThanMs: number, now?: number): number;
|
|
67
|
+
depth(): {
|
|
68
|
+
pending: number;
|
|
69
|
+
claimed: number;
|
|
70
|
+
dead: number;
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
//# sourceMappingURL=conductor-inbox.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"conductor-inbox.d.ts","sourceRoot":"","sources":["../../src/operator/conductor-inbox.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AACH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAsBnD,MAAM,WAAW,UAAU;IACzB,UAAU,EAAE,MAAM,CAAC;IACnB,kDAAkD;IAClD,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,+EAA+E;IAC/E,KAAK,EAAE,MAAM,EAAE,CAAC;CACjB;AAED,MAAM,WAAW,QAAS,SAAQ,UAAU;IAC1C,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,SAAS,GAAG,SAAS,GAAG,OAAO,GAAG,MAAM,CAAC;IACjD,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,qBAAa,cAAc;IAcb,OAAO,CAAC,QAAQ,CAAC,EAAE;IAb/B,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAC;IACjC,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAC;IACjC,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAC;IACjC,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAC;IACjC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC;IACzB,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAC;IAC3B,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAC;IACjC,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAC;IAChC,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAC;IAClC,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAC;IACjC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAC;IAC5B,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAC;gBAEE,EAAE,EAAE,cAAc;IA4E/C,OAAO,CAAC,GAAG;IAIX;;;;;;;;OAQG;IACH,OAAO,CAAC,KAAK,EAAE,UAAU,GAAG,MAAM,GAAG,IAAI;IA+BzC,SAAS,IAAI,QAAQ,GAAG,IAAI;IA2B5B,GAAG,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI;IAIrB;;;;OAIG;IACH,KAAK,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,GAAG,MAAM;IAS7D,WAAW,CAAC,WAAW,EAAE,MAAM,EAAE,GAAG,SAAa,GAAG,MAAM;IAW1D,KAAK,IAAI;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE;CAS5D"}
|
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ConductorInbox = void 0;
|
|
4
|
+
const MAX_ATTEMPTS = 5;
|
|
5
|
+
const ACKED_RETENTION_MS = 7 * 86_400_000;
|
|
6
|
+
/**
|
|
7
|
+
* Pending rows older than this park as dead: in shadow mode nothing acks, and
|
|
8
|
+
* an unbounded pending queue detonates as months of stale chat replayed at 8
|
|
9
|
+
* runs per 30s tick the day the owner flips the flag (review F4). 7 days of
|
|
10
|
+
* shadow data is the observation window; older batches are stale, not lost -
|
|
11
|
+
* dead rows stay visible in depth().
|
|
12
|
+
*/
|
|
13
|
+
const PENDING_RETENTION_MS = 7 * 86_400_000;
|
|
14
|
+
/**
|
|
15
|
+
* Dedupe horizon. Event ids must outlive their batch rows or a redelivery
|
|
16
|
+
* after batch pruning re-processes old events - but they cannot live forever
|
|
17
|
+
* either (one TEXT-PK row per event ever drained; review measured 30k+ rows
|
|
18
|
+
* in a single connector incident). 30 days is far wider than any redelivery
|
|
19
|
+
* gap the delta cursor can produce.
|
|
20
|
+
*/
|
|
21
|
+
const EVENT_RETENTION_MS = 30 * 86_400_000;
|
|
22
|
+
const SEEN_CHUNK = 500; // stay under SQLITE_MAX_VARIABLE_NUMBER
|
|
23
|
+
class ConductorInbox {
|
|
24
|
+
db;
|
|
25
|
+
stmtInsertEvent;
|
|
26
|
+
stmtInsertBatch;
|
|
27
|
+
stmtClaimSelect;
|
|
28
|
+
stmtClaimUpdate;
|
|
29
|
+
stmtAck;
|
|
30
|
+
stmtRetry;
|
|
31
|
+
stmtRetryStatus;
|
|
32
|
+
stmtPruneAcked;
|
|
33
|
+
stmtPrunePending;
|
|
34
|
+
stmtPruneEvents;
|
|
35
|
+
stmtReplay;
|
|
36
|
+
stmtDepth;
|
|
37
|
+
constructor(db) {
|
|
38
|
+
this.db = db;
|
|
39
|
+
this.db.exec(`
|
|
40
|
+
CREATE TABLE IF NOT EXISTS conductor_inbox (
|
|
41
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
42
|
+
channel_key TEXT NOT NULL,
|
|
43
|
+
event_ids_json TEXT NOT NULL,
|
|
44
|
+
lines_json TEXT NOT NULL,
|
|
45
|
+
status TEXT NOT NULL DEFAULT 'pending'
|
|
46
|
+
CHECK (status IN ('pending','claimed','acked','dead')),
|
|
47
|
+
attempts INTEGER NOT NULL DEFAULT 0,
|
|
48
|
+
last_error TEXT,
|
|
49
|
+
created_at INTEGER NOT NULL,
|
|
50
|
+
claimed_at INTEGER,
|
|
51
|
+
acked_at INTEGER
|
|
52
|
+
);
|
|
53
|
+
CREATE INDEX IF NOT EXISTS idx_conductor_inbox_status
|
|
54
|
+
ON conductor_inbox(status, id);
|
|
55
|
+
CREATE TABLE IF NOT EXISTS conductor_inbox_events (
|
|
56
|
+
event_id TEXT PRIMARY KEY,
|
|
57
|
+
seen_at INTEGER NOT NULL DEFAULT 0
|
|
58
|
+
);
|
|
59
|
+
CREATE INDEX IF NOT EXISTS idx_conductor_inbox_events_seen
|
|
60
|
+
ON conductor_inbox_events(seen_at);
|
|
61
|
+
`);
|
|
62
|
+
// Prepared once: enqueue runs per channel per drain tick and re-preparing
|
|
63
|
+
// statements per call was measurable on backfill drains.
|
|
64
|
+
this.stmtInsertEvent = this.db.prepare(`INSERT OR IGNORE INTO conductor_inbox_events (event_id, seen_at) VALUES (?, ?)`);
|
|
65
|
+
this.stmtInsertBatch = this.db.prepare(`INSERT INTO conductor_inbox (channel_key, event_ids_json, lines_json, created_at)
|
|
66
|
+
VALUES (?, ?, ?, ?)`);
|
|
67
|
+
this.stmtClaimSelect = this.db.prepare(`SELECT id, channel_key, event_ids_json, lines_json, attempts
|
|
68
|
+
FROM conductor_inbox WHERE status = 'pending' ORDER BY id ASC LIMIT 1`);
|
|
69
|
+
this.stmtClaimUpdate = this.db.prepare(`UPDATE conductor_inbox SET status = 'claimed', claimed_at = ?
|
|
70
|
+
WHERE id = ? AND status = 'pending'`);
|
|
71
|
+
this.stmtAck = this.db.prepare(`UPDATE conductor_inbox SET status = 'acked', acked_at = ? WHERE id = ?`);
|
|
72
|
+
this.stmtRetry = this.db.prepare(`UPDATE conductor_inbox
|
|
73
|
+
SET status = CASE WHEN attempts + 1 >= ${MAX_ATTEMPTS} THEN 'dead' ELSE 'pending' END,
|
|
74
|
+
attempts = attempts + 1, last_error = ?, claimed_at = NULL
|
|
75
|
+
WHERE id = ? AND status = 'claimed'`);
|
|
76
|
+
this.stmtRetryStatus = this.db.prepare(`SELECT status FROM conductor_inbox WHERE id = ?`);
|
|
77
|
+
this.stmtPruneAcked = this.db.prepare(`DELETE FROM conductor_inbox WHERE status = 'acked' AND acked_at <= ?`);
|
|
78
|
+
this.stmtPrunePending = this.db.prepare(`UPDATE conductor_inbox
|
|
79
|
+
SET status = 'dead', last_error = 'stale_pending_expired'
|
|
80
|
+
WHERE status = 'pending' AND created_at <= ?`);
|
|
81
|
+
this.stmtPruneEvents = this.db.prepare(`DELETE FROM conductor_inbox_events WHERE seen_at <= ?`);
|
|
82
|
+
// Same poison cap as retry(): a claim that expires its lease repeatedly
|
|
83
|
+
// (hung run, daemon death mid-flight) must park as dead too, not re-pend
|
|
84
|
+
// forever at the head of the queue (review F8).
|
|
85
|
+
this.stmtReplay = this.db.prepare(`UPDATE conductor_inbox
|
|
86
|
+
SET status = CASE WHEN attempts + 1 >= ${MAX_ATTEMPTS} THEN 'dead' ELSE 'pending' END,
|
|
87
|
+
attempts = attempts + 1, claimed_at = NULL
|
|
88
|
+
WHERE status = 'claimed' AND COALESCE(claimed_at, 0) <= ?`);
|
|
89
|
+
// Grouped on the (status, id) index; never scans the acked bulk.
|
|
90
|
+
this.stmtDepth = this.db.prepare(`SELECT status, COUNT(*) AS n FROM conductor_inbox
|
|
91
|
+
WHERE status IN ('pending','claimed','dead') GROUP BY status`);
|
|
92
|
+
}
|
|
93
|
+
now() {
|
|
94
|
+
return Date.now();
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Dedupe is PER EVENT, not per batch shape. A batch-boundary key fails on
|
|
98
|
+
* partial redelivery: [e1] enqueues, the cursor commit fails elsewhere, the
|
|
99
|
+
* next drain delivers [e1,e2] under a different boundary - and e1 runs
|
|
100
|
+
* twice. Seen event ids live in their own table; a batch with no unseen
|
|
101
|
+
* events is dropped, a batch with any unseen event is stored whole (its
|
|
102
|
+
* display lines may briefly re-show an already-seen event; identity never
|
|
103
|
+
* lies).
|
|
104
|
+
*/
|
|
105
|
+
enqueue(batch) {
|
|
106
|
+
const seenIds = new Set();
|
|
107
|
+
for (let i = 0; i < batch.eventIds.length; i += SEEN_CHUNK) {
|
|
108
|
+
const chunk = batch.eventIds.slice(i, i + SEEN_CHUNK);
|
|
109
|
+
const rows = this.db
|
|
110
|
+
.prepare(`SELECT event_id FROM conductor_inbox_events WHERE event_id IN (${chunk
|
|
111
|
+
.map(() => '?')
|
|
112
|
+
.join(',')})`)
|
|
113
|
+
.all(...chunk);
|
|
114
|
+
for (const row of rows)
|
|
115
|
+
seenIds.add(row.event_id);
|
|
116
|
+
}
|
|
117
|
+
const fresh = batch.eventIds.filter((id) => !seenIds.has(id));
|
|
118
|
+
if (fresh.length === 0) {
|
|
119
|
+
return null; // fully redelivered - already durable
|
|
120
|
+
}
|
|
121
|
+
const run = this.db.transaction(() => {
|
|
122
|
+
const now = this.now();
|
|
123
|
+
for (const id of fresh)
|
|
124
|
+
this.stmtInsertEvent.run(id, now);
|
|
125
|
+
return this.stmtInsertBatch.run(batch.channelKey, JSON.stringify(fresh), JSON.stringify(batch.lines), now);
|
|
126
|
+
});
|
|
127
|
+
return Number(run().lastInsertRowid);
|
|
128
|
+
}
|
|
129
|
+
claimNext() {
|
|
130
|
+
const row = this.stmtClaimSelect.get();
|
|
131
|
+
if (!row) {
|
|
132
|
+
return null;
|
|
133
|
+
}
|
|
134
|
+
const claimed = this.stmtClaimUpdate.run(this.now(), row.id);
|
|
135
|
+
if (claimed.changes !== 1) {
|
|
136
|
+
return null; // lost a race; caller just tries again next tick
|
|
137
|
+
}
|
|
138
|
+
return {
|
|
139
|
+
id: row.id,
|
|
140
|
+
channelKey: row.channel_key,
|
|
141
|
+
eventIds: JSON.parse(row.event_ids_json),
|
|
142
|
+
lines: JSON.parse(row.lines_json),
|
|
143
|
+
status: 'claimed',
|
|
144
|
+
attempts: row.attempts,
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
ack(id) {
|
|
148
|
+
this.stmtAck.run(this.now(), id);
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* Return a claim to pending, or park it dead after MAX_ATTEMPTS. Returns
|
|
152
|
+
* the resulting status so the caller can be LOUD about a dead batch - a
|
|
153
|
+
* permanent loss must never be silent.
|
|
154
|
+
*/
|
|
155
|
+
retry(id, error) {
|
|
156
|
+
const result = this.stmtRetry.run(error.slice(0, 500), id);
|
|
157
|
+
if (result.changes !== 1) {
|
|
158
|
+
return 'noop'; // replayStale already flipped it
|
|
159
|
+
}
|
|
160
|
+
const row = this.stmtRetryStatus.get(id);
|
|
161
|
+
return row?.status === 'dead' ? 'dead' : 'pending';
|
|
162
|
+
}
|
|
163
|
+
replayStale(olderThanMs, now = this.now()) {
|
|
164
|
+
// Housekeeping rides along: acked rows age out, stale pending rows park
|
|
165
|
+
// as dead (visible, bounded), and the dedupe table keeps a wide but
|
|
166
|
+
// finite horizon - no table here grows without bound.
|
|
167
|
+
this.stmtPruneAcked.run(now - ACKED_RETENTION_MS);
|
|
168
|
+
this.stmtPrunePending.run(now - PENDING_RETENTION_MS);
|
|
169
|
+
this.stmtPruneEvents.run(now - EVENT_RETENTION_MS);
|
|
170
|
+
const result = this.stmtReplay.run(now - olderThanMs);
|
|
171
|
+
return result.changes;
|
|
172
|
+
}
|
|
173
|
+
depth() {
|
|
174
|
+
const rows = this.stmtDepth.all();
|
|
175
|
+
const byStatus = new Map(rows.map((row) => [row.status, row.n]));
|
|
176
|
+
return {
|
|
177
|
+
pending: byStatus.get('pending') ?? 0,
|
|
178
|
+
claimed: byStatus.get('claimed') ?? 0,
|
|
179
|
+
dead: byStatus.get('dead') ?? 0,
|
|
180
|
+
};
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
exports.ConductorInbox = ConductorInbox;
|
|
184
|
+
//# sourceMappingURL=conductor-inbox.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"conductor-inbox.js","sourceRoot":"","sources":["../../src/operator/conductor-inbox.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
export declare const CONDUCTOR_SOURCE = "conductor";
|
|
2
|
+
export declare const CONDUCTOR_CHANNEL_ID = "conductor";
|
|
3
|
+
export declare const CONDUCTOR_SESSION_KEY = "conductor:main";
|
|
4
|
+
/** Pool identity: agent-loop derives it from (source, channelId). */
|
|
5
|
+
export declare const CONDUCTOR_POOL_KEY: string;
|
|
6
|
+
export interface ConductorSessionPolicy {
|
|
7
|
+
maxAgeMs: number;
|
|
8
|
+
maxTurns: number;
|
|
9
|
+
maxTokens: number;
|
|
10
|
+
/**
|
|
11
|
+
* Treat the session as expired after this much idle time. Must stay BELOW
|
|
12
|
+
* the pool's own sessionTimeoutMs (30min default): the pool silently drops
|
|
13
|
+
* idle entries, and a pool-expired session would otherwise get a warm turn
|
|
14
|
+
* with no re-ground (review F11). Recycling first keeps the invariant.
|
|
15
|
+
*/
|
|
16
|
+
idleExpiryMs: number;
|
|
17
|
+
}
|
|
18
|
+
interface PoolLike {
|
|
19
|
+
getTokenUsage(key: string): number;
|
|
20
|
+
}
|
|
21
|
+
export declare class ConductorSession {
|
|
22
|
+
private readonly pool;
|
|
23
|
+
private readonly now;
|
|
24
|
+
private readonly policy;
|
|
25
|
+
private bornAt;
|
|
26
|
+
private turns;
|
|
27
|
+
private lastRunAt;
|
|
28
|
+
private suspicion;
|
|
29
|
+
private regroundDue;
|
|
30
|
+
constructor(pool: PoolLike, policy?: Partial<ConductorSessionPolicy>, now?: () => number);
|
|
31
|
+
noteTurn(): void;
|
|
32
|
+
/**
|
|
33
|
+
* Force a recycle on the next tick. No production detector calls this yet -
|
|
34
|
+
* wiring one (denied-tool patterns, instruction-shaped batch lines) is named
|
|
35
|
+
* S2 work. The recycle path itself is pinned by tests so the hook is live
|
|
36
|
+
* the day a detector exists.
|
|
37
|
+
*/
|
|
38
|
+
flagSuspicion(reason: string): void;
|
|
39
|
+
shouldRecycle(): string | null;
|
|
40
|
+
recycle(reason: string): {
|
|
41
|
+
needsReground: true;
|
|
42
|
+
reason: string;
|
|
43
|
+
};
|
|
44
|
+
/** Read-only: does the next run owe the board a re-ground? */
|
|
45
|
+
needsReground(): boolean;
|
|
46
|
+
/**
|
|
47
|
+
* Called ONLY after a successful re-grounded run. A failed run must not
|
|
48
|
+
* consume the re-ground - the retry still owes the board its context
|
|
49
|
+
* (review: consume-before-run dropped the re-ground on the floor when the
|
|
50
|
+
* first run of a fresh session threw).
|
|
51
|
+
*/
|
|
52
|
+
markRegrounded(): void;
|
|
53
|
+
}
|
|
54
|
+
export {};
|
|
55
|
+
//# sourceMappingURL=conductor-session.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"conductor-session.d.ts","sourceRoot":"","sources":["../../src/operator/conductor-session.ts"],"names":[],"mappings":"AAkBA,eAAO,MAAM,gBAAgB,cAAc,CAAC;AAC5C,eAAO,MAAM,oBAAoB,cAAc,CAAC;AAMhD,eAAO,MAAM,qBAAqB,mBAAmB,CAAC;AACtD,qEAAqE;AACrE,eAAO,MAAM,kBAAkB,QAA0D,CAAC;AAE1F,MAAM,WAAW,sBAAsB;IACrC,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB;;;;;OAKG;IACH,YAAY,EAAE,MAAM,CAAC;CACtB;AAYD,UAAU,QAAQ;IAChB,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAAC;CACpC;AAED,qBAAa,gBAAgB;IASzB,OAAO,CAAC,QAAQ,CAAC,IAAI;IAErB,OAAO,CAAC,QAAQ,CAAC,GAAG;IAVtB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAyB;IAChD,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,KAAK,CAAK;IAClB,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,SAAS,CAAuB;IACxC,OAAO,CAAC,WAAW,CAAQ;gBAGR,IAAI,EAAE,QAAQ,EAC/B,MAAM,GAAE,OAAO,CAAC,sBAAsB,CAAM,EAC3B,GAAG,GAAE,MAAM,MAAyB;IAOvD,QAAQ,IAAI,IAAI;IAKhB;;;;;OAKG;IACH,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;IAInC,aAAa,IAAI,MAAM,GAAG,IAAI;IAmB9B,OAAO,CAAC,MAAM,EAAE,MAAM,GAAG;QAAE,aAAa,EAAE,IAAI,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE;IAShE,8DAA8D;IAC9D,aAAa,IAAI,OAAO;IAIxB;;;;;OAKG;IACH,cAAc,IAAI,IAAI;CAGvB"}
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ConductorSession = exports.CONDUCTOR_POOL_KEY = exports.CONDUCTOR_SESSION_KEY = exports.CONDUCTOR_CHANNEL_ID = exports.CONDUCTOR_SOURCE = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* Session lifecycle for the stateful conductor.
|
|
6
|
+
*
|
|
7
|
+
* Injected text persists in a long-lived buffer - that is the pivot's one new
|
|
8
|
+
* risk, and this class is the antidote: sessions are disposable on age, turn,
|
|
9
|
+
* token, idle, or suspicion budgets, and every fresh session (boot included)
|
|
10
|
+
* owes the board one re-ground before its first judgment. State survives
|
|
11
|
+
* because it lives in cards; the buffer never has to.
|
|
12
|
+
*
|
|
13
|
+
* Recycle does NOT touch the pool directly: agent-loop's `freshSession: true`
|
|
14
|
+
* is the one sanctioned reset path (it resets the pool entry AND marks the
|
|
15
|
+
* run new in the same place - review F5: `pool.resetSession()` alone swaps a
|
|
16
|
+
* UUID while the fallback branch overwrites `resumeSession` with the pool's
|
|
17
|
+
* own `isNew`, so the old buffer survives). The conductor passes
|
|
18
|
+
* `freshSession: true` whenever `needsReground()` is true.
|
|
19
|
+
*/
|
|
20
|
+
const session_pool_js_1 = require("../agent/session-pool.js");
|
|
21
|
+
exports.CONDUCTOR_SOURCE = 'conductor';
|
|
22
|
+
exports.CONDUCTOR_CHANNEL_ID = 'conductor';
|
|
23
|
+
// THREE keys, one identity. The LANE comes from the session key's FIRST
|
|
24
|
+
// `:` segment (agent-loop.ts resolveGlobalLaneForSession) - NOT from
|
|
25
|
+
// options.source. 'operator:conductor' would resolve to the GLOBAL operator
|
|
26
|
+
// lane where Stage-2 workers serialize (review F1), so the key must lead
|
|
27
|
+
// with a segment absent from SOURCE_GLOBAL_LANES.
|
|
28
|
+
exports.CONDUCTOR_SESSION_KEY = 'conductor:main'; // lane: session:conductor:main
|
|
29
|
+
/** Pool identity: agent-loop derives it from (source, channelId). */
|
|
30
|
+
exports.CONDUCTOR_POOL_KEY = (0, session_pool_js_1.buildChannelKey)(exports.CONDUCTOR_SOURCE, exports.CONDUCTOR_CHANNEL_ID);
|
|
31
|
+
const DEFAULTS = {
|
|
32
|
+
maxAgeMs: 6 * 60 * 60 * 1000,
|
|
33
|
+
maxTurns: 400,
|
|
34
|
+
// Below the pool's own 160k context threshold (session-pool.ts
|
|
35
|
+
// CONTEXT_THRESHOLD_TOKENS) so the conductor always recycles BEFORE the
|
|
36
|
+
// pool silently swaps the session out from under it.
|
|
37
|
+
maxTokens: 150_000,
|
|
38
|
+
idleExpiryMs: 25 * 60 * 1000,
|
|
39
|
+
};
|
|
40
|
+
class ConductorSession {
|
|
41
|
+
pool;
|
|
42
|
+
now;
|
|
43
|
+
policy;
|
|
44
|
+
bornAt;
|
|
45
|
+
turns = 0;
|
|
46
|
+
lastRunAt;
|
|
47
|
+
suspicion = null;
|
|
48
|
+
regroundDue = true; // boot = fresh session = restart recovery
|
|
49
|
+
constructor(pool, policy = {}, now = () => Date.now()) {
|
|
50
|
+
this.pool = pool;
|
|
51
|
+
this.now = now;
|
|
52
|
+
this.policy = { ...DEFAULTS, ...policy };
|
|
53
|
+
this.bornAt = this.now();
|
|
54
|
+
this.lastRunAt = this.bornAt;
|
|
55
|
+
}
|
|
56
|
+
noteTurn() {
|
|
57
|
+
this.turns += 1;
|
|
58
|
+
this.lastRunAt = this.now();
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Force a recycle on the next tick. No production detector calls this yet -
|
|
62
|
+
* wiring one (denied-tool patterns, instruction-shaped batch lines) is named
|
|
63
|
+
* S2 work. The recycle path itself is pinned by tests so the hook is live
|
|
64
|
+
* the day a detector exists.
|
|
65
|
+
*/
|
|
66
|
+
flagSuspicion(reason) {
|
|
67
|
+
this.suspicion = reason;
|
|
68
|
+
}
|
|
69
|
+
shouldRecycle() {
|
|
70
|
+
if (this.suspicion) {
|
|
71
|
+
return `suspicion: ${this.suspicion}`;
|
|
72
|
+
}
|
|
73
|
+
if (this.now() - this.bornAt > this.policy.maxAgeMs) {
|
|
74
|
+
return 'max_age';
|
|
75
|
+
}
|
|
76
|
+
if (this.now() - this.lastRunAt > this.policy.idleExpiryMs) {
|
|
77
|
+
return 'idle_expiry';
|
|
78
|
+
}
|
|
79
|
+
if (this.turns >= this.policy.maxTurns) {
|
|
80
|
+
return 'max_turns';
|
|
81
|
+
}
|
|
82
|
+
if (this.pool.getTokenUsage(exports.CONDUCTOR_POOL_KEY) >= this.policy.maxTokens) {
|
|
83
|
+
return 'max_tokens';
|
|
84
|
+
}
|
|
85
|
+
return null;
|
|
86
|
+
}
|
|
87
|
+
recycle(reason) {
|
|
88
|
+
this.bornAt = this.now();
|
|
89
|
+
this.lastRunAt = this.bornAt;
|
|
90
|
+
this.turns = 0;
|
|
91
|
+
this.suspicion = null;
|
|
92
|
+
this.regroundDue = true;
|
|
93
|
+
return { needsReground: true, reason };
|
|
94
|
+
}
|
|
95
|
+
/** Read-only: does the next run owe the board a re-ground? */
|
|
96
|
+
needsReground() {
|
|
97
|
+
return this.regroundDue;
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Called ONLY after a successful re-grounded run. A failed run must not
|
|
101
|
+
* consume the re-ground - the retry still owes the board its context
|
|
102
|
+
* (review: consume-before-run dropped the re-ground on the floor when the
|
|
103
|
+
* first run of a fresh session threw).
|
|
104
|
+
*/
|
|
105
|
+
markRegrounded() {
|
|
106
|
+
this.regroundDue = false;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
exports.ConductorSession = ConductorSession;
|
|
110
|
+
//# sourceMappingURL=conductor-session.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"conductor-session.js","sourceRoot":"","sources":["../../src/operator/conductor-session.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The stateful conductor: consumes the durable inbox, judges each batch in
|
|
3
|
+
* ONE long-lived session, and delegates by COMMITTING work orders only - it
|
|
4
|
+
* never awaits a worker from its model turn.
|
|
5
|
+
*
|
|
6
|
+
* Lane: the session key 'conductor:main' leads with a segment absent from
|
|
7
|
+
* SOURCE_GLOBAL_LANES, so runs land on session:conductor:main - fully
|
|
8
|
+
* separate from the global operator lane where Stage-2 workers serialize
|
|
9
|
+
* (worker-run.ts documents the deadlock seal). The lane is derived from the
|
|
10
|
+
* session key's FIRST segment, not options.source (agent-loop.ts
|
|
11
|
+
* resolveGlobalLaneForSession) - tests pin this axis.
|
|
12
|
+
*
|
|
13
|
+
* Trust boundary: batch lines are connector-channel text - attacker-authored
|
|
14
|
+
* by definition, and this session's buffer is long-lived. Every batch enters
|
|
15
|
+
* the prompt through wrapUntrustedContent (the spec's standing "wrapping
|
|
16
|
+
* remains the first line"), under an owner-authored framing instruction.
|
|
17
|
+
*/
|
|
18
|
+
import type { ConductorInbox } from './conductor-inbox.js';
|
|
19
|
+
import { type ConductorSession } from './conductor-session.js';
|
|
20
|
+
import type { AgentContext } from '../agent/types.js';
|
|
21
|
+
import type { Envelope } from '../envelope/types.js';
|
|
22
|
+
interface RunnerLike {
|
|
23
|
+
run(prompt: string, options?: {
|
|
24
|
+
sessionKey?: string;
|
|
25
|
+
source?: string;
|
|
26
|
+
channelId?: string;
|
|
27
|
+
resumeSession?: boolean;
|
|
28
|
+
freshSession?: boolean;
|
|
29
|
+
agentContext?: AgentContext;
|
|
30
|
+
envelope?: Envelope;
|
|
31
|
+
}): Promise<{
|
|
32
|
+
response: string;
|
|
33
|
+
}>;
|
|
34
|
+
}
|
|
35
|
+
export declare class Conductor {
|
|
36
|
+
private readonly deps;
|
|
37
|
+
private readonly leaseMs;
|
|
38
|
+
private readonly maxBatchesPerTick;
|
|
39
|
+
constructor(deps: {
|
|
40
|
+
inbox: ConductorInbox;
|
|
41
|
+
session: ConductorSession;
|
|
42
|
+
runner: RunnerLike;
|
|
43
|
+
reground: () => string;
|
|
44
|
+
/**
|
|
45
|
+
* Per-run scoped authority, mirroring the report lane: without an
|
|
46
|
+
* agentContext the executor's permission checks take their documented
|
|
47
|
+
* "no context - allow all" branch, and without an envelope every
|
|
48
|
+
* model_tool call dies 'envelope_missing' while the run still resolves
|
|
49
|
+
* and acks (review F2). Both are REQUIRED wiring in start.ts; optional
|
|
50
|
+
* here only so unit tests can run the loop without the full boot.
|
|
51
|
+
*/
|
|
52
|
+
agentContext?: AgentContext;
|
|
53
|
+
issueEnvelope?: () => Promise<Envelope | null>;
|
|
54
|
+
log?: (line: string) => void;
|
|
55
|
+
leaseMs?: number;
|
|
56
|
+
/** Burst backpressure budget: batches processed per tick before yielding. */
|
|
57
|
+
maxBatchesPerTick?: number;
|
|
58
|
+
});
|
|
59
|
+
tick(): Promise<'idle' | 'processed' | 'failed'>;
|
|
60
|
+
/**
|
|
61
|
+
* A growing inbox must be loud - silence is how backlogs hide. Runs on the
|
|
62
|
+
* failure path too: a batch stuck in retries (attempts 1-4) is exactly when
|
|
63
|
+
* the backlog grows unattended (review).
|
|
64
|
+
*/
|
|
65
|
+
private logDepth;
|
|
66
|
+
}
|
|
67
|
+
export {};
|
|
68
|
+
//# sourceMappingURL=conductor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"conductor.d.ts","sourceRoot":"","sources":["../../src/operator/conductor.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AACH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAC3D,OAAO,EACL,KAAK,gBAAgB,EAItB,MAAM,wBAAwB,CAAC;AAKhC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACtD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAErD,UAAU,UAAU;IAClB,GAAG,CACD,MAAM,EAAE,MAAM,EACd,OAAO,CAAC,EAAE;QACR,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,aAAa,CAAC,EAAE,OAAO,CAAC;QACxB,YAAY,CAAC,EAAE,OAAO,CAAC;QACvB,YAAY,CAAC,EAAE,YAAY,CAAC;QAC5B,QAAQ,CAAC,EAAE,QAAQ,CAAC;KACrB,GACA,OAAO,CAAC;QAAE,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CAClC;AAED,qBAAa,SAAS;IAKlB,OAAO,CAAC,QAAQ,CAAC,IAAI;IAJvB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAS;gBAGxB,IAAI,EAAE;QACrB,KAAK,EAAE,cAAc,CAAC;QACtB,OAAO,EAAE,gBAAgB,CAAC;QAC1B,MAAM,EAAE,UAAU,CAAC;QACnB,QAAQ,EAAE,MAAM,MAAM,CAAC;QACvB;;;;;;;WAOG;QACH,YAAY,CAAC,EAAE,YAAY,CAAC;QAC5B,aAAa,CAAC,EAAE,MAAM,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC,CAAC;QAC/C,GAAG,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;QAC7B,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,6EAA6E;QAC7E,iBAAiB,CAAC,EAAE,MAAM,CAAC;KAC5B;IAMG,IAAI,IAAI,OAAO,CAAC,MAAM,GAAG,WAAW,GAAG,QAAQ,CAAC;IAuEtD;;;;OAIG;IACH,OAAO,CAAC,QAAQ;CAQjB"}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Conductor = void 0;
|
|
4
|
+
const conductor_session_js_1 = require("./conductor-session.js");
|
|
5
|
+
const untrusted_content_js_1 = require("../utils/untrusted-content.js");
|
|
6
|
+
class Conductor {
|
|
7
|
+
deps;
|
|
8
|
+
leaseMs;
|
|
9
|
+
maxBatchesPerTick;
|
|
10
|
+
constructor(deps) {
|
|
11
|
+
this.deps = deps;
|
|
12
|
+
this.leaseMs = deps.leaseMs ?? 10 * 60_000;
|
|
13
|
+
this.maxBatchesPerTick = deps.maxBatchesPerTick ?? 8;
|
|
14
|
+
}
|
|
15
|
+
async tick() {
|
|
16
|
+
const replayed = this.deps.inbox.replayStale(this.leaseMs);
|
|
17
|
+
if (replayed > 0) {
|
|
18
|
+
this.deps.log?.(`[conductor] replayed ${replayed} stale claim(s)`);
|
|
19
|
+
}
|
|
20
|
+
const reason = this.deps.session.shouldRecycle();
|
|
21
|
+
if (reason) {
|
|
22
|
+
this.deps.session.recycle(reason);
|
|
23
|
+
this.deps.log?.(`[conductor] session recycled: ${reason}`);
|
|
24
|
+
}
|
|
25
|
+
let processed = 0;
|
|
26
|
+
for (; processed < this.maxBatchesPerTick;) {
|
|
27
|
+
const batch = this.deps.inbox.claimNext();
|
|
28
|
+
if (!batch) {
|
|
29
|
+
break;
|
|
30
|
+
}
|
|
31
|
+
const fresh = this.deps.session.needsReground();
|
|
32
|
+
const parts = [];
|
|
33
|
+
if (fresh) {
|
|
34
|
+
parts.push(this.deps.reground());
|
|
35
|
+
}
|
|
36
|
+
parts.push(untrusted_content_js_1.UNTRUSTED_EXTERNAL_EVIDENCE_INSTRUCTION, (0, untrusted_content_js_1.wrapUntrustedContent)(`channel:${batch.channelKey}`, batch.lines.join('\n')));
|
|
37
|
+
try {
|
|
38
|
+
// freshSession is the ONE sanctioned reset path: agent-loop resets the
|
|
39
|
+
// pool entry AND marks the run new together. resumeSession alone is
|
|
40
|
+
// overwritten by the pool's own isNew in the fallback branch, so it
|
|
41
|
+
// cannot express "start over" (review F5).
|
|
42
|
+
const envelope = (await this.deps.issueEnvelope?.()) ?? undefined;
|
|
43
|
+
await this.deps.runner.run(parts.join('\n'), {
|
|
44
|
+
sessionKey: conductor_session_js_1.CONDUCTOR_SESSION_KEY, // lane (first segment picks it)
|
|
45
|
+
source: conductor_session_js_1.CONDUCTOR_SOURCE, // pool key half 1
|
|
46
|
+
channelId: conductor_session_js_1.CONDUCTOR_CHANNEL_ID, // pool key half 2
|
|
47
|
+
...(fresh ? { freshSession: true } : { resumeSession: true }),
|
|
48
|
+
agentContext: this.deps.agentContext,
|
|
49
|
+
envelope,
|
|
50
|
+
});
|
|
51
|
+
this.deps.inbox.ack(batch.id);
|
|
52
|
+
this.deps.session.noteTurn();
|
|
53
|
+
if (fresh) {
|
|
54
|
+
this.deps.session.markRegrounded();
|
|
55
|
+
}
|
|
56
|
+
processed += 1;
|
|
57
|
+
}
|
|
58
|
+
catch (error) {
|
|
59
|
+
const outcome = this.deps.inbox.retry(batch.id, error instanceof Error ? error.message : String(error));
|
|
60
|
+
if (outcome === 'dead') {
|
|
61
|
+
// A dead batch is a permanent loss - it must never die quietly.
|
|
62
|
+
this.deps.log?.(`[conductor] batch ${batch.id} (${batch.channelKey}) parked DEAD after repeated failures: ${error instanceof Error ? error.message : String(error)}`);
|
|
63
|
+
}
|
|
64
|
+
this.logDepth(processed);
|
|
65
|
+
return 'failed';
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
this.logDepth(processed);
|
|
69
|
+
return processed > 0 ? 'processed' : 'idle';
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* A growing inbox must be loud - silence is how backlogs hide. Runs on the
|
|
73
|
+
* failure path too: a batch stuck in retries (attempts 1-4) is exactly when
|
|
74
|
+
* the backlog grows unattended (review).
|
|
75
|
+
*/
|
|
76
|
+
logDepth(processed) {
|
|
77
|
+
const depth = this.deps.inbox.depth();
|
|
78
|
+
if (depth.pending > 0 || depth.dead > 0) {
|
|
79
|
+
this.deps.log?.(`[conductor] tick budget spent: ${processed} processed, ${depth.pending} pending, ${depth.dead} dead`);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
exports.Conductor = Conductor;
|
|
84
|
+
//# sourceMappingURL=conductor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"conductor.js","sourceRoot":"","sources":["../../src/operator/conductor.ts"],"names":[],"mappings":"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"}
|
|
@@ -91,6 +91,19 @@ export interface TriggerLoopDeps {
|
|
|
91
91
|
* on this batch; carrying it is the difference between a fact and a claim.
|
|
92
92
|
*/
|
|
93
93
|
onChannelDelta?: (channelKey: string, lines: string[], eventIds: string[]) => void;
|
|
94
|
+
/**
|
|
95
|
+
* S1: durable conductor feed. Each per-channel batch is enqueued BEFORE
|
|
96
|
+
* `delta.commit()` - a crash between the two redelivers the events and the
|
|
97
|
+
* inbox's per-event dedupe absorbs the duplicate. Structural type, no import
|
|
98
|
+
* cycle. Absent -> no conductor leg.
|
|
99
|
+
*/
|
|
100
|
+
conductorInbox?: {
|
|
101
|
+
enqueue(batch: {
|
|
102
|
+
channelKey: string;
|
|
103
|
+
eventIds: string[];
|
|
104
|
+
lines: string[];
|
|
105
|
+
}): number | null;
|
|
106
|
+
};
|
|
94
107
|
/** Kagemusha dual output: FULL report also publishes the operator board slots. */
|
|
95
108
|
fullReportBoardLines?: string[];
|
|
96
109
|
/** Context carry (plan v6 S1-T4): persist the delivered FULL report text. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"operator-trigger-loop.d.ts","sourceRoot":"","sources":["../../src/operator/operator-trigger-loop.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"operator-trigger-loop.d.ts","sourceRoot":"","sources":["../../src/operator/operator-trigger-loop.ts"],"names":[],"mappings":"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"}
|