@cohortapp/agent-sdk 2.18.17 → 2.18.19
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.
|
@@ -421,3 +421,65 @@ export default {
|
|
|
421
421
|
firstReplyPlan,
|
|
422
422
|
stampFirstReplyPlan,
|
|
423
423
|
};
|
|
424
|
+
|
|
425
|
+
/**
|
|
426
|
+
* The AGENT STATUS NOTICE family — a seat narrating its own progress, failure
|
|
427
|
+
* or recovery to a room.
|
|
428
|
+
*
|
|
429
|
+
* ── WHY THIS EXISTS, AND WHY IT IS SEPARATE FROM THE RETIRED REGISTER ───────
|
|
430
|
+
*
|
|
431
|
+
* The register above answers "may this seat SEND this line?". This answers a
|
|
432
|
+
* different question: "is this line, arriving from ANOTHER seat, a piece of
|
|
433
|
+
* work?" — and the answer is always no. A colleague saying how their own task
|
|
434
|
+
* went is a status report. It is not an ask, and it must never mint a board row.
|
|
435
|
+
*
|
|
436
|
+
* On 2026-09-30 it did. `assurance.isOwnNarratorText` already recognised these
|
|
437
|
+
* notices, but only for SELF-echo — a seat ignoring its own words. Nothing
|
|
438
|
+
* stopped Jacob's recovery notice reaching Candace as an ordinary message, and
|
|
439
|
+
* with no `--title` on the claim the row took the ask's own first sentence as
|
|
440
|
+
* its title. Production, in three hours:
|
|
441
|
+
*
|
|
442
|
+
* "Here's where I got to: Archived, logged."
|
|
443
|
+
* "Here's where I got to: Declined, logged, no reply."
|
|
444
|
+
* "Here's where I got to: Here's where I got to: Queued, not archived …"
|
|
445
|
+
*
|
|
446
|
+
* Sixty-four rows, several seats each opening and closing the same non-task,
|
|
447
|
+
* and the doubled title is the output of the path re-entering its own input —
|
|
448
|
+
* a row minted from a report ABOUT a row. One of them read "eleventh turn".
|
|
449
|
+
*
|
|
450
|
+
* FROZEN LITERALS for the same reason the register above is frozen: a notice
|
|
451
|
+
* arriving from a seat that has not upgraded yet must still be recognised long
|
|
452
|
+
* after the local composer that produced it has changed.
|
|
453
|
+
*/
|
|
454
|
+
const STATUS_NOTICE_PATTERNS = Object.freeze([
|
|
455
|
+
// composeSilentSuccess — the recovery notice, with or without an excerpt.
|
|
456
|
+
// The excerpt is unbounded prose, so this anchors on the head alone.
|
|
457
|
+
/^finished this but didn'?t get a reply out to you\s*[—–-]\s*my fault\b/i,
|
|
458
|
+
// composeInterrupted.
|
|
459
|
+
/^heads up\s*[—–-]\s*my session on this was interrupted\b/i,
|
|
460
|
+
// notice-voice's generated failure/progress lines, which name the topic:
|
|
461
|
+
// The work on "X" broke before it finished: …
|
|
462
|
+
// The work on "X" didn't get through: …
|
|
463
|
+
/^the work (on ".+?"|you asked for)\s+(broke|didn'?t|never|has)\b/i,
|
|
464
|
+
// The board-status shape that closed the loop on itself.
|
|
465
|
+
/^here'?s where i got to:/i,
|
|
466
|
+
]);
|
|
467
|
+
|
|
468
|
+
/**
|
|
469
|
+
* Is this body a seat narrating its own work, rather than asking for any?
|
|
470
|
+
*
|
|
471
|
+
* Judged per PARAGRAPH like the register above, because these notices are
|
|
472
|
+
* routinely concatenated with an excerpt or with each other.
|
|
473
|
+
*
|
|
474
|
+
* @param {unknown} body
|
|
475
|
+
* @returns {boolean}
|
|
476
|
+
*/
|
|
477
|
+
export function isAgentStatusNotice(body) {
|
|
478
|
+
const paras = String(body == null ? "" : body).split(/\n\s*\n/);
|
|
479
|
+
for (const p of paras) {
|
|
480
|
+
const line = normaliseLine(p);
|
|
481
|
+
if (!line) continue;
|
|
482
|
+
if (STATUS_NOTICE_PATTERNS.some((re) => re.test(line))) return true;
|
|
483
|
+
}
|
|
484
|
+
return false;
|
|
485
|
+
}
|
package/lib/runtime/adapter.mjs
CHANGED
|
@@ -239,6 +239,19 @@ export function sessionArgs(i = {}) {
|
|
|
239
239
|
: ["--session-id", String(i.sessionId)];
|
|
240
240
|
}
|
|
241
241
|
|
|
242
|
+
/**
|
|
243
|
+
* Argv for a lane whose whole job is text in, JSON out (capture, reflect,
|
|
244
|
+
* curator). The child gets NO tools and NO MCP servers: it reads a transcript
|
|
245
|
+
* or a memory set, and anything in that text that reads like an instruction
|
|
246
|
+
* ("merge the PR", "run this") must stay text. A tool-bearing child would
|
|
247
|
+
* inherit the seat's permission mode and could act on it. The parent parses
|
|
248
|
+
* the child's stdout, so nothing the lane needs is lost.
|
|
249
|
+
*
|
|
250
|
+
* @param {{model: string}} i - the lane input.
|
|
251
|
+
* @returns {string[]} the claude argv.
|
|
252
|
+
*/
|
|
253
|
+
const TEXT_ONLY_ARGV = (i) => ["--print", "--model", i.model, "--strict-mcp-config", "--tools", ""];
|
|
254
|
+
|
|
242
255
|
const LANES = Object.freeze({
|
|
243
256
|
dispatcher: {
|
|
244
257
|
posture: "stock-oauth", stdin: false, retarget: true,
|
|
@@ -270,15 +283,15 @@ const LANES = Object.freeze({
|
|
|
270
283
|
},
|
|
271
284
|
capture: {
|
|
272
285
|
posture: "path", stdin: true, retarget: false, collectiveChild: true,
|
|
273
|
-
argv: (i
|
|
286
|
+
argv: (i) => TEXT_ONLY_ARGV(i),
|
|
274
287
|
},
|
|
275
288
|
reflect: {
|
|
276
289
|
posture: "path", stdin: true, retarget: false, collectiveChild: true,
|
|
277
|
-
argv: (i
|
|
290
|
+
argv: (i) => TEXT_ONLY_ARGV(i),
|
|
278
291
|
},
|
|
279
292
|
curator: {
|
|
280
293
|
posture: "path", stdin: true, retarget: false, collectiveChild: true,
|
|
281
|
-
argv: (i
|
|
294
|
+
argv: (i) => TEXT_ONLY_ARGV(i),
|
|
282
295
|
},
|
|
283
296
|
enrich: {
|
|
284
297
|
posture: "inherit", stdin: false, retarget: false,
|
|
@@ -490,7 +503,7 @@ export const ENGINE_RUN_FLAGS = Object.freeze([
|
|
|
490
503
|
"-p", "--print", "--output-format", "--model", "--session-id", "--resume", "--max-turns", "--append-system-prompt",
|
|
491
504
|
// W2-D: MCP, permissions, settings.
|
|
492
505
|
"--mcp-config", "--strict-mcp-config", "--permission-mode", "--dangerously-skip-permissions",
|
|
493
|
-
"--allowedTools", "--disallowedTools", "--settings",
|
|
506
|
+
"--allowedTools", "--disallowedTools", "--settings", "--tools",
|
|
494
507
|
// W3-G (CF-45): the router knobs and the daemon's bare mode.
|
|
495
508
|
"--add-dir", "--plugin-dir", "--effort", "--agents", "--bare",
|
|
496
509
|
// W4-E1 (row 24): the per-session spend cap.
|
|
@@ -516,6 +529,7 @@ const CLAUDE_TO_ENGINE = Object.freeze({
|
|
|
516
529
|
"--permission-mode": { flag: "--permission-mode", value: true },
|
|
517
530
|
"--allowedTools": { flag: "--allowedTools", value: true },
|
|
518
531
|
"--disallowedTools": { flag: "--disallowedTools", value: true },
|
|
532
|
+
"--tools": { flag: "--tools", value: true },
|
|
519
533
|
"--settings": { flag: "--settings", value: true },
|
|
520
534
|
"--add-dir": { flag: "--add-dir", value: true },
|
|
521
535
|
"--plugin-dir": { flag: "--plugin-dir", value: true },
|
|
@@ -215,6 +215,28 @@ export function ledgerStepsFor(a = {}) {
|
|
|
215
215
|
* @returns {Promise<{steps:Array<object>, results:Array<object>}>}
|
|
216
216
|
*/
|
|
217
217
|
export async function runAskLedger(a = {}) {
|
|
218
|
+
// ── A STATUS REPORT IS NOT WORK ──────────────────────────────────────────
|
|
219
|
+
//
|
|
220
|
+
// A colleague narrating how their own task went is not an ask, and a row
|
|
221
|
+
// opened from one is a row nobody requested. On 2026-09-30 this minted 64
|
|
222
|
+
// rows in three hours — titled "Here's where I got to: Archived, logged."
|
|
223
|
+
// and once "Here's where I got to: Here's where I got to: …", which is a row
|
|
224
|
+
// minted from a report ABOUT a row. Several seats each opened and closed the
|
|
225
|
+
// same non-task; one row's note read "eleventh turn".
|
|
226
|
+
//
|
|
227
|
+
// The notice family was already recognised (`assurance.isOwnNarratorText`)
|
|
228
|
+
// but only for SELF-echo, so a seat ignored its own words and happily
|
|
229
|
+
// actioned everyone else's. This applies the same recognition to the question
|
|
230
|
+
// that matters here: not "did I say this?" but "is this work?".
|
|
231
|
+
//
|
|
232
|
+
// Deliberately at the LEDGER, not at ingestion: the seat should still READ a
|
|
233
|
+
// colleague's status notice and may still reply to it. What it must not do is
|
|
234
|
+
// open a board row for it.
|
|
235
|
+
const { isAgentStatusNotice } = await import("../assurance/first-reply.mjs");
|
|
236
|
+
const body = (a.item && (a.item.content || a.item.subject)) || a.text || "";
|
|
237
|
+
if (isAgentStatusNotice(body)) {
|
|
238
|
+
return { steps: [], results: [{ tracked: false, reason: "status-notice-not-an-ask" }] };
|
|
239
|
+
}
|
|
218
240
|
const steps = ledgerStepsFor(a);
|
|
219
241
|
const results = [];
|
|
220
242
|
if (steps.length === 0) return { steps, results };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cohortapp/agent-sdk",
|
|
3
|
-
"version": "2.18.
|
|
3
|
+
"version": "2.18.19",
|
|
4
4
|
"description": "Cohort Agent SDK — autonomous AI colleague runtime. Deploy senior AI colleagues on dedicated Mac minis, wired to the Cohort operating surface.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|