@jungjaehoon/mama-os 0.32.1 → 0.32.2
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/CHANGELOG.md +8 -0
- package/README.md +15 -13
- package/dist/agent/agent-loop.d.ts +5 -0
- package/dist/agent/agent-loop.d.ts.map +1 -1
- package/dist/agent/agent-loop.js +160 -55
- package/dist/agent/agent-loop.js.map +1 -1
- package/dist/agent/backend-model-policy.d.ts +9 -0
- package/dist/agent/backend-model-policy.d.ts.map +1 -0
- package/dist/agent/backend-model-policy.js +21 -0
- package/dist/agent/backend-model-policy.js.map +1 -0
- package/dist/agent/backend-model-runner-factory.d.ts +27 -0
- package/dist/agent/backend-model-runner-factory.d.ts.map +1 -0
- package/dist/agent/backend-model-runner-factory.js +85 -0
- package/dist/agent/backend-model-runner-factory.js.map +1 -0
- package/dist/agent/cline-cli-adapter.d.ts +124 -0
- package/dist/agent/cline-cli-adapter.d.ts.map +1 -0
- package/dist/agent/cline-cli-adapter.js +1040 -0
- package/dist/agent/cline-cli-adapter.js.map +1 -0
- package/dist/agent/cline-native-tool-policy.d.ts +3 -0
- package/dist/agent/cline-native-tool-policy.d.ts.map +1 -0
- package/dist/agent/cline-native-tool-policy.js +50 -0
- package/dist/agent/cline-native-tool-policy.js.map +1 -0
- package/dist/agent/code-act/constants.d.ts +1 -1
- package/dist/agent/code-act/constants.d.ts.map +1 -1
- package/dist/agent/code-act/constants.js +13 -1
- package/dist/agent/code-act/constants.js.map +1 -1
- package/dist/agent/codex-app-server-process.d.ts +5 -0
- package/dist/agent/codex-app-server-process.d.ts.map +1 -1
- package/dist/agent/codex-app-server-process.js +30 -0
- package/dist/agent/codex-app-server-process.js.map +1 -1
- package/dist/agent/codex-auxiliary-tools.d.ts +17 -0
- package/dist/agent/codex-auxiliary-tools.d.ts.map +1 -0
- package/dist/agent/codex-auxiliary-tools.js +267 -0
- package/dist/agent/codex-auxiliary-tools.js.map +1 -0
- package/dist/agent/codex-home.d.ts.map +1 -1
- package/dist/agent/codex-home.js +1 -0
- package/dist/agent/codex-home.js.map +1 -1
- package/dist/agent/managed-agent-runtime-sync.d.ts.map +1 -1
- package/dist/agent/managed-agent-runtime-sync.js +17 -3
- package/dist/agent/managed-agent-runtime-sync.js.map +1 -1
- package/dist/agent/managed-agent-validation.js +1 -1
- package/dist/agent/managed-agent-validation.js.map +1 -1
- package/dist/agent/model-runner.d.ts +11 -1
- package/dist/agent/model-runner.d.ts.map +1 -1
- package/dist/agent/model-runner.js +12 -1
- package/dist/agent/model-runner.js.map +1 -1
- package/dist/agent/session-pool.d.ts +10 -9
- package/dist/agent/session-pool.d.ts.map +1 -1
- package/dist/agent/session-pool.js +12 -47
- package/dist/agent/session-pool.js.map +1 -1
- package/dist/agent/types.d.ts +18 -2
- package/dist/agent/types.d.ts.map +1 -1
- package/dist/agent/types.js.map +1 -1
- package/dist/api/graph-api.d.ts.map +1 -1
- package/dist/api/graph-api.js +15 -5
- package/dist/api/graph-api.js.map +1 -1
- package/dist/cli/commands/init.d.ts +1 -1
- package/dist/cli/commands/init.d.ts.map +1 -1
- package/dist/cli/commands/init.js +43 -10
- package/dist/cli/commands/init.js.map +1 -1
- package/dist/cli/commands/run.d.ts.map +1 -1
- package/dist/cli/commands/run.js +12 -0
- package/dist/cli/commands/run.js.map +1 -1
- package/dist/cli/commands/setup.d.ts +22 -0
- package/dist/cli/commands/setup.d.ts.map +1 -1
- package/dist/cli/commands/setup.js +79 -28
- package/dist/cli/commands/setup.js.map +1 -1
- package/dist/cli/commands/start.d.ts +2 -1
- package/dist/cli/commands/start.d.ts.map +1 -1
- package/dist/cli/commands/start.js +35 -9
- package/dist/cli/commands/start.js.map +1 -1
- package/dist/cli/commands/status.d.ts.map +1 -1
- package/dist/cli/commands/status.js +4 -0
- package/dist/cli/commands/status.js.map +1 -1
- package/dist/cli/config/config-manager.d.ts.map +1 -1
- package/dist/cli/config/config-manager.js +63 -14
- package/dist/cli/config/config-manager.js.map +1 -1
- package/dist/cli/config/types.d.ts +12 -5
- package/dist/cli/config/types.d.ts.map +1 -1
- package/dist/cli/config/types.js +3 -0
- package/dist/cli/config/types.js.map +1 -1
- package/dist/cli/index.js +6 -4
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/runtime/agent-loop-init.d.ts +1 -1
- package/dist/cli/runtime/agent-loop-init.d.ts.map +1 -1
- package/dist/cli/runtime/agent-loop-init.js +8 -3
- package/dist/cli/runtime/agent-loop-init.js.map +1 -1
- package/dist/cli/runtime/gateway-init.d.ts +1 -1
- package/dist/cli/runtime/gateway-init.d.ts.map +1 -1
- package/dist/cli/runtime/gateway-init.js.map +1 -1
- package/dist/cli/runtime/mama-core-init.d.ts +10 -2
- package/dist/cli/runtime/mama-core-init.d.ts.map +1 -1
- package/dist/cli/runtime/mama-core-init.js +52 -68
- package/dist/cli/runtime/mama-core-init.js.map +1 -1
- package/dist/cli/runtime/memory-agent-init.d.ts.map +1 -1
- package/dist/cli/runtime/memory-agent-init.js +18 -5
- package/dist/cli/runtime/memory-agent-init.js.map +1 -1
- package/dist/cli/runtime/scheduler-init.d.ts +4 -0
- package/dist/cli/runtime/scheduler-init.d.ts.map +1 -1
- package/dist/cli/runtime/scheduler-init.js +24 -3
- package/dist/cli/runtime/scheduler-init.js.map +1 -1
- package/dist/cli/runtime/shutdown.d.ts +4 -0
- package/dist/cli/runtime/shutdown.d.ts.map +1 -1
- package/dist/cli/runtime/shutdown.js +30 -6
- package/dist/cli/runtime/shutdown.js.map +1 -1
- package/dist/cli/runtime/utilities.d.ts +2 -0
- package/dist/cli/runtime/utilities.d.ts.map +1 -1
- package/dist/cli/runtime/utilities.js +33 -0
- package/dist/cli/runtime/utilities.js.map +1 -1
- package/dist/gateways/discord.d.ts.map +1 -1
- package/dist/gateways/discord.js +11 -6
- package/dist/gateways/discord.js.map +1 -1
- package/dist/gateways/image-analyzer.d.ts +5 -0
- package/dist/gateways/image-analyzer.d.ts.map +1 -1
- package/dist/gateways/image-analyzer.js +8 -0
- package/dist/gateways/image-analyzer.js.map +1 -1
- package/dist/gateways/message-router.d.ts.map +1 -1
- package/dist/gateways/message-router.js +29 -15
- package/dist/gateways/message-router.js.map +1 -1
- package/dist/gateways/slack.d.ts.map +1 -1
- package/dist/gateways/slack.js +6 -2
- package/dist/gateways/slack.js.map +1 -1
- package/dist/gateways/types.d.ts +1 -1
- package/dist/gateways/types.d.ts.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/multi-agent/agent-process-manager.d.ts +6 -4
- package/dist/multi-agent/agent-process-manager.d.ts.map +1 -1
- package/dist/multi-agent/agent-process-manager.js +103 -34
- package/dist/multi-agent/agent-process-manager.js.map +1 -1
- package/dist/multi-agent/runtime-process.d.ts +3 -0
- package/dist/multi-agent/runtime-process.d.ts.map +1 -1
- package/dist/multi-agent/runtime-process.js +10 -2
- package/dist/multi-agent/runtime-process.js.map +1 -1
- package/dist/multi-agent/types.d.ts +12 -2
- package/dist/multi-agent/types.d.ts.map +1 -1
- package/dist/multi-agent/types.js.map +1 -1
- package/dist/multi-agent/workflow-types.d.ts +1 -1
- package/dist/multi-agent/workflow-types.d.ts.map +1 -1
- package/dist/onboarding/complete-autonomous-prompt.d.ts +1 -1
- package/dist/onboarding/complete-autonomous-prompt.d.ts.map +1 -1
- package/dist/onboarding/complete-autonomous-prompt.js +9 -9
- package/dist/operator/situation-report.d.ts.map +1 -1
- package/dist/operator/situation-report.js +38 -23
- package/dist/operator/situation-report.js.map +1 -1
- package/dist/operator/temporal-runtime.d.ts.map +1 -1
- package/dist/operator/temporal-runtime.js +3 -1
- package/dist/operator/temporal-runtime.js.map +1 -1
- package/dist/operator/trigger-author.d.ts +13 -1
- package/dist/operator/trigger-author.d.ts.map +1 -1
- package/dist/operator/trigger-author.js +35 -0
- package/dist/operator/trigger-author.js.map +1 -1
- package/dist/operator/worker-run.d.ts.map +1 -1
- package/dist/operator/worker-run.js +10 -4
- package/dist/operator/worker-run.js.map +1 -1
- package/dist/scheduler/cron-worker.d.ts +8 -4
- package/dist/scheduler/cron-worker.d.ts.map +1 -1
- package/dist/scheduler/cron-worker.js +56 -39
- package/dist/scheduler/cron-worker.js.map +1 -1
- package/dist/setup/setup-actions.d.ts +26 -0
- package/dist/setup/setup-actions.d.ts.map +1 -0
- package/dist/setup/setup-actions.js +371 -0
- package/dist/setup/setup-actions.js.map +1 -0
- package/dist/setup/setup-prompt.d.ts +1 -1
- package/dist/setup/setup-prompt.d.ts.map +1 -1
- package/dist/setup/setup-prompt.js +28 -33
- package/dist/setup/setup-prompt.js.map +1 -1
- package/dist/setup/setup-server.d.ts +6 -1
- package/dist/setup/setup-server.d.ts.map +1 -1
- package/dist/setup/setup-server.js +55 -9
- package/dist/setup/setup-server.js.map +1 -1
- package/dist/setup/setup-websocket.d.ts +14 -2
- package/dist/setup/setup-websocket.d.ts.map +1 -1
- package/dist/setup/setup-websocket.js +121 -37
- package/dist/setup/setup-websocket.js.map +1 -1
- package/package.json +1 -1
- package/public/setup.html +9 -6
- package/public/viewer/js/modules/agents.js +5 -4
- package/public/viewer/js/modules/settings.js +34 -10
- package/public/viewer/src/modules/agents.ts +5 -4
- package/public/viewer/src/modules/settings.ts +49 -11
- package/public/viewer/src/utils/api.ts +3 -2
package/dist/agent/agent-loop.js
CHANGED
|
@@ -54,6 +54,8 @@ const fs_1 = require("fs");
|
|
|
54
54
|
const prompt_size_monitor_js_1 = require("./prompt-size-monitor.js");
|
|
55
55
|
const skill_loader_js_1 = require("./skill-loader.js");
|
|
56
56
|
const persistent_cli_adapter_js_1 = require("./persistent-cli-adapter.js");
|
|
57
|
+
const cline_cli_adapter_js_1 = require("./cline-cli-adapter.js");
|
|
58
|
+
const cline_native_tool_policy_js_1 = require("./cline-native-tool-policy.js");
|
|
57
59
|
const runtime_process_js_1 = require("../multi-agent/runtime-process.js");
|
|
58
60
|
const model_runner_js_1 = require("./model-runner.js");
|
|
59
61
|
const gateway_tool_executor_js_1 = require("./gateway-tool-executor.js");
|
|
@@ -75,6 +77,14 @@ const pre_compact_handler_js_1 = require("./pre-compact-handler.js");
|
|
|
75
77
|
const debugLogger = __importStar(require("@jungjaehoon/mama-core/debug-logger"));
|
|
76
78
|
const { DebugLogger } = debugLogger;
|
|
77
79
|
const logger = new DebugLogger('AgentLoop');
|
|
80
|
+
const MODEL_RUNNER_AGENT_ERROR_CODES = {
|
|
81
|
+
timeout: 'NETWORK_ERROR',
|
|
82
|
+
crash: 'CLI_ERROR',
|
|
83
|
+
context_overflow: 'MAX_TOKENS',
|
|
84
|
+
auth_failure: 'AUTH_ERROR',
|
|
85
|
+
rate_limit: 'RATE_LIMIT',
|
|
86
|
+
unknown: 'CLI_ERROR',
|
|
87
|
+
};
|
|
78
88
|
/**
|
|
79
89
|
* Default configuration
|
|
80
90
|
*/
|
|
@@ -506,6 +516,11 @@ class AgentLoop {
|
|
|
506
516
|
// overlapping owner chat) would steal each other's callbacks and leak tiers
|
|
507
517
|
// if these were instance fields.
|
|
508
518
|
disallowedTools;
|
|
519
|
+
clineNativeAllowedTools;
|
|
520
|
+
clineNativeDisallowedTools;
|
|
521
|
+
clineNativePolicyConfigured;
|
|
522
|
+
clineAllowSpawnAgent;
|
|
523
|
+
clineAllowAgentTeams;
|
|
509
524
|
constructor(_oauthManager, options = {}, _clientOptions, executorOptions) {
|
|
510
525
|
// Initialize tools config (hybrid Gateway/MCP routing)
|
|
511
526
|
this.toolsConfig = {
|
|
@@ -525,7 +540,9 @@ class AgentLoop {
|
|
|
525
540
|
const useGatewayMode = gatewayTools.includes('*') || gatewayTools.length > 0;
|
|
526
541
|
const useMCPMode = mcpTools.includes('*') || mcpTools.length > 0;
|
|
527
542
|
this.useCodeAct = options.useCodeAct ?? false;
|
|
528
|
-
this.isGatewayMode =
|
|
543
|
+
this.isGatewayMode =
|
|
544
|
+
useGatewayMode ||
|
|
545
|
+
((options.backend === 'codex' || options.backend === 'cline') && this.useCodeAct);
|
|
529
546
|
this.disallowedTools = this.useCodeAct
|
|
530
547
|
? options.disallowedTools
|
|
531
548
|
: [
|
|
@@ -535,6 +552,13 @@ class AgentLoop {
|
|
|
535
552
|
CODE_ACT_MCP_COMPAT_NAME,
|
|
536
553
|
]),
|
|
537
554
|
];
|
|
555
|
+
this.clineNativeAllowedTools = [...(options.clineNativeAllowedTools ?? [])];
|
|
556
|
+
this.clineNativeDisallowedTools = [...(options.clineNativeDisallowedTools ?? [])];
|
|
557
|
+
this.clineNativePolicyConfigured =
|
|
558
|
+
options.clineNativeAllowedTools !== undefined ||
|
|
559
|
+
options.clineNativeDisallowedTools !== undefined;
|
|
560
|
+
this.clineAllowSpawnAgent = options.clineAllowSpawnAgent ?? false;
|
|
561
|
+
this.clineAllowAgentTeams = options.clineAllowAgentTeams ?? false;
|
|
538
562
|
if (useGatewayMode && useMCPMode) {
|
|
539
563
|
logger.debug('🔀 Hybrid mode: Gateway + MCP tools enabled');
|
|
540
564
|
}
|
|
@@ -691,6 +715,25 @@ class AgentLoop {
|
|
|
691
715
|
});
|
|
692
716
|
logger.debug('Codex app-server backend enabled');
|
|
693
717
|
}
|
|
718
|
+
else if (this.backend === 'cline') {
|
|
719
|
+
const workspaceDir = options.clineCwd ?? (0, path_1.join)((0, os_1.homedir)(), '.mama', 'workspace');
|
|
720
|
+
if (!(0, fs_1.existsSync)(workspaceDir)) {
|
|
721
|
+
(0, fs_1.mkdirSync)(workspaceDir, { recursive: true });
|
|
722
|
+
}
|
|
723
|
+
this.agent = new cline_cli_adapter_js_1.ClineCLIAdapter({
|
|
724
|
+
command: options.clineCommand,
|
|
725
|
+
provider: options.clineProvider ?? 'cline',
|
|
726
|
+
model: options.model,
|
|
727
|
+
systemPrompt: defaultSystemPrompt,
|
|
728
|
+
cwd: workspaceDir,
|
|
729
|
+
// Cline receives MAMA CodeAct as a session-bound Hub custom tool.
|
|
730
|
+
// Its shared daemon owns native MCP settings independently.
|
|
731
|
+
dataDir: options.clineDataDir,
|
|
732
|
+
requestTimeout: options.timeoutMs,
|
|
733
|
+
sessionId,
|
|
734
|
+
});
|
|
735
|
+
logger.debug('Cline CLI backend enabled');
|
|
736
|
+
}
|
|
694
737
|
else {
|
|
695
738
|
// Claude backend: always use PersistentCLI for fast responses (~2-3s vs ~16-30s)
|
|
696
739
|
this.persistentCLI = new persistent_cli_adapter_js_1.PersistentCLIAdapter({
|
|
@@ -981,8 +1024,20 @@ class AgentLoop {
|
|
|
981
1024
|
let ownedSession = false;
|
|
982
1025
|
// Set session ID on the agent
|
|
983
1026
|
// Claude PersistentCLI: process alive → CONTINUE (stdin message), process dead → NEW (spawn with --session-id)
|
|
984
|
-
// Codex:
|
|
1027
|
+
// Codex/Cline: durable runtime session alive → CONTINUE, missing → NEW.
|
|
985
1028
|
const isCodex = this.backend === 'codex';
|
|
1029
|
+
const isCline = this.backend === 'cline';
|
|
1030
|
+
const isDurableRuntime = isCodex || isCline;
|
|
1031
|
+
const clineRole = options?.agentContext?.role;
|
|
1032
|
+
const clineAllowedTools = this.clineNativePolicyConfigured
|
|
1033
|
+
? this.clineNativeAllowedTools
|
|
1034
|
+
: (0, cline_native_tool_policy_js_1.projectClineNativeTools)(clineRole?.allowedTools);
|
|
1035
|
+
const clineDisallowedTools = this.clineNativePolicyConfigured
|
|
1036
|
+
? this.clineNativeDisallowedTools
|
|
1037
|
+
: (0, cline_native_tool_policy_js_1.projectClineNativeTools)(clineRole?.blockedTools);
|
|
1038
|
+
const clineDelegationBlocked = clineRole?.blockedTools?.includes('delegate') ?? false;
|
|
1039
|
+
const clineAllowSpawnAgent = this.clineAllowSpawnAgent && !clineDelegationBlocked;
|
|
1040
|
+
const clineAllowAgentTeams = this.clineAllowAgentTeams && !clineDelegationBlocked;
|
|
986
1041
|
const codeActPolicy = this.useCodeAct
|
|
987
1042
|
? (0, index_js_1.projectCodeActToolPolicy)({
|
|
988
1043
|
tier: runScope.tier,
|
|
@@ -995,12 +1050,12 @@ class AgentLoop {
|
|
|
995
1050
|
})
|
|
996
1051
|
: undefined;
|
|
997
1052
|
const outerCodeActAllowed = this.useCodeAct && roleAllowsOuterCodeAct(options?.agentContext?.role, this.disallowedTools);
|
|
998
|
-
const effectiveSessionPolicyFingerprint =
|
|
1053
|
+
const effectiveSessionPolicyFingerprint = isDurableRuntime && codeActPolicy
|
|
999
1054
|
? combineCodeActSessionPolicyFingerprint(options?.sessionPolicyFingerprint, codeActPolicy)
|
|
1000
1055
|
: options?.sessionPolicyFingerprint;
|
|
1001
1056
|
let resolvedCliSessionId = options?.cliSessionId ?? null;
|
|
1002
1057
|
const sessionLabel = (isNew) => {
|
|
1003
|
-
if (
|
|
1058
|
+
if (isDurableRuntime) {
|
|
1004
1059
|
return isNew ? 'NEW thread' : 'CONTINUE thread';
|
|
1005
1060
|
}
|
|
1006
1061
|
return isNew ? 'NEW process' : 'CONTINUE session';
|
|
@@ -1009,7 +1064,7 @@ class AgentLoop {
|
|
|
1009
1064
|
// Session routing travels per prompt() call via resolvedCliSessionId - no
|
|
1010
1065
|
// shared-adapter mutation (setSessionId re-pointed channelKey/currentProcess
|
|
1011
1066
|
// across awaits, cross-wiring concurrent lanes).
|
|
1012
|
-
console.log(`[AgentLoop] [${
|
|
1067
|
+
console.log(`[AgentLoop] [${this.backend}] ${channelKey} (${sessionLabel(sessionIsNew)})`);
|
|
1013
1068
|
}
|
|
1014
1069
|
else if (options?.freshSession) {
|
|
1015
1070
|
// Stateless lanes (operator reports): session context is a cache, not
|
|
@@ -1020,7 +1075,7 @@ class AgentLoop {
|
|
|
1020
1075
|
sessionIsNew = true;
|
|
1021
1076
|
ownedSession = true;
|
|
1022
1077
|
resolvedCliSessionId = cliSessionId;
|
|
1023
|
-
console.log(`[AgentLoop] [${
|
|
1078
|
+
console.log(`[AgentLoop] [${this.backend}] ${channelKey} (FRESH session - stateless lane)`);
|
|
1024
1079
|
}
|
|
1025
1080
|
else {
|
|
1026
1081
|
// Fallback: get session from pool (for direct AgentLoop usage)
|
|
@@ -1033,7 +1088,7 @@ class AgentLoop {
|
|
|
1033
1088
|
ownedSession = true;
|
|
1034
1089
|
resolvedCliSessionId = cliSessionId;
|
|
1035
1090
|
// Per-call routing via resolvedCliSessionId - no shared-adapter mutation.
|
|
1036
|
-
console.log(`[AgentLoop] [${
|
|
1091
|
+
console.log(`[AgentLoop] [${this.backend}] ${channelKey} (${sessionLabel(isNew)})`);
|
|
1037
1092
|
}
|
|
1038
1093
|
try {
|
|
1039
1094
|
if (this.shouldBeginModelRun(options)) {
|
|
@@ -1047,7 +1102,7 @@ class AgentLoop {
|
|
|
1047
1102
|
let nativeToolCallCount = 0;
|
|
1048
1103
|
let nativeConsecutiveToolCalls = 0;
|
|
1049
1104
|
let nativeLastToolSignature = '';
|
|
1050
|
-
const hostToolBridge =
|
|
1105
|
+
const hostToolBridge = isDurableRuntime && this.isGatewayMode
|
|
1051
1106
|
? {
|
|
1052
1107
|
tools: this.useCodeAct
|
|
1053
1108
|
? outerCodeActAllowed
|
|
@@ -1089,13 +1144,18 @@ class AgentLoop {
|
|
|
1089
1144
|
name: call.name,
|
|
1090
1145
|
input: call.input,
|
|
1091
1146
|
};
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
content: [toolUse]
|
|
1097
|
-
|
|
1098
|
-
|
|
1147
|
+
// Codex does not return completed host exchanges, so record them
|
|
1148
|
+
// here. Cline reports the paired custom-tool exchange from its Hub
|
|
1149
|
+
// event stream and AgentLoop appends it exactly once below.
|
|
1150
|
+
if (isCodex) {
|
|
1151
|
+
history.push({ role: 'assistant', content: [toolUse] });
|
|
1152
|
+
runScope.onTurn?.({
|
|
1153
|
+
turn,
|
|
1154
|
+
role: 'assistant',
|
|
1155
|
+
content: [toolUse],
|
|
1156
|
+
stopReason: 'tool_use',
|
|
1157
|
+
});
|
|
1158
|
+
}
|
|
1099
1159
|
const callExecutionContext = toolExecutionContext
|
|
1100
1160
|
? {
|
|
1101
1161
|
...toolExecutionContext,
|
|
@@ -1115,13 +1175,15 @@ class AgentLoop {
|
|
|
1115
1175
|
if (!toolResult.terminalCode) {
|
|
1116
1176
|
callSignal.throwIfAborted();
|
|
1117
1177
|
}
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1178
|
+
if (isCodex) {
|
|
1179
|
+
const persistedToolResult = historyToolResult(toolResult);
|
|
1180
|
+
history.push({ role: 'user', content: [persistedToolResult] });
|
|
1181
|
+
runScope.onTurn?.({
|
|
1182
|
+
turn,
|
|
1183
|
+
role: 'user',
|
|
1184
|
+
content: [persistedToolResult],
|
|
1185
|
+
});
|
|
1186
|
+
}
|
|
1125
1187
|
return {
|
|
1126
1188
|
content: toolResult.content,
|
|
1127
1189
|
isError: toolResult.is_error === true,
|
|
@@ -1141,7 +1203,7 @@ class AgentLoop {
|
|
|
1141
1203
|
if (outerCodeActAllowed) {
|
|
1142
1204
|
const policy = codeActPolicy;
|
|
1143
1205
|
const typeDefs = index_js_1.TypeDefinitionGenerator.generate(policy);
|
|
1144
|
-
gatewayToolsPrompt = wrapGeneratedPromptSection('codeAct', (0, index_js_1.getCodeActInstructions)(
|
|
1206
|
+
gatewayToolsPrompt = wrapGeneratedPromptSection('codeAct', (0, index_js_1.getCodeActInstructions)(this.backend, policy.names) +
|
|
1145
1207
|
'\n```typescript\n' +
|
|
1146
1208
|
typeDefs +
|
|
1147
1209
|
'\n```');
|
|
@@ -1201,7 +1263,13 @@ class AgentLoop {
|
|
|
1201
1263
|
return effectivePrompt;
|
|
1202
1264
|
};
|
|
1203
1265
|
let perCallSystemPrompt;
|
|
1204
|
-
if (
|
|
1266
|
+
if (isCline && this.isGatewayMode && this.useCodeAct && !sessionIsNew) {
|
|
1267
|
+
// TG-05: a compatible Cline Hub session ignores the per-call system prompt.
|
|
1268
|
+
// Keep the continuation stub cheap; missing/mismatched sessions rebuild the
|
|
1269
|
+
// complete policy lazily through freshSessionSystemPrompt below.
|
|
1270
|
+
perCallSystemPrompt = options?.systemPrompt ?? this.defaultSystemPrompt;
|
|
1271
|
+
}
|
|
1272
|
+
else if (options?.systemPrompt ||
|
|
1205
1273
|
options?.gatewayToolsPrompt !== undefined ||
|
|
1206
1274
|
(this.isGatewayMode && this.useCodeAct)) {
|
|
1207
1275
|
perCallSystemPrompt = prepareSystemPrompt(options?.systemPrompt, options?.resumeSession === true);
|
|
@@ -1210,15 +1278,15 @@ class AgentLoop {
|
|
|
1210
1278
|
perCallSystemPrompt = this.defaultSystemPrompt;
|
|
1211
1279
|
console.log(`[AgentLoop] No systemPrompt in options - using spawn default for this call`);
|
|
1212
1280
|
}
|
|
1213
|
-
//
|
|
1214
|
-
//
|
|
1281
|
+
// Durable backends re-anchor a lost session with the complete current policy.
|
|
1282
|
+
// A CONTINUE
|
|
1215
1283
|
// turn's per-call prompt is deliberately minimal (message-router
|
|
1216
1284
|
// buildMinimalResumePrompt), so resuming with it would REPLACE the thread's full
|
|
1217
1285
|
// policy with a stub - only freshSessionSystemPrompt rebuilds the complete one.
|
|
1218
1286
|
// That rebuild costs an embedding search, so hand the backend a lazy builder it
|
|
1219
1287
|
// invokes only inside the resume branch; a live thread never pays for it.
|
|
1220
1288
|
const freshSystemPromptBuilder = options?.freshSessionSystemPrompt;
|
|
1221
|
-
const resumeInstructions =
|
|
1289
|
+
const resumeInstructions = isDurableRuntime && freshSystemPromptBuilder
|
|
1222
1290
|
? async () => prepareSystemPrompt(await freshSystemPromptBuilder(), false)
|
|
1223
1291
|
: undefined;
|
|
1224
1292
|
// Reset StopContinuation state for this channel to prevent leaking
|
|
@@ -1276,24 +1344,27 @@ class AgentLoop {
|
|
|
1276
1344
|
};
|
|
1277
1345
|
let piResult;
|
|
1278
1346
|
// Claude: First turn → --session-id (inject system prompt), subsequent → --resume
|
|
1279
|
-
// Codex: resumeSession
|
|
1280
|
-
let shouldResume =
|
|
1347
|
+
// Codex/Cline: resumeSession controls durable session reset/continuation.
|
|
1348
|
+
let shouldResume = isDurableRuntime
|
|
1281
1349
|
? turn > 1 || (options?.freshSession === true ? false : (options?.resumeSession ?? true))
|
|
1282
1350
|
: !sessionIsNew || turn > 1;
|
|
1283
1351
|
let requestSystemPrompt = perCallSystemPrompt;
|
|
1284
|
-
let
|
|
1285
|
-
//
|
|
1352
|
+
let provisionalDurableSessionId;
|
|
1353
|
+
// All three backends preserve context and receive only the new user message.
|
|
1286
1354
|
const promptText = this.formatLastMessageOnly(history);
|
|
1287
1355
|
const promptStart = Date.now();
|
|
1288
1356
|
const throwFinalCliError = (error) => {
|
|
1289
1357
|
const normalizedError = error instanceof Error ? error : new Error(String(error));
|
|
1358
|
+
const modelRunnerErrorCode = normalizedError instanceof model_runner_js_1.ModelRunnerError
|
|
1359
|
+
? MODEL_RUNNER_AGENT_ERROR_CODES[normalizedError.code]
|
|
1360
|
+
: undefined;
|
|
1290
1361
|
const errorType = normalizedError instanceof types_js_1.McpResultMissingError ||
|
|
1291
1362
|
normalizedError instanceof types_js_1.McpCompletedMutationInterruptedError ||
|
|
1292
1363
|
normalizedError instanceof types_js_1.ClaudeToolStreamProtocolError
|
|
1293
1364
|
? normalizedError.code
|
|
1294
1365
|
: normalizedError instanceof model_runner_js_1.HostToolTerminalError
|
|
1295
1366
|
? normalizedError.terminalCode
|
|
1296
|
-
: 'CLI_ERROR';
|
|
1367
|
+
: (modelRunnerErrorCode ?? 'CLI_ERROR');
|
|
1297
1368
|
this.onMetric?.('prompt_error', 1, {
|
|
1298
1369
|
backend: this.backend,
|
|
1299
1370
|
error_type: errorType,
|
|
@@ -1307,12 +1378,15 @@ class AgentLoop {
|
|
|
1307
1378
|
if (normalizedError instanceof model_runner_js_1.HostToolTerminalError) {
|
|
1308
1379
|
throw new types_js_1.AgentError(normalizedError.message, normalizedError.terminalCode, normalizedError, false);
|
|
1309
1380
|
}
|
|
1381
|
+
if (normalizedError instanceof model_runner_js_1.HostToolAbortError) {
|
|
1382
|
+
throw new types_js_1.AgentError(normalizedError.message, 'CLI_ERROR', normalizedError, false);
|
|
1383
|
+
}
|
|
1310
1384
|
if (normalizedError instanceof types_js_1.McpResultMissingError ||
|
|
1311
1385
|
normalizedError instanceof types_js_1.McpCompletedMutationInterruptedError ||
|
|
1312
1386
|
normalizedError instanceof types_js_1.ClaudeToolStreamProtocolError) {
|
|
1313
1387
|
throw new types_js_1.AgentError(normalizedError.message, normalizedError.code, normalizedError, false);
|
|
1314
1388
|
}
|
|
1315
|
-
throw new types_js_1.AgentError(`CLI error: ${normalizedError.message}`, 'CLI_ERROR', normalizedError, true);
|
|
1389
|
+
throw new types_js_1.AgentError(`CLI error: ${normalizedError.message}`, modelRunnerErrorCode ?? 'CLI_ERROR', normalizedError, normalizedError instanceof model_runner_js_1.ModelRunnerError ? normalizedError.retryable : true);
|
|
1316
1390
|
};
|
|
1317
1391
|
const appendCompletedToolExchanges = (exchanges) => {
|
|
1318
1392
|
for (const exchange of exchanges) {
|
|
@@ -1332,7 +1406,7 @@ class AgentLoop {
|
|
|
1332
1406
|
}
|
|
1333
1407
|
};
|
|
1334
1408
|
try {
|
|
1335
|
-
const durablePolicyStatus =
|
|
1409
|
+
const durablePolicyStatus = isDurableRuntime && turn === 1 && shouldResume
|
|
1336
1410
|
? this.agent.getSessionPolicyStatus?.({
|
|
1337
1411
|
model: options?.model,
|
|
1338
1412
|
resumeSession: true,
|
|
@@ -1342,15 +1416,23 @@ class AgentLoop {
|
|
|
1342
1416
|
sessionId: resolvedCliSessionId ?? undefined,
|
|
1343
1417
|
requestTimeout: options?.requestTimeoutMs,
|
|
1344
1418
|
hostToolBridge,
|
|
1419
|
+
...(isCline
|
|
1420
|
+
? {
|
|
1421
|
+
allowedTools: clineAllowedTools,
|
|
1422
|
+
disallowedTools: clineDisallowedTools,
|
|
1423
|
+
allowSpawnAgent: clineAllowSpawnAgent,
|
|
1424
|
+
allowAgentTeams: clineAllowAgentTeams,
|
|
1425
|
+
}
|
|
1426
|
+
: {}),
|
|
1345
1427
|
})
|
|
1346
1428
|
: undefined;
|
|
1347
1429
|
if (durablePolicyStatus === 'mismatch' || durablePolicyStatus === 'missing') {
|
|
1348
|
-
console.log(`[AgentLoop]
|
|
1430
|
+
console.log(`[AgentLoop] ${this.backend} durable session ${durablePolicyStatus}; ` +
|
|
1349
1431
|
'opening the full policy before model request');
|
|
1350
1432
|
const newSessionId = this.sessionPool.resetSession(channelKey);
|
|
1351
1433
|
options?.onCliSessionReset?.(newSessionId);
|
|
1352
1434
|
resolvedCliSessionId = newSessionId;
|
|
1353
|
-
|
|
1435
|
+
provisionalDurableSessionId = newSessionId;
|
|
1354
1436
|
try {
|
|
1355
1437
|
if (options?.freshSessionSystemPrompt) {
|
|
1356
1438
|
requestSystemPrompt = prepareSystemPrompt(await options.freshSessionSystemPrompt(), false);
|
|
@@ -1358,7 +1440,7 @@ class AgentLoop {
|
|
|
1358
1440
|
}
|
|
1359
1441
|
catch (rebuildError) {
|
|
1360
1442
|
this.sessionPool.invalidateSession(channelKey, newSessionId);
|
|
1361
|
-
|
|
1443
|
+
provisionalDurableSessionId = undefined;
|
|
1362
1444
|
attemptReportedError =
|
|
1363
1445
|
rebuildError instanceof Error ? rebuildError : new Error(String(rebuildError));
|
|
1364
1446
|
throw rebuildError;
|
|
@@ -1378,13 +1460,21 @@ class AgentLoop {
|
|
|
1378
1460
|
requestTimeout: options?.requestTimeoutMs,
|
|
1379
1461
|
hostToolBridge,
|
|
1380
1462
|
toolExecutionContext,
|
|
1463
|
+
...(isCline
|
|
1464
|
+
? {
|
|
1465
|
+
allowedTools: clineAllowedTools,
|
|
1466
|
+
disallowedTools: clineDisallowedTools,
|
|
1467
|
+
allowSpawnAgent: clineAllowSpawnAgent,
|
|
1468
|
+
allowAgentTeams: clineAllowAgentTeams,
|
|
1469
|
+
}
|
|
1470
|
+
: {}),
|
|
1381
1471
|
});
|
|
1382
|
-
|
|
1472
|
+
provisionalDurableSessionId = undefined;
|
|
1383
1473
|
}
|
|
1384
1474
|
catch (error) {
|
|
1385
|
-
if (
|
|
1386
|
-
this.sessionPool.invalidateSession(channelKey,
|
|
1387
|
-
|
|
1475
|
+
if (provisionalDurableSessionId) {
|
|
1476
|
+
this.sessionPool.invalidateSession(channelKey, provisionalDurableSessionId);
|
|
1477
|
+
provisionalDurableSessionId = undefined;
|
|
1388
1478
|
}
|
|
1389
1479
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
1390
1480
|
console.error(`[AgentLoop] ${this.backend} CLI error:`, errorMessage);
|
|
@@ -1396,13 +1486,18 @@ class AgentLoop {
|
|
|
1396
1486
|
appendCompletedToolExchanges(error.completedToolExchanges);
|
|
1397
1487
|
throwFinalCliError(error);
|
|
1398
1488
|
}
|
|
1489
|
+
if (error instanceof model_runner_js_1.HostToolAbortError && error.completedToolExchanges.length > 0) {
|
|
1490
|
+
appendCompletedToolExchanges(error.completedToolExchanges);
|
|
1491
|
+
throwFinalCliError(error);
|
|
1492
|
+
}
|
|
1399
1493
|
// Check if this is a recoverable session error
|
|
1400
1494
|
// 1. "No conversation found" - CLI session was lost (daemon restart, timeout)
|
|
1401
1495
|
// 2. "Session ID already in use" - concurrent request conflict
|
|
1402
1496
|
// 3. "Prompt is too long" - session context exceeded API limits
|
|
1403
1497
|
const isSessionNotFound = errorMessage.includes('No conversation found with session ID');
|
|
1404
1498
|
const isSessionInUse = errorMessage.includes('is already in use');
|
|
1405
|
-
const isPromptTooLong =
|
|
1499
|
+
const isPromptTooLong = (error instanceof model_runner_js_1.ModelRunnerError && error.code === 'context_overflow') ||
|
|
1500
|
+
errorMessage.includes('Prompt is too long') ||
|
|
1406
1501
|
errorMessage.includes('prompt is too long') ||
|
|
1407
1502
|
errorMessage.includes('request_too_large') ||
|
|
1408
1503
|
errorMessage.includes('context window') ||
|
|
@@ -1433,16 +1528,16 @@ class AgentLoop {
|
|
|
1433
1528
|
// Per-call routing: hand the new id to this prompt() and update the
|
|
1434
1529
|
// resolved id so later turns follow it - no shared-adapter mutation.
|
|
1435
1530
|
resolvedCliSessionId = newSessionId;
|
|
1436
|
-
// A
|
|
1437
|
-
// whose per-call prompt is intentionally minimal.
|
|
1438
|
-
// policy
|
|
1531
|
+
// A recoverable durable-session error can occur on a resumed
|
|
1532
|
+
// MessageRouter session whose per-call prompt is intentionally minimal.
|
|
1533
|
+
// Rebuild the full policy before opening every replacement session.
|
|
1439
1534
|
let resetSystemPrompt = perCallSystemPrompt;
|
|
1440
1535
|
try {
|
|
1441
1536
|
// Discard the recoverable first-attempt error before any reset
|
|
1442
1537
|
// preparation. A prompt rebuild or retry failure must surface
|
|
1443
1538
|
// its own final error, never the mismatch that triggered it.
|
|
1444
1539
|
attemptReportedError = undefined;
|
|
1445
|
-
if (
|
|
1540
|
+
if (options?.freshSessionSystemPrompt) {
|
|
1446
1541
|
resetSystemPrompt = prepareSystemPrompt(await options.freshSessionSystemPrompt(), false);
|
|
1447
1542
|
}
|
|
1448
1543
|
piResult = await this.agent.prompt(promptText, callbacks, {
|
|
@@ -1456,6 +1551,14 @@ class AgentLoop {
|
|
|
1456
1551
|
requestTimeout: options?.requestTimeoutMs,
|
|
1457
1552
|
hostToolBridge,
|
|
1458
1553
|
toolExecutionContext,
|
|
1554
|
+
...(isCline
|
|
1555
|
+
? {
|
|
1556
|
+
allowedTools: clineAllowedTools,
|
|
1557
|
+
disallowedTools: clineDisallowedTools,
|
|
1558
|
+
allowSpawnAgent: clineAllowSpawnAgent,
|
|
1559
|
+
allowAgentTeams: clineAllowAgentTeams,
|
|
1560
|
+
}
|
|
1561
|
+
: {}),
|
|
1459
1562
|
});
|
|
1460
1563
|
}
|
|
1461
1564
|
catch (retryError) {
|
|
@@ -1493,7 +1596,7 @@ class AgentLoop {
|
|
|
1493
1596
|
const contentBlocks = [];
|
|
1494
1597
|
let parsedToolCalls = [];
|
|
1495
1598
|
// Parse tool_call / code_act blocks from text response (Gateway Tools mode ONLY)
|
|
1496
|
-
if (this.isGatewayMode && !
|
|
1599
|
+
if (this.isGatewayMode && !isDurableRuntime) {
|
|
1497
1600
|
parsedToolCalls = this.parseToolCallsFromText(piResult.response || '');
|
|
1498
1601
|
// Code-Act: parse ```js blocks only if enabled
|
|
1499
1602
|
if (this.useCodeAct) {
|
|
@@ -1570,9 +1673,9 @@ class AgentLoop {
|
|
|
1570
1673
|
// Ignore recording errors - never break the agent loop
|
|
1571
1674
|
}
|
|
1572
1675
|
}
|
|
1573
|
-
//
|
|
1574
|
-
|
|
1575
|
-
const tokenStatus = this.sessionPool.updateTokens(channelKey, response.usage.input_tokens,
|
|
1676
|
+
// Preserve the SessionPool usage-status contract. Billing telemetry is
|
|
1677
|
+
// recorded above; durable runtimes own model-aware compaction.
|
|
1678
|
+
const tokenStatus = this.sessionPool.updateTokens(channelKey, response.usage.input_tokens, this.backend);
|
|
1576
1679
|
// Claude's MCP server may already have executed these tool calls while the
|
|
1577
1680
|
// prompt was streaming. Preserve the observed exchange in conversation
|
|
1578
1681
|
// order, but never put the completed tool_use back into executeTools().
|
|
@@ -1588,7 +1691,8 @@ class AgentLoop {
|
|
|
1588
1691
|
if (piResult.terminalError) {
|
|
1589
1692
|
throwFinalCliError(new model_runner_js_1.HostToolTerminalError(piResult.terminalError.code, piResult.terminalError.message));
|
|
1590
1693
|
}
|
|
1591
|
-
// PreCompact
|
|
1694
|
+
// PreCompact remains available for a future authoritative occupancy
|
|
1695
|
+
// signal. Runtime-owned sessions do not infer one from usage telemetry.
|
|
1592
1696
|
if (tokenStatus.nearThreshold && this.preCompactHandler && !runScope.preCompactInjected) {
|
|
1593
1697
|
runScope.preCompactInjected = true;
|
|
1594
1698
|
try {
|
|
@@ -2016,6 +2120,7 @@ class AgentLoop {
|
|
|
2016
2120
|
* Persistent CLI maintains context automatically, so we only send the new message
|
|
2017
2121
|
*/
|
|
2018
2122
|
formatLastMessageOnly(history) {
|
|
2123
|
+
const imageReaderTool = this.backend === 'cline' ? 'read_files' : this.backend === 'codex' ? 'view_image' : 'Read';
|
|
2019
2124
|
// Find the last user message in the history
|
|
2020
2125
|
for (let i = history.length - 1; i >= 0; i--) {
|
|
2021
2126
|
const msg = history[i];
|
|
@@ -2035,9 +2140,9 @@ class AgentLoop {
|
|
|
2035
2140
|
else if (block.type === 'image' && block.localPath) {
|
|
2036
2141
|
parts.push(`⚠️ CRITICAL: The user has uploaded an image file.\n` +
|
|
2037
2142
|
`Image path: ${block.localPath}\n` +
|
|
2038
|
-
`You MUST call the
|
|
2143
|
+
`You MUST call the ${imageReaderTool} tool on "${block.localPath}" to view this image FIRST.\n` +
|
|
2039
2144
|
`DO NOT describe or guess the image contents without reading it.\n` +
|
|
2040
|
-
`DO NOT say you cannot read images -
|
|
2145
|
+
`DO NOT say you cannot read images - ${imageReaderTool} supports image files.`);
|
|
2041
2146
|
}
|
|
2042
2147
|
else if (block.type === 'image' && block.source?.data) {
|
|
2043
2148
|
// Base64-encoded image — save to disk so persistent CLI can read it
|
|
@@ -2061,9 +2166,9 @@ class AgentLoop {
|
|
|
2061
2166
|
fs.writeFileSync(imagePath, Buffer.from(block.source.data, 'base64'));
|
|
2062
2167
|
parts.push(`⚠️ CRITICAL: The user has uploaded an image file.\n` +
|
|
2063
2168
|
`Image path: ${imagePath}\n` +
|
|
2064
|
-
`You MUST call the
|
|
2169
|
+
`You MUST call the ${imageReaderTool} tool on "${imagePath}" to view this image FIRST.\n` +
|
|
2065
2170
|
`DO NOT describe or guess the image contents without reading it.\n` +
|
|
2066
|
-
`DO NOT say you cannot read images -
|
|
2171
|
+
`DO NOT say you cannot read images - ${imageReaderTool} supports image files.`);
|
|
2067
2172
|
}
|
|
2068
2173
|
catch {
|
|
2069
2174
|
parts.push('[Image attached but could not be processed]');
|