salmon-loop 0.2.16 → 0.3.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.
- package/dist/cli/authorization/non-interactive.js +7 -21
- package/dist/cli/commands/chat.js +1 -1
- package/dist/cli/commands/parallel.js +46 -41
- package/dist/cli/commands/run/assistant-message.js +3 -0
- package/dist/cli/commands/run/handler.js +2 -1
- package/dist/cli/commands/serve.js +112 -156
- package/dist/cli/headless/json-protocol.js +1 -1
- package/dist/cli/headless/stream-json-protocol.js +3 -2
- package/dist/cli/program-bootstrap.js +2 -2
- package/dist/cli/slash/runtime.js +5 -1
- package/dist/core/adapters/fs/node-fs.js +1 -0
- package/dist/core/backends/salmon-loop/task-executor.js +1 -0
- package/dist/core/benchmark/patch-artifact.js +1 -1
- package/dist/core/context/service.js +5 -2
- package/dist/core/extensions/index.js +2 -35
- package/dist/core/extensions/merge.js +14 -0
- package/dist/core/extensions/redact.js +9 -3
- package/dist/core/extensions/schemas.js +2 -51
- package/dist/core/facades/cli-authorization-non-interactive.js +1 -1
- package/dist/core/facades/cli-program-bootstrap.js +1 -0
- package/dist/core/facades/cli-serve.js +2 -1
- package/dist/core/grizzco/dsl/strategies.js +1 -3
- package/dist/core/grizzco/engine/outcome/loop-result-mapper.js +12 -7
- package/dist/core/grizzco/engine/transaction/attempt-failure.js +23 -23
- package/dist/core/grizzco/engine/transaction/report-mapper.js +3 -0
- package/dist/core/grizzco/engine/transaction/transaction-runner.js +14 -0
- package/dist/core/grizzco/flows/AutopilotFlow.js +1 -0
- package/dist/core/grizzco/flows/SalmonLoopFlow.js +1 -0
- package/dist/core/grizzco/steps/apply.js +0 -7
- package/dist/core/grizzco/steps/autopilot.js +108 -6
- package/dist/core/grizzco/steps/preflight.js +10 -0
- package/dist/core/grizzco/steps/tool-runtime.js +1 -0
- package/dist/core/interaction/events/bus.js +14 -0
- package/dist/core/interaction/orchestration/facade.js +11 -1
- package/dist/core/llm/ai-sdk/request-params.js +40 -1
- package/dist/core/mcp/bridge/index.js +4 -0
- package/dist/core/mcp/bridge/prompt-command-provider.js +261 -0
- package/dist/core/mcp/bridge/resource-context-provider.js +259 -0
- package/dist/core/mcp/bridge/tool-bridge.js +303 -0
- package/dist/core/mcp/cache/resource-cache.js +41 -0
- package/dist/core/mcp/catalog/discovery.js +51 -0
- package/dist/core/mcp/catalog/notification-router.js +28 -0
- package/dist/core/mcp/catalog/prompt-catalog.js +4 -0
- package/dist/core/mcp/catalog/resource-catalog.js +7 -0
- package/dist/core/mcp/catalog/tool-catalog.js +4 -0
- package/dist/core/mcp/client/connection-manager.js +239 -0
- package/dist/core/mcp/client/lifecycle.js +13 -0
- package/dist/core/mcp/client/transport-factory.js +168 -0
- package/dist/core/mcp/config/index.js +32 -0
- package/dist/core/mcp/config/schema-v2.js +129 -0
- package/dist/core/mcp/host/elicitation-provider.js +209 -0
- package/dist/core/mcp/host/roots-provider.js +70 -0
- package/dist/core/mcp/host/sampling-provider.js +170 -0
- package/dist/core/mcp/index.js +4 -0
- package/dist/core/mcp/observability/events.js +19 -0
- package/dist/core/mcp/policy/approval-policy.js +2 -0
- package/dist/core/mcp/policy/classifier.js +172 -0
- package/dist/core/mcp/policy/grants.js +356 -0
- package/dist/core/mcp/policy/uri-policy.js +60 -0
- package/dist/core/mcp/schema/json-schema-to-zod.js +511 -0
- package/dist/core/mcp/types.js +2 -0
- package/dist/core/protocols/a2a/agent-card.js +38 -12
- package/dist/core/protocols/a2a/sdk/executor.js +105 -36
- package/dist/core/protocols/a2a/sdk/server.js +1311 -3
- package/dist/core/protocols/acp/acp-checkpoint-probe.js +113 -0
- package/dist/core/protocols/acp/acp-session-persistence.js +336 -0
- package/dist/core/protocols/acp/acp-types.js +17 -0
- package/dist/core/protocols/acp/formal-agent.js +389 -502
- package/dist/core/protocols/acp/handlers.js +3 -0
- package/dist/core/protocols/acp/permission-provider.js +11 -39
- package/dist/core/protocols/acp/stdio-server.js +20 -1
- package/dist/core/protocols/acp/tool-kind-mapping.js +62 -0
- package/dist/core/protocols/shared/flow-mode-mapping.js +0 -8
- package/dist/core/public-capabilities/flow-mode-metadata.js +0 -6
- package/dist/core/public-capabilities/projections.js +1 -0
- package/dist/core/runtime/agent-server-runtime.js +2 -3
- package/dist/core/runtime/spawn-command.js +8 -2
- package/dist/core/runtime/spawn-interactive.js +26 -0
- package/dist/core/session/manager.js +48 -25
- package/dist/core/tools/builtin/index.js +6 -1
- package/dist/core/tools/builtin/proposal.js +0 -7
- package/dist/core/tools/builtin/workspace.js +76 -0
- package/dist/core/tools/dispatcher.js +1 -0
- package/dist/core/tools/loader.js +92 -46
- package/dist/core/verification/runner.js +60 -31
- package/dist/core/version.js +17 -0
- package/dist/core/workspace/capabilities.js +80 -0
- package/dist/locales/en.js +17 -3
- package/package.json +4 -2
- package/dist/core/protocols/a2a/mapper.js +0 -14
- package/dist/core/protocols/a2a/sdk/auth-middleware.js +0 -31
- package/dist/core/protocols/a2a/task-projection.js +0 -45
- package/dist/core/protocols/acp/checkpoint-meta.js +0 -2
- package/dist/core/tools/mcp/client.js +0 -308
- package/dist/core/tools/mcp/loader.js +0 -110
- package/dist/core/tools/mcp/schema.js +0 -54
- package/dist/core/tools/mcp/streamable-http.js +0 -101
- package/dist/core/tools/mcp/types.js +0 -26
|
@@ -10,6 +10,7 @@ export function createA2AInteractionExecutor(deps) {
|
|
|
10
10
|
const submittedPublished = new Set();
|
|
11
11
|
// Prevents duplicate terminal status events when publishTaskStatus is called multiple times
|
|
12
12
|
const terminalPublished = new Set();
|
|
13
|
+
const artifactSignaturesByTaskId = new Map();
|
|
13
14
|
return {
|
|
14
15
|
async execute(requestContext, executionEventBus) {
|
|
15
16
|
const capability = parseA2ASkillFlowMode(deps.capabilityResolver?.(requestContext.userMessage)) ?? 'autopilot';
|
|
@@ -89,24 +90,9 @@ export function createA2AInteractionExecutor(deps) {
|
|
|
89
90
|
// ALWAYS publish "submitted" first if not yet published
|
|
90
91
|
if (!submittedPublished.has(taskId)) {
|
|
91
92
|
submittedPublished.add(taskId);
|
|
92
|
-
const
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
message: undefined,
|
|
96
|
-
};
|
|
97
|
-
const submittedUpdate = {
|
|
98
|
-
kind: 'status-update',
|
|
99
|
-
taskId: envelope.id,
|
|
100
|
-
contextId: metadata.contextId,
|
|
101
|
-
status: submittedStatus,
|
|
102
|
-
final: false,
|
|
103
|
-
metadata: { attempt: envelope.attempt },
|
|
104
|
-
};
|
|
105
|
-
eventBus.publish(submittedUpdate);
|
|
106
|
-
// Save as 'running' state (not completed) to keep task cancelable during grace period.
|
|
107
|
-
// SDK rejects cancellation if task is already in terminal state in the store.
|
|
108
|
-
const submittedEnvelope = { ...envelope, state: 'running' };
|
|
109
|
-
const snapshot = buildTaskSnapshot(submittedEnvelope, metadata);
|
|
93
|
+
const submittedEnvelope = { ...envelope, state: 'accepted' };
|
|
94
|
+
const snapshot = buildTaskSnapshot(submittedEnvelope, metadata, submittedEnvelope.createdAt ?? new Date().toISOString());
|
|
95
|
+
eventBus.publish(snapshot);
|
|
110
96
|
await store.save(snapshot);
|
|
111
97
|
// If the current state is still "submitted", we're done
|
|
112
98
|
if (currentState === 'submitted') {
|
|
@@ -124,10 +110,11 @@ export function createA2AInteractionExecutor(deps) {
|
|
|
124
110
|
if (cancelledTaskIds.has(taskId)) {
|
|
125
111
|
terminalPublished.add(taskId);
|
|
126
112
|
const canceledEnvelope = { ...envelope, state: 'cancelled' };
|
|
127
|
-
const
|
|
113
|
+
const recordedAt = new Date().toISOString();
|
|
114
|
+
const snapshot = buildTaskSnapshot(canceledEnvelope, metadata, recordedAt);
|
|
128
115
|
await store.save(snapshot);
|
|
129
116
|
const status = {
|
|
130
|
-
...buildTaskStatus(envelope, metadata.contextId),
|
|
117
|
+
...buildTaskStatus(envelope, metadata.contextId, recordedAt),
|
|
131
118
|
state: 'canceled',
|
|
132
119
|
};
|
|
133
120
|
const update = {
|
|
@@ -149,13 +136,14 @@ export function createA2AInteractionExecutor(deps) {
|
|
|
149
136
|
const wasCancelled = cancelledTaskIds.has(taskId) || taskAfterGrace?.status.state === 'canceled';
|
|
150
137
|
if (wasCancelled) {
|
|
151
138
|
terminalPublished.add(taskId);
|
|
139
|
+
const recordedAt = new Date().toISOString();
|
|
152
140
|
if (taskAfterGrace?.status.state !== 'canceled') {
|
|
153
141
|
const canceledEnvelope = { ...envelope, state: 'cancelled' };
|
|
154
|
-
const snapshot = buildTaskSnapshot(canceledEnvelope, metadata);
|
|
142
|
+
const snapshot = buildTaskSnapshot(canceledEnvelope, metadata, recordedAt);
|
|
155
143
|
await store.save(snapshot);
|
|
156
144
|
}
|
|
157
145
|
const status = {
|
|
158
|
-
...buildTaskStatus(envelope, metadata.contextId),
|
|
146
|
+
...buildTaskStatus(envelope, metadata.contextId, recordedAt),
|
|
159
147
|
state: 'canceled',
|
|
160
148
|
};
|
|
161
149
|
const update = {
|
|
@@ -171,9 +159,11 @@ export function createA2AInteractionExecutor(deps) {
|
|
|
171
159
|
}
|
|
172
160
|
// No cancellation detected, safe to publish "completed"
|
|
173
161
|
terminalPublished.add(taskId);
|
|
174
|
-
const
|
|
162
|
+
const recordedAt = new Date().toISOString();
|
|
163
|
+
const snapshot = buildTaskSnapshot(envelope, metadata, recordedAt);
|
|
175
164
|
await store.save(snapshot);
|
|
176
|
-
|
|
165
|
+
publishArtifactUpdates(envelope, metadata, eventBus);
|
|
166
|
+
const status = buildTaskStatus(envelope, metadata.contextId, recordedAt);
|
|
177
167
|
const update = {
|
|
178
168
|
kind: 'status-update',
|
|
179
169
|
taskId: envelope.id,
|
|
@@ -186,9 +176,11 @@ export function createA2AInteractionExecutor(deps) {
|
|
|
186
176
|
return true;
|
|
187
177
|
}
|
|
188
178
|
// For all other states (working, failed, canceled, etc.), save and publish immediately
|
|
189
|
-
const
|
|
179
|
+
const recordedAt = new Date().toISOString();
|
|
180
|
+
const snapshot = buildTaskSnapshot(envelope, metadata, recordedAt);
|
|
190
181
|
await store.save(snapshot);
|
|
191
|
-
|
|
182
|
+
publishArtifactUpdates(envelope, metadata, eventBus);
|
|
183
|
+
const status = buildTaskStatus(envelope, metadata.contextId, recordedAt);
|
|
192
184
|
const isFinal = isTerminalState(status.state);
|
|
193
185
|
if (isFinal) {
|
|
194
186
|
terminalPublished.add(taskId);
|
|
@@ -215,6 +207,7 @@ export function createA2AInteractionExecutor(deps) {
|
|
|
215
207
|
cancelledTaskIds.delete(taskId);
|
|
216
208
|
submittedPublished.delete(taskId);
|
|
217
209
|
terminalPublished.delete(taskId);
|
|
210
|
+
artifactSignaturesByTaskId.delete(taskId);
|
|
218
211
|
}
|
|
219
212
|
function extractInstruction(message) {
|
|
220
213
|
const textParts = message.parts
|
|
@@ -247,10 +240,10 @@ export function createA2AInteractionExecutor(deps) {
|
|
|
247
240
|
function isTerminalState(state) {
|
|
248
241
|
return (state === 'completed' || state === 'failed' || state === 'canceled' || state === 'rejected');
|
|
249
242
|
}
|
|
250
|
-
function buildTaskStatus(envelope, contextId) {
|
|
243
|
+
function buildTaskStatus(envelope, contextId, timestamp = envelope.createdAt ?? new Date().toISOString()) {
|
|
251
244
|
return {
|
|
252
245
|
state: mapState(envelope.state),
|
|
253
|
-
timestamp
|
|
246
|
+
timestamp,
|
|
254
247
|
message: buildStatusMessage(envelope, contextId),
|
|
255
248
|
};
|
|
256
249
|
}
|
|
@@ -271,7 +264,7 @@ export function createA2AInteractionExecutor(deps) {
|
|
|
271
264
|
],
|
|
272
265
|
};
|
|
273
266
|
}
|
|
274
|
-
function buildTaskSnapshot(envelope, metadata) {
|
|
267
|
+
function buildTaskSnapshot(envelope, metadata, timestamp) {
|
|
275
268
|
return {
|
|
276
269
|
id: envelope.id,
|
|
277
270
|
kind: 'task',
|
|
@@ -282,22 +275,98 @@ export function createA2AInteractionExecutor(deps) {
|
|
|
282
275
|
attempt: envelope.attempt,
|
|
283
276
|
},
|
|
284
277
|
artifacts: convertArtifacts(envelope.artifacts),
|
|
285
|
-
status: buildTaskStatus(envelope, metadata.contextId),
|
|
278
|
+
status: buildTaskStatus(envelope, metadata.contextId, timestamp),
|
|
286
279
|
};
|
|
287
280
|
}
|
|
281
|
+
function publishArtifactUpdates(envelope, metadata, eventBus) {
|
|
282
|
+
if (!envelope.artifacts || envelope.artifacts.length === 0) {
|
|
283
|
+
return;
|
|
284
|
+
}
|
|
285
|
+
let knownSignatures = artifactSignaturesByTaskId.get(envelope.id);
|
|
286
|
+
if (!knownSignatures) {
|
|
287
|
+
knownSignatures = new Map();
|
|
288
|
+
artifactSignaturesByTaskId.set(envelope.id, knownSignatures);
|
|
289
|
+
}
|
|
290
|
+
for (const artifact of envelope.artifacts) {
|
|
291
|
+
const signature = artifactSignature(artifact);
|
|
292
|
+
if (knownSignatures.get(artifact.id) === signature) {
|
|
293
|
+
continue;
|
|
294
|
+
}
|
|
295
|
+
knownSignatures.set(artifact.id, signature);
|
|
296
|
+
const update = {
|
|
297
|
+
kind: 'artifact-update',
|
|
298
|
+
taskId: envelope.id,
|
|
299
|
+
contextId: metadata.contextId,
|
|
300
|
+
artifact: {
|
|
301
|
+
artifactId: artifact.id,
|
|
302
|
+
name: artifact.name,
|
|
303
|
+
parts: [artifactToPart(artifact)],
|
|
304
|
+
},
|
|
305
|
+
append: false,
|
|
306
|
+
lastChunk: true,
|
|
307
|
+
metadata: { attempt: envelope.attempt },
|
|
308
|
+
};
|
|
309
|
+
eventBus.publish(update);
|
|
310
|
+
}
|
|
311
|
+
}
|
|
288
312
|
function convertArtifacts(artifacts) {
|
|
289
313
|
if (!artifacts || artifacts.length === 0)
|
|
290
314
|
return undefined;
|
|
291
315
|
return artifacts.map((artifact) => ({
|
|
292
316
|
artifactId: artifact.id,
|
|
293
317
|
name: artifact.name,
|
|
294
|
-
parts: [
|
|
295
|
-
{
|
|
296
|
-
kind: 'text',
|
|
297
|
-
text: artifact.content ?? artifact.name ?? '',
|
|
298
|
-
},
|
|
299
|
-
],
|
|
318
|
+
parts: [artifactToPart(artifact)],
|
|
300
319
|
}));
|
|
301
320
|
}
|
|
321
|
+
function artifactToPart(artifact) {
|
|
322
|
+
if (artifact.url) {
|
|
323
|
+
return {
|
|
324
|
+
kind: 'file',
|
|
325
|
+
file: {
|
|
326
|
+
name: artifact.name,
|
|
327
|
+
mimeType: artifact.mimeType,
|
|
328
|
+
uri: artifact.url,
|
|
329
|
+
},
|
|
330
|
+
};
|
|
331
|
+
}
|
|
332
|
+
if (artifact.handle) {
|
|
333
|
+
return {
|
|
334
|
+
kind: 'file',
|
|
335
|
+
file: {
|
|
336
|
+
name: artifact.name,
|
|
337
|
+
mimeType: artifact.mimeType,
|
|
338
|
+
bytes: artifact.handle,
|
|
339
|
+
},
|
|
340
|
+
};
|
|
341
|
+
}
|
|
342
|
+
if (artifact.kind === 'data' && artifact.content) {
|
|
343
|
+
try {
|
|
344
|
+
return {
|
|
345
|
+
kind: 'data',
|
|
346
|
+
data: JSON.parse(artifact.content),
|
|
347
|
+
};
|
|
348
|
+
}
|
|
349
|
+
catch {
|
|
350
|
+
// Fall through to text
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
return {
|
|
354
|
+
kind: 'text',
|
|
355
|
+
text: artifact.content ?? artifact.name ?? '',
|
|
356
|
+
};
|
|
357
|
+
}
|
|
358
|
+
function artifactSignature(artifact) {
|
|
359
|
+
return JSON.stringify({
|
|
360
|
+
id: artifact.id,
|
|
361
|
+
name: artifact.name,
|
|
362
|
+
kind: artifact.kind,
|
|
363
|
+
mimeType: artifact.mimeType,
|
|
364
|
+
content: artifact.content,
|
|
365
|
+
delivery: artifact.delivery,
|
|
366
|
+
handle: artifact.handle,
|
|
367
|
+
url: artifact.url,
|
|
368
|
+
expiresAt: artifact.expiresAt,
|
|
369
|
+
});
|
|
370
|
+
}
|
|
302
371
|
}
|
|
303
372
|
//# sourceMappingURL=executor.js.map
|