@enderfga/claw-orchestrator 7.12.1 → 7.14.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/README.md +14 -11
- package/configs/engines/README.md +20 -0
- package/configs/engines/dsh.json +17 -0
- package/configs/engines/kimi-code.json +17 -0
- package/dist/bin/cli.js +123 -34
- package/dist/bin/cli.js.map +1 -1
- package/dist/src/acp-server.js +4 -2
- package/dist/src/acp-server.js.map +1 -1
- package/dist/src/autoloop/dispatcher.d.ts +19 -0
- package/dist/src/autoloop/dispatcher.js +57 -0
- package/dist/src/autoloop/dispatcher.js.map +1 -1
- package/dist/src/autoloop/runner.d.ts +102 -2
- package/dist/src/autoloop/runner.js +367 -44
- package/dist/src/autoloop/runner.js.map +1 -1
- package/dist/src/autoloop/types.d.ts +17 -0
- package/dist/src/autoloop/types.js.map +1 -1
- package/dist/src/dashboard/index.html +79 -73
- package/dist/src/embedded-server.js +35 -7
- package/dist/src/embedded-server.js.map +1 -1
- package/dist/src/engine-presets.d.ts +7 -3
- package/dist/src/engine-presets.js +39 -6
- package/dist/src/engine-presets.js.map +1 -1
- package/dist/src/engine-spawn.d.ts +8 -1
- package/dist/src/engine-spawn.js +13 -3
- package/dist/src/engine-spawn.js.map +1 -1
- package/dist/src/index.js +78 -71
- package/dist/src/index.js.map +1 -1
- package/dist/src/kernel/agent-step.d.ts +3 -0
- package/dist/src/kernel/agent-step.js.map +1 -1
- package/dist/src/kernel/engine.d.ts +5 -2
- package/dist/src/kernel/engine.js +11 -12
- package/dist/src/kernel/engine.js.map +1 -1
- package/dist/src/kernel/nodes/autoloop.d.ts +32 -2
- package/dist/src/kernel/nodes/autoloop.js +122 -15
- package/dist/src/kernel/nodes/autoloop.js.map +1 -1
- package/dist/src/kernel/nodes/goal.d.ts +94 -0
- package/dist/src/kernel/nodes/goal.js +386 -0
- package/dist/src/kernel/nodes/goal.js.map +1 -0
- package/dist/src/kernel/nodes/index.d.ts +2 -1
- package/dist/src/kernel/nodes/index.js +3 -1
- package/dist/src/kernel/nodes/index.js.map +1 -1
- package/dist/src/kernel/templates/index.d.ts +27 -3
- package/dist/src/kernel/templates/index.js +78 -1
- package/dist/src/kernel/templates/index.js.map +1 -1
- package/dist/src/kernel/types.d.ts +41 -2
- package/dist/src/kernel/types.js.map +1 -1
- package/dist/src/persistent-acp-session.d.ts +76 -0
- package/dist/src/persistent-acp-session.js +409 -0
- package/dist/src/persistent-acp-session.js.map +1 -0
- package/dist/src/persistent-agy-session.js +1 -0
- package/dist/src/persistent-agy-session.js.map +1 -1
- package/dist/src/persistent-codex-app-session.d.ts +55 -26
- package/dist/src/persistent-codex-app-session.js +109 -24
- package/dist/src/persistent-codex-app-session.js.map +1 -1
- package/dist/src/persistent-codex-session.js +1 -0
- package/dist/src/persistent-codex-session.js.map +1 -1
- package/dist/src/persistent-cursor-session.js +1 -0
- package/dist/src/persistent-cursor-session.js.map +1 -1
- package/dist/src/persistent-custom-session.js +2 -0
- package/dist/src/persistent-custom-session.js.map +1 -1
- package/dist/src/persistent-gemini-session.js +1 -0
- package/dist/src/persistent-gemini-session.js.map +1 -1
- package/dist/src/persistent-grok-session.js +1 -0
- package/dist/src/persistent-grok-session.js.map +1 -1
- package/dist/src/persistent-opencode-session.js +1 -0
- package/dist/src/persistent-opencode-session.js.map +1 -1
- package/dist/src/persistent-session.js +1 -0
- package/dist/src/persistent-session.js.map +1 -1
- package/dist/src/sanitize.d.ts +10 -0
- package/dist/src/sanitize.js +26 -0
- package/dist/src/sanitize.js.map +1 -1
- package/dist/src/session-manager.d.ts +25 -20
- package/dist/src/session-manager.js +92 -43
- package/dist/src/session-manager.js.map +1 -1
- package/dist/src/types.d.ts +35 -1
- package/dist/src/types.js +2 -0
- package/dist/src/types.js.map +1 -1
- package/openclaw.plugin.json +1 -1
- package/package.json +2 -2
- package/skills/SKILL.md +8 -5
- package/skills/references/acp.md +4 -0
- package/skills/references/autoloop.md +27 -2
- package/skills/references/claude-cli-tracking.md +3 -1
- package/skills/references/cli.md +79 -39
- package/skills/references/dashboard.md +5 -1
- package/skills/references/multi-engine.md +39 -10
- package/skills/references/tools.md +77 -65
- package/skills/references/workflow.md +87 -13
package/dist/src/sanitize.js
CHANGED
|
@@ -31,6 +31,32 @@ export function sanitizeSecrets(text) {
|
|
|
31
31
|
}
|
|
32
32
|
return result;
|
|
33
33
|
}
|
|
34
|
+
/**
|
|
35
|
+
* A short, single-line reason for a log line, or `unknown error`.
|
|
36
|
+
*
|
|
37
|
+
* Source is `err instanceof Error ? String(err.message) : String(err)`; a throw
|
|
38
|
+
* during that conversion returns `unknown error`. Whitespace runs become one
|
|
39
|
+
* space, then trim; known secret shapes are redacted; the result is capped at
|
|
40
|
+
* 300 UTF-16 units (a trailing high surrogate is dropped). Empty output, or
|
|
41
|
+
* any Unicode Cc/Cf code point, becomes `unknown error`.
|
|
42
|
+
*/
|
|
43
|
+
export function boundedErrorReason(err) {
|
|
44
|
+
let text;
|
|
45
|
+
try {
|
|
46
|
+
text = err instanceof Error ? String(err.message) : String(err);
|
|
47
|
+
}
|
|
48
|
+
catch {
|
|
49
|
+
return 'unknown error';
|
|
50
|
+
}
|
|
51
|
+
text = text.replace(/\s+/g, ' ').trim();
|
|
52
|
+
text = sanitizeSecrets(text);
|
|
53
|
+
text = text.slice(0, 300);
|
|
54
|
+
if (/[\uD800-\uDBFF]$/.test(text))
|
|
55
|
+
text = text.slice(0, -1);
|
|
56
|
+
if (!text || /[\p{Cc}\p{Cf}]/u.test(text))
|
|
57
|
+
return 'unknown error';
|
|
58
|
+
return text;
|
|
59
|
+
}
|
|
34
60
|
/** Build a sanitizer from common secret patterns plus optional config patterns. */
|
|
35
61
|
export function buildSanitizer(options = {}) {
|
|
36
62
|
const patterns = [...SECRET_PATTERNS];
|
package/dist/src/sanitize.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sanitize.js","sourceRoot":"","sources":["../../src/sanitize.ts"],"names":[],"mappings":"AAAA,OAAO,GAAG,MAAM,KAAK,CAAC;AAEtB;;;;;;;;;;GAUG;AAEH,MAAM,CAAC,MAAM,eAAe,GAAuD;IACjF,mEAAmE;IACnE,+DAA+D;IAC/D,EAAE,EAAE,EAAE,yBAAyB,EAAE,WAAW,EAAE,YAAY,EAAE;IAC5D,8DAA8D;IAC9D,EAAE,EAAE,EAAE,wBAAwB,EAAE,WAAW,EAAE,QAAQ,EAAE;IACvD,4DAA4D;IAC5D,EAAE,EAAE,EAAE,wCAAwC,EAAE,WAAW,EAAE,OAAO,EAAE;IACtE,kDAAkD;IAClD,mFAAmF;IACnF,EAAE,EAAE,EAAE,iDAAiD,EAAE,WAAW,EAAE,QAAQ,EAAE;CACjF,CAAC;AAEF,6DAA6D;AAC7D,MAAM,UAAU,eAAe,CAAC,IAAY;IAC1C,IAAI,MAAM,GAAG,IAAI,CAAC;IAClB,KAAK,MAAM,EAAE,EAAE,EAAE,WAAW,EAAE,IAAI,eAAe,EAAE,CAAC;QAClD,EAAE,CAAC,SAAS,GAAG,CAAC,CAAC;QACjB,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC,EAAE,EAAE,WAAW,CAAC,CAAC;IAC3C,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAOD,mFAAmF;AACnF,MAAM,UAAU,cAAc,CAAC,UAA4B,EAAE;IAC3D,MAAM,QAAQ,GAA+C,CAAC,GAAG,eAAe,CAAC,CAAC;IAClF,KAAK,MAAM,OAAO,IAAI,OAAO,CAAC,aAAa,IAAI,EAAE,EAAE,CAAC;QAClD,IAAI,CAAC;YACH,0EAA0E;YAC1E,+DAA+D;YAC/D,QAAQ,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,IAAI,GAAG,CAAC,OAAO,EAAE,GAAG,CAAsB,EAAE,WAAW,EAAE,KAAK,EAAE,CAAC,CAAC;QACxF,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,OAAO,CAAC,KAAK,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;YACzD,OAAO,CAAC,IAAI,CAAC,GAAG,KAAK,oCAAoC,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,KAAM,GAAa,CAAC,OAAO,EAAE,CAAC,CAAC;QACjH,CAAC;IACH,CAAC;IAED,OAAO,CAAC,IAAY,EAAU,EAAE;QAC9B,IAAI,MAAM,GAAG,IAAI,CAAC;QAClB,KAAK,MAAM,EAAE,EAAE,EAAE,WAAW,EAAE,IAAI,QAAQ,EAAE,CAAC;YAC3C,EAAE,CAAC,SAAS,GAAG,CAAC,CAAC;YACjB,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC,EAAE,EAAE,WAAW,CAAC,CAAC;QAC3C,CAAC;QACD,OAAO,MAAM,CAAC;IAChB,CAAC,CAAC;AACJ,CAAC"}
|
|
1
|
+
{"version":3,"file":"sanitize.js","sourceRoot":"","sources":["../../src/sanitize.ts"],"names":[],"mappings":"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"}
|
|
@@ -22,12 +22,15 @@ import { type RunSummary } from './kernel/store.js';
|
|
|
22
22
|
import type { KernelEvent, RunRecord, RunState, WorkflowSpec } from './kernel/types.js';
|
|
23
23
|
import { type EvidenceBundle } from './verify/evidence.js';
|
|
24
24
|
import { type RunLedgerQuery, type RunLedgerRow, type RunLedgerSummary } from './run-ledger.js';
|
|
25
|
+
import { type ThreadGoal } from './persistent-codex-app-session.js';
|
|
26
|
+
import type { GoalSession } from './kernel/nodes/goal.js';
|
|
25
27
|
import { type SessionConfig, type SessionInfo, type SendOptions, type SendResult, type PluginConfig, type EffortLevel, type EngineType, type CustomEngineConfig, type AgentInfo, type SkillInfo, type RuleInfo, type ISession, type CouncilConfig, type CouncilSession, type CouncilReviewResult, type CouncilAcceptResult, type CouncilRejectResult, type InboxMessage, type UltraplanResult, type UltrareviewResult } from './types.js';
|
|
26
28
|
import { Council } from './council.js';
|
|
27
29
|
import { type FanoutConfig, type FanoutSession } from './fanout.js';
|
|
28
30
|
import { AutoloopRunner } from './autoloop/runner.js';
|
|
29
31
|
import { ClaudeAgentDispatcher } from './autoloop/dispatcher.js';
|
|
30
32
|
import type { AutoloopState } from './autoloop/types.js';
|
|
33
|
+
import { type AnyAutoloopMessage } from './autoloop/messages.js';
|
|
31
34
|
import { UltraappManager } from './ultraapp/manager.js';
|
|
32
35
|
import type { UltraappRouter } from './ultraapp/router.js';
|
|
33
36
|
type AutoloopRoleName = 'planner' | 'coder' | 'reviewer';
|
|
@@ -327,30 +330,26 @@ export declare class SessionManager {
|
|
|
327
330
|
* After shutdown(), no new sessions can be started. Idempotent.
|
|
328
331
|
*/
|
|
329
332
|
shutdown(): Promise<void>;
|
|
333
|
+
/** The live `codex-app` session behind `name`, for the kernel's `goal` node. */
|
|
334
|
+
codexGoalSession(name: string): GoalSession | undefined;
|
|
330
335
|
/**
|
|
331
|
-
*
|
|
332
|
-
* the `codex_goal_*` tools
|
|
333
|
-
*
|
|
334
|
-
* caches.
|
|
336
|
+
* Act on a `codex-app` session's goal through the app-server's
|
|
337
|
+
* `thread/goal/*` RPCs. Used by the `codex_goal_*` tools; `get` asks the
|
|
338
|
+
* server rather than a cache.
|
|
335
339
|
*
|
|
336
|
-
* Errors clearly when called against a non-`codex-app` session —
|
|
337
|
-
*
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
340
|
+
* Errors clearly when called against a non-`codex-app` session — `codex
|
|
341
|
+
* exec` has no goal surface.
|
|
342
|
+
*/
|
|
343
|
+
codexGoal(name: string, op: {
|
|
344
|
+
action: 'set';
|
|
345
|
+
objective: string;
|
|
346
|
+
tokenBudget?: number | null;
|
|
347
|
+
} | {
|
|
348
|
+
action: 'pause' | 'resume' | 'clear' | 'get';
|
|
349
|
+
}): Promise<{
|
|
341
350
|
ok: true;
|
|
342
|
-
|
|
343
|
-
goal: unknown;
|
|
351
|
+
goal: ThreadGoal | null;
|
|
344
352
|
}>;
|
|
345
|
-
/**
|
|
346
|
-
* Read the cached goal state from a `codex-app` session without sending
|
|
347
|
-
* any command. Returns null if no goal is set or the session has not yet
|
|
348
|
-
* received a `thread/goal/updated` notification.
|
|
349
|
-
*/
|
|
350
|
-
codexGoalGet(name: string): {
|
|
351
|
-
ok: true;
|
|
352
|
-
goal: unknown;
|
|
353
|
-
};
|
|
354
353
|
private _getCodexAppSession;
|
|
355
354
|
codexInterrupt(name: string): Promise<{
|
|
356
355
|
ok: true;
|
|
@@ -679,6 +678,12 @@ export declare class SessionManager {
|
|
|
679
678
|
plannerSession: string;
|
|
680
679
|
state: AutoloopState;
|
|
681
680
|
}>;
|
|
681
|
+
/**
|
|
682
|
+
* Durably accept a chat message for a live run's Planner and return the
|
|
683
|
+
* envelope to deliver. Throws, with nothing accepted, when the run cannot
|
|
684
|
+
* checkpoint it. Internal: callers pass the result to `runner.send`.
|
|
685
|
+
*/
|
|
686
|
+
acceptAutoloopChat(runId: string, text: string): AnyAutoloopMessage;
|
|
682
687
|
/**
|
|
683
688
|
* Inject a user chat message into a v2 run's Planner. Returns the Planner's
|
|
684
689
|
* natural-language reply.
|
|
@@ -136,15 +136,17 @@ import { PersistentGrokSession } from './persistent-grok-session.js';
|
|
|
136
136
|
import { PersistentOpencodeSession } from './persistent-opencode-session.js';
|
|
137
137
|
import { PersistentAgySession } from './persistent-agy-session.js';
|
|
138
138
|
import { PersistentCustomSession } from './persistent-custom-session.js';
|
|
139
|
+
import { PersistentAcpSession } from './persistent-acp-session.js';
|
|
139
140
|
import { resolveCustomEngine } from './engine-presets.js';
|
|
140
141
|
import { EFFORT_LEVELS, ENGINE_TYPES, overrideModelPricing, ENGINE_BINARY_NAMES, } from './types.js';
|
|
141
142
|
import { resolveAlias, isClaudeModel, lookupModel } from './models.js';
|
|
142
143
|
import { isAgyConversationId } from './agy-conversation.js';
|
|
143
144
|
import { Council } from './council.js';
|
|
144
145
|
import { AutoloopRunner } from './autoloop/runner.js';
|
|
146
|
+
import { boundedErrorReason } from './sanitize.js';
|
|
145
147
|
import { ClaudeAgentDispatcher } from './autoloop/dispatcher.js';
|
|
146
148
|
import { DEFAULT_PUSH_POLICY, DEFAULT_SEND_TIMEOUT_MS, MAX_METRIC_HISTORY, validateAutoloopTimeoutConfig, } from './autoloop/types.js';
|
|
147
|
-
import { Msg as AutoloopMsg } from './autoloop/messages.js';
|
|
149
|
+
import { Msg as AutoloopMsg, } from './autoloop/messages.js';
|
|
148
150
|
import { appendPushLog, notifyUserFallbackChain } from './autoloop/notify.js';
|
|
149
151
|
import { UltraappManager } from './ultraapp/manager.js';
|
|
150
152
|
import { UltraappStore, defaultStoreRoot } from './ultraapp/store.js';
|
|
@@ -1421,7 +1423,7 @@ export class SessionManager {
|
|
|
1421
1423
|
// its executor is registered here with a builder closed over `this`
|
|
1422
1424
|
// rather than living in the kernel.
|
|
1423
1425
|
kernel.setExecutor('autoloop', makeAutoloopExecutor({
|
|
1424
|
-
boot: (config, secrets, { freshStart }) => this._bootAutoloop({
|
|
1426
|
+
boot: (config, secrets, { freshStart, restoredInput }) => this._bootAutoloop({
|
|
1425
1427
|
...config,
|
|
1426
1428
|
// Custom-engine configs never reach the spec, so they come from
|
|
1427
1429
|
// the run's in-memory secret bag — supplied at start, and
|
|
@@ -1432,6 +1434,7 @@ export class SessionManager {
|
|
|
1432
1434
|
// Always set (including false on resume) — omitting false left a
|
|
1433
1435
|
// `_freshStart: true` from config/secrets intact.
|
|
1434
1436
|
_freshStart: freshStart,
|
|
1437
|
+
_restoredInput: restoredInput,
|
|
1435
1438
|
}),
|
|
1436
1439
|
ready: (key, value) => {
|
|
1437
1440
|
const deferred = this._autoloopReady.get(key);
|
|
@@ -1968,46 +1971,35 @@ export class SessionManager {
|
|
|
1968
1971
|
// Persist final state (TTL-expired sessions already removed by cleanup)
|
|
1969
1972
|
this._savePersisted();
|
|
1970
1973
|
}
|
|
1971
|
-
// ─── Codex
|
|
1974
|
+
// ─── Codex goals (codex-app engine only) ─────────────────────────────
|
|
1975
|
+
/** The live `codex-app` session behind `name`, for the kernel's `goal` node. */
|
|
1976
|
+
codexGoalSession(name) {
|
|
1977
|
+
const session = this.sessions.get(name)?.session;
|
|
1978
|
+
return session instanceof PersistentCodexAppServerSession ? session : undefined;
|
|
1979
|
+
}
|
|
1972
1980
|
/**
|
|
1973
|
-
*
|
|
1974
|
-
* the `codex_goal_*` tools
|
|
1975
|
-
*
|
|
1976
|
-
* caches.
|
|
1981
|
+
* Act on a `codex-app` session's goal through the app-server's
|
|
1982
|
+
* `thread/goal/*` RPCs. Used by the `codex_goal_*` tools; `get` asks the
|
|
1983
|
+
* server rather than a cache.
|
|
1977
1984
|
*
|
|
1978
|
-
* Errors clearly when called against a non-`codex-app` session —
|
|
1979
|
-
*
|
|
1980
|
-
* command surface).
|
|
1985
|
+
* Errors clearly when called against a non-`codex-app` session — `codex
|
|
1986
|
+
* exec` has no goal surface.
|
|
1981
1987
|
*/
|
|
1982
|
-
async
|
|
1983
|
-
const
|
|
1984
|
-
|
|
1985
|
-
|
|
1986
|
-
|
|
1987
|
-
|
|
1988
|
-
|
|
1989
|
-
|
|
1990
|
-
|
|
1988
|
+
async codexGoal(name, op) {
|
|
1989
|
+
const session = this._getCodexAppSession(name, '/goal');
|
|
1990
|
+
switch (op.action) {
|
|
1991
|
+
case 'set':
|
|
1992
|
+
return { ok: true, goal: await session.setGoal({ objective: op.objective, tokenBudget: op.tokenBudget }) };
|
|
1993
|
+
case 'pause':
|
|
1994
|
+
return { ok: true, goal: await session.setGoal({ status: 'paused' }) };
|
|
1995
|
+
case 'resume':
|
|
1996
|
+
return { ok: true, goal: await session.setGoal({ status: 'active' }) };
|
|
1997
|
+
case 'clear':
|
|
1998
|
+
await session.clearGoal();
|
|
1999
|
+
return { ok: true, goal: null };
|
|
2000
|
+
case 'get':
|
|
2001
|
+
return { ok: true, goal: await session.getGoal() };
|
|
1991
2002
|
}
|
|
1992
|
-
const result = await session.sendGoalCommand(slashArgs, timeoutMs);
|
|
1993
|
-
return { ok: true, text: result.text, goal: result.goal };
|
|
1994
|
-
}
|
|
1995
|
-
/**
|
|
1996
|
-
* Read the cached goal state from a `codex-app` session without sending
|
|
1997
|
-
* any command. Returns null if no goal is set or the session has not yet
|
|
1998
|
-
* received a `thread/goal/updated` notification.
|
|
1999
|
-
*/
|
|
2000
|
-
codexGoalGet(name) {
|
|
2001
|
-
const managed = this.sessions.get(name);
|
|
2002
|
-
if (!managed)
|
|
2003
|
-
throw new Error(`Session not found: ${name}`);
|
|
2004
|
-
const session = managed.session;
|
|
2005
|
-
if (!('goal' in session)) {
|
|
2006
|
-
const engine = managed.config.engine || 'claude';
|
|
2007
|
-
throw new Error(`Session "${name}" uses engine "${engine}" which does not track goal state. ` +
|
|
2008
|
-
`Start a session with engine: "codex-app" to use the goal tools.`);
|
|
2009
|
-
}
|
|
2010
|
-
return { ok: true, goal: session.goal ?? null };
|
|
2011
2003
|
}
|
|
2012
2004
|
// ─── Codex app-server v2 RPCs (codex-app engine only, Codex 0.137) ────────
|
|
2013
2005
|
//
|
|
@@ -2679,6 +2671,16 @@ export class SessionManager {
|
|
|
2679
2671
|
if (engine === 'codex') {
|
|
2680
2672
|
return session.threadId;
|
|
2681
2673
|
}
|
|
2674
|
+
// `sessionId` on a codex-app session is a label of ours; `thread/resume`
|
|
2675
|
+
// needs the app-server's own thread id, and silently opened a new thread
|
|
2676
|
+
// when handed the label.
|
|
2677
|
+
if (engine === 'codex-app') {
|
|
2678
|
+
return session.codexThreadId;
|
|
2679
|
+
}
|
|
2680
|
+
// Likewise an ACP session's `sessionId` is ours; the agent resumes its own.
|
|
2681
|
+
if (engine === 'acp') {
|
|
2682
|
+
return session.agentSessionId;
|
|
2683
|
+
}
|
|
2682
2684
|
return session.sessionId;
|
|
2683
2685
|
}
|
|
2684
2686
|
_storedResumeId(engine, id) {
|
|
@@ -2688,6 +2690,10 @@ export class SessionManager {
|
|
|
2688
2690
|
return id && !/^codex-\d+-/.test(id) ? id : undefined;
|
|
2689
2691
|
if (engine === 'grok')
|
|
2690
2692
|
return id && !/^grok-\d+-/.test(id) ? id : undefined;
|
|
2693
|
+
if (engine === 'codex-app')
|
|
2694
|
+
return id && !id.startsWith('codex-app-') ? id : undefined;
|
|
2695
|
+
if (engine === 'acp')
|
|
2696
|
+
return id && !id.startsWith('acp-') ? id : undefined;
|
|
2691
2697
|
return id;
|
|
2692
2698
|
}
|
|
2693
2699
|
_listMdFiles(dir) {
|
|
@@ -2729,6 +2735,8 @@ export class SessionManager {
|
|
|
2729
2735
|
if (!config.customEngine)
|
|
2730
2736
|
throw new Error('customEngine config is required for engine type "custom"');
|
|
2731
2737
|
return new PersistentCustomSession(config);
|
|
2738
|
+
case 'acp':
|
|
2739
|
+
return new PersistentAcpSession(config);
|
|
2732
2740
|
case 'claude':
|
|
2733
2741
|
default:
|
|
2734
2742
|
return new PersistentClaudeSession(config, this.pluginConfig.claudeBin);
|
|
@@ -3261,6 +3269,10 @@ export class SessionManager {
|
|
|
3261
3269
|
run_id: opts.runId,
|
|
3262
3270
|
workspace: opts.workspace,
|
|
3263
3271
|
ledger_dir: ledgerDir,
|
|
3272
|
+
persistCheckpoint: () => {
|
|
3273
|
+
const publish = this._autoloopPublishers.get(runId);
|
|
3274
|
+
return publish ? publish() : false;
|
|
3275
|
+
},
|
|
3264
3276
|
push_policy: pushPolicy,
|
|
3265
3277
|
notifyUser: async (level, summary, detail, channel) => {
|
|
3266
3278
|
const result = await notifyUserFallbackChain({
|
|
@@ -3285,11 +3297,18 @@ export class SessionManager {
|
|
|
3285
3297
|
activityLeaseMs: opts.activityLeaseMs,
|
|
3286
3298
|
autoloopHardTimeoutMs: opts.autoloopHardTimeoutMs,
|
|
3287
3299
|
});
|
|
3300
|
+
// Background resume/deadline/stall paths emit 'error' after a void catch.
|
|
3301
|
+
// Without a listener, Node turns that into an unhandled rejection.
|
|
3302
|
+
runner.on('error', (err) => {
|
|
3303
|
+
this.logger.error?.(`[autoloop/${runId}] background runner task failed: ${boundedErrorReason(err)}`);
|
|
3304
|
+
});
|
|
3288
3305
|
runnerRef = runner;
|
|
3289
3306
|
if (closedLedgerRestore) {
|
|
3290
3307
|
runner.state.iter = closedLedgerRestore.iter;
|
|
3291
3308
|
runner.state.metric_history = closedLedgerRestore.metric_history.slice();
|
|
3292
3309
|
}
|
|
3310
|
+
if (opts._restoredInput)
|
|
3311
|
+
runner.loadRestoredInput(opts._restoredInput);
|
|
3293
3312
|
try {
|
|
3294
3313
|
await runner.start();
|
|
3295
3314
|
// A reconstructed migration becomes externally visible only after its
|
|
@@ -3297,7 +3316,6 @@ export class SessionManager {
|
|
|
3297
3316
|
// this inside the startup try makes an append failure follow the same
|
|
3298
3317
|
// cleanup path as any other failed resume.
|
|
3299
3318
|
opts._commitTimeoutMigration?.();
|
|
3300
|
-
await this._recoverCommittedCoderIteration(opts.workspace, ledgerDir, runId, runner, dispatcher);
|
|
3301
3319
|
}
|
|
3302
3320
|
catch (err) {
|
|
3303
3321
|
try {
|
|
@@ -3311,7 +3329,17 @@ export class SessionManager {
|
|
|
3311
3329
|
runner.stop();
|
|
3312
3330
|
throw err;
|
|
3313
3331
|
}
|
|
3314
|
-
|
|
3332
|
+
// Committed-iteration recovery runs after publisher registration, the
|
|
3333
|
+
// initial-publish check and notice reconciliation (see afterPublishReconcile
|
|
3334
|
+
// in makeAutoloopExecutor) — never inside boot before that gate.
|
|
3335
|
+
return {
|
|
3336
|
+
runner,
|
|
3337
|
+
dispatcher,
|
|
3338
|
+
ledgerDir,
|
|
3339
|
+
pushPolicy,
|
|
3340
|
+
abort: () => runner.markCancelledByKernel(),
|
|
3341
|
+
afterPublishReconcile: () => this._recoverCommittedCoderIteration(opts.workspace, ledgerDir, runId, runner, dispatcher),
|
|
3342
|
+
};
|
|
3315
3343
|
}
|
|
3316
3344
|
/**
|
|
3317
3345
|
* If the durable ledger has a committed Coder iteration with no Reviewer
|
|
@@ -3352,8 +3380,12 @@ export class SessionManager {
|
|
|
3352
3380
|
return;
|
|
3353
3381
|
this.logger.info?.(`[autoloop/${runId}] recovering committed iter ${n} into Reviewer`);
|
|
3354
3382
|
await dispatcher.ensureReviewerForCommittedRecovery();
|
|
3355
|
-
|
|
3383
|
+
// Keep a reconciled chat_notice_pending pause so Planner-bound follow-ups
|
|
3384
|
+
// park until the notice is recorded; live spawn_subagents stays unchanged.
|
|
3385
|
+
runner.markSubagentsSpawned({ preservePause: true });
|
|
3356
3386
|
runner.state.iter = n;
|
|
3387
|
+
// Queue only — never await the physical Reviewer turn. Readiness and the
|
|
3388
|
+
// cancellation observer must install before any model transport settles.
|
|
3357
3389
|
void runner
|
|
3358
3390
|
.send(AutoloopMsg.reviewRequest(n, {
|
|
3359
3391
|
iter: n,
|
|
@@ -3441,12 +3473,21 @@ export class SessionManager {
|
|
|
3441
3473
|
this._autoloopStarting.delete(tag);
|
|
3442
3474
|
}
|
|
3443
3475
|
}
|
|
3476
|
+
/**
|
|
3477
|
+
* Durably accept a chat message for a live run's Planner and return the
|
|
3478
|
+
* envelope to deliver. Throws, with nothing accepted, when the run cannot
|
|
3479
|
+
* checkpoint it. Internal: callers pass the result to `runner.send`.
|
|
3480
|
+
*/
|
|
3481
|
+
acceptAutoloopChat(runId, text) {
|
|
3482
|
+
return this._liveAutoloop(runId).runner.acceptChat(text);
|
|
3483
|
+
}
|
|
3444
3484
|
/**
|
|
3445
3485
|
* Inject a user chat message into a v2 run's Planner. Returns the Planner's
|
|
3446
3486
|
* natural-language reply.
|
|
3447
3487
|
*/
|
|
3448
3488
|
async autoloopChat(runId, text) {
|
|
3449
3489
|
const ctx = this._liveAutoloop(runId);
|
|
3490
|
+
const env = this.acceptAutoloopChat(runId, text);
|
|
3450
3491
|
let reply = '';
|
|
3451
3492
|
const onReply = (...args) => {
|
|
3452
3493
|
const t = args[0];
|
|
@@ -3455,7 +3496,7 @@ export class SessionManager {
|
|
|
3455
3496
|
};
|
|
3456
3497
|
ctx.dispatcher.on('planner_reply', onReply);
|
|
3457
3498
|
try {
|
|
3458
|
-
await ctx.runner.send(
|
|
3499
|
+
await ctx.runner.send(env);
|
|
3459
3500
|
}
|
|
3460
3501
|
finally {
|
|
3461
3502
|
ctx.dispatcher.off('planner_reply', onReply);
|
|
@@ -3566,8 +3607,16 @@ export class SessionManager {
|
|
|
3566
3607
|
}
|
|
3567
3608
|
const live = this.kernel.handle(runId, LEGACY_NODE);
|
|
3568
3609
|
if (live) {
|
|
3569
|
-
if (!hasTimeoutIncrease)
|
|
3610
|
+
if (!hasTimeoutIncrease) {
|
|
3611
|
+
// Ordinary and activity-lease pauses have no uncertain in-flight
|
|
3612
|
+
// dispatch. A pending send timeout stays the historical no-op until
|
|
3613
|
+
// an explicit timeout increase names that dispatch.
|
|
3614
|
+
if (live.runner.state.status === 'paused' && live.runner.state.pending_dispatch === null) {
|
|
3615
|
+
live.runner.resumePaused();
|
|
3616
|
+
this._autoloopPublishers.get(runId)?.();
|
|
3617
|
+
}
|
|
3570
3618
|
return live.runner.state;
|
|
3619
|
+
}
|
|
3571
3620
|
const pending = live.runner.state.pending_dispatch;
|
|
3572
3621
|
if (live.runner.state.status !== 'paused' || !pending) {
|
|
3573
3622
|
throw new Error(`Autoloop run '${runId}' is not awaiting a recoverable send timeout`);
|