amalgm 0.1.72 → 0.1.73
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 +1 -2
- package/runtime/scripts/amalgm-mcp/agents/rest.js +29 -22
- package/runtime/scripts/amalgm-mcp/agents/store.js +90 -24
- package/runtime/scripts/amalgm-mcp/agents/talk.js +66 -37
- package/runtime/scripts/amalgm-mcp/agents/tools.js +0 -4
- package/runtime/scripts/amalgm-mcp/automations/runner.js +4 -5
- package/runtime/scripts/amalgm-mcp/automations/tool-actions.js +54 -57
- package/runtime/scripts/amalgm-mcp/automations/tools.js +4 -4
- package/runtime/scripts/amalgm-mcp/email/inbound.js +21 -0
- package/runtime/scripts/amalgm-mcp/events/internal-workflows.js +3 -3
- package/runtime/scripts/amalgm-mcp/index.js +3 -1
- package/runtime/scripts/amalgm-mcp/lib/prefs.js +15 -0
- package/runtime/scripts/amalgm-mcp/mcp-connections/rest.js +5 -3
- package/runtime/scripts/amalgm-mcp/runtime-worker.js +47 -0
- package/runtime/scripts/amalgm-mcp/server/combined-service.js +27 -0
- package/runtime/scripts/amalgm-mcp/server/control-plane-service.js +24 -0
- package/runtime/scripts/amalgm-mcp/server/core-tools.js +52 -7
- package/runtime/scripts/amalgm-mcp/server/http-context.js +44 -0
- package/runtime/scripts/amalgm-mcp/server/http-service.js +34 -0
- package/runtime/scripts/amalgm-mcp/server/http.js +31 -465
- package/runtime/scripts/amalgm-mcp/server/local-service-router.js +57 -0
- package/runtime/scripts/amalgm-mcp/server/mcp-adapter.js +22 -0
- package/runtime/scripts/amalgm-mcp/server/mcp-http-service.js +24 -0
- package/runtime/scripts/amalgm-mcp/server/mcp-request-context.js +32 -0
- package/runtime/scripts/amalgm-mcp/server/mcp.js +14 -73
- package/runtime/scripts/amalgm-mcp/server/routes/agents.js +29 -0
- package/runtime/scripts/amalgm-mcp/server/routes/apps.js +59 -0
- package/runtime/scripts/amalgm-mcp/server/routes/automations.js +45 -0
- package/runtime/scripts/amalgm-mcp/server/routes/browser.js +49 -0
- package/runtime/scripts/amalgm-mcp/server/routes/credentials.js +30 -0
- package/runtime/scripts/amalgm-mcp/server/routes/events.js +18 -0
- package/runtime/scripts/amalgm-mcp/server/routes/files.js +33 -0
- package/runtime/scripts/amalgm-mcp/server/routes/health.js +24 -0
- package/runtime/scripts/amalgm-mcp/server/routes/inbound.js +18 -0
- package/runtime/scripts/amalgm-mcp/server/routes/local.js +21 -0
- package/runtime/scripts/amalgm-mcp/server/routes/preferences.js +18 -0
- package/runtime/scripts/amalgm-mcp/server/routes/state.js +23 -0
- package/runtime/scripts/amalgm-mcp/server/routes/toolbox.js +59 -0
- package/runtime/scripts/amalgm-mcp/server/routes/workspace.js +57 -0
- package/runtime/scripts/amalgm-mcp/server/service-lifecycle.js +54 -0
- package/runtime/scripts/amalgm-mcp/services/control-plane.js +19 -0
- package/runtime/scripts/amalgm-mcp/services/mcp-adapter.js +12 -0
- package/runtime/scripts/amalgm-mcp/services/runtime-worker.js +18 -0
- package/runtime/scripts/amalgm-mcp/slack/inbound.js +21 -0
- package/runtime/scripts/amalgm-mcp/state/snapshot.js +3 -3
- package/runtime/scripts/amalgm-mcp/tests/agents-source-of-truth.test.js +82 -0
- package/runtime/scripts/amalgm-mcp/tests/automations-store-runner.test.js +5 -5
- package/runtime/scripts/amalgm-mcp/tests/core-tools.test.js +37 -0
- package/runtime/scripts/amalgm-mcp/tests/mcp-surface.test.js +158 -0
- package/runtime/scripts/amalgm-mcp/tests/server-routing.test.js +81 -0
- package/runtime/scripts/amalgm-mcp/tests/server-services.test.js +156 -0
- package/runtime/scripts/amalgm-mcp/tests/system-catalog.test.js +81 -0
- package/runtime/scripts/amalgm-mcp/tests/toolbox-service.test.js +250 -0
- package/runtime/scripts/amalgm-mcp/toolbox/mcp-surface.js +106 -0
- package/runtime/scripts/amalgm-mcp/toolbox/names.js +41 -0
- package/runtime/scripts/amalgm-mcp/toolbox/rest.js +107 -53
- package/runtime/scripts/amalgm-mcp/toolbox/runner.js +9 -75
- package/runtime/scripts/amalgm-mcp/toolbox/selection.js +22 -0
- package/runtime/scripts/amalgm-mcp/toolbox/service.js +227 -0
- package/runtime/scripts/amalgm-mcp/toolbox/store.js +9 -78
- package/runtime/scripts/amalgm-mcp/toolbox/system-catalog.js +112 -0
- package/runtime/scripts/amalgm-mcp/toolbox/tools.js +11 -74
- package/runtime/scripts/amalgm-mcp/workflows/compiler.js +1 -1
- package/runtime/scripts/amalgm-mcp/workflows/runner.js +4 -5
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "amalgm",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.73",
|
|
4
4
|
"description": "Amalgm local computer runtime: login, MCP, chat, events, previews, and tunnels.",
|
|
5
5
|
"license": "UNLICENSED",
|
|
6
6
|
"private": false,
|
|
@@ -15,7 +15,6 @@
|
|
|
15
15
|
],
|
|
16
16
|
"scripts": {
|
|
17
17
|
"sync-runtime": "node ../../scripts/sync-npm-package-runtime.mjs",
|
|
18
|
-
"prepack": "node ../../scripts/sync-npm-package-runtime.mjs",
|
|
19
18
|
"pack:dry": "npm pack --dry-run",
|
|
20
19
|
"check": "node --check bin/amalgm.js && node --check lib/auth-store.js && node --check lib/cli.js && node --check lib/paths.js && node --check lib/process-cleanup.js && node --check lib/runtime-identity.js && node --check lib/runtime-manifest.js && node --check lib/service.js && node --check lib/state-migration.js && node --check lib/supervisor.js && node --check lib/tunnel-chat.js && node --check lib/tunnel-events.js && node --check runtime/lib/runtime-manifest.js && node --check runtime/scripts/runtime-auth.js && node --check runtime/scripts/proxy-token-store.js && node --check runtime/scripts/local-gateway.js && node --check runtime/scripts/port-monitor.js && node --check runtime/scripts/chat-server.js && node --check runtime/scripts/chat-server/index.js && node --check runtime/scripts/chat-server/config.js && node --check runtime/scripts/chat-core/tooling/native-binaries.js && node --check runtime/scripts/chat-core/tooling/package-import.js && node --check runtime/scripts/chat-core/tooling/runtime-home.js && node --check runtime/scripts/amalgm-mcp/index.js && node --check runtime/scripts/amalgm-mcp/config.js && node --check runtime/scripts/lib/project-paths.js && node --check runtime/scripts/lib/runtime-paths.js"
|
|
21
20
|
},
|
|
@@ -11,6 +11,9 @@ const {
|
|
|
11
11
|
} = require('./store');
|
|
12
12
|
const { hydrateModelPreferences } = require('../lib/prefs');
|
|
13
13
|
const credentialAdapter = require('../../credential-adapter');
|
|
14
|
+
const {
|
|
15
|
+
defaultToolboxService: toolboxService,
|
|
16
|
+
} = require('../toolbox/service');
|
|
14
17
|
|
|
15
18
|
function coerceAuthMethodForHarness(harnessId, authMethod) {
|
|
16
19
|
const supported = credentialAdapter.SUPPORTED_AUTH_BY_HARNESS?.[harnessId] || ['amalgm'];
|
|
@@ -25,27 +28,28 @@ function normalizeStringList(values) {
|
|
|
25
28
|
.filter(Boolean))];
|
|
26
29
|
}
|
|
27
30
|
|
|
28
|
-
function
|
|
31
|
+
function derivedMcpTransportConfig(toolConfig) {
|
|
32
|
+
const appIds = toolboxService.externalMcpToolIdsForMode(
|
|
33
|
+
toolConfig.mode,
|
|
34
|
+
toolConfig.selectedToolIds,
|
|
35
|
+
);
|
|
29
36
|
return {
|
|
30
|
-
inheritAll:
|
|
31
|
-
customServers:
|
|
32
|
-
appIds
|
|
33
|
-
nativeMcps:
|
|
37
|
+
inheritAll: toolConfig.mode !== 'selected',
|
|
38
|
+
customServers: [],
|
|
39
|
+
appIds,
|
|
40
|
+
nativeMcps: [],
|
|
34
41
|
};
|
|
35
42
|
}
|
|
36
43
|
|
|
37
|
-
function normalizeToolConfig(tools
|
|
44
|
+
function normalizeToolConfig(tools) {
|
|
38
45
|
const raw = tools && typeof tools === 'object' && !Array.isArray(tools) ? tools : null;
|
|
39
46
|
const selectedToolIds = normalizeStringList(
|
|
40
47
|
raw?.selectedToolIds
|
|
41
48
|
?? raw?.selected
|
|
42
|
-
?? [
|
|
43
|
-
...normalizeStringList(legacyMcp?.appIds),
|
|
44
|
-
...normalizeStringList(legacyMcp?.nativeMcps),
|
|
45
|
-
],
|
|
49
|
+
?? [],
|
|
46
50
|
);
|
|
47
51
|
return {
|
|
48
|
-
mode: raw?.mode === 'selected'
|
|
52
|
+
mode: raw?.mode === 'selected' ? 'selected' : 'all',
|
|
49
53
|
selectedToolIds,
|
|
50
54
|
};
|
|
51
55
|
}
|
|
@@ -68,20 +72,18 @@ async function handleCreate(body, sendJson) {
|
|
|
68
72
|
description,
|
|
69
73
|
baseHarnessId,
|
|
70
74
|
baseModelId,
|
|
75
|
+
modelSettings,
|
|
71
76
|
systemPrompt,
|
|
72
77
|
files,
|
|
73
78
|
skills,
|
|
74
|
-
mcpAppIds,
|
|
75
|
-
nativeMcps,
|
|
76
|
-
mcp,
|
|
77
79
|
tools,
|
|
78
80
|
authMethod,
|
|
79
81
|
} = body;
|
|
80
82
|
if (!name || !name.trim()) return sendJson(400, { error: 'name is required' });
|
|
81
83
|
if (!baseHarnessId) return sendJson(400, { error: 'baseHarnessId is required' });
|
|
82
84
|
|
|
83
|
-
const
|
|
84
|
-
const
|
|
85
|
+
const toolConfig = normalizeToolConfig(tools);
|
|
86
|
+
const mcpConfig = derivedMcpTransportConfig(toolConfig);
|
|
85
87
|
let agent;
|
|
86
88
|
try {
|
|
87
89
|
agent = createAgent({
|
|
@@ -89,16 +91,14 @@ async function handleCreate(body, sendJson) {
|
|
|
89
91
|
description: description || '',
|
|
90
92
|
baseHarnessId,
|
|
91
93
|
baseModelId: baseModelId || '',
|
|
94
|
+
modelSettings,
|
|
92
95
|
systemPrompt: systemPrompt || '',
|
|
93
96
|
files: normalizeStringList(files),
|
|
94
97
|
skills: normalizeStringList(skills),
|
|
95
|
-
mcpAppIds:
|
|
96
|
-
nativeMcps:
|
|
98
|
+
mcpAppIds: mcpConfig.appIds,
|
|
99
|
+
nativeMcps: mcpConfig.nativeMcps,
|
|
97
100
|
tools: toolConfig,
|
|
98
|
-
mcp:
|
|
99
|
-
...mcpConfig,
|
|
100
|
-
inheritAll: toolConfig.mode !== 'selected',
|
|
101
|
-
},
|
|
101
|
+
mcp: mcpConfig,
|
|
102
102
|
authMethod: coerceAuthMethodForHarness(baseHarnessId, authMethod),
|
|
103
103
|
});
|
|
104
104
|
} catch (error) {
|
|
@@ -121,6 +121,13 @@ async function handleUpdate(body, sendJson) {
|
|
|
121
121
|
updates.authMethod = coerceAuthMethodForHarness(targetHarnessId, existing.authMethod);
|
|
122
122
|
}
|
|
123
123
|
|
|
124
|
+
const toolConfig = normalizeToolConfig(updates.tools ?? existing.tools);
|
|
125
|
+
const mcpConfig = derivedMcpTransportConfig(toolConfig);
|
|
126
|
+
updates.tools = toolConfig;
|
|
127
|
+
updates.mcpAppIds = mcpConfig.appIds;
|
|
128
|
+
updates.nativeMcps = mcpConfig.nativeMcps;
|
|
129
|
+
updates.mcp = mcpConfig;
|
|
130
|
+
|
|
124
131
|
let agent;
|
|
125
132
|
try {
|
|
126
133
|
agent = updateAgent(agent_id, updates);
|
|
@@ -25,13 +25,26 @@ const {
|
|
|
25
25
|
} = require('../lib/storage');
|
|
26
26
|
const { openLocalDb } = require('../state/db');
|
|
27
27
|
const { insertStateEvent, publishStateEvent } = require('../state/events');
|
|
28
|
-
const {
|
|
28
|
+
const {
|
|
29
|
+
getModelSettingsForSelection,
|
|
30
|
+
getPreferredAuthMethod,
|
|
31
|
+
getSelectedModel,
|
|
32
|
+
readUserPreferences,
|
|
33
|
+
} = require('../lib/prefs');
|
|
29
34
|
const credentialAdapter = require('../../credential-adapter');
|
|
30
35
|
|
|
31
36
|
const DEFAULT_AGENT_STATUS = 'unknown';
|
|
32
37
|
const CUSTOM_AGENT_STATUS = 'ready';
|
|
33
38
|
const BUILTIN_AGENT_IDS = ['claude_code', 'codex', 'opencode', 'pi'];
|
|
34
39
|
const DEFAULT_AGENTS_SEEDED_FILE = path.join(STORAGE_DIR, '.default-agents-seeded');
|
|
40
|
+
const DEFAULT_AGENT_MODEL_SETTINGS_BACKFILLED_FILE = path.join(
|
|
41
|
+
STORAGE_DIR,
|
|
42
|
+
'.default-agent-model-settings-backfilled',
|
|
43
|
+
);
|
|
44
|
+
const DEFAULT_AGENT_AUTH_BACKFILLED_FILE = path.join(
|
|
45
|
+
STORAGE_DIR,
|
|
46
|
+
'.default-agent-auth-backfilled',
|
|
47
|
+
);
|
|
35
48
|
const AMALGM_COMPUTER_ID = process.env.AMALGM_COMPUTER_ID || '';
|
|
36
49
|
|
|
37
50
|
const BUILTIN_AGENT_BLUEPRINTS = [
|
|
@@ -146,16 +159,47 @@ function persistedAuthMethod(baseHarnessId) {
|
|
|
146
159
|
return localFallback;
|
|
147
160
|
}
|
|
148
161
|
|
|
149
|
-
function defaultAgentAuthMethod(baseHarnessId, existing) {
|
|
162
|
+
function defaultAgentAuthMethod(baseHarnessId, existing, allowPreferenceBackfill = false) {
|
|
150
163
|
const persisted = persistedAuthMethod(baseHarnessId);
|
|
151
164
|
const existingAuth = nonEmptyString(existing?.authMethod);
|
|
152
165
|
if (!existingAuth) return persisted;
|
|
153
|
-
if (existingAuth === 'amalgm' && persisted && persisted !== 'amalgm') {
|
|
166
|
+
if (allowPreferenceBackfill && existingAuth === 'amalgm' && persisted && persisted !== 'amalgm') {
|
|
154
167
|
return persisted;
|
|
155
168
|
}
|
|
156
169
|
return existingAuth;
|
|
157
170
|
}
|
|
158
171
|
|
|
172
|
+
function normalizeEffort(value) {
|
|
173
|
+
if (typeof value !== 'string') return null;
|
|
174
|
+
const normalized = value.trim().toLowerCase().replace(/_/g, '-');
|
|
175
|
+
if (normalized === 'low') return 'low';
|
|
176
|
+
if (normalized === 'medium') return 'medium';
|
|
177
|
+
if (normalized === 'high') return 'high';
|
|
178
|
+
if (normalized === 'xhigh' || normalized === 'extra-high' || normalized === 'extra high') return 'xhigh';
|
|
179
|
+
if (normalized === 'max') return 'max';
|
|
180
|
+
return null;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
function normalizeModelSettings(value, fallback = null, harnessId = null) {
|
|
184
|
+
const raw = isObject(value) ? value : isObject(fallback) ? fallback : null;
|
|
185
|
+
if (!raw) return null;
|
|
186
|
+
const effort = normalizeEffort(raw.effort || raw.reasoningEffort || raw.reasoning);
|
|
187
|
+
const allowedEfforts =
|
|
188
|
+
harnessId === 'claude_code'
|
|
189
|
+
? new Set(['low', 'medium', 'high', 'xhigh', 'max'])
|
|
190
|
+
: harnessId === 'codex'
|
|
191
|
+
? new Set(['low', 'medium', 'high', 'xhigh'])
|
|
192
|
+
: null;
|
|
193
|
+
const normalized = {
|
|
194
|
+
...(effort && (!allowedEfforts || allowedEfforts.has(effort)) ? { effort } : {}),
|
|
195
|
+
...((harnessId === 'claude_code' || harnessId === 'codex' || !harnessId)
|
|
196
|
+
&& (raw.fastMode === true || raw.speed === 'fast')
|
|
197
|
+
? { fastMode: true }
|
|
198
|
+
: {}),
|
|
199
|
+
};
|
|
200
|
+
return Object.keys(normalized).length > 0 ? normalized : null;
|
|
201
|
+
}
|
|
202
|
+
|
|
159
203
|
function normalizeLocation(inputLocation, fallback = {}) {
|
|
160
204
|
const id = nonEmptyString(fallback.ownerComputerId) || computerId();
|
|
161
205
|
const name = nonEmptyString(fallback.locationName) || computerName();
|
|
@@ -190,27 +234,24 @@ function defaultCapabilities(agent) {
|
|
|
190
234
|
};
|
|
191
235
|
}
|
|
192
236
|
|
|
193
|
-
function
|
|
237
|
+
function normalizeMcpTransportConfig(toolConfig, mcpAppIds, nativeMcps) {
|
|
194
238
|
return {
|
|
195
|
-
inheritAll:
|
|
196
|
-
customServers:
|
|
197
|
-
appIds: normalizeStringList(mcpAppIds
|
|
198
|
-
nativeMcps: normalizeStringList(nativeMcps
|
|
239
|
+
inheritAll: toolConfig.mode !== 'selected',
|
|
240
|
+
customServers: [],
|
|
241
|
+
appIds: normalizeStringList(mcpAppIds),
|
|
242
|
+
nativeMcps: normalizeStringList(nativeMcps),
|
|
199
243
|
};
|
|
200
244
|
}
|
|
201
245
|
|
|
202
|
-
function normalizeToolConfig(tools
|
|
246
|
+
function normalizeToolConfig(tools) {
|
|
203
247
|
const raw = isObject(tools) ? tools : null;
|
|
204
248
|
const selectedToolIds = normalizeStringList(
|
|
205
249
|
raw?.selectedToolIds
|
|
206
250
|
?? raw?.selected
|
|
207
|
-
?? [
|
|
208
|
-
...normalizeStringList(legacyMcp?.appIds),
|
|
209
|
-
...normalizeStringList(legacyMcp?.nativeMcps),
|
|
210
|
-
],
|
|
251
|
+
?? [],
|
|
211
252
|
);
|
|
212
253
|
return {
|
|
213
|
-
mode: raw?.mode === 'selected'
|
|
254
|
+
mode: raw?.mode === 'selected' ? 'selected' : 'all',
|
|
214
255
|
selectedToolIds,
|
|
215
256
|
};
|
|
216
257
|
}
|
|
@@ -221,8 +262,8 @@ function normalizeAgent(input, existing) {
|
|
|
221
262
|
const builtin = input.builtin === true;
|
|
222
263
|
const baseHarnessId = nonEmptyString(input.baseHarnessId || input.base_harness_id) || id;
|
|
223
264
|
const adapter = nonEmptyString(input.adapter) || baseHarnessId;
|
|
224
|
-
const
|
|
225
|
-
const
|
|
265
|
+
const toolConfig = normalizeToolConfig(input.tools);
|
|
266
|
+
const mcpConfig = normalizeMcpTransportConfig(toolConfig, input.mcpAppIds, input.nativeMcps);
|
|
226
267
|
const ownerComputerId = nonEmptyString(input.ownerComputerId || input.owner_computer_id)
|
|
227
268
|
|| nonEmptyString(existing?.ownerComputerId)
|
|
228
269
|
|| computerId();
|
|
@@ -240,6 +281,7 @@ function normalizeAgent(input, existing) {
|
|
|
240
281
|
adapter,
|
|
241
282
|
baseHarnessId,
|
|
242
283
|
baseModelId: input.baseModelId || existing?.baseModelId || '',
|
|
284
|
+
modelSettings: normalizeModelSettings(input.modelSettings, existing?.modelSettings, baseHarnessId),
|
|
243
285
|
systemPrompt: input.systemPrompt || '',
|
|
244
286
|
files: normalizeStringList(input.files),
|
|
245
287
|
skills: normalizeStringList(input.skills),
|
|
@@ -395,25 +437,46 @@ function customAgentRowCount(db = openLocalDb()) {
|
|
|
395
437
|
function seedBuiltinAgents(options = {}) {
|
|
396
438
|
const db = openLocalDb();
|
|
397
439
|
const alreadySeeded = fs.existsSync(DEFAULT_AGENTS_SEEDED_FILE);
|
|
440
|
+
const authBackfilled = fs.existsSync(DEFAULT_AGENT_AUTH_BACKFILLED_FILE);
|
|
441
|
+
const modelSettingsBackfilled = fs.existsSync(DEFAULT_AGENT_MODEL_SETTINGS_BACKFILLED_FILE);
|
|
442
|
+
try {
|
|
443
|
+
readUserPreferences();
|
|
444
|
+
} catch {
|
|
445
|
+
// Best-effort preference cache fill for default agent bootstrapping.
|
|
446
|
+
}
|
|
398
447
|
const events = db.transaction(() => {
|
|
399
448
|
const inserted = [];
|
|
400
449
|
for (const blueprint of BUILTIN_AGENT_BLUEPRINTS) {
|
|
401
450
|
const existing = readAgentRow(db, blueprint.id);
|
|
402
451
|
if (!existing && alreadySeeded) continue;
|
|
452
|
+
const baseModelId =
|
|
453
|
+
existing?.baseModelId ||
|
|
454
|
+
getSelectedModel(blueprint.baseHarnessId) ||
|
|
455
|
+
blueprint.baseModelId;
|
|
456
|
+
const modelSettings =
|
|
457
|
+
existing?.modelSettings ||
|
|
458
|
+
(!modelSettingsBackfilled
|
|
459
|
+
? getModelSettingsForSelection(blueprint.baseHarnessId, baseModelId)
|
|
460
|
+
: null);
|
|
403
461
|
const next = normalizeAgent({
|
|
404
462
|
...blueprint,
|
|
405
463
|
name: existing?.name || blueprint.name,
|
|
406
464
|
description: existing?.description ?? blueprint.description,
|
|
407
465
|
adapter: existing?.adapter || blueprint.adapter,
|
|
408
466
|
baseHarnessId: existing?.baseHarnessId || blueprint.baseHarnessId,
|
|
409
|
-
baseModelId
|
|
467
|
+
baseModelId,
|
|
410
468
|
systemPrompt: existing?.systemPrompt || '',
|
|
411
469
|
files: existing?.files || [],
|
|
412
470
|
skills: existing?.skills || [],
|
|
413
471
|
mcpAppIds: existing?.mcpAppIds || [],
|
|
414
|
-
nativeMcps:
|
|
472
|
+
nativeMcps: [],
|
|
415
473
|
tools: existing?.tools || { mode: 'all', selectedToolIds: [] },
|
|
416
|
-
mcp:
|
|
474
|
+
mcp: {
|
|
475
|
+
inheritAll: existing?.tools?.mode !== 'selected',
|
|
476
|
+
customServers: [],
|
|
477
|
+
appIds: existing?.mcpAppIds || [],
|
|
478
|
+
nativeMcps: [],
|
|
479
|
+
},
|
|
417
480
|
builtin: false,
|
|
418
481
|
deletable: true,
|
|
419
482
|
editable: true,
|
|
@@ -423,7 +486,12 @@ function seedBuiltinAgents(options = {}) {
|
|
|
423
486
|
authDetails: existing?.authDetails,
|
|
424
487
|
configDir: existing?.configDir,
|
|
425
488
|
createdAt: existing?.createdAt,
|
|
426
|
-
|
|
489
|
+
modelSettings,
|
|
490
|
+
authMethod: defaultAgentAuthMethod(
|
|
491
|
+
existing?.baseHarnessId || blueprint.baseHarnessId,
|
|
492
|
+
existing,
|
|
493
|
+
!authBackfilled,
|
|
494
|
+
),
|
|
427
495
|
}, existing);
|
|
428
496
|
if (existing && agentsEqualForWrite(existing, next)) continue;
|
|
429
497
|
upsertAgentRow(db, next);
|
|
@@ -438,6 +506,8 @@ function seedBuiltinAgents(options = {}) {
|
|
|
438
506
|
try {
|
|
439
507
|
ensureDir(STORAGE_DIR);
|
|
440
508
|
fs.writeFileSync(DEFAULT_AGENTS_SEEDED_FILE, nowIso());
|
|
509
|
+
fs.writeFileSync(DEFAULT_AGENT_AUTH_BACKFILLED_FILE, nowIso());
|
|
510
|
+
fs.writeFileSync(DEFAULT_AGENT_MODEL_SETTINGS_BACKFILLED_FILE, nowIso());
|
|
441
511
|
} catch {
|
|
442
512
|
// Best-effort marker; default seeding still works without it.
|
|
443
513
|
}
|
|
@@ -564,7 +634,6 @@ function updateAgent(agentId, updates, options = {}) {
|
|
|
564
634
|
if (duplicate) throw new Error(`An agent named "${requestedName}" already exists`);
|
|
565
635
|
}
|
|
566
636
|
|
|
567
|
-
const hasOwn = (key) => Object.prototype.hasOwnProperty.call(updates || {}, key);
|
|
568
637
|
const merged = {
|
|
569
638
|
...existing,
|
|
570
639
|
...updates,
|
|
@@ -574,9 +643,6 @@ function updateAgent(agentId, updates, options = {}) {
|
|
|
574
643
|
editable: existing.editable,
|
|
575
644
|
updatedAt: nowIso(),
|
|
576
645
|
};
|
|
577
|
-
if (!hasOwn('tools') && (hasOwn('mcp') || hasOwn('mcpAppIds') || hasOwn('nativeMcps'))) {
|
|
578
|
-
delete merged.tools;
|
|
579
|
-
}
|
|
580
646
|
|
|
581
647
|
const next = normalizeAgent(merged, existing);
|
|
582
648
|
|
|
@@ -40,6 +40,9 @@ const {
|
|
|
40
40
|
} = require('../../../lib/chatInput');
|
|
41
41
|
const credentialAdapter = require('../../credential-adapter');
|
|
42
42
|
const { buildLocalMcpServerConfigs } = require('../lib/mcp-resolver');
|
|
43
|
+
const {
|
|
44
|
+
defaultToolboxService: toolboxService,
|
|
45
|
+
} = require('../toolbox/service');
|
|
43
46
|
|
|
44
47
|
const MAX_INLINE_MESSAGE_CHARS = Number(
|
|
45
48
|
process.env.AMALGM_TALK_TO_AGENT_MAX_INLINE_CHARS
|
|
@@ -340,6 +343,39 @@ function coerceAuthMethodForHarness(harnessId, authMethod) {
|
|
|
340
343
|
return supported.includes(authMethod) ? authMethod : supported[0] || 'amalgm';
|
|
341
344
|
}
|
|
342
345
|
|
|
346
|
+
function normalizeEffort(value) {
|
|
347
|
+
if (typeof value !== 'string') return null;
|
|
348
|
+
const normalized = value.trim().toLowerCase().replace(/_/g, '-');
|
|
349
|
+
if (normalized === 'low') return 'low';
|
|
350
|
+
if (normalized === 'medium') return 'medium';
|
|
351
|
+
if (normalized === 'high') return 'high';
|
|
352
|
+
if (normalized === 'xhigh' || normalized === 'extra-high' || normalized === 'extra high') return 'xhigh';
|
|
353
|
+
if (normalized === 'max') return 'max';
|
|
354
|
+
return null;
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
function sanitizeAgentModelSettings(settings, harness) {
|
|
358
|
+
if (!settings || typeof settings !== 'object' || Array.isArray(settings)) return {};
|
|
359
|
+
const effort = normalizeEffort(settings.effort || settings.reasoningEffort || settings.reasoning);
|
|
360
|
+
const allowedEfforts =
|
|
361
|
+
harness === 'claude_code'
|
|
362
|
+
? new Set(['low', 'medium', 'high', 'xhigh', 'max'])
|
|
363
|
+
: harness === 'codex'
|
|
364
|
+
? new Set(['low', 'medium', 'high', 'xhigh'])
|
|
365
|
+
: new Set();
|
|
366
|
+
return {
|
|
367
|
+
...(effort && allowedEfforts.has(effort) ? { effort } : {}),
|
|
368
|
+
...((harness === 'claude_code' || harness === 'codex') && settings.fastMode === true ? { fastMode: true } : {}),
|
|
369
|
+
};
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
function modelIdForAgentSettings(modelId, harness, modelSettings) {
|
|
373
|
+
if (harness !== 'codex' || !modelSettings.effort || typeof modelId !== 'string') return modelId;
|
|
374
|
+
return modelId
|
|
375
|
+
.replace(/(?::thinking-|-thinking-)(low|medium|high|xhigh)$/i, '')
|
|
376
|
+
.replace(/\/(low|medium|high|xhigh)$/i, '') + '/' + modelSettings.effort;
|
|
377
|
+
}
|
|
378
|
+
|
|
343
379
|
async function appendAsyncCompletionToCallerSession({
|
|
344
380
|
callerSessionId,
|
|
345
381
|
agent,
|
|
@@ -550,19 +586,17 @@ async function handleTalkToAgent(args, context = {}) {
|
|
|
550
586
|
? credentialAdapter.getPersistedAuthMode(agent.baseHarnessId)
|
|
551
587
|
: 'amalgm';
|
|
552
588
|
const preferredAuthMethod = getPreferredAuthMethod(agent.baseHarnessId, persistedAuthMethod);
|
|
553
|
-
const isDefaultAgentClass = agent.id === agent.baseHarnessId;
|
|
554
589
|
const defaultAuthMethod = coerceAuthMethodForHarness(
|
|
555
590
|
agent.baseHarnessId,
|
|
556
|
-
|
|
557
|
-
? preferredAuthMethod
|
|
558
|
-
: agent.authMethod || preferredAuthMethod,
|
|
591
|
+
agent.authMethod || preferredAuthMethod,
|
|
559
592
|
);
|
|
560
593
|
const agentFiles = normalizeStringList(agent.files);
|
|
561
594
|
const agentSkills = normalizeStringList(agent.skills);
|
|
562
595
|
const agentTools = agent.tools || { mode: 'all', selectedToolIds: [] };
|
|
563
|
-
const agentMcpAppIds =
|
|
564
|
-
|
|
565
|
-
|
|
596
|
+
const agentMcpAppIds = toolboxService.externalMcpToolIdsForMode(
|
|
597
|
+
agentTools.mode,
|
|
598
|
+
agentTools.selectedToolIds,
|
|
599
|
+
);
|
|
566
600
|
const baseAgentSystemPrompt = buildAgentInstructions(
|
|
567
601
|
agent.systemPrompt,
|
|
568
602
|
agentFiles,
|
|
@@ -576,35 +610,27 @@ async function handleTalkToAgent(args, context = {}) {
|
|
|
576
610
|
const fallbackModelId = agent.builtin
|
|
577
611
|
? agent.baseModelId
|
|
578
612
|
: agent.baseModelId || DEFAULT_SELECTED_MODELS[agent.baseHarnessId] || null;
|
|
613
|
+
const agentModelSettings = sanitizeAgentModelSettings(agent.modelSettings, agent.baseHarnessId);
|
|
614
|
+
const effectiveModelId = modelIdForAgentSettings(
|
|
615
|
+
fallbackModelId,
|
|
616
|
+
agent.baseHarnessId,
|
|
617
|
+
agentModelSettings,
|
|
618
|
+
);
|
|
579
619
|
const normalizedChatInput = normalizeChatInput({
|
|
580
620
|
...(isObject(chatInput) ? chatInput : {}),
|
|
581
621
|
agent: {
|
|
582
622
|
...((isObject(chatInput) && isObject(chatInput.agent)) ? chatInput.agent : {}),
|
|
583
|
-
harness:
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
model:
|
|
587
|
-
((isObject(chatInput) && isObject(chatInput.agent) && chatInput.agent.model) || null)
|
|
588
|
-
|| fallbackModelId,
|
|
589
|
-
authMethod: coerceAuthMethodForHarness(
|
|
590
|
-
agent.baseHarnessId,
|
|
591
|
-
((isObject(chatInput) && isObject(chatInput.agent) && chatInput.agent.authMethod) || null)
|
|
592
|
-
|| defaultAuthMethod,
|
|
593
|
-
),
|
|
623
|
+
harness: agent.baseHarnessId,
|
|
624
|
+
model: effectiveModelId,
|
|
625
|
+
authMethod: defaultAuthMethod,
|
|
594
626
|
customAgentId: agent.builtin ? null : agent.id,
|
|
595
|
-
systemPrompt:
|
|
596
|
-
((isObject(chatInput) && isObject(chatInput.agent) && chatInput.agent.systemPrompt) || null)
|
|
597
|
-
|| agentSystemPrompt
|
|
598
|
-
|| null,
|
|
627
|
+
systemPrompt: agentSystemPrompt || null,
|
|
599
628
|
},
|
|
600
629
|
tools: {
|
|
601
630
|
...((isObject(chatInput) && isObject(chatInput.tools)) ? chatInput.tools : {}),
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
? chatInput.tools.mcpAppIds
|
|
606
|
-
: []))),
|
|
607
|
-
]),
|
|
631
|
+
mode: agentTools.mode,
|
|
632
|
+
toolIds: normalizeStringList(agentTools.selectedToolIds),
|
|
633
|
+
mcpAppIds: agentMcpAppIds,
|
|
608
634
|
},
|
|
609
635
|
execution: {
|
|
610
636
|
...((isObject(chatInput) && isObject(chatInput.execution)) ? chatInput.execution : {}),
|
|
@@ -616,7 +642,7 @@ async function handleTalkToAgent(args, context = {}) {
|
|
|
616
642
|
}, {
|
|
617
643
|
prompt: taskPrompt,
|
|
618
644
|
harness: agent.baseHarnessId,
|
|
619
|
-
modelId:
|
|
645
|
+
modelId: effectiveModelId,
|
|
620
646
|
authMethod: defaultAuthMethod,
|
|
621
647
|
cwd,
|
|
622
648
|
systemPrompt: agentSystemPrompt,
|
|
@@ -624,7 +650,7 @@ async function handleTalkToAgent(args, context = {}) {
|
|
|
624
650
|
const legacyChatFields = chatInputToLegacyFields(normalizedChatInput, {
|
|
625
651
|
prompt: taskPrompt,
|
|
626
652
|
harness: agent.baseHarnessId,
|
|
627
|
-
modelId:
|
|
653
|
+
modelId: effectiveModelId,
|
|
628
654
|
authMethod: defaultAuthMethod,
|
|
629
655
|
cwd,
|
|
630
656
|
systemPrompt: agentSystemPrompt,
|
|
@@ -723,11 +749,12 @@ async function handleTalkToAgent(args, context = {}) {
|
|
|
723
749
|
taskDescription,
|
|
724
750
|
computerId,
|
|
725
751
|
baseHarnessId: agent.baseHarnessId,
|
|
726
|
-
baseModelId:
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
752
|
+
baseModelId:
|
|
753
|
+
agent.baseModelId ||
|
|
754
|
+
getSelectedModel(agent.baseHarnessId) ||
|
|
755
|
+
DEFAULT_SELECTED_MODELS[agent.baseHarnessId],
|
|
756
|
+
modelSettings: agentModelSettings,
|
|
757
|
+
authMethod: defaultAuthMethod,
|
|
731
758
|
isAgentConversation: true,
|
|
732
759
|
builtin: !!agent.builtin,
|
|
733
760
|
systemPrompt: baseAgentSystemPrompt || '',
|
|
@@ -776,8 +803,9 @@ async function handleTalkToAgent(args, context = {}) {
|
|
|
776
803
|
try {
|
|
777
804
|
const { modelId: uiModelId, cliModel, reasoningEffort } = resolveModelSelection(
|
|
778
805
|
agent.baseHarnessId,
|
|
779
|
-
legacyChatFields.modelId ||
|
|
806
|
+
legacyChatFields.modelId || effectiveModelId,
|
|
780
807
|
);
|
|
808
|
+
const effectiveReasoningEffort = agentModelSettings.effort || reasoningEffort;
|
|
781
809
|
const mcpServers = await buildLocalMcpServerConfigs(legacyChatFields.mcpAppIds || []);
|
|
782
810
|
|
|
783
811
|
const chatPayload = {
|
|
@@ -793,7 +821,8 @@ async function handleTalkToAgent(args, context = {}) {
|
|
|
793
821
|
agentId: chatAgentId,
|
|
794
822
|
modelId: uiModelId,
|
|
795
823
|
cliModel,
|
|
796
|
-
...(
|
|
824
|
+
...(effectiveReasoningEffort ? { reasoningEffort: effectiveReasoningEffort } : {}),
|
|
825
|
+
...(agentModelSettings.fastMode ? { fastMode: true } : {}),
|
|
797
826
|
cwd: legacyChatFields.cwd || DEFAULT_CWD,
|
|
798
827
|
authMethod: legacyChatFields.authMethod || defaultAuthMethod,
|
|
799
828
|
mcpServers,
|
|
@@ -64,10 +64,6 @@ module.exports = [
|
|
|
64
64
|
getSelectedModel(agent.baseHarnessId) ||
|
|
65
65
|
DEFAULT_SELECTED_MODELS[agent.baseHarnessId],
|
|
66
66
|
systemPrompt: agent.systemPrompt ? '(configured)' : '(none)',
|
|
67
|
-
mcp: {
|
|
68
|
-
inheritAll: agent.mcp?.inheritAll ?? true,
|
|
69
|
-
customServerCount: agent.mcp?.customServers?.length ?? 0,
|
|
70
|
-
},
|
|
71
67
|
tools: agent.tools || { mode: 'all', selectedToolIds: [] },
|
|
72
68
|
location: agent.location || null,
|
|
73
69
|
locationName: agent.locationName || null,
|
|
@@ -9,7 +9,7 @@ const { DEFAULT_CWD } = require('../config');
|
|
|
9
9
|
const { compileWorkflowText } = require('../workflows/compiler');
|
|
10
10
|
const { callToolboxMcpTool, toolboxMcpToolName } = require('../toolbox/runner');
|
|
11
11
|
const { buildWorkflowInput } = require('./context');
|
|
12
|
-
const {
|
|
12
|
+
const { resolveFirstPartyToolAction, resolveToolboxAction, suggestWorkflowToolActions } = require('./tool-actions');
|
|
13
13
|
const {
|
|
14
14
|
getAutomation,
|
|
15
15
|
getAutomationByTriggerId,
|
|
@@ -290,10 +290,9 @@ async function runToolCell(cell, args, allowlist) {
|
|
|
290
290
|
return runHttpTool(args);
|
|
291
291
|
}
|
|
292
292
|
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
const result = await coreTool.handler(args, {
|
|
293
|
+
const firstPartyAction = resolveFirstPartyToolAction(cell.toolId, cell.actionName);
|
|
294
|
+
if (firstPartyAction) {
|
|
295
|
+
const result = await firstPartyAction.tool.handler(args, {
|
|
297
296
|
workflow: true,
|
|
298
297
|
sessionMetadata: {
|
|
299
298
|
origin: 'automation-workflow',
|