amalgm 0.1.69 → 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.
Files changed (26) hide show
  1. package/package.json +4 -3
  2. package/runtime/lib/harnesses.js +47 -37
  3. package/runtime/scripts/amalgm-mcp/agents/store.js +1 -1
  4. package/runtime/scripts/amalgm-mcp/agents/talk.js +48 -38
  5. package/runtime/scripts/amalgm-mcp/lib/computer.js +75 -0
  6. package/runtime/scripts/amalgm-mcp/lib/prefs.js +38 -28
  7. package/runtime/scripts/amalgm-mcp/tasks/executor.js +25 -18
  8. package/runtime/scripts/chat-core/adapters/claude.js +1 -1
  9. package/runtime/scripts/chat-core/adapters/codex.js +3 -1
  10. package/runtime/scripts/chat-core/adapters/opencode.js +7 -4
  11. package/runtime/scripts/chat-core/auth.js +11 -29
  12. package/runtime/scripts/chat-core/contract.js +44 -32
  13. package/runtime/scripts/chat-core/engine.js +0 -1
  14. package/runtime/scripts/chat-core/normalizers/codex.js +29 -6
  15. package/runtime/scripts/chat-core/parts.js +2 -0
  16. package/runtime/scripts/chat-core/tests/auth.test.js +50 -44
  17. package/runtime/scripts/chat-core/tests/engine.test.js +1 -1
  18. package/runtime/scripts/chat-core/tests/native-binaries.test.js +126 -0
  19. package/runtime/scripts/chat-core/tests/native-config.test.js +87 -9
  20. package/runtime/scripts/chat-core/tool-shape.js +4 -2
  21. package/runtime/scripts/chat-core/tooling/native-binaries.js +20 -3
  22. package/runtime/scripts/chat-core/tooling/native-config.js +54 -39
  23. package/runtime/scripts/chat-core/tooling/runtime-home.js +3 -1
  24. package/runtime/scripts/chat-server/model-catalog.js +10 -5
  25. package/runtime/scripts/credential-adapter.js +1 -1
  26. 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.69",
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.2.122",
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.27.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",
@@ -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.7",
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 CLAUDE_OPUS_4_7_1M_MODEL_ID = "anthropic/claude-opus-4.7-1m";
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.7",
68
- "claude-code-opus-47": "anthropic/claude-opus-4.7",
69
- "claude-code-opus-46": "anthropic/claude-opus-4.7",
70
- "claude-code-opus-45": "anthropic/claude-opus-4.7",
71
- "claude-code-opus-4.7": "anthropic/claude-opus-4.7",
72
- "claude-code-opus-4-7": "anthropic/claude-opus-4.7",
73
- "claude-code-opus-4.6": "anthropic/claude-opus-4.7",
74
- "claude-code-opus-4-6": "anthropic/claude-opus-4.7",
75
- "claude-code-opus-4.5": "anthropic/claude-opus-4.7",
76
- "claude-code-opus-4-5": "anthropic/claude-opus-4.7",
77
- "claude-code-opus1m": CLAUDE_OPUS_4_7_1M_MODEL_ID,
78
- "claude-code-opus-1m": CLAUDE_OPUS_4_7_1M_MODEL_ID,
79
- "claude-code-opus-4.7-1m": CLAUDE_OPUS_4_7_1M_MODEL_ID,
80
- "claude-code-opus-4-7-1m": CLAUDE_OPUS_4_7_1M_MODEL_ID,
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.6": "anthropic/claude-opus-4.7",
91
- "anthropic/claude-opus-4.5": "anthropic/claude-opus-4.7",
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.7-1m": CLAUDE_OPUS_4_7_1M_MODEL_ID,
94
- "claude-opus-4-7-1m": CLAUDE_OPUS_4_7_1M_MODEL_ID,
95
- opus: "anthropic/claude-opus-4.7",
96
- opus1m: CLAUDE_OPUS_4_7_1M_MODEL_ID,
97
- "opus[1m]": CLAUDE_OPUS_4_7_1M_MODEL_ID,
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
- [CLAUDE_OPUS_4_7_1M_MODEL_ID]: "anthropic/claude-opus-4.7"
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.6": "claude-opus-4.7",
152
- "claude-opus-4.5": "claude-opus-4.7",
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.7" ? `${currentBase}-1m` : currentBase;
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.7",
408
- name: "Opus 4.7",
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.7",
411
- cliModel: modelIdToHarnessModel("anthropic/claude-opus-4.7", "claude_code"),
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.7-1m",
417
- name: "Opus 4.7 1M",
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.7",
420
- cliModel: modelIdToHarnessModel("anthropic/claude-opus-4.7-1m", "claude_code"),
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
  }
@@ -774,7 +784,7 @@ var HARNESSES = {
774
784
  logoKey: "opencode",
775
785
  models: OPENCODE_MODELS,
776
786
  defaultModelId: DEFAULT_MODEL_IDS.opencode,
777
- supportedAuthMethods: ["amalgm", "byok"],
787
+ supportedAuthMethods: ["amalgm", "byok", "provider_auth"],
778
788
  dynamicModels: true
779
789
  },
780
790
  codex: {
@@ -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.7',
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
- await supabaseInsert('sessions', {
706
- id: sessionId,
707
- user_id: AMALGM_USER_ID,
708
- container_id: os.hostname() || 'agent-conversation',
709
- harness: agent.id,
710
- title: taskDescription || 'New Chat',
711
- status: 'in-progress',
712
- origin: 'agent',
713
- origin_id: callerSessionId,
714
- metadata: {
715
- agentId: agent.id,
716
- agentName: agent.name,
717
- taskDescription,
718
- baseHarnessId: agent.baseHarnessId,
719
- baseModelId: agent.builtin
720
- ? getSelectedModel(agent.baseHarnessId) || agent.baseModelId
721
- : agent.baseModelId ||
722
- getSelectedModel(agent.baseHarnessId) ||
723
- DEFAULT_SELECTED_MODELS[agent.baseHarnessId],
724
- isAgentConversation: true,
725
- builtin: !!agent.builtin,
726
- systemPrompt: baseAgentSystemPrompt || '',
727
- ...(returnChannelInstructions
728
- ? {
729
- returnChannel: {
730
- deliveryTool: 'talk_to_agent',
731
- mode: 'response_to_caller',
732
- callerConversationId: normalizeConversationId(context.callerSessionId),
733
- },
734
- }
735
- : {}),
736
- files: agentFiles,
737
- skills: agentSkills,
738
- mcpAppIds: agentMcpAppIds,
739
- tools: agentTools,
740
- ...(parentOrigin || {}),
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.7',
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',
@@ -34,7 +34,7 @@ const DEFAULT_AUTH_METHODS = {
34
34
  const SUPPORTED_AUTH_BY_HARNESS = {
35
35
  claude_code: ['amalgm', 'byok', 'provider_auth'],
36
36
  codex: ['amalgm', 'byok', 'provider_auth'],
37
- opencode: ['amalgm', 'byok'],
37
+ opencode: ['amalgm', 'byok', 'provider_auth'],
38
38
  pi: ['amalgm', 'byok', 'provider_auth'],
39
39
  amp: ['provider_auth'],
40
40
  cursor: ['provider_auth'],
@@ -48,23 +48,28 @@ const GATEWAY_PROVIDER_PREFIXES = [
48
48
  'perplexity', 'xai', 'xiaomi', 'zai',
49
49
  ];
50
50
 
51
- const CLAUDE_OPUS_4_7_1M_MODEL_ID = 'anthropic/claude-opus-4.7-1m';
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.7',
55
- 'claude-code-opus-47': 'anthropic/claude-opus-4.7',
56
- 'claude-code-opus-46': 'anthropic/claude-opus-4.7',
57
- 'claude-code-opus-45': 'anthropic/claude-opus-4.7',
58
- 'claude-code-opus-4.7': 'anthropic/claude-opus-4.7',
59
- 'claude-code-opus-4-7': 'anthropic/claude-opus-4.7',
60
- 'claude-code-opus-4.6': 'anthropic/claude-opus-4.7',
61
- 'claude-code-opus-4-6': 'anthropic/claude-opus-4.7',
62
- 'claude-code-opus-4.5': 'anthropic/claude-opus-4.7',
63
- 'claude-code-opus-4-5': 'anthropic/claude-opus-4.7',
64
- 'claude-code-opus1m': CLAUDE_OPUS_4_7_1M_MODEL_ID,
65
- 'claude-code-opus-1m': CLAUDE_OPUS_4_7_1M_MODEL_ID,
66
- 'claude-code-opus-4.7-1m': CLAUDE_OPUS_4_7_1M_MODEL_ID,
67
- 'claude-code-opus-4-7-1m': CLAUDE_OPUS_4_7_1M_MODEL_ID,
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.6': 'anthropic/claude-opus-4.7',
78
- 'anthropic/claude-opus-4.5': 'anthropic/claude-opus-4.7',
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.7-1m': CLAUDE_OPUS_4_7_1M_MODEL_ID,
81
- 'claude-opus-4-7-1m': CLAUDE_OPUS_4_7_1M_MODEL_ID,
82
- opus: 'anthropic/claude-opus-4.7',
83
- opus1m: CLAUDE_OPUS_4_7_1M_MODEL_ID,
84
- 'opus[1m]': CLAUDE_OPUS_4_7_1M_MODEL_ID,
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.6': 'claude-opus-4.7',
166
- 'claude-opus-4.5': 'claude-opus-4.7',
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.7'
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 { AMALGM_COMPUTER_ID, AMALGM_USER_ID, DEFAULT_CWD } = require('../config');
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
- try {
173
- await supabaseInsert('sessions', {
174
- id: codeSessionId,
175
- user_id: AMALGM_USER_ID,
176
- computer_id: AMALGM_COMPUTER_ID,
177
- container_id: os.hostname() || 'task-execution',
178
- harness,
179
- title: 'New Chat',
180
- origin: 'task',
181
- origin_id: task.id,
182
- project_path: projectPath,
183
- status: 'in-progress',
184
- metadata: { taskRunId: runId, automated: true, originName: task.name },
185
- });
186
- } catch (err) {
187
- console.error('[AmalgmMCP:Exec] DB session creation failed:', err.message);
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: AMALGM_COMPUTER_ID,
209
+ computerId,
210
+ skipPersistence: hasSupabase() && !computerId,
204
211
  assistantMessageId,
205
212
  userMessageId,
206
213
  agentId: harnessToAgent(harness),
@@ -36,7 +36,7 @@ class ClaudeAdapter {
36
36
  const systemPrompt = composeSystemPrompt(contract);
37
37
  const pathToClaudeCodeExecutable = process.env.CLAUDE_CODE_BINARY || bundledClaudeBinary();
38
38
  const settings = {
39
- ...(claudeNativeHookSettings({ cwd: contract.cwd }) || {}),
39
+ ...(contract.authMethod === 'provider_auth' ? (claudeNativeHookSettings({ cwd: contract.cwd }) || {}) : {}),
40
40
  ...(contract.fastMode ? { fastMode: true, fastModePerSessionOptIn: true } : {}),
41
41
  };
42
42
  return {
@@ -363,7 +363,9 @@ function writeConfig(contract, syncInfo) {
363
363
  const home = contract.auth.runtimeHome;
364
364
  if (!home) return;
365
365
  fs.mkdirSync(home, { recursive: true });
366
- if (syncInfo === undefined) syncInfo = syncCodexNativeConfig(home);
366
+ if (syncInfo === undefined) {
367
+ syncInfo = contract.authMethod === 'provider_auth' ? syncCodexNativeConfig(home) : null;
368
+ }
367
369
  const nativeConfig = baseNativeConfigForContract(contract, syncInfo);
368
370
  const configPath = path.join(home, 'config.toml');
369
371
  if (contract.authMethod === 'provider_auth') {
@@ -39,7 +39,7 @@ function splitModel(model, auth) {
39
39
  function configFor(contract) {
40
40
  const model = splitModel(contract.cliModel || contract.usageModelId, contract.auth);
41
41
  const systemPrompt = composeSystemPrompt(contract);
42
- return {
42
+ const config = {
43
43
  logLevel: process.env.OPENCODE_LOG_LEVEL || 'ERROR',
44
44
  enabled_providers: [model.providerID],
45
45
  disabled_providers: [],
@@ -75,7 +75,9 @@ function configFor(contract) {
75
75
  title: { disable: true },
76
76
  },
77
77
  mcp: toOpenCodeMcpConfig(contract),
78
- provider: {
78
+ };
79
+ if (contract.authMethod !== 'provider_auth') {
80
+ config.provider = {
79
81
  [model.providerID]: {
80
82
  options: {
81
83
  baseURL: contract.auth.baseUrl,
@@ -85,8 +87,9 @@ function configFor(contract) {
85
87
  chunkTimeout: 300000,
86
88
  },
87
89
  },
88
- },
89
- };
90
+ };
91
+ }
92
+ return config;
90
93
  }
91
94
 
92
95
  function resultData(result) {