amalgm 0.1.70 → 0.1.71
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/package.json +4 -3
- package/runtime/lib/harnesses.js +46 -36
- package/runtime/scripts/amalgm-mcp/agents/store.js +1 -1
- package/runtime/scripts/amalgm-mcp/agents/talk.js +48 -38
- package/runtime/scripts/amalgm-mcp/lib/computer.js +75 -0
- package/runtime/scripts/amalgm-mcp/lib/prefs.js +37 -27
- package/runtime/scripts/amalgm-mcp/tasks/executor.js +25 -18
- package/runtime/scripts/chat-core/contract.js +44 -30
- package/runtime/scripts/chat-core/normalizers/codex.js +29 -6
- package/runtime/scripts/chat-core/parts.js +2 -0
- package/runtime/scripts/chat-core/tests/engine.test.js +1 -1
- package/runtime/scripts/chat-core/tests/native-config.test.js +1 -1
- package/runtime/scripts/chat-core/tool-shape.js +4 -2
- package/runtime/scripts/chat-server/model-catalog.js +10 -5
- package/runtime/scripts/test-claude-code-models.js +17 -12
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "amalgm",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.71",
|
|
4
4
|
"description": "Amalgm local computer runtime: login, MCP, chat, events, previews, and tunnels.",
|
|
5
5
|
"license": "UNLICENSED",
|
|
6
6
|
"private": false,
|
|
@@ -24,9 +24,10 @@
|
|
|
24
24
|
},
|
|
25
25
|
"dependencies": {
|
|
26
26
|
"@ai-sdk/gateway": "^3.0.107",
|
|
27
|
-
"@anthropic-ai/claude-agent-sdk": "^0.
|
|
27
|
+
"@anthropic-ai/claude-agent-sdk": "^0.3.154",
|
|
28
|
+
"@anthropic-ai/sdk": "^0.100.0",
|
|
28
29
|
"@homebridge/node-pty-prebuilt-multiarch": "^0.13.1",
|
|
29
|
-
"@modelcontextprotocol/sdk": "^1.
|
|
30
|
+
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
30
31
|
"@openai/codex": "^0.128.0",
|
|
31
32
|
"@opencode-ai/sdk": "^1.14.29",
|
|
32
33
|
"agent-browser": "^0.27.0",
|
package/runtime/lib/harnesses.js
CHANGED
|
@@ -55,29 +55,34 @@ function buildGatewayCliModel(gatewayId, harness) {
|
|
|
55
55
|
|
|
56
56
|
// lib/modelNaming.ts
|
|
57
57
|
var DEFAULT_MODEL_IDS = {
|
|
58
|
-
claude_code: "anthropic/claude-opus-4.
|
|
58
|
+
claude_code: "anthropic/claude-opus-4.8",
|
|
59
59
|
codex: "openai/gpt-5.5",
|
|
60
60
|
opencode: "opencode-deepseek-deepseek-v4-pro",
|
|
61
61
|
pi: "pi-anthropic-claude-sonnet-4.6",
|
|
62
62
|
amp: "amp-default",
|
|
63
63
|
cursor: "cursor/composer-2-fast"
|
|
64
64
|
};
|
|
65
|
-
var
|
|
65
|
+
var CLAUDE_OPUS_4_8_1M_MODEL_ID = "anthropic/claude-opus-4.8-1m";
|
|
66
66
|
var CLAUDE_LEGACY_ALIASES = {
|
|
67
|
-
"claude-code-opus": "anthropic/claude-opus-4.
|
|
68
|
-
"claude-code-opus-
|
|
69
|
-
"claude-code-opus-
|
|
70
|
-
"claude-code-opus-
|
|
71
|
-
"claude-code-opus-
|
|
72
|
-
"claude-code-opus-4
|
|
73
|
-
"claude-code-opus-4
|
|
74
|
-
"claude-code-opus-4
|
|
75
|
-
"claude-code-opus-4
|
|
76
|
-
"claude-code-opus-4
|
|
77
|
-
"claude-code-
|
|
78
|
-
"claude-code-opus-
|
|
79
|
-
"claude-code-opus-4
|
|
80
|
-
"claude-code-
|
|
67
|
+
"claude-code-opus": "anthropic/claude-opus-4.8",
|
|
68
|
+
"claude-code-opus-48": "anthropic/claude-opus-4.8",
|
|
69
|
+
"claude-code-opus-47": "anthropic/claude-opus-4.8",
|
|
70
|
+
"claude-code-opus-46": "anthropic/claude-opus-4.8",
|
|
71
|
+
"claude-code-opus-45": "anthropic/claude-opus-4.8",
|
|
72
|
+
"claude-code-opus-4.8": "anthropic/claude-opus-4.8",
|
|
73
|
+
"claude-code-opus-4-8": "anthropic/claude-opus-4.8",
|
|
74
|
+
"claude-code-opus-4.7": "anthropic/claude-opus-4.8",
|
|
75
|
+
"claude-code-opus-4-7": "anthropic/claude-opus-4.8",
|
|
76
|
+
"claude-code-opus-4.6": "anthropic/claude-opus-4.8",
|
|
77
|
+
"claude-code-opus-4-6": "anthropic/claude-opus-4.8",
|
|
78
|
+
"claude-code-opus-4.5": "anthropic/claude-opus-4.8",
|
|
79
|
+
"claude-code-opus-4-5": "anthropic/claude-opus-4.8",
|
|
80
|
+
"claude-code-opus1m": CLAUDE_OPUS_4_8_1M_MODEL_ID,
|
|
81
|
+
"claude-code-opus-1m": CLAUDE_OPUS_4_8_1M_MODEL_ID,
|
|
82
|
+
"claude-code-opus-4.8-1m": CLAUDE_OPUS_4_8_1M_MODEL_ID,
|
|
83
|
+
"claude-code-opus-4-8-1m": CLAUDE_OPUS_4_8_1M_MODEL_ID,
|
|
84
|
+
"claude-code-opus-4.7-1m": CLAUDE_OPUS_4_8_1M_MODEL_ID,
|
|
85
|
+
"claude-code-opus-4-7-1m": CLAUDE_OPUS_4_8_1M_MODEL_ID,
|
|
81
86
|
"claude-code-sonnet": "anthropic/claude-sonnet-4.6",
|
|
82
87
|
"claude-code-sonnet-45": "anthropic/claude-sonnet-4.6",
|
|
83
88
|
"claude-code-sonnet-4.6": "anthropic/claude-sonnet-4.6",
|
|
@@ -87,21 +92,25 @@ var CLAUDE_LEGACY_ALIASES = {
|
|
|
87
92
|
"claude-code-haiku": "anthropic/claude-haiku-4.5",
|
|
88
93
|
"claude-code-haiku-4.5": "anthropic/claude-haiku-4.5",
|
|
89
94
|
"claude-code-haiku-4-5": "anthropic/claude-haiku-4.5",
|
|
90
|
-
"anthropic/claude-opus-4.
|
|
91
|
-
"anthropic/claude-opus-4.
|
|
95
|
+
"anthropic/claude-opus-4.7": "anthropic/claude-opus-4.8",
|
|
96
|
+
"anthropic/claude-opus-4.6": "anthropic/claude-opus-4.8",
|
|
97
|
+
"anthropic/claude-opus-4.5": "anthropic/claude-opus-4.8",
|
|
92
98
|
"anthropic/claude-sonnet-4.5": "anthropic/claude-sonnet-4.6",
|
|
93
|
-
"claude-opus-4.
|
|
94
|
-
"claude-opus-4-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
"opus
|
|
99
|
+
"claude-opus-4.8-1m": CLAUDE_OPUS_4_8_1M_MODEL_ID,
|
|
100
|
+
"claude-opus-4-8-1m": CLAUDE_OPUS_4_8_1M_MODEL_ID,
|
|
101
|
+
"claude-opus-4.7-1m": CLAUDE_OPUS_4_8_1M_MODEL_ID,
|
|
102
|
+
"claude-opus-4-7-1m": CLAUDE_OPUS_4_8_1M_MODEL_ID,
|
|
103
|
+
opus: "anthropic/claude-opus-4.8",
|
|
104
|
+
opus1m: CLAUDE_OPUS_4_8_1M_MODEL_ID,
|
|
105
|
+
"opus[1m]": CLAUDE_OPUS_4_8_1M_MODEL_ID,
|
|
98
106
|
sonnet: "anthropic/claude-sonnet-4.6",
|
|
99
107
|
"sonnet[1m]": "anthropic/claude-sonnet-4.6",
|
|
100
108
|
haiku: "anthropic/claude-haiku-4.5"
|
|
101
109
|
};
|
|
102
110
|
var CLAUDE_HARNESS_MODELS = {
|
|
111
|
+
"anthropic/claude-opus-4.8": "opus",
|
|
112
|
+
[CLAUDE_OPUS_4_8_1M_MODEL_ID]: "opus[1m]",
|
|
103
113
|
"anthropic/claude-opus-4.7": "opus",
|
|
104
|
-
[CLAUDE_OPUS_4_7_1M_MODEL_ID]: "opus[1m]",
|
|
105
114
|
"anthropic/claude-opus-4.6": "opus",
|
|
106
115
|
"anthropic/claude-opus-4.5": "opus",
|
|
107
116
|
"anthropic/claude-sonnet-4.6": "sonnet",
|
|
@@ -109,7 +118,7 @@ var CLAUDE_HARNESS_MODELS = {
|
|
|
109
118
|
"anthropic/claude-haiku-4.5": "haiku"
|
|
110
119
|
};
|
|
111
120
|
var INTERNAL_TO_GATEWAY_MODEL_IDS = {
|
|
112
|
-
[
|
|
121
|
+
[CLAUDE_OPUS_4_8_1M_MODEL_ID]: "anthropic/claude-opus-4.8"
|
|
113
122
|
};
|
|
114
123
|
var CURSOR_MODEL_ALIASES = {
|
|
115
124
|
"cursor-opus-4.6-thinking": "anthropic/claude-opus-4.6-high-thinking",
|
|
@@ -148,11 +157,12 @@ function normalizeClaudeModelPart(modelPart) {
|
|
|
148
157
|
const hasOneMillionContext = /(?:\[\s*1m\s*\]|:1m|-1m)$/i.test(modelPart);
|
|
149
158
|
const base = modelPart.replace(/\[\s*1m\s*\]$/i, "").replace(/:1m$/i, "").replace(/-1m$/i, "").replace(/-\d{8}$/, "").replace(/-(\d+)-(\d+)(?=$|[-:])/, "-$1.$2");
|
|
150
159
|
const currentBase = {
|
|
151
|
-
"claude-opus-4.
|
|
152
|
-
"claude-opus-4.
|
|
160
|
+
"claude-opus-4.7": "claude-opus-4.8",
|
|
161
|
+
"claude-opus-4.6": "claude-opus-4.8",
|
|
162
|
+
"claude-opus-4.5": "claude-opus-4.8",
|
|
153
163
|
"claude-sonnet-4.5": "claude-sonnet-4.6"
|
|
154
164
|
}[base] ?? base;
|
|
155
|
-
return hasOneMillionContext && currentBase === "claude-opus-4.
|
|
165
|
+
return hasOneMillionContext && currentBase === "claude-opus-4.8" ? `${currentBase}-1m` : currentBase;
|
|
156
166
|
}
|
|
157
167
|
function normalizeClaudeModelId(value) {
|
|
158
168
|
const cleaned = cleanModelId(value);
|
|
@@ -404,20 +414,20 @@ var CLAUDE_MODELS = [
|
|
|
404
414
|
providerGroup: "anthropic"
|
|
405
415
|
},
|
|
406
416
|
{
|
|
407
|
-
id: "anthropic/claude-opus-4.
|
|
408
|
-
name: "Opus 4.
|
|
417
|
+
id: "anthropic/claude-opus-4.8",
|
|
418
|
+
name: "Opus 4.8",
|
|
409
419
|
description: "Most capable Claude Code model",
|
|
410
|
-
gatewayModelId: "anthropic/claude-opus-4.
|
|
411
|
-
cliModel: modelIdToHarnessModel("anthropic/claude-opus-4.
|
|
420
|
+
gatewayModelId: "anthropic/claude-opus-4.8",
|
|
421
|
+
cliModel: modelIdToHarnessModel("anthropic/claude-opus-4.8", "claude_code"),
|
|
412
422
|
provider: "claude",
|
|
413
423
|
providerGroup: "anthropic"
|
|
414
424
|
},
|
|
415
425
|
{
|
|
416
|
-
id: "anthropic/claude-opus-4.
|
|
417
|
-
name: "Opus 4.
|
|
426
|
+
id: "anthropic/claude-opus-4.8-1m",
|
|
427
|
+
name: "Opus 4.8 1M",
|
|
418
428
|
description: "Claude Code Opus with 1M context",
|
|
419
|
-
gatewayModelId: "anthropic/claude-opus-4.
|
|
420
|
-
cliModel: modelIdToHarnessModel("anthropic/claude-opus-4.
|
|
429
|
+
gatewayModelId: "anthropic/claude-opus-4.8",
|
|
430
|
+
cliModel: modelIdToHarnessModel("anthropic/claude-opus-4.8-1m", "claude_code"),
|
|
421
431
|
provider: "claude",
|
|
422
432
|
providerGroup: "anthropic"
|
|
423
433
|
}
|
|
@@ -42,7 +42,7 @@ const BUILTIN_AGENT_BLUEPRINTS = [
|
|
|
42
42
|
'Anthropic Claude agent — general-purpose coding, research, and reasoning',
|
|
43
43
|
adapter: 'claude_code',
|
|
44
44
|
baseHarnessId: 'claude_code',
|
|
45
|
-
baseModelId: 'anthropic/claude-opus-4.
|
|
45
|
+
baseModelId: 'anthropic/claude-opus-4.8',
|
|
46
46
|
},
|
|
47
47
|
{
|
|
48
48
|
id: 'codex',
|
|
@@ -22,6 +22,7 @@ const {
|
|
|
22
22
|
supabasePatch,
|
|
23
23
|
supabaseSelect,
|
|
24
24
|
} = require('../lib/supabase');
|
|
25
|
+
const { resolveLocalComputerId } = require('../lib/computer');
|
|
25
26
|
const {
|
|
26
27
|
hydrateModelPreferences,
|
|
27
28
|
getPreferredAuthMethod,
|
|
@@ -537,6 +538,7 @@ async function handleTalkToAgent(args, context = {}) {
|
|
|
537
538
|
const userMessageId = crypto.randomUUID();
|
|
538
539
|
const assistantMessageId = crypto.randomUUID();
|
|
539
540
|
const runId = assistantMessageId;
|
|
541
|
+
const computerId = resolveLocalComputerId();
|
|
540
542
|
const asyncMode = run_in_background === true || String(mode || '').toLowerCase() === 'async';
|
|
541
543
|
const includeMetrics = includeMetricsFlag(include_metrics);
|
|
542
544
|
const foregroundTimeoutMs = coerceForegroundTimeoutMs(timeout_ms);
|
|
@@ -702,44 +704,50 @@ async function handleTalkToAgent(args, context = {}) {
|
|
|
702
704
|
}
|
|
703
705
|
}
|
|
704
706
|
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
707
|
+
if (!computerId) {
|
|
708
|
+
console.error('[AmalgmMCP:Agent] DB session creation skipped: missing registered computer_id');
|
|
709
|
+
} else {
|
|
710
|
+
await supabaseInsert('sessions', {
|
|
711
|
+
id: sessionId,
|
|
712
|
+
user_id: AMALGM_USER_ID,
|
|
713
|
+
computer_id: computerId,
|
|
714
|
+
container_id: os.hostname() || 'agent-conversation',
|
|
715
|
+
harness: agent.id,
|
|
716
|
+
title: taskDescription || 'New Chat',
|
|
717
|
+
status: 'in-progress',
|
|
718
|
+
origin: 'agent',
|
|
719
|
+
origin_id: callerSessionId,
|
|
720
|
+
metadata: {
|
|
721
|
+
agentId: agent.id,
|
|
722
|
+
agentName: agent.name,
|
|
723
|
+
taskDescription,
|
|
724
|
+
computerId,
|
|
725
|
+
baseHarnessId: agent.baseHarnessId,
|
|
726
|
+
baseModelId: agent.builtin
|
|
727
|
+
? getSelectedModel(agent.baseHarnessId) || agent.baseModelId
|
|
728
|
+
: agent.baseModelId ||
|
|
729
|
+
getSelectedModel(agent.baseHarnessId) ||
|
|
730
|
+
DEFAULT_SELECTED_MODELS[agent.baseHarnessId],
|
|
731
|
+
isAgentConversation: true,
|
|
732
|
+
builtin: !!agent.builtin,
|
|
733
|
+
systemPrompt: baseAgentSystemPrompt || '',
|
|
734
|
+
...(returnChannelInstructions
|
|
735
|
+
? {
|
|
736
|
+
returnChannel: {
|
|
737
|
+
deliveryTool: 'talk_to_agent',
|
|
738
|
+
mode: 'response_to_caller',
|
|
739
|
+
callerConversationId: normalizeConversationId(context.callerSessionId),
|
|
740
|
+
},
|
|
741
|
+
}
|
|
742
|
+
: {}),
|
|
743
|
+
files: agentFiles,
|
|
744
|
+
skills: agentSkills,
|
|
745
|
+
mcpAppIds: agentMcpAppIds,
|
|
746
|
+
tools: agentTools,
|
|
747
|
+
...(parentOrigin || {}),
|
|
748
|
+
},
|
|
749
|
+
});
|
|
750
|
+
}
|
|
743
751
|
} catch (err) {
|
|
744
752
|
console.error('[AmalgmMCP:Agent] DB session creation failed:', err.message);
|
|
745
753
|
}
|
|
@@ -777,6 +785,8 @@ async function handleTalkToAgent(args, context = {}) {
|
|
|
777
785
|
prompt: legacyChatFields.prompt,
|
|
778
786
|
userId: AMALGM_USER_ID,
|
|
779
787
|
codeSessionId: sessionId,
|
|
788
|
+
computerId,
|
|
789
|
+
skipPersistence: hasSupabase() && isNewConversation && !computerId,
|
|
780
790
|
assistantMessageId,
|
|
781
791
|
userMessageId,
|
|
782
792
|
userParts: legacyChatFields.userParts,
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const fs = require('fs');
|
|
4
|
+
const path = require('path');
|
|
5
|
+
const os = require('os');
|
|
6
|
+
const {
|
|
7
|
+
AMALGM_DIR,
|
|
8
|
+
AMALGM_USER_ID,
|
|
9
|
+
COMPUTER_RECORD_FILE,
|
|
10
|
+
} = require('../config');
|
|
11
|
+
|
|
12
|
+
const UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
|
|
13
|
+
|
|
14
|
+
function nonEmptyString(value) {
|
|
15
|
+
return typeof value === 'string' && value.trim() ? value.trim() : '';
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
function isUuid(value) {
|
|
19
|
+
return UUID_RE.test(nonEmptyString(value));
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function readJson(filePath) {
|
|
23
|
+
try {
|
|
24
|
+
return JSON.parse(fs.readFileSync(filePath, 'utf8'));
|
|
25
|
+
} catch {
|
|
26
|
+
return null;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function runtimeLabel() {
|
|
31
|
+
const raw = nonEmptyString(
|
|
32
|
+
process.env.AMALGM_RUNTIME_LABEL
|
|
33
|
+
|| process.env.NEXT_PUBLIC_AMALGM_RUNTIME_LABEL
|
|
34
|
+
|| process.env.AMALGM_BRANCH,
|
|
35
|
+
).toLowerCase();
|
|
36
|
+
if (['preview', 'canary', 'native-chat', 'staging'].includes(raw)) return 'preview';
|
|
37
|
+
if (['local', 'dev', 'development'].includes(raw)) return 'local';
|
|
38
|
+
return 'main';
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function candidateComputerFiles() {
|
|
42
|
+
const home = process.env.AMALGM_HOME || path.join(os.homedir(), '.amalgm');
|
|
43
|
+
const label = runtimeLabel();
|
|
44
|
+
const files = [
|
|
45
|
+
COMPUTER_RECORD_FILE,
|
|
46
|
+
path.join(AMALGM_DIR, 'runtime-state.json'),
|
|
47
|
+
path.join(AMALGM_DIR, 'runtimes', label, 'runtime-state.json'),
|
|
48
|
+
path.join(home, 'computer.json'),
|
|
49
|
+
];
|
|
50
|
+
if (AMALGM_USER_ID) {
|
|
51
|
+
files.push(
|
|
52
|
+
path.join(home, 'users', AMALGM_USER_ID, 'computer.json'),
|
|
53
|
+
path.join(home, 'users', AMALGM_USER_ID, 'runtimes', label, 'runtime-state.json'),
|
|
54
|
+
);
|
|
55
|
+
}
|
|
56
|
+
return [...new Set(files)];
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
function resolveLocalComputerId() {
|
|
60
|
+
const explicit = nonEmptyString(process.env.AMALGM_COMPUTER_ID);
|
|
61
|
+
if (isUuid(explicit)) return explicit;
|
|
62
|
+
|
|
63
|
+
for (const filePath of candidateComputerFiles()) {
|
|
64
|
+
const record = readJson(filePath);
|
|
65
|
+
if (isUuid(record?.computer_id)) return record.computer_id.trim();
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
const legacyContainerId = nonEmptyString(process.env.AMALGM_CONTAINER_ID);
|
|
69
|
+
return isUuid(legacyContainerId) ? legacyContainerId : '';
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
module.exports = {
|
|
73
|
+
isUuid,
|
|
74
|
+
resolveLocalComputerId,
|
|
75
|
+
};
|
|
@@ -14,7 +14,7 @@ const {
|
|
|
14
14
|
} = require('../../lib/project-paths');
|
|
15
15
|
|
|
16
16
|
const DEFAULT_SELECTED_MODELS = {
|
|
17
|
-
claude_code: 'anthropic/claude-opus-4.
|
|
17
|
+
claude_code: 'anthropic/claude-opus-4.8',
|
|
18
18
|
codex: 'openai/gpt-5.5',
|
|
19
19
|
opencode: 'opencode-deepseek-deepseek-v4-pro',
|
|
20
20
|
pi: 'pi-anthropic-claude-sonnet-4.6',
|
|
@@ -48,23 +48,28 @@ const GATEWAY_PROVIDER_PREFIXES = [
|
|
|
48
48
|
'perplexity', 'xai', 'xiaomi', 'zai',
|
|
49
49
|
];
|
|
50
50
|
|
|
51
|
-
const
|
|
51
|
+
const CLAUDE_OPUS_4_8_1M_MODEL_ID = 'anthropic/claude-opus-4.8-1m';
|
|
52
52
|
|
|
53
53
|
const CLAUDE_LEGACY_ALIASES = {
|
|
54
|
-
'claude-code-opus': 'anthropic/claude-opus-4.
|
|
55
|
-
'claude-code-opus-
|
|
56
|
-
'claude-code-opus-
|
|
57
|
-
'claude-code-opus-
|
|
58
|
-
'claude-code-opus-
|
|
59
|
-
'claude-code-opus-4
|
|
60
|
-
'claude-code-opus-4
|
|
61
|
-
'claude-code-opus-4
|
|
62
|
-
'claude-code-opus-4
|
|
63
|
-
'claude-code-opus-4
|
|
64
|
-
'claude-code-
|
|
65
|
-
'claude-code-opus-
|
|
66
|
-
'claude-code-opus-4
|
|
67
|
-
'claude-code-
|
|
54
|
+
'claude-code-opus': 'anthropic/claude-opus-4.8',
|
|
55
|
+
'claude-code-opus-48': 'anthropic/claude-opus-4.8',
|
|
56
|
+
'claude-code-opus-47': 'anthropic/claude-opus-4.8',
|
|
57
|
+
'claude-code-opus-46': 'anthropic/claude-opus-4.8',
|
|
58
|
+
'claude-code-opus-45': 'anthropic/claude-opus-4.8',
|
|
59
|
+
'claude-code-opus-4.8': 'anthropic/claude-opus-4.8',
|
|
60
|
+
'claude-code-opus-4-8': 'anthropic/claude-opus-4.8',
|
|
61
|
+
'claude-code-opus-4.7': 'anthropic/claude-opus-4.8',
|
|
62
|
+
'claude-code-opus-4-7': 'anthropic/claude-opus-4.8',
|
|
63
|
+
'claude-code-opus-4.6': 'anthropic/claude-opus-4.8',
|
|
64
|
+
'claude-code-opus-4-6': 'anthropic/claude-opus-4.8',
|
|
65
|
+
'claude-code-opus-4.5': 'anthropic/claude-opus-4.8',
|
|
66
|
+
'claude-code-opus-4-5': 'anthropic/claude-opus-4.8',
|
|
67
|
+
'claude-code-opus1m': CLAUDE_OPUS_4_8_1M_MODEL_ID,
|
|
68
|
+
'claude-code-opus-1m': CLAUDE_OPUS_4_8_1M_MODEL_ID,
|
|
69
|
+
'claude-code-opus-4.8-1m': CLAUDE_OPUS_4_8_1M_MODEL_ID,
|
|
70
|
+
'claude-code-opus-4-8-1m': CLAUDE_OPUS_4_8_1M_MODEL_ID,
|
|
71
|
+
'claude-code-opus-4.7-1m': CLAUDE_OPUS_4_8_1M_MODEL_ID,
|
|
72
|
+
'claude-code-opus-4-7-1m': CLAUDE_OPUS_4_8_1M_MODEL_ID,
|
|
68
73
|
'claude-code-sonnet': 'anthropic/claude-sonnet-4.6',
|
|
69
74
|
'claude-code-sonnet-45': 'anthropic/claude-sonnet-4.6',
|
|
70
75
|
'claude-code-sonnet-4.6': 'anthropic/claude-sonnet-4.6',
|
|
@@ -74,22 +79,26 @@ const CLAUDE_LEGACY_ALIASES = {
|
|
|
74
79
|
'claude-code-haiku': 'anthropic/claude-haiku-4.5',
|
|
75
80
|
'claude-code-haiku-4.5': 'anthropic/claude-haiku-4.5',
|
|
76
81
|
'claude-code-haiku-4-5': 'anthropic/claude-haiku-4.5',
|
|
77
|
-
'anthropic/claude-opus-4.
|
|
78
|
-
'anthropic/claude-opus-4.
|
|
82
|
+
'anthropic/claude-opus-4.7': 'anthropic/claude-opus-4.8',
|
|
83
|
+
'anthropic/claude-opus-4.6': 'anthropic/claude-opus-4.8',
|
|
84
|
+
'anthropic/claude-opus-4.5': 'anthropic/claude-opus-4.8',
|
|
79
85
|
'anthropic/claude-sonnet-4.5': 'anthropic/claude-sonnet-4.6',
|
|
80
|
-
'claude-opus-4.
|
|
81
|
-
'claude-opus-4-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
'opus
|
|
86
|
+
'claude-opus-4.8-1m': CLAUDE_OPUS_4_8_1M_MODEL_ID,
|
|
87
|
+
'claude-opus-4-8-1m': CLAUDE_OPUS_4_8_1M_MODEL_ID,
|
|
88
|
+
'claude-opus-4.7-1m': CLAUDE_OPUS_4_8_1M_MODEL_ID,
|
|
89
|
+
'claude-opus-4-7-1m': CLAUDE_OPUS_4_8_1M_MODEL_ID,
|
|
90
|
+
opus: 'anthropic/claude-opus-4.8',
|
|
91
|
+
opus1m: CLAUDE_OPUS_4_8_1M_MODEL_ID,
|
|
92
|
+
'opus[1m]': CLAUDE_OPUS_4_8_1M_MODEL_ID,
|
|
85
93
|
sonnet: 'anthropic/claude-sonnet-4.6',
|
|
86
94
|
'sonnet[1m]': 'anthropic/claude-sonnet-4.6',
|
|
87
95
|
haiku: 'anthropic/claude-haiku-4.5',
|
|
88
96
|
};
|
|
89
97
|
|
|
90
98
|
const CLAUDE_HARNESS_MODELS = {
|
|
99
|
+
'anthropic/claude-opus-4.8': 'opus',
|
|
100
|
+
[CLAUDE_OPUS_4_8_1M_MODEL_ID]: 'opus[1m]',
|
|
91
101
|
'anthropic/claude-opus-4.7': 'opus',
|
|
92
|
-
[CLAUDE_OPUS_4_7_1M_MODEL_ID]: 'opus[1m]',
|
|
93
102
|
'anthropic/claude-opus-4.6': 'opus',
|
|
94
103
|
'anthropic/claude-opus-4.5': 'opus',
|
|
95
104
|
'anthropic/claude-sonnet-4.6': 'sonnet',
|
|
@@ -162,11 +171,12 @@ function normalizeClaudeModelPart(modelPart) {
|
|
|
162
171
|
.replace(/-\d{8}$/, '')
|
|
163
172
|
.replace(/-(\d+)-(\d+)(?=$|[-:])/, '-$1.$2');
|
|
164
173
|
const currentBase = {
|
|
165
|
-
'claude-opus-4.
|
|
166
|
-
'claude-opus-4.
|
|
174
|
+
'claude-opus-4.7': 'claude-opus-4.8',
|
|
175
|
+
'claude-opus-4.6': 'claude-opus-4.8',
|
|
176
|
+
'claude-opus-4.5': 'claude-opus-4.8',
|
|
167
177
|
'claude-sonnet-4.5': 'claude-sonnet-4.6',
|
|
168
178
|
}[base] || base;
|
|
169
|
-
return hasOneMillionContext && currentBase === 'claude-opus-4.
|
|
179
|
+
return hasOneMillionContext && currentBase === 'claude-opus-4.8'
|
|
170
180
|
? currentBase + '-1m'
|
|
171
181
|
: currentBase;
|
|
172
182
|
}
|
|
@@ -14,9 +14,10 @@
|
|
|
14
14
|
const crypto = require('crypto');
|
|
15
15
|
const os = require('os');
|
|
16
16
|
|
|
17
|
-
const {
|
|
17
|
+
const { AMALGM_USER_ID, DEFAULT_CWD } = require('../config');
|
|
18
18
|
const { runThroughChatServer } = require('../lib/chat-runner');
|
|
19
19
|
const { hasSupabase, supabaseInsert, supabasePatch } = require('../lib/supabase');
|
|
20
|
+
const { resolveLocalComputerId } = require('../lib/computer');
|
|
20
21
|
const { appendRunLog, updateTaskMeta } = require('./store');
|
|
21
22
|
const {
|
|
22
23
|
chatInputToLegacyFields,
|
|
@@ -167,24 +168,29 @@ async function executeTask(task, claimedRun = null) {
|
|
|
167
168
|
const codeSessionId = crypto.randomUUID();
|
|
168
169
|
const userMessageId = crypto.randomUUID();
|
|
169
170
|
const assistantMessageId = crypto.randomUUID();
|
|
171
|
+
const computerId = resolveLocalComputerId();
|
|
170
172
|
|
|
171
173
|
if (hasSupabase()) {
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
174
|
+
if (!computerId) {
|
|
175
|
+
console.error('[AmalgmMCP:Exec] DB session creation skipped: missing registered computer_id');
|
|
176
|
+
} else {
|
|
177
|
+
try {
|
|
178
|
+
await supabaseInsert('sessions', {
|
|
179
|
+
id: codeSessionId,
|
|
180
|
+
user_id: AMALGM_USER_ID,
|
|
181
|
+
computer_id: computerId,
|
|
182
|
+
container_id: os.hostname() || 'task-execution',
|
|
183
|
+
harness,
|
|
184
|
+
title: 'New Chat',
|
|
185
|
+
origin: 'task',
|
|
186
|
+
origin_id: task.id,
|
|
187
|
+
project_path: projectPath,
|
|
188
|
+
status: 'in-progress',
|
|
189
|
+
metadata: { taskRunId: runId, automated: true, originName: task.name, computerId },
|
|
190
|
+
});
|
|
191
|
+
} catch (err) {
|
|
192
|
+
console.error('[AmalgmMCP:Exec] DB session creation failed:', err.message);
|
|
193
|
+
}
|
|
188
194
|
}
|
|
189
195
|
}
|
|
190
196
|
|
|
@@ -200,7 +206,8 @@ async function executeTask(task, claimedRun = null) {
|
|
|
200
206
|
prompt: legacy.prompt,
|
|
201
207
|
userId: AMALGM_USER_ID,
|
|
202
208
|
codeSessionId,
|
|
203
|
-
computerId
|
|
209
|
+
computerId,
|
|
210
|
+
skipPersistence: hasSupabase() && !computerId,
|
|
204
211
|
assistantMessageId,
|
|
205
212
|
userMessageId,
|
|
206
213
|
agentId: harnessToAgent(harness),
|
|
@@ -28,26 +28,31 @@ function canonicalModel(modelId, harness) {
|
|
|
28
28
|
'haiku': 'anthropic/claude-haiku-4.5',
|
|
29
29
|
'sonnet': 'anthropic/claude-sonnet-4.6',
|
|
30
30
|
'sonnet[1m]': 'anthropic/claude-sonnet-4.6',
|
|
31
|
-
'opus': 'anthropic/claude-opus-4.
|
|
32
|
-
'opus1m': 'anthropic/claude-opus-4.
|
|
33
|
-
'opus[1m]': 'anthropic/claude-opus-4.
|
|
31
|
+
'opus': 'anthropic/claude-opus-4.8',
|
|
32
|
+
'opus1m': 'anthropic/claude-opus-4.8-1m',
|
|
33
|
+
'opus[1m]': 'anthropic/claude-opus-4.8-1m',
|
|
34
34
|
'claude-code-haiku': 'anthropic/claude-haiku-4.5',
|
|
35
35
|
'claude-code-sonnet': 'anthropic/claude-sonnet-4.6',
|
|
36
36
|
'claude-code-sonnet-45': 'anthropic/claude-sonnet-4.6',
|
|
37
|
-
'claude-code-opus': 'anthropic/claude-opus-4.
|
|
38
|
-
'claude-code-opus-45': 'anthropic/claude-opus-4.
|
|
39
|
-
'claude-code-opus-46': 'anthropic/claude-opus-4.
|
|
40
|
-
'claude-code-opus-47': 'anthropic/claude-opus-4.
|
|
41
|
-
'claude-code-opus-
|
|
42
|
-
'claude-code-opus-4
|
|
43
|
-
'claude-code-opus-4
|
|
44
|
-
'claude-code-opus-4
|
|
45
|
-
'claude-code-opus-4
|
|
46
|
-
'claude-code-opus-4
|
|
47
|
-
'claude-code-
|
|
48
|
-
'claude-code-opus-
|
|
49
|
-
'claude-code-opus-4
|
|
50
|
-
'claude-code-
|
|
37
|
+
'claude-code-opus': 'anthropic/claude-opus-4.8',
|
|
38
|
+
'claude-code-opus-45': 'anthropic/claude-opus-4.8',
|
|
39
|
+
'claude-code-opus-46': 'anthropic/claude-opus-4.8',
|
|
40
|
+
'claude-code-opus-47': 'anthropic/claude-opus-4.8',
|
|
41
|
+
'claude-code-opus-48': 'anthropic/claude-opus-4.8',
|
|
42
|
+
'claude-code-opus-4.5': 'anthropic/claude-opus-4.8',
|
|
43
|
+
'claude-code-opus-4-5': 'anthropic/claude-opus-4.8',
|
|
44
|
+
'claude-code-opus-4.6': 'anthropic/claude-opus-4.8',
|
|
45
|
+
'claude-code-opus-4-6': 'anthropic/claude-opus-4.8',
|
|
46
|
+
'claude-code-opus-4.7': 'anthropic/claude-opus-4.8',
|
|
47
|
+
'claude-code-opus-4-7': 'anthropic/claude-opus-4.8',
|
|
48
|
+
'claude-code-opus-4.8': 'anthropic/claude-opus-4.8',
|
|
49
|
+
'claude-code-opus-4-8': 'anthropic/claude-opus-4.8',
|
|
50
|
+
'claude-code-opus1m': 'anthropic/claude-opus-4.8-1m',
|
|
51
|
+
'claude-code-opus-1m': 'anthropic/claude-opus-4.8-1m',
|
|
52
|
+
'claude-code-opus-4.8-1m': 'anthropic/claude-opus-4.8-1m',
|
|
53
|
+
'claude-code-opus-4-8-1m': 'anthropic/claude-opus-4.8-1m',
|
|
54
|
+
'claude-code-opus-4.7-1m': 'anthropic/claude-opus-4.8-1m',
|
|
55
|
+
'claude-code-opus-4-7-1m': 'anthropic/claude-opus-4.8-1m',
|
|
51
56
|
'claude-code-sonnet-4.5': 'anthropic/claude-sonnet-4.6',
|
|
52
57
|
'claude-code-sonnet-4-5': 'anthropic/claude-sonnet-4.6',
|
|
53
58
|
'claude-code-sonnet-4.6': 'anthropic/claude-sonnet-4.6',
|
|
@@ -57,25 +62,32 @@ function canonicalModel(modelId, harness) {
|
|
|
57
62
|
'claude-haiku-4-5': 'anthropic/claude-haiku-4.5',
|
|
58
63
|
'claude-sonnet-4-5': 'anthropic/claude-sonnet-4.6',
|
|
59
64
|
'claude-sonnet-4-6': 'anthropic/claude-sonnet-4.6',
|
|
60
|
-
'claude-opus-4-5': 'anthropic/claude-opus-4.
|
|
61
|
-
'claude-opus-4-6': 'anthropic/claude-opus-4.
|
|
62
|
-
'claude-opus-4-7': 'anthropic/claude-opus-4.
|
|
63
|
-
'claude-opus-4-
|
|
64
|
-
'claude-opus-4
|
|
65
|
+
'claude-opus-4-5': 'anthropic/claude-opus-4.8',
|
|
66
|
+
'claude-opus-4-6': 'anthropic/claude-opus-4.8',
|
|
67
|
+
'claude-opus-4-7': 'anthropic/claude-opus-4.8',
|
|
68
|
+
'claude-opus-4-8': 'anthropic/claude-opus-4.8',
|
|
69
|
+
'claude-opus-4-8-1m': 'anthropic/claude-opus-4.8-1m',
|
|
70
|
+
'claude-opus-4.8-1m': 'anthropic/claude-opus-4.8-1m',
|
|
71
|
+
'claude-opus-4-7-1m': 'anthropic/claude-opus-4.8-1m',
|
|
72
|
+
'claude-opus-4.7-1m': 'anthropic/claude-opus-4.8-1m',
|
|
65
73
|
'anthropic/claude-haiku-4-5': 'anthropic/claude-haiku-4.5',
|
|
66
74
|
'anthropic/claude-haiku-4.5': 'anthropic/claude-haiku-4.5',
|
|
67
75
|
'anthropic/claude-sonnet-4-5': 'anthropic/claude-sonnet-4.6',
|
|
68
76
|
'anthropic/claude-sonnet-4-6': 'anthropic/claude-sonnet-4.6',
|
|
69
77
|
'anthropic/claude-sonnet-4.5': 'anthropic/claude-sonnet-4.6',
|
|
70
78
|
'anthropic/claude-sonnet-4.6': 'anthropic/claude-sonnet-4.6',
|
|
71
|
-
'anthropic/claude-opus-4-5': 'anthropic/claude-opus-4.
|
|
72
|
-
'anthropic/claude-opus-4-6': 'anthropic/claude-opus-4.
|
|
73
|
-
'anthropic/claude-opus-4-7': 'anthropic/claude-opus-4.
|
|
74
|
-
'anthropic/claude-opus-4-
|
|
75
|
-
'anthropic/claude-opus-4
|
|
76
|
-
'anthropic/claude-opus-4
|
|
77
|
-
'anthropic/claude-opus-4.
|
|
78
|
-
'anthropic/claude-opus-4.
|
|
79
|
+
'anthropic/claude-opus-4-5': 'anthropic/claude-opus-4.8',
|
|
80
|
+
'anthropic/claude-opus-4-6': 'anthropic/claude-opus-4.8',
|
|
81
|
+
'anthropic/claude-opus-4-7': 'anthropic/claude-opus-4.8',
|
|
82
|
+
'anthropic/claude-opus-4-8': 'anthropic/claude-opus-4.8',
|
|
83
|
+
'anthropic/claude-opus-4-8-1m': 'anthropic/claude-opus-4.8-1m',
|
|
84
|
+
'anthropic/claude-opus-4-7-1m': 'anthropic/claude-opus-4.8-1m',
|
|
85
|
+
'anthropic/claude-opus-4.5': 'anthropic/claude-opus-4.8',
|
|
86
|
+
'anthropic/claude-opus-4.6': 'anthropic/claude-opus-4.8',
|
|
87
|
+
'anthropic/claude-opus-4.7': 'anthropic/claude-opus-4.8',
|
|
88
|
+
'anthropic/claude-opus-4.8': 'anthropic/claude-opus-4.8',
|
|
89
|
+
'anthropic/claude-opus-4.8-1m': 'anthropic/claude-opus-4.8-1m',
|
|
90
|
+
'anthropic/claude-opus-4.7-1m': 'anthropic/claude-opus-4.8-1m',
|
|
79
91
|
};
|
|
80
92
|
if (aliases[cleaned]) return aliases[cleaned];
|
|
81
93
|
if (cleaned.startsWith('anthropic/')) return cleaned.replace(/-(\d+)-(\d+)(?=$|-)/, '-$1.$2');
|
|
@@ -98,6 +110,8 @@ function cliModelFor({ harness, modelId, cliModel, reasoningEffort }) {
|
|
|
98
110
|
const aliases = {
|
|
99
111
|
'anthropic/claude-haiku-4.5': 'haiku',
|
|
100
112
|
'anthropic/claude-sonnet-4.6': 'sonnet',
|
|
113
|
+
'anthropic/claude-opus-4.8': 'opus',
|
|
114
|
+
'anthropic/claude-opus-4.8-1m': 'opus[1m]',
|
|
101
115
|
'anthropic/claude-opus-4.7': 'opus',
|
|
102
116
|
'anthropic/claude-opus-4.7-1m': 'opus[1m]',
|
|
103
117
|
'haiku': 'haiku',
|
|
@@ -7,8 +7,12 @@ const { normalizeUsage } = require('../usage');
|
|
|
7
7
|
|
|
8
8
|
const NON_TOOL_ITEM_TYPES = new Set(['agentMessage', 'contextCompaction', 'reasoning', 'userMessage']);
|
|
9
9
|
|
|
10
|
+
function codexToolCallId(item = {}) {
|
|
11
|
+
return item?.id || item?.callId || item?.call_id || item?.toolCallId || item?.tool_call_id;
|
|
12
|
+
}
|
|
13
|
+
|
|
10
14
|
function isCodexToolItem(item = {}) {
|
|
11
|
-
return Boolean(item
|
|
15
|
+
return Boolean(codexToolCallId(item) && item?.type && !NON_TOOL_ITEM_TYPES.has(item.type));
|
|
12
16
|
}
|
|
13
17
|
|
|
14
18
|
function codexToolName(item = {}) {
|
|
@@ -37,7 +41,10 @@ function codexToolInput(item = {}) {
|
|
|
37
41
|
if (item[key] !== undefined) input[key] = item[key];
|
|
38
42
|
}
|
|
39
43
|
if (item.input && typeof item.input === 'object') Object.assign(input, item.input);
|
|
40
|
-
|
|
44
|
+
const args = parseObjectish(item.arguments);
|
|
45
|
+
if (args) Object.assign(input, args);
|
|
46
|
+
const rawInput = parseObjectish(item.rawInput);
|
|
47
|
+
if (rawInput) Object.assign(input, rawInput);
|
|
41
48
|
if (item.action && typeof item.action === 'object') {
|
|
42
49
|
if (useful(item.action.query) || !useful(input.query)) input.query = item.action.query;
|
|
43
50
|
if (useful(item.action.url) || !useful(input.url)) input.url = item.action.url;
|
|
@@ -52,6 +59,18 @@ function useful(value) {
|
|
|
52
59
|
return value !== undefined && value !== null && value !== '';
|
|
53
60
|
}
|
|
54
61
|
|
|
62
|
+
function parseObjectish(value) {
|
|
63
|
+
if (!value) return null;
|
|
64
|
+
if (typeof value === 'object' && !Array.isArray(value)) return value;
|
|
65
|
+
if (typeof value !== 'string') return null;
|
|
66
|
+
try {
|
|
67
|
+
const parsed = JSON.parse(value);
|
|
68
|
+
return parsed && typeof parsed === 'object' && !Array.isArray(parsed) ? parsed : null;
|
|
69
|
+
} catch {
|
|
70
|
+
return null;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
55
74
|
function codexToolOutput(item = {}) {
|
|
56
75
|
if (item.status === 'failed' && item.error) return '';
|
|
57
76
|
const direct = item.aggregatedOutput ?? item.output ?? item.result ?? item.diff ?? item.error ?? item.message ?? item.text ?? item.finalText;
|
|
@@ -122,7 +141,7 @@ function codexDelta(msg, p = {}) {
|
|
|
122
141
|
}
|
|
123
142
|
|
|
124
143
|
function codexItemId(p = {}) {
|
|
125
|
-
return p.itemId || p.item
|
|
144
|
+
return p.itemId || codexToolCallId(p.item) || p.id || p.callId || p.call_id || p.toolCallId || p.tool_call_id;
|
|
126
145
|
}
|
|
127
146
|
|
|
128
147
|
function codexTokenTotal(value = {}) {
|
|
@@ -248,11 +267,12 @@ function normalizeCodexNotification(msg, providerSessionId, state) {
|
|
|
248
267
|
})];
|
|
249
268
|
}
|
|
250
269
|
if (method === 'item/started' && isCodexToolItem(p.item)) {
|
|
270
|
+
const toolCallId = codexToolCallId(p.item);
|
|
251
271
|
const toolName = codexToolName(p.item);
|
|
252
272
|
const input = codexToolInput(p.item);
|
|
253
273
|
const detail = codexToolDetail(p.item);
|
|
254
274
|
const metadata = codexToolMetadata(p.item);
|
|
255
|
-
return [toolStarted(
|
|
275
|
+
return [toolStarted(toolCallId, {
|
|
256
276
|
providerSessionId,
|
|
257
277
|
toolName,
|
|
258
278
|
title: codexToolTitle(p.item),
|
|
@@ -265,10 +285,11 @@ function normalizeCodexNotification(msg, providerSessionId, state) {
|
|
|
265
285
|
})];
|
|
266
286
|
}
|
|
267
287
|
if (method === 'item/updated' && isCodexToolItem(p.item)) {
|
|
288
|
+
const toolCallId = codexToolCallId(p.item);
|
|
268
289
|
const input = codexToolInput(p.item);
|
|
269
290
|
const toolName = codexToolName(p.item);
|
|
270
291
|
const metadata = codexToolMetadata(p.item);
|
|
271
|
-
return [toolUpdated(
|
|
292
|
+
return [toolUpdated(toolCallId, {
|
|
272
293
|
providerSessionId,
|
|
273
294
|
toolName,
|
|
274
295
|
title: codexToolTitle(p.item),
|
|
@@ -282,13 +303,14 @@ function normalizeCodexNotification(msg, providerSessionId, state) {
|
|
|
282
303
|
})];
|
|
283
304
|
}
|
|
284
305
|
if (method === 'item/completed' && isCodexToolItem(p.item)) {
|
|
306
|
+
const toolCallId = codexToolCallId(p.item);
|
|
285
307
|
const toolName = codexToolName(p.item);
|
|
286
308
|
const input = codexToolInput(p.item);
|
|
287
309
|
const output = codexToolOutput(p.item);
|
|
288
310
|
const error = codexToolError(p.item);
|
|
289
311
|
const metadata = codexToolMetadata(p.item);
|
|
290
312
|
const detail = codexToolDetail(p.item);
|
|
291
|
-
return [toolCompleted(
|
|
313
|
+
return [toolCompleted(toolCallId, {
|
|
292
314
|
providerSessionId,
|
|
293
315
|
toolName,
|
|
294
316
|
title: codexToolTitle(p.item),
|
|
@@ -384,6 +406,7 @@ module.exports = {
|
|
|
384
406
|
codexToolInput,
|
|
385
407
|
codexToolDetail,
|
|
386
408
|
codexToolError,
|
|
409
|
+
codexToolCallId,
|
|
387
410
|
codexToolName,
|
|
388
411
|
codexToolOutput,
|
|
389
412
|
codexToolTitle,
|
|
@@ -14,7 +14,7 @@ function payload(overrides = {}) {
|
|
|
14
14
|
userId: 'user-test',
|
|
15
15
|
agentId: 'claude_code',
|
|
16
16
|
authMethod: 'amalgm',
|
|
17
|
-
modelId: 'anthropic/claude-opus-4.
|
|
17
|
+
modelId: 'anthropic/claude-opus-4.8',
|
|
18
18
|
cwd: process.cwd(),
|
|
19
19
|
prompt: 'hello',
|
|
20
20
|
proxyToken: 'proxy-token',
|
|
@@ -253,7 +253,7 @@ test('claude extracts native hooks without enabling full filesystem settings', (
|
|
|
253
253
|
authMethod: 'provider_auth',
|
|
254
254
|
auth: { runtimeHome },
|
|
255
255
|
cwd: home,
|
|
256
|
-
cliModel: 'anthropic/claude-opus-4.
|
|
256
|
+
cliModel: 'anthropic/claude-opus-4.8',
|
|
257
257
|
mcpServers: [],
|
|
258
258
|
});
|
|
259
259
|
|
|
@@ -52,11 +52,12 @@ function normalizeError(error, fallback = 'Tool failed') {
|
|
|
52
52
|
|
|
53
53
|
function toolKind(name = '', input = {}, metadata = {}) {
|
|
54
54
|
const clean = String(name || '').toLowerCase();
|
|
55
|
+
const compact = clean.replace(/[^a-z0-9]/g, '');
|
|
55
56
|
const mcp = metadata.mcp || parseMcpName(name);
|
|
56
57
|
if (metadata.subagent || clean === 'task' || clean.includes('spawnagent') || clean.includes('collabagent')) return 'subagent';
|
|
57
58
|
if (clean.includes('todo')) return 'todo';
|
|
58
59
|
if (clean.includes('question') || clean.includes('askuser')) return 'question';
|
|
59
|
-
if (
|
|
60
|
+
if (compact.includes('toolsearch')) return 'search';
|
|
60
61
|
if (clean.includes('bash') || clean.includes('command')) return 'bash';
|
|
61
62
|
if (clean.includes('websearch') || clean === 'websearch') return 'web_search';
|
|
62
63
|
if (clean.includes('browser') || mcp?.tool?.startsWith?.('browser_')) return 'browser';
|
|
@@ -101,6 +102,7 @@ function titleForTool({ name, input = {}, output, error, metadata = {}, fallback
|
|
|
101
102
|
if (mcp) return titleFromMcp(mcp.tool, input);
|
|
102
103
|
|
|
103
104
|
const clean = String(name || '').toLowerCase();
|
|
105
|
+
const compact = clean.replace(/[^a-z0-9]/g, '');
|
|
104
106
|
if (metadata.action?.type === 'search') {
|
|
105
107
|
return `Searching ${compactText(metadata.action.query || input.query || 'the web', 80)}`;
|
|
106
108
|
}
|
|
@@ -114,7 +116,7 @@ function titleForTool({ name, input = {}, output, error, metadata = {}, fallback
|
|
|
114
116
|
const host = hostLabel(url) || 'current page';
|
|
115
117
|
return pattern ? `Finding "${compactText(pattern, 60)}" on ${host}` : `Finding text on ${host}`;
|
|
116
118
|
}
|
|
117
|
-
if (
|
|
119
|
+
if (compact.includes('toolsearch')) {
|
|
118
120
|
const selected = String(input.query || '').replace(/^select:/i, '').trim();
|
|
119
121
|
return selected ? `Selecting ${compactText(selected, 80)}` : 'Selecting tool';
|
|
120
122
|
}
|
|
@@ -49,6 +49,8 @@ const MODEL_CATALOG = [
|
|
|
49
49
|
{ id: "anthropic/claude-opus-4.6-1m", name: "Claude Opus 4.6 (1M context)", provider: "anthropic", contextWindow: 1000000, maxOutput: 128000, inputPrice: 5, outputPrice: 25, cacheRead: 0.5, cacheWrite: 6.25, tags: ["tool-use", "reasoning", "vision", "file-input", "explicit-caching", "web-search"], released: "2026-02-05" },
|
|
50
50
|
{ id: "anthropic/claude-opus-4.7", name: "Claude Opus 4.7", provider: "anthropic", contextWindow: 200000, maxOutput: 128000, inputPrice: 5, outputPrice: 25, cacheRead: 0.5, cacheWrite: 6.25, tags: ["tool-use", "reasoning", "vision", "file-input", "explicit-caching", "web-search"], released: "2026-04-16" },
|
|
51
51
|
{ id: "anthropic/claude-opus-4.7-1m", name: "Claude Opus 4.7 (1M context)", provider: "anthropic", contextWindow: 1000000, maxOutput: 128000, inputPrice: 5, outputPrice: 25, cacheRead: 0.5, cacheWrite: 6.25, tags: ["tool-use", "reasoning", "vision", "file-input", "explicit-caching", "web-search"], released: "2026-04-16" },
|
|
52
|
+
{ id: "anthropic/claude-opus-4.8", name: "Claude Opus 4.8", provider: "anthropic", contextWindow: 200000, maxOutput: 128000, inputPrice: 5, outputPrice: 25, cacheRead: 0.5, cacheWrite: 6.25, tags: ["tool-use", "reasoning", "vision", "file-input", "explicit-caching", "web-search"], released: null },
|
|
53
|
+
{ id: "anthropic/claude-opus-4.8-1m", name: "Claude Opus 4.8 (1M context)", provider: "anthropic", contextWindow: 1000000, maxOutput: 128000, inputPrice: 5, outputPrice: 25, cacheRead: 0.5, cacheWrite: 6.25, tags: ["tool-use", "reasoning", "vision", "file-input", "explicit-caching", "web-search"], released: null },
|
|
52
54
|
{ id: "anthropic/claude-sonnet-4", name: "Claude Sonnet 4", provider: "anthropic", contextWindow: 1000000, maxOutput: 64000, inputPrice: 3, outputPrice: 15, cacheRead: 0.3, cacheWrite: 3.75, tags: ["file-input", "reasoning", "tool-use", "vision", "explicit-caching"], released: "2025-05-22" },
|
|
53
55
|
{ id: "anthropic/claude-sonnet-4.5", name: "Claude Sonnet 4.5", provider: "anthropic", contextWindow: 1000000, maxOutput: 64000, inputPrice: 3, outputPrice: 15, cacheRead: 0.3, cacheWrite: 3.75, tags: ["file-input", "reasoning", "tool-use", "vision", "explicit-caching"], released: "2025-09-29" },
|
|
54
56
|
{ id: "anthropic/claude-sonnet-4.6", name: "Claude Sonnet 4.6", provider: "anthropic", contextWindow: 1000000, maxOutput: 128000, inputPrice: 3, outputPrice: 15, cacheRead: 0.3, cacheWrite: 3.75, tags: ["file-input", "reasoning", "tool-use", "vision", "explicit-caching", "web-search"], released: "2026-02-17" },
|
|
@@ -236,10 +238,13 @@ const MODEL_CATALOG = [
|
|
|
236
238
|
/** Find model by exact ID or fuzzy match (strips provider prefix, date suffixes). */
|
|
237
239
|
// CLI agent internal model names → catalog IDs
|
|
238
240
|
const MODEL_ALIASES = {
|
|
239
|
-
'claude-code-opus': 'anthropic/claude-opus-4.
|
|
240
|
-
'opus': 'anthropic/claude-opus-4.
|
|
241
|
-
'opus1m': 'anthropic/claude-opus-4.
|
|
242
|
-
'opus[1m]': 'anthropic/claude-opus-4.
|
|
241
|
+
'claude-code-opus': 'anthropic/claude-opus-4.8',
|
|
242
|
+
'opus': 'anthropic/claude-opus-4.8',
|
|
243
|
+
'opus1m': 'anthropic/claude-opus-4.8-1m',
|
|
244
|
+
'opus[1m]': 'anthropic/claude-opus-4.8-1m',
|
|
245
|
+
'claude-opus-4-8': 'anthropic/claude-opus-4.8',
|
|
246
|
+
'claude-opus-4.8-1m': 'anthropic/claude-opus-4.8-1m',
|
|
247
|
+
'claude-opus-4.8:1m': 'anthropic/claude-opus-4.8-1m',
|
|
243
248
|
'claude-opus-4-7': 'anthropic/claude-opus-4.7',
|
|
244
249
|
'claude-opus-4.7-1m': 'anthropic/claude-opus-4.7-1m',
|
|
245
250
|
'claude-opus-4.7:1m': 'anthropic/claude-opus-4.7-1m',
|
|
@@ -255,7 +260,7 @@ function getModel(modelId) {
|
|
|
255
260
|
if (!modelId) return null;
|
|
256
261
|
const id = modelId.toLowerCase();
|
|
257
262
|
|
|
258
|
-
// Check aliases first (e.g. claude-code-opus -> anthropic/claude-opus-4.
|
|
263
|
+
// Check aliases first (e.g. claude-code-opus -> anthropic/claude-opus-4.8)
|
|
259
264
|
const aliased = MODEL_ALIASES[id];
|
|
260
265
|
if (aliased) return MODEL_CATALOG.find(e => e.id === aliased) || null;
|
|
261
266
|
|
|
@@ -15,7 +15,7 @@ const {
|
|
|
15
15
|
resolveModelSelection,
|
|
16
16
|
} = require('./amalgm-mcp/lib/prefs');
|
|
17
17
|
|
|
18
|
-
const OPUS_1M = 'anthropic/claude-opus-4.
|
|
18
|
+
const OPUS_1M = 'anthropic/claude-opus-4.8-1m';
|
|
19
19
|
|
|
20
20
|
assert.deepEqual(
|
|
21
21
|
getHarnessModels('claude_code').map((model) => ({
|
|
@@ -26,21 +26,26 @@ assert.deepEqual(
|
|
|
26
26
|
[
|
|
27
27
|
{ id: 'anthropic/claude-haiku-4.5', name: 'Haiku 4.5', cliModel: 'haiku' },
|
|
28
28
|
{ id: 'anthropic/claude-sonnet-4.6', name: 'Sonnet 4.6', cliModel: 'sonnet' },
|
|
29
|
-
{ id: 'anthropic/claude-opus-4.
|
|
30
|
-
{ id: OPUS_1M, name: 'Opus 4.
|
|
29
|
+
{ id: 'anthropic/claude-opus-4.8', name: 'Opus 4.8', cliModel: 'opus' },
|
|
30
|
+
{ id: OPUS_1M, name: 'Opus 4.8 1M', cliModel: 'opus[1m]' },
|
|
31
31
|
],
|
|
32
32
|
);
|
|
33
33
|
|
|
34
34
|
assert.equal(canonicalModel('haiku', 'claude_code'), 'anthropic/claude-haiku-4.5');
|
|
35
35
|
assert.equal(canonicalModel('sonnet', 'claude_code'), 'anthropic/claude-sonnet-4.6');
|
|
36
|
-
assert.equal(canonicalModel('opus', 'claude_code'), 'anthropic/claude-opus-4.
|
|
36
|
+
assert.equal(canonicalModel('opus', 'claude_code'), 'anthropic/claude-opus-4.8');
|
|
37
37
|
assert.equal(canonicalModel('opus1m', 'claude_code'), OPUS_1M);
|
|
38
38
|
assert.equal(canonicalModel('opus[1m]', 'claude_code'), OPUS_1M);
|
|
39
|
-
assert.equal(canonicalModel('claude-code-opus-
|
|
40
|
-
assert.equal(canonicalModel('claude-code-opus-4.
|
|
41
|
-
assert.equal(canonicalModel('claude-opus-4-
|
|
42
|
-
assert.equal(canonicalModel('
|
|
43
|
-
assert.equal(canonicalModel('
|
|
39
|
+
assert.equal(canonicalModel('claude-code-opus-48', 'claude_code'), 'anthropic/claude-opus-4.8');
|
|
40
|
+
assert.equal(canonicalModel('claude-code-opus-4.8', 'claude_code'), 'anthropic/claude-opus-4.8');
|
|
41
|
+
assert.equal(canonicalModel('claude-opus-4-8', 'claude_code'), 'anthropic/claude-opus-4.8');
|
|
42
|
+
assert.equal(canonicalModel('claude-code-opus-47', 'claude_code'), 'anthropic/claude-opus-4.8');
|
|
43
|
+
assert.equal(canonicalModel('claude-code-opus-46', 'claude_code'), 'anthropic/claude-opus-4.8');
|
|
44
|
+
assert.equal(canonicalModel('claude-code-opus-4.6', 'claude_code'), 'anthropic/claude-opus-4.8');
|
|
45
|
+
assert.equal(canonicalModel('claude-opus-4-6', 'claude_code'), 'anthropic/claude-opus-4.8');
|
|
46
|
+
assert.equal(canonicalModel('anthropic/claude-opus-4-6', 'claude_code'), 'anthropic/claude-opus-4.8');
|
|
47
|
+
assert.equal(canonicalModel('anthropic/claude-opus-4.7', 'claude_code'), 'anthropic/claude-opus-4.8');
|
|
48
|
+
assert.equal(canonicalModel('anthropic/claude-opus-4.5', 'claude_code'), 'anthropic/claude-opus-4.8');
|
|
44
49
|
assert.equal(canonicalModel('claude-code-sonnet-45', 'claude_code'), 'anthropic/claude-sonnet-4.6');
|
|
45
50
|
assert.equal(canonicalModel('claude-code-sonnet-4.5', 'claude_code'), 'anthropic/claude-sonnet-4.6');
|
|
46
51
|
assert.equal(canonicalModel('claude-sonnet-4-5', 'claude_code'), 'anthropic/claude-sonnet-4.6');
|
|
@@ -49,14 +54,14 @@ assert.equal(canonicalModel('claude-code-haiku-4.5', 'claude_code'), 'anthropic/
|
|
|
49
54
|
|
|
50
55
|
assert.equal(cliModelFor({ harness: 'claude_code', modelId: 'anthropic/claude-haiku-4.5' }), 'haiku');
|
|
51
56
|
assert.equal(cliModelFor({ harness: 'claude_code', modelId: 'anthropic/claude-sonnet-4.6' }), 'sonnet');
|
|
52
|
-
assert.equal(cliModelFor({ harness: 'claude_code', modelId: 'anthropic/claude-opus-4.
|
|
57
|
+
assert.equal(cliModelFor({ harness: 'claude_code', modelId: 'anthropic/claude-opus-4.8' }), 'opus');
|
|
53
58
|
assert.equal(cliModelFor({ harness: 'claude_code', modelId: OPUS_1M }), 'opus[1m]');
|
|
54
|
-
assert.equal(cliModelFor({ harness: 'claude_code', modelId: 'anthropic/claude-opus-4.
|
|
59
|
+
assert.equal(cliModelFor({ harness: 'claude_code', modelId: 'anthropic/claude-opus-4.8', cliModel: 'opus1m' }), 'opus[1m]');
|
|
55
60
|
|
|
56
61
|
for (const [modelId, cliModel] of [
|
|
57
62
|
['anthropic/claude-haiku-4.5', 'haiku'],
|
|
58
63
|
['anthropic/claude-sonnet-4.6', 'sonnet'],
|
|
59
|
-
['anthropic/claude-opus-4.
|
|
64
|
+
['anthropic/claude-opus-4.8', 'opus'],
|
|
60
65
|
[OPUS_1M, 'opus[1m]'],
|
|
61
66
|
]) {
|
|
62
67
|
const contract = createContract({
|