qlogicagent 0.2.1 → 0.3.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.js +1 -0
- package/dist/cli.js +9 -0
- package/dist/contracts.js +1 -0
- package/dist/index.js +5 -15
- package/dist/orchestration.js +118 -0
- package/package.json +56 -42
- package/dist/agent/agent.js +0 -113
- package/dist/agent/tool-loop.js +0 -575
- package/dist/agent/types.js +0 -14
- package/dist/cli/main.js +0 -23
- package/dist/cli/stdio-server.js +0 -463
- package/dist/config/config.js +0 -21
- package/dist/contracts/hooks.js +0 -7
- package/dist/contracts/index.js +0 -10
- package/dist/contracts/planner.js +0 -2
- package/dist/contracts/skill-candidate.js +0 -195
- package/dist/contracts/todo.js +0 -9
- package/dist/llm/builtin-providers.js +0 -531
- package/dist/llm/index.js +0 -14
- package/dist/llm/llm-client.js +0 -67
- package/dist/llm/model-catalog.js +0 -191
- package/dist/llm/provider-def.js +0 -12
- package/dist/llm/provider-registry.js +0 -147
- package/dist/llm/transport.js +0 -27
- package/dist/llm/transports/anthropic-messages.js +0 -293
- package/dist/llm/transports/openai-chat.js +0 -165
- package/dist/orchestration/agent-registry.js +0 -116
- package/dist/orchestration/approval-aware-tool-plan.js +0 -87
- package/dist/orchestration/context-compression.js +0 -583
- package/dist/orchestration/conversation-repair.js +0 -429
- package/dist/orchestration/curator-scheduler.js +0 -135
- package/dist/orchestration/embedded-failover-policy.js +0 -168
- package/dist/orchestration/error-classification.js +0 -77
- package/dist/orchestration/failover-classification.js +0 -381
- package/dist/orchestration/failover-error.js +0 -198
- package/dist/orchestration/fork-subagent.js +0 -98
- package/dist/orchestration/index.js +0 -267
- package/dist/orchestration/memory-flush-policy.js +0 -85
- package/dist/orchestration/memory-provider.js +0 -2
- package/dist/orchestration/parallel-tool-calls.js +0 -59
- package/dist/orchestration/prompt-cache-strategy.js +0 -228
- package/dist/orchestration/reactive-compact.js +0 -78
- package/dist/orchestration/retry-loop.js +0 -24
- package/dist/orchestration/skill-candidate.js +0 -141
- package/dist/orchestration/skill-consolidation.js +0 -220
- package/dist/orchestration/skill-improvement.js +0 -66
- package/dist/orchestration/skill-similarity.js +0 -131
- package/dist/orchestration/streaming-tool-executor.js +0 -96
- package/dist/orchestration/team-orchestration.js +0 -369
- package/dist/orchestration/team-tool-loop-wiring.js +0 -147
- package/dist/orchestration/tool-choice-policy.js +0 -164
- package/dist/orchestration/tool-loop-state.js +0 -133
- package/dist/orchestration/tool-schema.js +0 -297
- package/dist/orchestration/transcript-repair.js +0 -426
- package/dist/orchestration/turn-loop-guard.js +0 -92
- package/dist/orchestration/web-browser-policy.js +0 -39
- package/dist/runtime/context-compression.js +0 -274
- package/dist/runtime/hook-registry.js +0 -53
- package/dist/runtime/memory-hooks.js +0 -65
- package/dist/runtime/tool-eligibility.js +0 -111
- package/dist/skills/index.js +0 -82
- package/dist/skills/memory-extractor.js +0 -173
- package/dist/skills/memory-query-tool.js +0 -127
- package/dist/skills/memory-store.js +0 -228
- package/dist/skills/memory-tool.js +0 -192
- package/dist/skills/portable-tool.js +0 -14
- package/dist/skills/qmemory-adapter.js +0 -165
- package/dist/skills/skill-frontmatter.js +0 -344
- package/dist/skills/skill-guard.js +0 -229
- package/dist/skills/skill-loader.js +0 -303
- package/dist/skills/skill-source.js +0 -126
- package/dist/skills/skill-types.js +0 -6
- package/dist/skills/think-tool.js +0 -59
- package/dist/skills/todo-tool.js +0 -114
- package/dist/skills/tools/agent-tool.js +0 -142
- package/dist/skills/tools/apply-patch-tool.js +0 -184
- package/dist/skills/tools/ask-user-tool.js +0 -121
- package/dist/skills/tools/brief-tool.js +0 -95
- package/dist/skills/tools/browser-tool.js +0 -155
- package/dist/skills/tools/checkpoint-tool.js +0 -102
- package/dist/skills/tools/config-tool.js +0 -143
- package/dist/skills/tools/cron-tool.js +0 -175
- package/dist/skills/tools/edit-tool.js +0 -70
- package/dist/skills/tools/exec-tool.js +0 -133
- package/dist/skills/tools/image-generate-tool.js +0 -67
- package/dist/skills/tools/instructions-tool.js +0 -187
- package/dist/skills/tools/lsp-tool.js +0 -227
- package/dist/skills/tools/mcp-client-types.js +0 -53
- package/dist/skills/tools/mcp-tool.js +0 -503
- package/dist/skills/tools/memory-tool.js +0 -88
- package/dist/skills/tools/monitor-tool.js +0 -131
- package/dist/skills/tools/music-generate-tool.js +0 -62
- package/dist/skills/tools/notify-tool.js +0 -62
- package/dist/skills/tools/patch-tool.js +0 -505
- package/dist/skills/tools/pdf-tool.js +0 -88
- package/dist/skills/tools/plan-mode-tool.js +0 -122
- package/dist/skills/tools/read-tool.js +0 -84
- package/dist/skills/tools/repl-tool.js +0 -69
- package/dist/skills/tools/search-tool.js +0 -225
- package/dist/skills/tools/send-message-tool.js +0 -76
- package/dist/skills/tools/skill-list-tool.js +0 -54
- package/dist/skills/tools/skill-manage-tool.js +0 -153
- package/dist/skills/tools/skill-view-tool.js +0 -72
- package/dist/skills/tools/sleep-tool.js +0 -81
- package/dist/skills/tools/structured-output-tool.js +0 -176
- package/dist/skills/tools/task-tool.js +0 -161
- package/dist/skills/tools/team-tool.js +0 -105
- package/dist/skills/tools/tool-search-tool.js +0 -110
- package/dist/skills/tools/tts-tool.js +0 -45
- package/dist/skills/tools/video-edit-tool.js +0 -74
- package/dist/skills/tools/video-generate-tool.js +0 -66
- package/dist/skills/tools/video-merge-tool.js +0 -92
- package/dist/skills/tools/video-upscale-tool.js +0 -52
- package/dist/skills/tools/web-fetch-tool.js +0 -92
- package/dist/skills/tools/web-search-tool.js +0 -86
- package/dist/skills/tools/worktree-tool.js +0 -147
- package/dist/skills/tools/write-tool.js +0 -81
- /package/dist/{agent → types/agent}/agent.d.ts +0 -0
- /package/dist/{agent → types/agent}/tool-loop.d.ts +0 -0
- /package/dist/{agent → types/agent}/types.d.ts +0 -0
- /package/dist/{cli → types/cli}/main.d.ts +0 -0
- /package/dist/{cli → types/cli}/stdio-server.d.ts +0 -0
- /package/dist/{config → types/config}/config.d.ts +0 -0
- /package/dist/{contracts → types/contracts}/hooks.d.ts +0 -0
- /package/dist/{contracts → types/contracts}/index.d.ts +0 -0
- /package/dist/{contracts → types/contracts}/planner.d.ts +0 -0
- /package/dist/{contracts → types/contracts}/skill-candidate.d.ts +0 -0
- /package/dist/{contracts → types/contracts}/todo.d.ts +0 -0
- /package/dist/{index.d.ts → types/index.d.ts} +0 -0
- /package/dist/{llm → types/llm}/builtin-providers.d.ts +0 -0
- /package/dist/{llm → types/llm}/index.d.ts +0 -0
- /package/dist/{llm → types/llm}/llm-client.d.ts +0 -0
- /package/dist/{llm → types/llm}/model-catalog.d.ts +0 -0
- /package/dist/{llm → types/llm}/provider-def.d.ts +0 -0
- /package/dist/{llm → types/llm}/provider-registry.d.ts +0 -0
- /package/dist/{llm → types/llm}/transport.d.ts +0 -0
- /package/dist/{llm → types/llm}/transports/anthropic-messages.d.ts +0 -0
- /package/dist/{llm → types/llm}/transports/openai-chat.d.ts +0 -0
- /package/dist/{orchestration → types/orchestration}/agent-registry.d.ts +0 -0
- /package/dist/{orchestration → types/orchestration}/approval-aware-tool-plan.d.ts +0 -0
- /package/dist/{orchestration → types/orchestration}/context-compression.d.ts +0 -0
- /package/dist/{orchestration → types/orchestration}/conversation-repair.d.ts +0 -0
- /package/dist/{orchestration → types/orchestration}/curator-scheduler.d.ts +0 -0
- /package/dist/{orchestration → types/orchestration}/embedded-failover-policy.d.ts +0 -0
- /package/dist/{orchestration → types/orchestration}/error-classification.d.ts +0 -0
- /package/dist/{orchestration → types/orchestration}/failover-classification.d.ts +0 -0
- /package/dist/{orchestration → types/orchestration}/failover-error.d.ts +0 -0
- /package/dist/{orchestration → types/orchestration}/fork-subagent.d.ts +0 -0
- /package/dist/{orchestration → types/orchestration}/index.d.ts +0 -0
- /package/dist/{orchestration → types/orchestration}/memory-flush-policy.d.ts +0 -0
- /package/dist/{orchestration → types/orchestration}/memory-provider.d.ts +0 -0
- /package/dist/{orchestration → types/orchestration}/parallel-tool-calls.d.ts +0 -0
- /package/dist/{orchestration → types/orchestration}/prompt-cache-strategy.d.ts +0 -0
- /package/dist/{orchestration → types/orchestration}/reactive-compact.d.ts +0 -0
- /package/dist/{orchestration → types/orchestration}/retry-loop.d.ts +0 -0
- /package/dist/{orchestration → types/orchestration}/skill-candidate.d.ts +0 -0
- /package/dist/{orchestration → types/orchestration}/skill-consolidation.d.ts +0 -0
- /package/dist/{orchestration → types/orchestration}/skill-improvement.d.ts +0 -0
- /package/dist/{orchestration → types/orchestration}/skill-similarity.d.ts +0 -0
- /package/dist/{orchestration → types/orchestration}/streaming-tool-executor.d.ts +0 -0
- /package/dist/{orchestration → types/orchestration}/team-orchestration.d.ts +0 -0
- /package/dist/{orchestration → types/orchestration}/team-tool-loop-wiring.d.ts +0 -0
- /package/dist/{orchestration → types/orchestration}/tool-choice-policy.d.ts +0 -0
- /package/dist/{orchestration → types/orchestration}/tool-loop-state.d.ts +0 -0
- /package/dist/{orchestration → types/orchestration}/tool-schema.d.ts +0 -0
- /package/dist/{orchestration → types/orchestration}/transcript-repair.d.ts +0 -0
- /package/dist/{orchestration → types/orchestration}/turn-loop-guard.d.ts +0 -0
- /package/dist/{orchestration → types/orchestration}/web-browser-policy.d.ts +0 -0
- /package/dist/{runtime → types/runtime}/context-compression.d.ts +0 -0
- /package/dist/{runtime → types/runtime}/hook-registry.d.ts +0 -0
- /package/dist/{runtime → types/runtime}/memory-hooks.d.ts +0 -0
- /package/dist/{runtime → types/runtime}/tool-eligibility.d.ts +0 -0
- /package/dist/{skills → types/skills}/index.d.ts +0 -0
- /package/dist/{skills → types/skills}/memory-extractor.d.ts +0 -0
- /package/dist/{skills → types/skills}/memory-query-tool.d.ts +0 -0
- /package/dist/{skills → types/skills}/memory-store.d.ts +0 -0
- /package/dist/{skills → types/skills}/memory-tool.d.ts +0 -0
- /package/dist/{skills → types/skills}/portable-tool.d.ts +0 -0
- /package/dist/{skills → types/skills}/qmemory-adapter.d.ts +0 -0
- /package/dist/{skills → types/skills}/skill-frontmatter.d.ts +0 -0
- /package/dist/{skills → types/skills}/skill-guard.d.ts +0 -0
- /package/dist/{skills → types/skills}/skill-loader.d.ts +0 -0
- /package/dist/{skills → types/skills}/skill-source.d.ts +0 -0
- /package/dist/{skills → types/skills}/skill-types.d.ts +0 -0
- /package/dist/{skills → types/skills}/think-tool.d.ts +0 -0
- /package/dist/{skills → types/skills}/todo-tool.d.ts +0 -0
- /package/dist/{skills → types/skills}/tools/agent-tool.d.ts +0 -0
- /package/dist/{skills → types/skills}/tools/apply-patch-tool.d.ts +0 -0
- /package/dist/{skills → types/skills}/tools/ask-user-tool.d.ts +0 -0
- /package/dist/{skills → types/skills}/tools/brief-tool.d.ts +0 -0
- /package/dist/{skills → types/skills}/tools/browser-tool.d.ts +0 -0
- /package/dist/{skills → types/skills}/tools/checkpoint-tool.d.ts +0 -0
- /package/dist/{skills → types/skills}/tools/config-tool.d.ts +0 -0
- /package/dist/{skills → types/skills}/tools/cron-tool.d.ts +0 -0
- /package/dist/{skills → types/skills}/tools/edit-tool.d.ts +0 -0
- /package/dist/{skills → types/skills}/tools/exec-tool.d.ts +0 -0
- /package/dist/{skills → types/skills}/tools/image-generate-tool.d.ts +0 -0
- /package/dist/{skills → types/skills}/tools/instructions-tool.d.ts +0 -0
- /package/dist/{skills → types/skills}/tools/lsp-tool.d.ts +0 -0
- /package/dist/{skills → types/skills}/tools/mcp-client-types.d.ts +0 -0
- /package/dist/{skills → types/skills}/tools/mcp-tool.d.ts +0 -0
- /package/dist/{skills → types/skills}/tools/memory-tool.d.ts +0 -0
- /package/dist/{skills → types/skills}/tools/monitor-tool.d.ts +0 -0
- /package/dist/{skills → types/skills}/tools/music-generate-tool.d.ts +0 -0
- /package/dist/{skills → types/skills}/tools/notify-tool.d.ts +0 -0
- /package/dist/{skills → types/skills}/tools/patch-tool.d.ts +0 -0
- /package/dist/{skills → types/skills}/tools/pdf-tool.d.ts +0 -0
- /package/dist/{skills → types/skills}/tools/plan-mode-tool.d.ts +0 -0
- /package/dist/{skills → types/skills}/tools/read-tool.d.ts +0 -0
- /package/dist/{skills → types/skills}/tools/repl-tool.d.ts +0 -0
- /package/dist/{skills → types/skills}/tools/search-tool.d.ts +0 -0
- /package/dist/{skills → types/skills}/tools/send-message-tool.d.ts +0 -0
- /package/dist/{skills → types/skills}/tools/skill-list-tool.d.ts +0 -0
- /package/dist/{skills → types/skills}/tools/skill-manage-tool.d.ts +0 -0
- /package/dist/{skills → types/skills}/tools/skill-view-tool.d.ts +0 -0
- /package/dist/{skills → types/skills}/tools/sleep-tool.d.ts +0 -0
- /package/dist/{skills → types/skills}/tools/structured-output-tool.d.ts +0 -0
- /package/dist/{skills → types/skills}/tools/task-tool.d.ts +0 -0
- /package/dist/{skills → types/skills}/tools/team-tool.d.ts +0 -0
- /package/dist/{skills → types/skills}/tools/tool-search-tool.d.ts +0 -0
- /package/dist/{skills → types/skills}/tools/tts-tool.d.ts +0 -0
- /package/dist/{skills → types/skills}/tools/video-edit-tool.d.ts +0 -0
- /package/dist/{skills → types/skills}/tools/video-generate-tool.d.ts +0 -0
- /package/dist/{skills → types/skills}/tools/video-merge-tool.d.ts +0 -0
- /package/dist/{skills → types/skills}/tools/video-upscale-tool.d.ts +0 -0
- /package/dist/{skills → types/skills}/tools/web-fetch-tool.d.ts +0 -0
- /package/dist/{skills → types/skills}/tools/web-search-tool.d.ts +0 -0
- /package/dist/{skills → types/skills}/tools/worktree-tool.d.ts +0 -0
- /package/dist/{skills → types/skills}/tools/write-tool.d.ts +0 -0
|
@@ -1,426 +0,0 @@
|
|
|
1
|
-
const TOOL_CALL_NAME_MAX_CHARS = 64;
|
|
2
|
-
const TOOL_CALL_NAME_RE = /^[A-Za-z0-9_-]+$/;
|
|
3
|
-
const TOOL_CALL_TYPES = new Set(["toolCall", "toolUse", "functionCall"]);
|
|
4
|
-
const TRANSIENT_ERROR_RE = /rate limit|rate.limited|overloaded|too many requests|quota exceeded|timed?\s*out|billing|insufficient.*(balance|quota|credit)|try again later/i;
|
|
5
|
-
function isRawToolCallBlock(block) {
|
|
6
|
-
if (!block || typeof block !== "object") {
|
|
7
|
-
return false;
|
|
8
|
-
}
|
|
9
|
-
const type = block.type;
|
|
10
|
-
return typeof type === "string" && TOOL_CALL_TYPES.has(type);
|
|
11
|
-
}
|
|
12
|
-
function hasToolCallInput(block) {
|
|
13
|
-
const hasInput = "input" in block ? block.input !== undefined && block.input !== null : false;
|
|
14
|
-
const hasArguments = "arguments" in block ? block.arguments !== undefined && block.arguments !== null : false;
|
|
15
|
-
return hasInput || hasArguments;
|
|
16
|
-
}
|
|
17
|
-
function hasNonEmptyStringField(value) {
|
|
18
|
-
return typeof value === "string" && value.trim().length > 0;
|
|
19
|
-
}
|
|
20
|
-
function hasToolCallId(block) {
|
|
21
|
-
return hasNonEmptyStringField(block.id);
|
|
22
|
-
}
|
|
23
|
-
function trimNonEmptyString(value) {
|
|
24
|
-
if (typeof value !== "string") {
|
|
25
|
-
return undefined;
|
|
26
|
-
}
|
|
27
|
-
const trimmed = value.trim();
|
|
28
|
-
return trimmed || undefined;
|
|
29
|
-
}
|
|
30
|
-
function normalizeAllowedToolNames(allowedToolNames) {
|
|
31
|
-
if (!allowedToolNames) {
|
|
32
|
-
return null;
|
|
33
|
-
}
|
|
34
|
-
const normalized = new Set();
|
|
35
|
-
for (const name of allowedToolNames) {
|
|
36
|
-
if (typeof name !== "string") {
|
|
37
|
-
continue;
|
|
38
|
-
}
|
|
39
|
-
const trimmed = name.trim();
|
|
40
|
-
if (trimmed) {
|
|
41
|
-
normalized.add(trimmed.toLowerCase());
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
return normalized.size > 0 ? normalized : null;
|
|
45
|
-
}
|
|
46
|
-
function hasToolCallName(block, allowedToolNames) {
|
|
47
|
-
if (typeof block.name !== "string") {
|
|
48
|
-
return false;
|
|
49
|
-
}
|
|
50
|
-
const trimmed = block.name.trim();
|
|
51
|
-
if (!trimmed) {
|
|
52
|
-
return false;
|
|
53
|
-
}
|
|
54
|
-
if (trimmed.length > TOOL_CALL_NAME_MAX_CHARS || !TOOL_CALL_NAME_RE.test(trimmed)) {
|
|
55
|
-
return false;
|
|
56
|
-
}
|
|
57
|
-
if (!allowedToolNames) {
|
|
58
|
-
return true;
|
|
59
|
-
}
|
|
60
|
-
return allowedToolNames.has(trimmed.toLowerCase());
|
|
61
|
-
}
|
|
62
|
-
function redactSessionsSpawnAttachmentsArgs(value) {
|
|
63
|
-
if (!value || typeof value !== "object") {
|
|
64
|
-
return value;
|
|
65
|
-
}
|
|
66
|
-
const record = value;
|
|
67
|
-
const raw = record.attachments;
|
|
68
|
-
if (!Array.isArray(raw)) {
|
|
69
|
-
return value;
|
|
70
|
-
}
|
|
71
|
-
const next = raw.map((item) => {
|
|
72
|
-
if (!item || typeof item !== "object") {
|
|
73
|
-
return item;
|
|
74
|
-
}
|
|
75
|
-
const attachment = item;
|
|
76
|
-
if (!Object.hasOwn(attachment, "content")) {
|
|
77
|
-
return item;
|
|
78
|
-
}
|
|
79
|
-
const { content: _content, ...rest } = attachment;
|
|
80
|
-
return { ...rest, content: "__OPENCLAW_REDACTED__" };
|
|
81
|
-
});
|
|
82
|
-
return { ...record, attachments: next };
|
|
83
|
-
}
|
|
84
|
-
function sanitizeToolCallBlock(block) {
|
|
85
|
-
const rawName = typeof block.name === "string" ? block.name : undefined;
|
|
86
|
-
const trimmedName = rawName?.trim();
|
|
87
|
-
const hasTrimmedName = typeof trimmedName === "string" && trimmedName.length > 0;
|
|
88
|
-
const normalizedName = hasTrimmedName ? trimmedName : undefined;
|
|
89
|
-
const nameChanged = hasTrimmedName && rawName !== trimmedName;
|
|
90
|
-
const isDelegatedSessionSpawnToolCall = normalizedName?.toLowerCase() === "sessions_spawn";
|
|
91
|
-
if (!isDelegatedSessionSpawnToolCall) {
|
|
92
|
-
if (!nameChanged) {
|
|
93
|
-
return block;
|
|
94
|
-
}
|
|
95
|
-
return { ...block, name: normalizedName };
|
|
96
|
-
}
|
|
97
|
-
const nextArgs = redactSessionsSpawnAttachmentsArgs(block.arguments);
|
|
98
|
-
const nextInput = redactSessionsSpawnAttachmentsArgs(block.input);
|
|
99
|
-
if (nextArgs === block.arguments && nextInput === block.input && !nameChanged) {
|
|
100
|
-
return block;
|
|
101
|
-
}
|
|
102
|
-
const next = { ...block };
|
|
103
|
-
if (nameChanged && normalizedName) {
|
|
104
|
-
next.name = normalizedName;
|
|
105
|
-
}
|
|
106
|
-
if (nextArgs !== block.arguments || Object.hasOwn(block, "arguments")) {
|
|
107
|
-
next.arguments = nextArgs;
|
|
108
|
-
}
|
|
109
|
-
if (nextInput !== block.input || Object.hasOwn(block, "input")) {
|
|
110
|
-
next.input = nextInput;
|
|
111
|
-
}
|
|
112
|
-
return next;
|
|
113
|
-
}
|
|
114
|
-
function normalizeToolResultName(message, fallbackName) {
|
|
115
|
-
const rawToolName = message.toolName;
|
|
116
|
-
const normalizedToolName = trimNonEmptyString(rawToolName);
|
|
117
|
-
if (normalizedToolName) {
|
|
118
|
-
if (rawToolName === normalizedToolName) {
|
|
119
|
-
return message;
|
|
120
|
-
}
|
|
121
|
-
return { ...message, toolName: normalizedToolName };
|
|
122
|
-
}
|
|
123
|
-
const normalizedFallback = trimNonEmptyString(fallbackName);
|
|
124
|
-
if (normalizedFallback) {
|
|
125
|
-
return { ...message, toolName: normalizedFallback };
|
|
126
|
-
}
|
|
127
|
-
if (typeof rawToolName === "string") {
|
|
128
|
-
return { ...message, toolName: "unknown" };
|
|
129
|
-
}
|
|
130
|
-
return message;
|
|
131
|
-
}
|
|
132
|
-
function extractToolCallsFromAssistantLike(message) {
|
|
133
|
-
const content = message.content;
|
|
134
|
-
if (!Array.isArray(content)) {
|
|
135
|
-
return [];
|
|
136
|
-
}
|
|
137
|
-
const toolCalls = [];
|
|
138
|
-
for (const block of content) {
|
|
139
|
-
if (!block || typeof block !== "object") {
|
|
140
|
-
continue;
|
|
141
|
-
}
|
|
142
|
-
const record = block;
|
|
143
|
-
if (typeof record.id !== "string" || !record.id) {
|
|
144
|
-
continue;
|
|
145
|
-
}
|
|
146
|
-
if (typeof record.type === "string" && TOOL_CALL_TYPES.has(record.type)) {
|
|
147
|
-
toolCalls.push({
|
|
148
|
-
id: record.id,
|
|
149
|
-
name: typeof record.name === "string" ? record.name : undefined,
|
|
150
|
-
});
|
|
151
|
-
}
|
|
152
|
-
}
|
|
153
|
-
return toolCalls;
|
|
154
|
-
}
|
|
155
|
-
function extractToolResultIdLike(message) {
|
|
156
|
-
if (typeof message.toolCallId === "string" && message.toolCallId) {
|
|
157
|
-
return message.toolCallId;
|
|
158
|
-
}
|
|
159
|
-
if (typeof message.toolUseId === "string" && message.toolUseId) {
|
|
160
|
-
return message.toolUseId;
|
|
161
|
-
}
|
|
162
|
-
return null;
|
|
163
|
-
}
|
|
164
|
-
function defaultMissingToolResult(params) {
|
|
165
|
-
return {
|
|
166
|
-
role: "toolResult",
|
|
167
|
-
toolCallId: params.toolCallId,
|
|
168
|
-
toolName: params.toolName ?? "unknown",
|
|
169
|
-
content: [
|
|
170
|
-
{
|
|
171
|
-
type: "text",
|
|
172
|
-
text: "[qlogicagent] missing tool result in session history; inserted synthetic error result for transcript repair.",
|
|
173
|
-
},
|
|
174
|
-
],
|
|
175
|
-
isError: true,
|
|
176
|
-
timestamp: 0,
|
|
177
|
-
};
|
|
178
|
-
}
|
|
179
|
-
export function stripToolResultDetails(messages) {
|
|
180
|
-
let touched = false;
|
|
181
|
-
const out = [];
|
|
182
|
-
for (const message of messages) {
|
|
183
|
-
if (!message || typeof message !== "object" || message.role !== "toolResult") {
|
|
184
|
-
out.push(message);
|
|
185
|
-
continue;
|
|
186
|
-
}
|
|
187
|
-
if (!("details" in message)) {
|
|
188
|
-
out.push(message);
|
|
189
|
-
continue;
|
|
190
|
-
}
|
|
191
|
-
const sanitized = { ...message };
|
|
192
|
-
delete sanitized.details;
|
|
193
|
-
touched = true;
|
|
194
|
-
out.push(sanitized);
|
|
195
|
-
}
|
|
196
|
-
return touched ? out : [...messages];
|
|
197
|
-
}
|
|
198
|
-
export function repairToolCallInputs(messages, options) {
|
|
199
|
-
let droppedToolCalls = 0;
|
|
200
|
-
let droppedAssistantMessages = 0;
|
|
201
|
-
let changed = false;
|
|
202
|
-
const out = [];
|
|
203
|
-
const allowedToolNames = normalizeAllowedToolNames(options?.allowedToolNames);
|
|
204
|
-
for (const message of messages) {
|
|
205
|
-
if (!message || typeof message !== "object") {
|
|
206
|
-
out.push(message);
|
|
207
|
-
continue;
|
|
208
|
-
}
|
|
209
|
-
if (message.role !== "assistant" || !Array.isArray(message.content)) {
|
|
210
|
-
out.push(message);
|
|
211
|
-
continue;
|
|
212
|
-
}
|
|
213
|
-
const nextContent = [];
|
|
214
|
-
let droppedInMessage = 0;
|
|
215
|
-
let messageChanged = false;
|
|
216
|
-
for (const block of message.content) {
|
|
217
|
-
if (isRawToolCallBlock(block) &&
|
|
218
|
-
(!hasToolCallInput(block) ||
|
|
219
|
-
!hasToolCallId(block) ||
|
|
220
|
-
!hasToolCallName(block, allowedToolNames))) {
|
|
221
|
-
droppedToolCalls += 1;
|
|
222
|
-
droppedInMessage += 1;
|
|
223
|
-
changed = true;
|
|
224
|
-
messageChanged = true;
|
|
225
|
-
continue;
|
|
226
|
-
}
|
|
227
|
-
if (isRawToolCallBlock(block)) {
|
|
228
|
-
const blockName = typeof block.name === "string" ? block.name.trim() : undefined;
|
|
229
|
-
if (blockName?.toLowerCase() === "sessions_spawn") {
|
|
230
|
-
const sanitized = sanitizeToolCallBlock(block);
|
|
231
|
-
if (sanitized !== block) {
|
|
232
|
-
changed = true;
|
|
233
|
-
messageChanged = true;
|
|
234
|
-
}
|
|
235
|
-
nextContent.push(sanitized);
|
|
236
|
-
continue;
|
|
237
|
-
}
|
|
238
|
-
if (typeof block.name === "string") {
|
|
239
|
-
const trimmedName = block.name.trim();
|
|
240
|
-
if (trimmedName && trimmedName !== block.name) {
|
|
241
|
-
nextContent.push({ ...block, name: trimmedName });
|
|
242
|
-
changed = true;
|
|
243
|
-
messageChanged = true;
|
|
244
|
-
continue;
|
|
245
|
-
}
|
|
246
|
-
}
|
|
247
|
-
}
|
|
248
|
-
nextContent.push(block);
|
|
249
|
-
}
|
|
250
|
-
if (droppedInMessage > 0) {
|
|
251
|
-
if (nextContent.length === 0) {
|
|
252
|
-
droppedAssistantMessages += 1;
|
|
253
|
-
changed = true;
|
|
254
|
-
continue;
|
|
255
|
-
}
|
|
256
|
-
out.push({ ...message, content: nextContent });
|
|
257
|
-
continue;
|
|
258
|
-
}
|
|
259
|
-
if (messageChanged) {
|
|
260
|
-
out.push({ ...message, content: nextContent });
|
|
261
|
-
continue;
|
|
262
|
-
}
|
|
263
|
-
out.push(message);
|
|
264
|
-
}
|
|
265
|
-
return {
|
|
266
|
-
messages: changed ? out : [...messages],
|
|
267
|
-
droppedToolCalls,
|
|
268
|
-
droppedAssistantMessages,
|
|
269
|
-
};
|
|
270
|
-
}
|
|
271
|
-
export function sanitizeToolCallInputs(messages, options) {
|
|
272
|
-
return repairToolCallInputs(messages, options).messages;
|
|
273
|
-
}
|
|
274
|
-
export function repairToolUseResultPairing(messages, options) {
|
|
275
|
-
const out = [];
|
|
276
|
-
const added = [];
|
|
277
|
-
const seenToolResultIds = new Set();
|
|
278
|
-
let droppedDuplicateCount = 0;
|
|
279
|
-
let droppedOrphanCount = 0;
|
|
280
|
-
let moved = false;
|
|
281
|
-
let changed = false;
|
|
282
|
-
const createMissingToolResult = options?.createMissingToolResult ?? (defaultMissingToolResult);
|
|
283
|
-
const pushToolResult = (message) => {
|
|
284
|
-
const id = extractToolResultIdLike(message);
|
|
285
|
-
if (id && seenToolResultIds.has(id)) {
|
|
286
|
-
droppedDuplicateCount += 1;
|
|
287
|
-
changed = true;
|
|
288
|
-
return;
|
|
289
|
-
}
|
|
290
|
-
if (id) {
|
|
291
|
-
seenToolResultIds.add(id);
|
|
292
|
-
}
|
|
293
|
-
out.push(message);
|
|
294
|
-
};
|
|
295
|
-
for (let i = 0; i < messages.length; i += 1) {
|
|
296
|
-
const message = messages[i];
|
|
297
|
-
if (!message || typeof message !== "object") {
|
|
298
|
-
out.push(message);
|
|
299
|
-
continue;
|
|
300
|
-
}
|
|
301
|
-
if (message.role !== "assistant") {
|
|
302
|
-
if (message.role !== "toolResult") {
|
|
303
|
-
out.push(message);
|
|
304
|
-
}
|
|
305
|
-
else {
|
|
306
|
-
droppedOrphanCount += 1;
|
|
307
|
-
changed = true;
|
|
308
|
-
}
|
|
309
|
-
continue;
|
|
310
|
-
}
|
|
311
|
-
const stopReason = message.stopReason;
|
|
312
|
-
if (stopReason === "error" || stopReason === "aborted") {
|
|
313
|
-
out.push(message);
|
|
314
|
-
continue;
|
|
315
|
-
}
|
|
316
|
-
const toolCalls = extractToolCallsFromAssistantLike(message);
|
|
317
|
-
if (toolCalls.length === 0) {
|
|
318
|
-
out.push(message);
|
|
319
|
-
continue;
|
|
320
|
-
}
|
|
321
|
-
const toolCallIds = new Set(toolCalls.map((toolCall) => toolCall.id));
|
|
322
|
-
const toolCallNamesById = new Map(toolCalls.map((toolCall) => [toolCall.id, toolCall.name]));
|
|
323
|
-
const spanResultsById = new Map();
|
|
324
|
-
const remainder = [];
|
|
325
|
-
let j = i + 1;
|
|
326
|
-
for (; j < messages.length; j += 1) {
|
|
327
|
-
const next = messages[j];
|
|
328
|
-
if (!next || typeof next !== "object") {
|
|
329
|
-
remainder.push(next);
|
|
330
|
-
continue;
|
|
331
|
-
}
|
|
332
|
-
if (next.role === "assistant") {
|
|
333
|
-
break;
|
|
334
|
-
}
|
|
335
|
-
if (next.role === "toolResult") {
|
|
336
|
-
const id = extractToolResultIdLike(next);
|
|
337
|
-
if (id && toolCallIds.has(id)) {
|
|
338
|
-
if (seenToolResultIds.has(id)) {
|
|
339
|
-
droppedDuplicateCount += 1;
|
|
340
|
-
changed = true;
|
|
341
|
-
continue;
|
|
342
|
-
}
|
|
343
|
-
const normalizedToolResult = normalizeToolResultName(next, toolCallNamesById.get(id));
|
|
344
|
-
if (normalizedToolResult !== next) {
|
|
345
|
-
changed = true;
|
|
346
|
-
}
|
|
347
|
-
if (!spanResultsById.has(id)) {
|
|
348
|
-
spanResultsById.set(id, normalizedToolResult);
|
|
349
|
-
}
|
|
350
|
-
continue;
|
|
351
|
-
}
|
|
352
|
-
}
|
|
353
|
-
if (next.role !== "toolResult") {
|
|
354
|
-
remainder.push(next);
|
|
355
|
-
}
|
|
356
|
-
else {
|
|
357
|
-
droppedOrphanCount += 1;
|
|
358
|
-
changed = true;
|
|
359
|
-
}
|
|
360
|
-
}
|
|
361
|
-
out.push(message);
|
|
362
|
-
if (spanResultsById.size > 0 && remainder.length > 0) {
|
|
363
|
-
moved = true;
|
|
364
|
-
changed = true;
|
|
365
|
-
}
|
|
366
|
-
for (const call of toolCalls) {
|
|
367
|
-
const existing = spanResultsById.get(call.id);
|
|
368
|
-
if (existing) {
|
|
369
|
-
pushToolResult(existing);
|
|
370
|
-
}
|
|
371
|
-
else {
|
|
372
|
-
const missing = createMissingToolResult({
|
|
373
|
-
toolCallId: call.id,
|
|
374
|
-
toolName: call.name,
|
|
375
|
-
});
|
|
376
|
-
added.push(missing);
|
|
377
|
-
changed = true;
|
|
378
|
-
pushToolResult(missing);
|
|
379
|
-
}
|
|
380
|
-
}
|
|
381
|
-
for (const rem of remainder) {
|
|
382
|
-
out.push(rem);
|
|
383
|
-
}
|
|
384
|
-
i = j - 1;
|
|
385
|
-
}
|
|
386
|
-
const changedOrMoved = changed || moved;
|
|
387
|
-
return {
|
|
388
|
-
messages: changedOrMoved ? out : [...messages],
|
|
389
|
-
added,
|
|
390
|
-
droppedDuplicateCount,
|
|
391
|
-
droppedOrphanCount,
|
|
392
|
-
moved: changedOrMoved,
|
|
393
|
-
};
|
|
394
|
-
}
|
|
395
|
-
export function sanitizeToolUseResultPairing(messages, options) {
|
|
396
|
-
return repairToolUseResultPairing(messages, options).messages;
|
|
397
|
-
}
|
|
398
|
-
export function stripTransientErrorMessages(messages) {
|
|
399
|
-
let changed = false;
|
|
400
|
-
const out = [];
|
|
401
|
-
for (const message of messages) {
|
|
402
|
-
if (!message || typeof message !== "object") {
|
|
403
|
-
out.push(message);
|
|
404
|
-
continue;
|
|
405
|
-
}
|
|
406
|
-
if (message.role !== "assistant" || message.stopReason !== "error") {
|
|
407
|
-
out.push(message);
|
|
408
|
-
continue;
|
|
409
|
-
}
|
|
410
|
-
const content = message.content;
|
|
411
|
-
const text = typeof content === "string"
|
|
412
|
-
? content
|
|
413
|
-
: Array.isArray(content)
|
|
414
|
-
? content
|
|
415
|
-
.filter((block) => block.type === "text")
|
|
416
|
-
.map((block) => block.text ?? "")
|
|
417
|
-
.join(" ")
|
|
418
|
-
: "";
|
|
419
|
-
if (!TRANSIENT_ERROR_RE.test(text)) {
|
|
420
|
-
out.push(message);
|
|
421
|
-
continue;
|
|
422
|
-
}
|
|
423
|
-
changed = true;
|
|
424
|
-
}
|
|
425
|
-
return changed ? out : [...messages];
|
|
426
|
-
}
|
|
@@ -1,92 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Turn Loop Guard — Abort signal + token budget warning for preventive termination.
|
|
3
|
-
*
|
|
4
|
-
* Aligned with Claude Code's multi-condition termination:
|
|
5
|
-
* 1. AbortSignal from user cancellation
|
|
6
|
-
* 2. Token budget pre-check (don't send API call if over budget)
|
|
7
|
-
* 3. max_output_tokens escalation on truncation
|
|
8
|
-
* 4. Prompt-too-long reactive compact trigger
|
|
9
|
-
*/
|
|
10
|
-
/** Initial guard state. */
|
|
11
|
-
export function createTurnLoopGuardState(config) {
|
|
12
|
-
return {
|
|
13
|
-
promptTokens: 0,
|
|
14
|
-
hasAttemptedReactiveCompact: false,
|
|
15
|
-
currentMaxOutputTokens: config.maxOutputTokens,
|
|
16
|
-
consecutiveTruncations: 0,
|
|
17
|
-
aborted: config.abortSignal?.aborted ?? false,
|
|
18
|
-
};
|
|
19
|
-
}
|
|
20
|
-
/**
|
|
21
|
-
* Calculate token warning state before making an API call.
|
|
22
|
-
* If level is "blocking", do NOT send the API call.
|
|
23
|
-
*/
|
|
24
|
-
export function calculateTokenWarningState(state, config) {
|
|
25
|
-
if (state.aborted) {
|
|
26
|
-
return { level: "blocking", usagePercent: 100, reason: "budget_exhausted" };
|
|
27
|
-
}
|
|
28
|
-
const effectiveLimit = config.contextWindowTokens - config.responseBufferTokens - state.currentMaxOutputTokens;
|
|
29
|
-
const usagePercent = effectiveLimit > 0 ? (state.promptTokens / effectiveLimit) * 100 : 100;
|
|
30
|
-
if (state.promptTokens >= effectiveLimit) {
|
|
31
|
-
if (state.hasAttemptedReactiveCompact || !config.reactiveCompactEnabled) {
|
|
32
|
-
return { level: "blocking", usagePercent, reason: "prompt_too_long" };
|
|
33
|
-
}
|
|
34
|
-
return { level: "blocking", usagePercent, reason: "prompt_too_long" };
|
|
35
|
-
}
|
|
36
|
-
// Warning at 85%
|
|
37
|
-
if (usagePercent >= 85) {
|
|
38
|
-
return { level: "warning", usagePercent, remainingTokens: effectiveLimit - state.promptTokens };
|
|
39
|
-
}
|
|
40
|
-
return { level: "ok" };
|
|
41
|
-
}
|
|
42
|
-
export function resolveApiErrorRecovery(error, state, config) {
|
|
43
|
-
const msg = error.message?.toLowerCase() ?? "";
|
|
44
|
-
const status = error.status ?? 0;
|
|
45
|
-
// Prompt too long (413 or specific error message)
|
|
46
|
-
if (status === 413 || msg.includes("prompt_too_long") || msg.includes("context_length_exceeded")) {
|
|
47
|
-
if (!state.hasAttemptedReactiveCompact && config.reactiveCompactEnabled) {
|
|
48
|
-
return { action: "reactive_compact" };
|
|
49
|
-
}
|
|
50
|
-
return { action: "abort", reason: "prompt_too_long_unrecoverable" };
|
|
51
|
-
}
|
|
52
|
-
// 5xx transient errors
|
|
53
|
-
if (status >= 500 && status < 600) {
|
|
54
|
-
return { action: "retry", reason: `server_error_${status}` };
|
|
55
|
-
}
|
|
56
|
-
// Rate limit
|
|
57
|
-
if (status === 429) {
|
|
58
|
-
return { action: "retry", reason: "rate_limited" };
|
|
59
|
-
}
|
|
60
|
-
return { action: "abort", reason: msg || "unknown_error" };
|
|
61
|
-
}
|
|
62
|
-
/**
|
|
63
|
-
* Handle finish_reason === "max_tokens" — escalate max_output_tokens.
|
|
64
|
-
*
|
|
65
|
-
* CC pattern: double the output token budget up to model max.
|
|
66
|
-
*/
|
|
67
|
-
export function resolveOutputTokenEscalation(state, config, modelMaxOutput) {
|
|
68
|
-
if (!config.outputEscalationEnabled) {
|
|
69
|
-
return { shouldEscalate: false, newMax: state.currentMaxOutputTokens };
|
|
70
|
-
}
|
|
71
|
-
// Don't escalate more than 3 times
|
|
72
|
-
if (state.consecutiveTruncations >= 3) {
|
|
73
|
-
return { shouldEscalate: false, newMax: state.currentMaxOutputTokens };
|
|
74
|
-
}
|
|
75
|
-
const newMax = Math.min(state.currentMaxOutputTokens * 2, modelMaxOutput);
|
|
76
|
-
if (newMax <= state.currentMaxOutputTokens) {
|
|
77
|
-
return { shouldEscalate: false, newMax: state.currentMaxOutputTokens };
|
|
78
|
-
}
|
|
79
|
-
return { shouldEscalate: true, newMax };
|
|
80
|
-
}
|
|
81
|
-
/**
|
|
82
|
-
* Check if the turn should be aborted (user cancellation).
|
|
83
|
-
*/
|
|
84
|
-
export function shouldAbortTurn(state, config) {
|
|
85
|
-
if (state.aborted)
|
|
86
|
-
return true;
|
|
87
|
-
if (config.abortSignal?.aborted) {
|
|
88
|
-
state.aborted = true;
|
|
89
|
-
return true;
|
|
90
|
-
}
|
|
91
|
-
return false;
|
|
92
|
-
}
|
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
function pushReason(reasons, enabled, reason) {
|
|
2
|
-
if (enabled) {
|
|
3
|
-
reasons.add(reason);
|
|
4
|
-
}
|
|
5
|
-
}
|
|
6
|
-
export function resolveWebBrowserPolicy(params) {
|
|
7
|
-
const capability = params.capability;
|
|
8
|
-
const reasons = new Set(capability?.escalationReasons ?? []);
|
|
9
|
-
pushReason(reasons, params.needsInteractiveSession === true, "requires-interaction");
|
|
10
|
-
pushReason(reasons, params.needsLoginState === true, "requires-login-state");
|
|
11
|
-
pushReason(reasons, params.needsPersistentSession === true, "requires-persistent-session");
|
|
12
|
-
pushReason(reasons, params.needsStateChangingAction === true, "requires-state-changing-action");
|
|
13
|
-
const shouldEscalateToBrowser = capability?.capabilityFamily === "browser-execution"
|
|
14
|
-
|| capability?.taskMode === "interactive-browser"
|
|
15
|
-
|| reasons.size > 0;
|
|
16
|
-
if (!shouldEscalateToBrowser) {
|
|
17
|
-
return {
|
|
18
|
-
selectedCapabilityFamily: "web-intelligence",
|
|
19
|
-
selectedTaskMode: capability?.taskMode,
|
|
20
|
-
shouldEscalateToBrowser: false,
|
|
21
|
-
escalationReasons: [],
|
|
22
|
-
};
|
|
23
|
-
}
|
|
24
|
-
if (params.browserAvailable !== false) {
|
|
25
|
-
return {
|
|
26
|
-
selectedCapabilityFamily: "browser-execution",
|
|
27
|
-
selectedTaskMode: "interactive-browser",
|
|
28
|
-
shouldEscalateToBrowser: true,
|
|
29
|
-
escalationReasons: [...reasons],
|
|
30
|
-
};
|
|
31
|
-
}
|
|
32
|
-
return {
|
|
33
|
-
selectedCapabilityFamily: capability?.capabilityFamily ?? "web-intelligence",
|
|
34
|
-
selectedTaskMode: capability?.taskMode,
|
|
35
|
-
shouldEscalateToBrowser: false,
|
|
36
|
-
degradationTarget: capability?.degradationTarget,
|
|
37
|
-
escalationReasons: [...reasons],
|
|
38
|
-
};
|
|
39
|
-
}
|