amalgm 0.0.0 → 0.0.1

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 (107) hide show
  1. package/README.md +37 -1
  2. package/bin/amalgm.js +8 -2
  3. package/lib/auth-store.js +223 -0
  4. package/lib/cli.js +1000 -0
  5. package/lib/paths.js +30 -0
  6. package/lib/supervisor.js +467 -0
  7. package/lib/tunnel-chat.js +328 -0
  8. package/lib/tunnel-events.js +499 -0
  9. package/package.json +29 -3
  10. package/runtime/README.md +4 -0
  11. package/runtime/lib/chatInput.js +306 -0
  12. package/runtime/lib/harnesses.js +988 -0
  13. package/runtime/lib/local/amalgmStore.js +128 -0
  14. package/runtime/lib/local/credentialResolver.js +425 -0
  15. package/runtime/lib/mcpApps/registry.js +619 -0
  16. package/runtime/package.json +5 -0
  17. package/runtime/scripts/amalgm-mcp/agents/rest.js +165 -0
  18. package/runtime/scripts/amalgm-mcp/agents/store.js +153 -0
  19. package/runtime/scripts/amalgm-mcp/agents/talk.js +1156 -0
  20. package/runtime/scripts/amalgm-mcp/agents/tools.js +210 -0
  21. package/runtime/scripts/amalgm-mcp/artifacts/advertise.js +132 -0
  22. package/runtime/scripts/amalgm-mcp/artifacts/rest.js +103 -0
  23. package/runtime/scripts/amalgm-mcp/artifacts/store.js +141 -0
  24. package/runtime/scripts/amalgm-mcp/artifacts/supervisor.js +402 -0
  25. package/runtime/scripts/amalgm-mcp/artifacts/tools.js +176 -0
  26. package/runtime/scripts/amalgm-mcp/browser/page.js +637 -0
  27. package/runtime/scripts/amalgm-mcp/browser/tools.js +688 -0
  28. package/runtime/scripts/amalgm-mcp/config.js +138 -0
  29. package/runtime/scripts/amalgm-mcp/credentials/rest.js +45 -0
  30. package/runtime/scripts/amalgm-mcp/deps.js +40 -0
  31. package/runtime/scripts/amalgm-mcp/email/inbound.js +215 -0
  32. package/runtime/scripts/amalgm-mcp/events/executor.js +179 -0
  33. package/runtime/scripts/amalgm-mcp/events/ingress.js +113 -0
  34. package/runtime/scripts/amalgm-mcp/events/matcher.js +125 -0
  35. package/runtime/scripts/amalgm-mcp/events/rest.js +200 -0
  36. package/runtime/scripts/amalgm-mcp/events/ring-buffer.js +19 -0
  37. package/runtime/scripts/amalgm-mcp/events/store.js +98 -0
  38. package/runtime/scripts/amalgm-mcp/events/tools.js +306 -0
  39. package/runtime/scripts/amalgm-mcp/events/webhook-url.js +28 -0
  40. package/runtime/scripts/amalgm-mcp/fs/rest.js +293 -0
  41. package/runtime/scripts/amalgm-mcp/index.js +100 -0
  42. package/runtime/scripts/amalgm-mcp/lib/chat-runner.js +167 -0
  43. package/runtime/scripts/amalgm-mcp/lib/email-md.js +288 -0
  44. package/runtime/scripts/amalgm-mcp/lib/mcp-resolver.js +63 -0
  45. package/runtime/scripts/amalgm-mcp/lib/prefs.js +393 -0
  46. package/runtime/scripts/amalgm-mcp/lib/storage.js +92 -0
  47. package/runtime/scripts/amalgm-mcp/lib/supabase.js +118 -0
  48. package/runtime/scripts/amalgm-mcp/lib/tool-result.js +177 -0
  49. package/runtime/scripts/amalgm-mcp/local/rest.js +80 -0
  50. package/runtime/scripts/amalgm-mcp/mcp-connections/rest.js +151 -0
  51. package/runtime/scripts/amalgm-mcp/notify/index.js +107 -0
  52. package/runtime/scripts/amalgm-mcp/server/http.js +335 -0
  53. package/runtime/scripts/amalgm-mcp/server/mcp.js +116 -0
  54. package/runtime/scripts/amalgm-mcp/slack/inbound.js +200 -0
  55. package/runtime/scripts/amalgm-mcp/tasks/executor.js +225 -0
  56. package/runtime/scripts/amalgm-mcp/tasks/rest.js +110 -0
  57. package/runtime/scripts/amalgm-mcp/tasks/schedule-normalization.js +85 -0
  58. package/runtime/scripts/amalgm-mcp/tasks/scheduler.js +105 -0
  59. package/runtime/scripts/amalgm-mcp/tasks/store.js +139 -0
  60. package/runtime/scripts/amalgm-mcp/tasks/tools.js +391 -0
  61. package/runtime/scripts/amalgm-mcp/user-api-keys/rest.js +105 -0
  62. package/runtime/scripts/amalgm-mcp/workspace/rest.js +389 -0
  63. package/runtime/scripts/chat-core/adapters/claude.js +163 -0
  64. package/runtime/scripts/chat-core/adapters/codex.js +313 -0
  65. package/runtime/scripts/chat-core/adapters/opencode.js +412 -0
  66. package/runtime/scripts/chat-core/auth.js +177 -0
  67. package/runtime/scripts/chat-core/contract.js +326 -0
  68. package/runtime/scripts/chat-core/credentials/store.js +212 -0
  69. package/runtime/scripts/chat-core/egress.js +87 -0
  70. package/runtime/scripts/chat-core/engine.js +195 -0
  71. package/runtime/scripts/chat-core/event-schema.js +231 -0
  72. package/runtime/scripts/chat-core/events.js +190 -0
  73. package/runtime/scripts/chat-core/index.js +11 -0
  74. package/runtime/scripts/chat-core/input.js +50 -0
  75. package/runtime/scripts/chat-core/normalizers/claude.js +450 -0
  76. package/runtime/scripts/chat-core/normalizers/codex.js +380 -0
  77. package/runtime/scripts/chat-core/normalizers/normalizer_spec.md +259 -0
  78. package/runtime/scripts/chat-core/normalizers/opencode.js +552 -0
  79. package/runtime/scripts/chat-core/normalizers/tool_contract.md +123 -0
  80. package/runtime/scripts/chat-core/normalizers/usage_contract.md +304 -0
  81. package/runtime/scripts/chat-core/parts.js +253 -0
  82. package/runtime/scripts/chat-core/recorder.js +65 -0
  83. package/runtime/scripts/chat-core/runtime.js +86 -0
  84. package/runtime/scripts/chat-core/server.js +163 -0
  85. package/runtime/scripts/chat-core/sse.js +196 -0
  86. package/runtime/scripts/chat-core/stores.js +100 -0
  87. package/runtime/scripts/chat-core/tool-display.js +149 -0
  88. package/runtime/scripts/chat-core/tool-shape.js +143 -0
  89. package/runtime/scripts/chat-core/tooling/mcp-bundle.js +161 -0
  90. package/runtime/scripts/chat-core/tooling/mcp-relay.js +97 -0
  91. package/runtime/scripts/chat-core/tooling/native-binaries.js +608 -0
  92. package/runtime/scripts/chat-core/tooling/system-prompt.js +20 -0
  93. package/runtime/scripts/chat-core/usage.js +343 -0
  94. package/runtime/scripts/chat-server/config.js +110 -0
  95. package/runtime/scripts/chat-server/db.js +529 -0
  96. package/runtime/scripts/chat-server/index.js +33 -0
  97. package/runtime/scripts/chat-server/model-catalog.js +327 -0
  98. package/runtime/scripts/chat-server.js +75 -0
  99. package/runtime/scripts/credential-adapter.js +129 -0
  100. package/runtime/scripts/fs-watcher.js +888 -0
  101. package/runtime/scripts/local-gateway.js +852 -0
  102. package/runtime/scripts/platform-context.txt +246 -0
  103. package/runtime/scripts/port-monitor.js +175 -0
  104. package/runtime/scripts/proxy-token-store.js +162 -0
  105. package/runtime/scripts/runtime-auth.js +163 -0
  106. package/runtime/scripts/test-claude-code-models.js +87 -0
  107. package/runtime/tsconfig.json +15 -0
@@ -0,0 +1,306 @@
1
+ const { z } = require('zod');
2
+
3
+ const VALID_AUTH_METHODS = ['amalgm', 'byok', 'provider_auth'];
4
+
5
+ const ChatInputTextPartSchema = z.object({
6
+ type: z.literal('text'),
7
+ text: z.string().default(''),
8
+ }).passthrough();
9
+
10
+ const ChatInputFilePartSchema = z.object({
11
+ type: z.literal('file'),
12
+ filename: z.string().optional(),
13
+ mediaType: z.string().optional(),
14
+ url: z.string().optional(),
15
+ storagePath: z.string().optional(),
16
+ storage_path: z.string().optional(),
17
+ computerPath: z.string().optional(),
18
+ sandboxPath: z.string().optional(),
19
+ assetId: z.string().optional(),
20
+ }).passthrough();
21
+
22
+ const ChatInputUnknownPartSchema = z.object({
23
+ type: z.string(),
24
+ }).passthrough();
25
+
26
+ const ChatInputPartSchema = z.union([
27
+ ChatInputTextPartSchema,
28
+ ChatInputFilePartSchema,
29
+ ChatInputUnknownPartSchema,
30
+ ]);
31
+
32
+ const WorkspaceTargetSchema = z.discriminatedUnion('kind', [
33
+ z.object({
34
+ kind: z.literal('cwd'),
35
+ cwd: z.string(),
36
+ }),
37
+ z.object({
38
+ kind: z.literal('existing-worktree'),
39
+ path: z.string(),
40
+ }),
41
+ z.object({
42
+ kind: z.literal('managed-worktree'),
43
+ repoPath: z.string(),
44
+ branch: z.string(),
45
+ baseBranch: z.string().nullable().optional(),
46
+ path: z.string().nullable().optional(),
47
+ }),
48
+ ]);
49
+
50
+ const ChatInputSchema = z.object({
51
+ parts: z.array(ChatInputPartSchema).default([]),
52
+ agent: z.object({
53
+ harness: z.string().nullable().optional(),
54
+ model: z.string().nullable().optional(),
55
+ authMethod: z.enum(VALID_AUTH_METHODS).nullable().optional(),
56
+ customAgentId: z.string().nullable().optional(),
57
+ systemPrompt: z.string().nullable().optional(),
58
+ }).default({}),
59
+ tools: z.object({
60
+ mcpAppIds: z.array(z.string()).default([]),
61
+ }).default({}),
62
+ execution: z.object({
63
+ cwd: z.string().nullable().optional(),
64
+ computerId: z.string().nullable().optional(),
65
+ workspace: WorkspaceTargetSchema.nullable().optional(),
66
+ }).default({}),
67
+ });
68
+
69
+ function isObject(value) {
70
+ return !!value && typeof value === 'object' && !Array.isArray(value);
71
+ }
72
+
73
+ function cleanString(value) {
74
+ return typeof value === 'string' && value.trim() ? value : null;
75
+ }
76
+
77
+ function firstString(...values) {
78
+ for (const value of values) {
79
+ const cleaned = cleanString(value);
80
+ if (cleaned) return cleaned;
81
+ }
82
+ return null;
83
+ }
84
+
85
+ function uniqueStrings(values) {
86
+ if (!Array.isArray(values)) return [];
87
+ return [...new Set(values.filter((value) => typeof value === 'string' && value.trim()).map((value) => value.trim()))];
88
+ }
89
+
90
+ function normalizeWorkspace(rawWorkspace, fallbackCwd) {
91
+ if (isObject(rawWorkspace) && typeof rawWorkspace.kind === 'string') {
92
+ const parsed = WorkspaceTargetSchema.safeParse(rawWorkspace);
93
+ if (parsed.success) return parsed.data;
94
+ }
95
+
96
+ const cwd = cleanString(fallbackCwd);
97
+ return cwd ? { kind: 'cwd', cwd } : null;
98
+ }
99
+
100
+ function getWorkspaceCwd(workspace) {
101
+ if (!workspace || !isObject(workspace)) return null;
102
+ if (workspace.kind === 'cwd' && cleanString(workspace.cwd)) return workspace.cwd.trim();
103
+ if (workspace.kind === 'existing-worktree' && cleanString(workspace.path)) return workspace.path.trim();
104
+ if (workspace.kind === 'managed-worktree') {
105
+ return firstString(workspace.path, workspace.repoPath);
106
+ }
107
+ return null;
108
+ }
109
+
110
+ function normalizeChatPart(part) {
111
+ if (!isObject(part) || typeof part.type !== 'string') return null;
112
+
113
+ if (part.type === 'text') {
114
+ return {
115
+ ...part,
116
+ type: 'text',
117
+ text: typeof part.text === 'string' ? part.text : '',
118
+ };
119
+ }
120
+
121
+ if (part.type === 'file') {
122
+ const storagePath = firstString(part.storagePath, part.storage_path);
123
+ const computerPath = firstString(part.computerPath, part.sandboxPath);
124
+ return {
125
+ ...part,
126
+ type: 'file',
127
+ ...(cleanString(part.filename) ? { filename: part.filename.trim() } : {}),
128
+ ...(cleanString(part.mediaType) ? { mediaType: part.mediaType.trim() } : {}),
129
+ ...(cleanString(part.url) ? { url: part.url.trim() } : {}),
130
+ ...(storagePath ? { storagePath, storage_path: storagePath } : {}),
131
+ ...(computerPath ? { computerPath, sandboxPath: computerPath } : {}),
132
+ ...(cleanString(part.assetId) ? { assetId: part.assetId.trim() } : {}),
133
+ };
134
+ }
135
+
136
+ return { ...part };
137
+ }
138
+
139
+ function normalizeChatParts(parts, fallbackPrompt) {
140
+ const normalized = Array.isArray(parts)
141
+ ? parts.map(normalizeChatPart).filter(Boolean)
142
+ : [];
143
+
144
+ if (normalized.length > 0) return normalized;
145
+
146
+ const prompt = typeof fallbackPrompt === 'string' ? fallbackPrompt : '';
147
+ return prompt.trim() ? [{ type: 'text', text: prompt }] : [];
148
+ }
149
+
150
+ function getChatInputText(chatInput, fallbackPrompt) {
151
+ const normalized = normalizeChatInput(chatInput, { prompt: fallbackPrompt });
152
+ return normalized.parts
153
+ .filter((part) => part.type === 'text' && typeof part.text === 'string')
154
+ .map((part) => part.text)
155
+ .join('\n\n')
156
+ .trim();
157
+ }
158
+
159
+ function getAttachedFilePaths(parts) {
160
+ if (!Array.isArray(parts)) return [];
161
+ return parts
162
+ .filter((part) => part && part.type === 'file')
163
+ .map((part) => firstString(part.computerPath, part.sandboxPath))
164
+ .filter(Boolean);
165
+ }
166
+
167
+ function buildPromptFromParts(parts, fallbackPrompt) {
168
+ const normalizedParts = normalizeChatParts(parts, fallbackPrompt);
169
+ const text = normalizedParts
170
+ .filter((part) => part.type === 'text' && typeof part.text === 'string')
171
+ .map((part) => part.text)
172
+ .join('\n\n')
173
+ .trim();
174
+ const attachedPaths = getAttachedFilePaths(normalizedParts);
175
+
176
+ if (attachedPaths.length === 0) {
177
+ return text || (typeof fallbackPrompt === 'string' ? fallbackPrompt : '');
178
+ }
179
+
180
+ const attachedPrefix = `[Attached files: ${attachedPaths.join(', ')}]`;
181
+ return text ? `${attachedPrefix}\n\n${text}` : attachedPrefix;
182
+ }
183
+
184
+ function normalizeChatInput(chatInput, legacy = {}) {
185
+ const rawInput = isObject(chatInput) ? chatInput : {};
186
+ const rawAgent = isObject(rawInput.agent) ? rawInput.agent : {};
187
+ const rawTools = isObject(rawInput.tools) ? rawInput.tools : {};
188
+ const rawExecution = isObject(rawInput.execution) ? rawInput.execution : {};
189
+
190
+ const workspace = normalizeWorkspace(
191
+ rawExecution.workspace,
192
+ firstString(rawExecution.cwd, legacy.cwd, legacy.projectPath),
193
+ );
194
+ const resolvedCwd = firstString(
195
+ rawExecution.cwd,
196
+ getWorkspaceCwd(workspace),
197
+ legacy.cwd,
198
+ legacy.projectPath,
199
+ );
200
+
201
+ const normalized = {
202
+ parts: normalizeChatParts(
203
+ rawInput.parts,
204
+ Array.isArray(legacy.userParts) && legacy.userParts.length > 0
205
+ ? null
206
+ : legacy.prompt,
207
+ ),
208
+ agent: {
209
+ harness: firstString(rawAgent.harness, rawAgent.harnessId, legacy.harness),
210
+ model: firstString(rawAgent.model, rawAgent.modelId, legacy.modelId, legacy.model),
211
+ authMethod: firstString(rawAgent.authMethod, legacy.authMethod),
212
+ customAgentId: firstString(
213
+ rawAgent.customAgentId,
214
+ (typeof rawAgent.harness === 'string' && rawAgent.harness.startsWith('custom-'))
215
+ ? rawAgent.harness
216
+ : null,
217
+ (typeof legacy.harness === 'string' && legacy.harness.startsWith('custom-'))
218
+ ? legacy.harness
219
+ : null,
220
+ ),
221
+ systemPrompt: firstString(rawAgent.systemPrompt, legacy.systemPrompt),
222
+ },
223
+ tools: {
224
+ mcpAppIds: uniqueStrings(rawTools.mcpAppIds || legacy.mcpAppIds),
225
+ },
226
+ execution: {
227
+ cwd: resolvedCwd,
228
+ computerId: firstString(rawExecution.computerId, legacy.computerId),
229
+ workspace,
230
+ },
231
+ };
232
+
233
+ return ChatInputSchema.parse(normalized);
234
+ }
235
+
236
+ function chatInputToLegacyFields(chatInput, fallback = {}) {
237
+ const normalized = normalizeChatInput(chatInput, fallback);
238
+ const prompt = buildPromptFromParts(normalized.parts, fallback.prompt);
239
+ const harness = firstString(
240
+ normalized.agent.customAgentId,
241
+ normalized.agent.harness,
242
+ fallback.harness,
243
+ );
244
+ const modelId = firstString(
245
+ normalized.agent.model,
246
+ fallback.modelId,
247
+ fallback.model,
248
+ );
249
+ const cwd = firstString(
250
+ normalized.execution.cwd,
251
+ getWorkspaceCwd(normalized.execution.workspace),
252
+ fallback.cwd,
253
+ fallback.projectPath,
254
+ );
255
+ const authMethod = firstString(
256
+ normalized.agent.authMethod,
257
+ fallback.authMethod,
258
+ );
259
+ const systemPrompt = firstString(
260
+ normalized.agent.systemPrompt,
261
+ fallback.systemPrompt,
262
+ );
263
+
264
+ return {
265
+ prompt,
266
+ userParts: normalized.parts,
267
+ harness,
268
+ modelId,
269
+ model: modelId,
270
+ authMethod,
271
+ cwd,
272
+ projectPath: cwd,
273
+ computerId: firstString(normalized.execution.computerId, fallback.computerId),
274
+ mcpAppIds: normalized.tools.mcpAppIds,
275
+ systemPrompt,
276
+ };
277
+ }
278
+
279
+ function withChatInputText(chatInput, updater, legacy = {}) {
280
+ const normalized = normalizeChatInput(chatInput, legacy);
281
+ const parts = normalized.parts.map((part) => {
282
+ if (part.type !== 'text' || typeof part.text !== 'string') return part;
283
+ const nextText = updater(part.text, part);
284
+ return {
285
+ ...part,
286
+ text: typeof nextText === 'string' ? nextText : part.text,
287
+ };
288
+ });
289
+ return normalizeChatInput({ ...normalized, parts });
290
+ }
291
+
292
+ module.exports = {
293
+ ChatInputPartSchema,
294
+ ChatInputSchema,
295
+ WorkspaceTargetSchema,
296
+ buildPromptFromParts,
297
+ chatInputToLegacyFields,
298
+ getAttachedFilePaths,
299
+ getChatInputText,
300
+ getWorkspaceCwd,
301
+ normalizeChatInput,
302
+ normalizeChatPart,
303
+ normalizeChatParts,
304
+ uniqueStrings,
305
+ withChatInputText,
306
+ };