salmon-loop 0.2.13 → 0.2.16
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/argv/headless-detection.js +27 -0
- package/dist/cli/chat-flow.js +11 -0
- package/dist/cli/chat.js +160 -24
- package/dist/cli/commands/chat.js +14 -7
- package/dist/cli/commands/flow-mode.js +63 -0
- package/dist/cli/commands/registry.js +2 -0
- package/dist/cli/commands/run/benchmark-artifacts.js +41 -0
- package/dist/cli/commands/run/early-errors.js +23 -0
- package/dist/cli/commands/run/handler.js +115 -27
- package/dist/cli/commands/run/headless-error-writer.js +8 -0
- package/dist/cli/commands/run/loop-params.js +2 -0
- package/dist/cli/commands/run/mode.js +2 -5
- package/dist/cli/commands/run/parse-options.js +16 -0
- package/dist/cli/commands/run/persist-session.js +10 -1
- package/dist/cli/commands/run/preflight.js +10 -0
- package/dist/cli/commands/run/reporter-factory.js +4 -0
- package/dist/cli/commands/run/runtime-llm.js +38 -11
- package/dist/cli/commands/run/runtime-options.js +2 -2
- package/dist/cli/commands/serve.js +91 -71
- package/dist/cli/commands/tool-names.js +78 -78
- package/dist/cli/headless/anthropic-stream-normalized-encoder.js +6 -1
- package/dist/cli/headless/json-protocol.js +37 -0
- package/dist/cli/headless/native-stream-normalized-encoder.js +6 -1
- package/dist/cli/headless/protocol-metadata.js +22 -0
- package/dist/cli/headless/stream-json-protocol.js +34 -1
- package/dist/cli/index.js +6 -4
- package/dist/cli/locales/en.js +30 -6
- package/dist/cli/program-bootstrap.js +8 -3
- package/dist/cli/program-commands.js +5 -1
- package/dist/cli/reporters/anthropic-stream.js +7 -1
- package/dist/cli/reporters/json.js +4 -0
- package/dist/cli/reporters/stream-json.js +17 -2
- package/dist/cli/run-cli.js +5 -3
- package/dist/cli/slash/runtime.js +27 -12
- package/dist/cli/ui/components/CommandInput.js +7 -3
- package/dist/cli/ui/components/CommandSuggestionList.js +1 -1
- package/dist/cli/utils/command-option-source.js +13 -0
- package/dist/cli/utils/verify-resolver.js +8 -4
- package/dist/cli/utils/worktree-prepare-resolver.js +7 -3
- package/dist/core/adapters/fs/file-adapter.js +6 -0
- package/dist/core/adapters/fs/filesystem.js +2 -1
- package/dist/core/adapters/git/git-adapter.js +78 -1
- package/dist/core/benchmark/patch-artifact.js +124 -0
- package/dist/core/benchmark/swe-bench.js +25 -0
- package/dist/core/config/load.js +18 -11
- package/dist/core/config/resolve-llm.js +12 -0
- package/dist/core/config/resolvers/server.js +0 -6
- package/dist/core/config/validate.js +73 -21
- package/dist/core/context/gatherers/metadata-gatherer.js +1 -0
- package/dist/core/context/gatherers/ripgrep-gatherer.js +84 -2
- package/dist/core/context/keywords.js +18 -4
- package/dist/core/context/service-deps.js +2 -2
- package/dist/core/context/service.js +8 -0
- package/dist/core/context/steps/context-gather.js +38 -0
- package/dist/core/context/summarization/summarizer.js +55 -12
- package/dist/core/context/targeting/target-resolver.js +4 -4
- package/dist/core/extensions/index.js +23 -5
- package/dist/core/extensions/paths.js +31 -0
- package/dist/core/extensions/schemas.js +8 -5
- package/dist/core/facades/cli-chat.js +6 -2
- package/dist/core/facades/cli-command-chat.js +1 -0
- package/dist/core/facades/cli-command-tool-names.js +2 -0
- package/dist/core/facades/cli-observability.js +1 -1
- package/dist/core/facades/cli-run-handler.js +4 -2
- package/dist/core/facades/cli-run-persist-session.js +1 -0
- package/dist/core/facades/cli-serve.js +2 -4
- package/dist/core/facades/cli-utils-worktree.js +1 -1
- package/dist/core/failure/diagnostics.js +53 -1
- package/dist/core/grizzco/dsl/llm-strategy.js +4 -1
- package/dist/core/grizzco/engine/outcome/loop-result-mapper.js +67 -9
- package/dist/core/grizzco/engine/pipeline/pipeline.js +6 -2
- package/dist/core/grizzco/engine/transaction/attempt-failure.js +90 -15
- package/dist/core/grizzco/engine/transaction/report-mapper.js +17 -3
- package/dist/core/grizzco/engine/transaction/transaction-runner.js +165 -7
- package/dist/core/grizzco/flows/AutopilotFlow.js +18 -0
- package/dist/core/grizzco/flows/flow-dispatch.js +11 -0
- package/dist/core/grizzco/steps/answer.js +13 -14
- package/dist/core/grizzco/steps/autopilot.js +396 -0
- package/dist/core/grizzco/steps/cache-sharing.js +29 -0
- package/dist/core/grizzco/steps/explore.js +37 -21
- package/dist/core/grizzco/steps/generateReview.js +2 -5
- package/dist/core/grizzco/steps/patch/apply-check.js +10 -0
- package/dist/core/grizzco/steps/patch/diff-normalization.js +70 -0
- package/dist/core/grizzco/steps/patch/diff-salvage.js +46 -0
- package/dist/core/grizzco/steps/patch/prompt-input.js +42 -0
- package/dist/core/grizzco/steps/patch.js +105 -146
- package/dist/core/grizzco/steps/plan.js +101 -25
- package/dist/core/grizzco/steps/preflight.js +5 -6
- package/dist/core/grizzco/steps/request-assembly.js +78 -0
- package/dist/core/grizzco/steps/research.js +39 -36
- package/dist/core/grizzco/steps/tool-runtime.js +47 -0
- package/dist/core/grizzco/steps/verify-shared.js +23 -0
- package/dist/core/grizzco/steps/verify.js +13 -21
- package/dist/core/llm/ai-sdk/chat-executor.js +2 -0
- package/dist/core/llm/ai-sdk/high-level-phase-specs.js +63 -0
- package/dist/core/llm/ai-sdk/message-mapper.js +40 -10
- package/dist/core/llm/ai-sdk/provider-factory.js +14 -0
- package/dist/core/llm/ai-sdk/request-params.js +73 -0
- package/dist/core/llm/ai-sdk/result-mapper.js +16 -0
- package/dist/core/llm/ai-sdk.js +112 -27
- package/dist/core/llm/capabilities.js +12 -0
- package/dist/core/llm/contracts/repair.js +36 -30
- package/dist/core/llm/errors.js +83 -2
- package/dist/core/llm/message-composition.js +7 -22
- package/dist/core/llm/phase-router.js +29 -10
- package/dist/core/llm/redact.js +28 -3
- package/dist/core/llm/registry.js +2 -0
- package/dist/core/llm/request-augmentation.js +55 -0
- package/dist/core/llm/request-envelope.js +334 -0
- package/dist/core/llm/shared-request-assembly.js +35 -0
- package/dist/core/llm/stream-utils.js +13 -4
- package/dist/core/llm/utils.js +18 -29
- package/dist/core/memory/relevant-retrieval.js +144 -0
- package/dist/core/observability/logger.js +11 -2
- package/dist/core/patch/diff.js +1 -0
- package/dist/core/prompts/registry.js +39 -2
- package/dist/core/prompts/runtime.js +50 -12
- package/dist/core/prompts/templates/phases/patch_user.hbs +2 -5
- package/dist/core/prompts/templates/phases/research_user.hbs +11 -0
- package/dist/core/prompts/templates/phases/review_user.hbs +3 -0
- package/dist/core/prompts/templates/system/answer_system.hbs +5 -0
- package/dist/core/prompts/templates/system/autopilot_system.hbs +11 -0
- package/dist/core/prompts/templates/system/explore_system.hbs +14 -23
- package/dist/core/prompts/templates/system/main_system.hbs +4 -16
- package/dist/core/prompts/templates/system/patch_system.hbs +39 -8
- package/dist/core/prompts/templates/system/plan_system.hbs +86 -1
- package/dist/core/prompts/templates/system/research_system.hbs +2 -0
- package/dist/core/protocols/a2a/agent-card.js +3 -2
- package/dist/core/protocols/a2a/sdk/executor.js +2 -1
- package/dist/core/protocols/a2a/sdk/server.js +0 -1
- package/dist/core/protocols/acp/formal-agent.js +74 -51
- package/dist/core/protocols/acp/handlers.js +5 -1
- package/dist/core/protocols/acp/permission-provider.js +1 -1
- package/dist/core/protocols/shared/flow-mode-mapping.js +23 -0
- package/dist/core/public-capabilities/flow-mode-metadata.js +39 -0
- package/dist/core/public-capabilities/projections.js +29 -0
- package/dist/core/public-capabilities/registry.js +26 -0
- package/dist/core/public-capabilities/types.js +2 -0
- package/dist/core/runtime/agent-server-runtime.js +47 -43
- package/dist/core/runtime/execution-profile.js +67 -0
- package/dist/core/session/artifact-state.js +160 -0
- package/dist/core/session/compaction/index.js +183 -0
- package/dist/core/session/compaction/microcompact.js +78 -0
- package/dist/core/session/compaction/tracking.js +48 -0
- package/dist/core/session/compaction/types.js +11 -0
- package/dist/core/session/compression.js +8 -0
- package/dist/core/session/manager.js +244 -8
- package/dist/core/session/pruning-strategy.js +55 -9
- package/dist/core/session/replacement-preview-provider.js +24 -0
- package/dist/core/session/replacement-state.js +131 -0
- package/dist/core/session/resume-repair/pipeline.js +79 -0
- package/dist/core/session/resume-repair/stages/load-raw-archive-state.js +40 -0
- package/dist/core/session/resume-repair/stages/reattach-runtime-state.js +8 -0
- package/dist/core/session/resume-repair/stages/recover-orphaned-branches.js +10 -0
- package/dist/core/session/resume-repair/stages/relink-boundary-and-tail.js +36 -0
- package/dist/core/session/resume-repair/stages/replay-startup-hooks.js +23 -0
- package/dist/core/session/resume-repair/stages/rescue-stale-metadata.js +17 -0
- package/dist/core/session/resume-repair/types.js +2 -0
- package/dist/core/session/summary-sync.js +164 -13
- package/dist/core/session/token-tracker.js +6 -0
- package/dist/core/skills/audit.js +34 -0
- package/dist/core/skills/bridge.js +84 -7
- package/dist/core/skills/discovery.js +94 -0
- package/dist/core/skills/feature-flags.js +52 -0
- package/dist/core/skills/index.js +1 -1
- package/dist/core/skills/loader.js +195 -20
- package/dist/core/skills/parser.js +296 -24
- package/dist/core/skills/permissions.js +117 -0
- package/dist/core/skills/runtime/MicroTaskRunner.js +10 -4
- package/dist/core/skills/runtime/SkillRunner.js +240 -61
- package/dist/core/strata/layers/shadow-driver/shadow-driver.js +37 -7
- package/dist/core/strata/layers/worktree.js +67 -10
- package/dist/core/strata/runtime/synchronizer.js +29 -2
- package/dist/core/streaming/stream-assembler.js +75 -31
- package/dist/core/sub-agent/context-snapshot.js +156 -0
- package/dist/core/sub-agent/core/loop.js +1 -1
- package/dist/core/sub-agent/core/manager.js +119 -20
- package/dist/core/sub-agent/dispatch-policy.js +29 -0
- package/dist/core/sub-agent/prefix-consistency.js +48 -0
- package/dist/core/sub-agent/registry-defaults.js +4 -0
- package/dist/core/sub-agent/tools/task-spawn.js +79 -2
- package/dist/core/sub-agent/types.js +134 -5
- package/dist/core/tools/audit.js +13 -4
- package/dist/core/tools/builtin/ast-grep.js +1 -1
- package/dist/core/tools/builtin/ast.js +1 -1
- package/dist/core/tools/builtin/benchmark.js +360 -0
- package/dist/core/tools/builtin/code-search/backends/rg.js +2 -1
- package/dist/core/tools/builtin/code-search/executor.js +6 -1
- package/dist/core/tools/builtin/code-search/spec.js +26 -2
- package/dist/core/tools/builtin/fs.js +256 -23
- package/dist/core/tools/builtin/git.js +2 -2
- package/dist/core/tools/builtin/index.js +51 -2
- package/dist/core/tools/builtin/interaction.js +8 -1
- package/dist/core/tools/builtin/plan.js +37 -15
- package/dist/core/tools/builtin/shell.js +1 -1
- package/dist/core/tools/loader.js +39 -16
- package/dist/core/tools/mapper.js +17 -3
- package/dist/core/tools/parallel/scheduler.js +35 -4
- package/dist/core/tools/permissions/permission-rules.js +5 -10
- package/dist/core/tools/policy.js +6 -1
- package/dist/core/tools/recoverable-tool-errors.js +10 -0
- package/dist/core/tools/router.js +24 -6
- package/dist/core/tools/session.js +458 -48
- package/dist/core/tools/tool-visibility.js +62 -0
- package/dist/core/tools/types.js +9 -1
- package/dist/core/types/execution.js +4 -0
- package/dist/core/types/flow-mode.js +8 -0
- package/dist/core/utils/path.js +52 -0
- package/dist/core/verification/runner.js +4 -1
- package/dist/languages/typescript/index.js +4 -1
- package/dist/locales/en.js +35 -2
- package/dist/utils/eol.js +1 -1
- package/package.json +13 -6
- package/scripts/fix-es-abstract-compat.js +77 -0
- package/dist/core/runtime/fastify-server-bundle.js +0 -26
- package/dist/core/runtime/sidecar-fastify-plugin.js +0 -35
- package/dist/core/runtime/sidecar-paths.js +0 -47
- package/dist/core/runtime/sidecar-route-catalog.js +0 -103
|
@@ -6,8 +6,11 @@ import { defaultPathAdapter } from '../../adapters/path/path-adapter.js';
|
|
|
6
6
|
import { inferTurnStopReasonFromFailure } from '../../interaction/turn-stop-reason.js';
|
|
7
7
|
import { recordAuditEvent } from '../../observability/audit-trail.js';
|
|
8
8
|
import { readPlan } from '../../plan/index.js';
|
|
9
|
+
import { toAcpPublicModes } from '../../public-capabilities/projections.js';
|
|
10
|
+
import { buildPublicCapabilityRegistry } from '../../public-capabilities/registry.js';
|
|
9
11
|
import { parseSlashInput } from '../../slash/parser.js';
|
|
10
12
|
import { buildCanonicalExecutionRequest } from '../shared/execution-request.js';
|
|
13
|
+
import { parseAcpFlowMode } from '../shared/flow-mode-mapping.js';
|
|
11
14
|
import { createAcpCommandRunner } from './acp-command-runner.js';
|
|
12
15
|
import { createAcpFileSystem } from './acp-filesystem.js';
|
|
13
16
|
import { createAcpSessionStore, isTerminalTaskEvent } from './handlers.js';
|
|
@@ -35,7 +38,8 @@ const ACP_PERMISSION_POLICY_CONFIG_ID = '_salmonloop_permission_policy';
|
|
|
35
38
|
const ACP_MODE_CONFIG_ID = '_salmonloop_mode';
|
|
36
39
|
const ACP_PERMISSION_POLICY_ASK = 'ask';
|
|
37
40
|
const ACP_PERMISSION_POLICY_DENY_ALL = 'deny_all';
|
|
38
|
-
const
|
|
41
|
+
const ACP_PERMISSION_POLICY_ALLOW_ALL = 'allow_all';
|
|
42
|
+
const ACP_DEFAULT_MODE_ID = 'autopilot';
|
|
39
43
|
const ACP_SESSION_STORE_MAX_ENTRIES = 200;
|
|
40
44
|
const ACP_SESSION_STORE_MAX_AGE_MS = 1000 * 60 * 60 * 24 * 30;
|
|
41
45
|
const ACP_SESSION_STORE_LOCK_STALE_MS = 1000 * 30;
|
|
@@ -85,6 +89,15 @@ function buildJsonResourceContentBlock(data) {
|
|
|
85
89
|
const ACP_AVAILABLE_COMMANDS = [
|
|
86
90
|
{ name: 'help', description: text.acp.slashHelpDescription },
|
|
87
91
|
];
|
|
92
|
+
const ACP_PUBLIC_MODES = toAcpPublicModes(buildPublicCapabilityRegistry());
|
|
93
|
+
const ACP_PUBLIC_MODE_IDS = new Set(ACP_PUBLIC_MODES.map((mode) => mode.id));
|
|
94
|
+
function resolveExposedAcpModeId(value, fallback = ACP_DEFAULT_MODE_ID) {
|
|
95
|
+
const resolvedModeId = parseAcpFlowMode(value);
|
|
96
|
+
if (resolvedModeId && ACP_PUBLIC_MODE_IDS.has(resolvedModeId)) {
|
|
97
|
+
return resolvedModeId;
|
|
98
|
+
}
|
|
99
|
+
return fallback;
|
|
100
|
+
}
|
|
88
101
|
function formatResourceLink(block) {
|
|
89
102
|
const title = block.title ?? block.name ?? block.uri;
|
|
90
103
|
const description = block.description ? ` - ${block.description}` : '';
|
|
@@ -230,11 +243,10 @@ function loopEventToSessionUpdate(event) {
|
|
|
230
243
|
return null;
|
|
231
244
|
}
|
|
232
245
|
}
|
|
233
|
-
function createSessionRuntimeState() {
|
|
234
|
-
return createSessionRuntimeStateFromPersisted();
|
|
235
|
-
}
|
|
236
246
|
function isPermissionPolicyValue(value) {
|
|
237
|
-
return value === ACP_PERMISSION_POLICY_ASK ||
|
|
247
|
+
return (value === ACP_PERMISSION_POLICY_ASK ||
|
|
248
|
+
value === ACP_PERMISSION_POLICY_DENY_ALL ||
|
|
249
|
+
value === ACP_PERMISSION_POLICY_ALLOW_ALL);
|
|
238
250
|
}
|
|
239
251
|
function buildConfigOptions(state) {
|
|
240
252
|
return [
|
|
@@ -255,26 +267,24 @@ function buildConfigOptions(state) {
|
|
|
255
267
|
name: text.acp.permissionPolicyDenyAllName,
|
|
256
268
|
description: text.acp.permissionPolicyDenyAllDescription,
|
|
257
269
|
},
|
|
270
|
+
{
|
|
271
|
+
value: ACP_PERMISSION_POLICY_ALLOW_ALL,
|
|
272
|
+
name: text.acp.permissionPolicyAllowAllName,
|
|
273
|
+
description: text.acp.permissionPolicyAllowAllDescription,
|
|
274
|
+
},
|
|
258
275
|
],
|
|
259
276
|
},
|
|
260
277
|
{
|
|
261
278
|
type: 'select',
|
|
262
279
|
id: ACP_MODE_CONFIG_ID,
|
|
263
|
-
name: '
|
|
264
|
-
description:
|
|
280
|
+
name: 'Execution Flow',
|
|
281
|
+
description: 'Choose how the agent should execute this session.',
|
|
265
282
|
currentValue: state.modeId,
|
|
266
|
-
options:
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
},
|
|
272
|
-
{
|
|
273
|
-
value: 'yolo',
|
|
274
|
-
name: 'YOLO',
|
|
275
|
-
description: text.acp.modeYoloDescription,
|
|
276
|
-
},
|
|
277
|
-
],
|
|
283
|
+
options: ACP_PUBLIC_MODES.map((mode) => ({
|
|
284
|
+
value: mode.id,
|
|
285
|
+
name: mode.name,
|
|
286
|
+
description: mode.description,
|
|
287
|
+
})),
|
|
278
288
|
},
|
|
279
289
|
];
|
|
280
290
|
}
|
|
@@ -313,27 +323,13 @@ function buildSessionInfoUpdateIfChanged(session, state) {
|
|
|
313
323
|
updatedAt,
|
|
314
324
|
};
|
|
315
325
|
}
|
|
316
|
-
function isSessionModeId(value) {
|
|
317
|
-
return value === 'interactive' || value === 'yolo';
|
|
318
|
-
}
|
|
319
326
|
function buildCurrentModeUpdate(modeId) {
|
|
320
327
|
return { sessionUpdate: 'current_mode_update', currentModeId: modeId };
|
|
321
328
|
}
|
|
322
329
|
function buildModesState(modeId) {
|
|
323
330
|
return {
|
|
324
331
|
currentModeId: modeId,
|
|
325
|
-
availableModes:
|
|
326
|
-
{
|
|
327
|
-
id: 'interactive',
|
|
328
|
-
name: 'Interactive',
|
|
329
|
-
description: text.acp.modeInteractiveDescription,
|
|
330
|
-
},
|
|
331
|
-
{
|
|
332
|
-
id: 'yolo',
|
|
333
|
-
name: 'YOLO',
|
|
334
|
-
description: text.acp.modeYoloDescription,
|
|
335
|
-
},
|
|
336
|
-
],
|
|
332
|
+
availableModes: ACP_PUBLIC_MODES.map((mode) => ({ ...mode })),
|
|
337
333
|
};
|
|
338
334
|
}
|
|
339
335
|
function buildCurrentModeUpdateIfChanged(state) {
|
|
@@ -343,18 +339,28 @@ function buildCurrentModeUpdateIfChanged(state) {
|
|
|
343
339
|
state.lastModeDigest = digest;
|
|
344
340
|
return buildCurrentModeUpdate(state.modeId);
|
|
345
341
|
}
|
|
342
|
+
function getLegacyPermissionPolicyForModeValue(value) {
|
|
343
|
+
const normalized = String(value ?? '')
|
|
344
|
+
.trim()
|
|
345
|
+
.toLowerCase();
|
|
346
|
+
if (normalized === 'interactive')
|
|
347
|
+
return ACP_PERMISSION_POLICY_ASK;
|
|
348
|
+
if (normalized === 'yolo')
|
|
349
|
+
return ACP_PERMISSION_POLICY_ALLOW_ALL;
|
|
350
|
+
return null;
|
|
351
|
+
}
|
|
346
352
|
function getPermissionPolicyForAuthorization(state) {
|
|
347
|
-
if (state.modeId === 'yolo')
|
|
348
|
-
return 'allow_all';
|
|
349
353
|
return state.permissionPolicy;
|
|
350
354
|
}
|
|
351
355
|
function createSessionRuntimeStateFromPersisted(input) {
|
|
356
|
+
const defaultPermissionPolicy = isPermissionPolicyValue(String(input?.defaultPermissionPolicy))
|
|
357
|
+
? input?.defaultPermissionPolicy
|
|
358
|
+
: ACP_PERMISSION_POLICY_ASK;
|
|
352
359
|
const permissionPolicy = isPermissionPolicyValue(String(input?.permissionPolicy))
|
|
353
360
|
? input?.permissionPolicy
|
|
354
|
-
:
|
|
355
|
-
const
|
|
356
|
-
|
|
357
|
-
: (input?.defaultModeId ?? ACP_DEFAULT_MODE_ID);
|
|
361
|
+
: defaultPermissionPolicy;
|
|
362
|
+
const defaultModeId = resolveExposedAcpModeId(input?.defaultModeId);
|
|
363
|
+
const modeId = resolveExposedAcpModeId(input?.modeId, defaultModeId);
|
|
358
364
|
const state = {
|
|
359
365
|
runtimePlanSessionId: null,
|
|
360
366
|
runtimePlanPathHint: null,
|
|
@@ -546,8 +552,10 @@ export function createAcpFormalAgent(deps) {
|
|
|
546
552
|
title: entry.title,
|
|
547
553
|
taskId: undefined,
|
|
548
554
|
history: [],
|
|
549
|
-
permissionPolicy:
|
|
550
|
-
|
|
555
|
+
permissionPolicy: isPermissionPolicyValue(String(deps.defaultPermissionPolicy))
|
|
556
|
+
? deps.defaultPermissionPolicy
|
|
557
|
+
: ACP_PERMISSION_POLICY_ASK,
|
|
558
|
+
modeId: resolveExposedAcpModeId(deps.defaultModeId),
|
|
551
559
|
})),
|
|
552
560
|
};
|
|
553
561
|
}
|
|
@@ -757,6 +765,7 @@ export function createAcpFormalAgent(deps) {
|
|
|
757
765
|
if (!sessionRuntime.has(stored.id)) {
|
|
758
766
|
sessionRuntime.set(stored.id, createSessionRuntimeStateFromPersisted({
|
|
759
767
|
permissionPolicy: stored.permissionPolicy,
|
|
768
|
+
defaultPermissionPolicy: deps.defaultPermissionPolicy,
|
|
760
769
|
modeId: stored.modeId,
|
|
761
770
|
defaultModeId: deps.defaultModeId,
|
|
762
771
|
}));
|
|
@@ -894,10 +903,10 @@ export function createAcpFormalAgent(deps) {
|
|
|
894
903
|
const existing = sessionRuntime.get(sessionId);
|
|
895
904
|
if (existing)
|
|
896
905
|
return existing;
|
|
897
|
-
const created =
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
}
|
|
906
|
+
const created = createSessionRuntimeStateFromPersisted({
|
|
907
|
+
defaultPermissionPolicy: deps.defaultPermissionPolicy,
|
|
908
|
+
defaultModeId: deps.defaultModeId,
|
|
909
|
+
});
|
|
901
910
|
sessionRuntime.set(sessionId, created);
|
|
902
911
|
return created;
|
|
903
912
|
}
|
|
@@ -1095,10 +1104,15 @@ export function createAcpFormalAgent(deps) {
|
|
|
1095
1104
|
runtimeState.permissionPolicy = params.value;
|
|
1096
1105
|
}
|
|
1097
1106
|
else if (params.configId === ACP_MODE_CONFIG_ID) {
|
|
1098
|
-
|
|
1107
|
+
const parsedModeId = parseAcpFlowMode(params.value);
|
|
1108
|
+
if (!parsedModeId || !ACP_PUBLIC_MODE_IDS.has(parsedModeId)) {
|
|
1099
1109
|
throw new RequestError(-32602, `Invalid params: unsupported value "${params.value}" for "${params.configId}"`);
|
|
1100
1110
|
}
|
|
1101
|
-
runtimeState.modeId =
|
|
1111
|
+
runtimeState.modeId = parsedModeId;
|
|
1112
|
+
const legacyPermissionPolicy = getLegacyPermissionPolicyForModeValue(params.value);
|
|
1113
|
+
if (legacyPermissionPolicy) {
|
|
1114
|
+
runtimeState.permissionPolicy = legacyPermissionPolicy;
|
|
1115
|
+
}
|
|
1102
1116
|
}
|
|
1103
1117
|
else {
|
|
1104
1118
|
throw new RequestError(-32602, `Invalid params: unsupported configId "${params.configId}"`);
|
|
@@ -1122,13 +1136,22 @@ export function createAcpFormalAgent(deps) {
|
|
|
1122
1136
|
throw new RequestError(-32004, `Session not found: ${params.sessionId}`);
|
|
1123
1137
|
}
|
|
1124
1138
|
const runtimeState = ensureSessionRuntimeState(params.sessionId);
|
|
1125
|
-
|
|
1139
|
+
const resolvedModeId = parseAcpFlowMode(params.modeId);
|
|
1140
|
+
if (!resolvedModeId || !ACP_PUBLIC_MODE_IDS.has(resolvedModeId)) {
|
|
1126
1141
|
throw new RequestError(-32602, `Invalid params: unsupported modeId "${params.modeId}"`);
|
|
1127
1142
|
}
|
|
1128
|
-
runtimeState.modeId =
|
|
1143
|
+
runtimeState.modeId = resolvedModeId;
|
|
1144
|
+
const legacyPermissionPolicy = getLegacyPermissionPolicyForModeValue(params.modeId);
|
|
1145
|
+
if (legacyPermissionPolicy) {
|
|
1146
|
+
runtimeState.permissionPolicy = legacyPermissionPolicy;
|
|
1147
|
+
}
|
|
1129
1148
|
sessions.update(params.sessionId, (current) => ({ ...current }));
|
|
1130
1149
|
await persistSessionsBestEffort();
|
|
1131
1150
|
await emitSessionInfoUpdateBestEffort(params.sessionId);
|
|
1151
|
+
const configUpdate = buildConfigOptionUpdateIfChanged(runtimeState);
|
|
1152
|
+
if (configUpdate) {
|
|
1153
|
+
await emitSessionUpdate(params.sessionId, configUpdate);
|
|
1154
|
+
}
|
|
1132
1155
|
// Send mode update notification
|
|
1133
1156
|
const modeUpdate = buildCurrentModeUpdateIfChanged(runtimeState);
|
|
1134
1157
|
if (modeUpdate) {
|
|
@@ -1209,7 +1232,7 @@ export function createAcpFormalAgent(deps) {
|
|
|
1209
1232
|
}
|
|
1210
1233
|
const pendingUpdates = [];
|
|
1211
1234
|
const executionRequest = buildCanonicalExecutionRequest({
|
|
1212
|
-
capability:
|
|
1235
|
+
capability: runtimeState.modeId,
|
|
1213
1236
|
instruction: promptText,
|
|
1214
1237
|
checkpointSessionId: params.sessionId,
|
|
1215
1238
|
repoPath: session.cwd,
|
|
@@ -30,7 +30,11 @@ export function createAcpSessionStore() {
|
|
|
30
30
|
if (!current)
|
|
31
31
|
return undefined;
|
|
32
32
|
const updated = mutate(current);
|
|
33
|
-
|
|
33
|
+
const nextUpdatedAt = new Date().toISOString();
|
|
34
|
+
updated.updatedAt =
|
|
35
|
+
nextUpdatedAt > current.updatedAt
|
|
36
|
+
? nextUpdatedAt
|
|
37
|
+
: new Date(Date.parse(current.updatedAt) + 1).toISOString();
|
|
34
38
|
sessions.set(id, updated);
|
|
35
39
|
return updated;
|
|
36
40
|
},
|
|
@@ -104,7 +104,7 @@ export function createAcpToolAuthorizationProvider(params) {
|
|
|
104
104
|
const permissionPolicy = params.getPermissionPolicy?.() ?? 'ask';
|
|
105
105
|
if (permissionPolicy === 'allow_all') {
|
|
106
106
|
await emitInProgressBestEffort(request.id);
|
|
107
|
-
return { outcome: 'allow_session', source: 'auto', reason: '
|
|
107
|
+
return { outcome: 'allow_session', source: 'auto', reason: 'session_config:allow_all' };
|
|
108
108
|
}
|
|
109
109
|
const hasSideEffects = request.sideEffects.some((effect) => effect !== 'fs_read');
|
|
110
110
|
if (permissionPolicy === 'deny_all' && hasSideEffects) {
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { FLOW_MODE_PUBLIC_METADATA } from '../../public-capabilities/flow-mode-metadata.js';
|
|
2
|
+
import { FLOW_MODES, parseFlowMode } from '../../types/flow-mode.js';
|
|
3
|
+
export const SUPPORTED_PROTOCOL_FLOW_MODES = FLOW_MODES;
|
|
4
|
+
export function parseAcpFlowMode(value) {
|
|
5
|
+
const normalized = String(value ?? '')
|
|
6
|
+
.trim()
|
|
7
|
+
.toLowerCase();
|
|
8
|
+
if (normalized === 'interactive' || normalized === 'yolo') {
|
|
9
|
+
return 'autopilot';
|
|
10
|
+
}
|
|
11
|
+
return parseFlowMode(normalized);
|
|
12
|
+
}
|
|
13
|
+
export function parseA2ASkillFlowMode(value) {
|
|
14
|
+
return parseFlowMode(value);
|
|
15
|
+
}
|
|
16
|
+
export function buildA2AFlowSkills() {
|
|
17
|
+
return SUPPORTED_PROTOCOL_FLOW_MODES.map((mode) => ({
|
|
18
|
+
id: mode,
|
|
19
|
+
title: FLOW_MODE_PUBLIC_METADATA[mode].a2aTitle,
|
|
20
|
+
description: FLOW_MODE_PUBLIC_METADATA[mode].description,
|
|
21
|
+
}));
|
|
22
|
+
}
|
|
23
|
+
//# sourceMappingURL=flow-mode-mapping.js.map
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
export const FLOW_MODE_PUBLIC_METADATA = {
|
|
2
|
+
autopilot: {
|
|
3
|
+
publicTitle: 'Autopilot',
|
|
4
|
+
a2aTitle: 'Autopilot',
|
|
5
|
+
acpName: 'Autopilot',
|
|
6
|
+
description: 'Let the agent decide which actions and tools to use.',
|
|
7
|
+
},
|
|
8
|
+
patch: {
|
|
9
|
+
publicTitle: 'Patch code',
|
|
10
|
+
a2aTitle: 'Patch code',
|
|
11
|
+
acpName: 'Patch',
|
|
12
|
+
description: 'Apply code changes with verification.',
|
|
13
|
+
},
|
|
14
|
+
review: {
|
|
15
|
+
publicTitle: 'Review code',
|
|
16
|
+
a2aTitle: 'Review code',
|
|
17
|
+
acpName: 'Review',
|
|
18
|
+
description: 'Inspect code and report findings without mutating files.',
|
|
19
|
+
},
|
|
20
|
+
debug: {
|
|
21
|
+
publicTitle: 'Debug issue',
|
|
22
|
+
a2aTitle: 'Debug issue',
|
|
23
|
+
acpName: 'Debug',
|
|
24
|
+
description: 'Investigate issues and make targeted fixes when needed.',
|
|
25
|
+
},
|
|
26
|
+
research: {
|
|
27
|
+
publicTitle: 'Research request',
|
|
28
|
+
a2aTitle: 'Research request',
|
|
29
|
+
acpName: 'Research',
|
|
30
|
+
description: 'Explore the codebase and summarize relevant findings.',
|
|
31
|
+
},
|
|
32
|
+
answer: {
|
|
33
|
+
publicTitle: 'Answer question',
|
|
34
|
+
a2aTitle: 'Answer question',
|
|
35
|
+
acpName: 'Answer',
|
|
36
|
+
description: 'Answer questions directly without editing files.',
|
|
37
|
+
},
|
|
38
|
+
};
|
|
39
|
+
//# sourceMappingURL=flow-mode-metadata.js.map
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { FLOW_MODE_PUBLIC_METADATA } from './flow-mode-metadata.js';
|
|
2
|
+
import { buildPublicCapabilityRegistry } from './registry.js';
|
|
3
|
+
export function selectPublicCapabilitiesForSurface(surface, entries = buildPublicCapabilityRegistry()) {
|
|
4
|
+
return entries.filter((entry) => entry.reachability === 'reachable' && entry.surfaces[surface]);
|
|
5
|
+
}
|
|
6
|
+
function isFlowModeCapability(entry) {
|
|
7
|
+
return entry.kind === 'flow_mode';
|
|
8
|
+
}
|
|
9
|
+
export function toAcpPublicModes(entries = buildPublicCapabilityRegistry()) {
|
|
10
|
+
return selectPublicCapabilitiesForSurface('acp', entries)
|
|
11
|
+
.filter(isFlowModeCapability)
|
|
12
|
+
.map((entry) => ({
|
|
13
|
+
id: entry.target,
|
|
14
|
+
name: FLOW_MODE_PUBLIC_METADATA[entry.target].acpName,
|
|
15
|
+
description: entry.description,
|
|
16
|
+
}));
|
|
17
|
+
}
|
|
18
|
+
export function toA2APublicSkills(entries = buildPublicCapabilityRegistry()) {
|
|
19
|
+
return selectPublicCapabilitiesForSurface('a2a', entries).map((entry) => ({
|
|
20
|
+
id: entry.id,
|
|
21
|
+
title: entry.title,
|
|
22
|
+
description: entry.description,
|
|
23
|
+
tags: entry.tags,
|
|
24
|
+
examples: entry.examples,
|
|
25
|
+
inputModes: entry.inputModes,
|
|
26
|
+
outputModes: entry.outputModes,
|
|
27
|
+
}));
|
|
28
|
+
}
|
|
29
|
+
//# sourceMappingURL=projections.js.map
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { FLOW_MODES } from '../types/flow-mode.js';
|
|
2
|
+
import { FLOW_MODE_PUBLIC_METADATA } from './flow-mode-metadata.js';
|
|
3
|
+
function getFlowModeSurfaces(mode) {
|
|
4
|
+
if (mode === 'autopilot') {
|
|
5
|
+
return {
|
|
6
|
+
a2a: true,
|
|
7
|
+
acp: true,
|
|
8
|
+
};
|
|
9
|
+
}
|
|
10
|
+
return {
|
|
11
|
+
a2a: false,
|
|
12
|
+
acp: true,
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
export function buildPublicCapabilityRegistry() {
|
|
16
|
+
return FLOW_MODES.map((mode) => ({
|
|
17
|
+
id: mode,
|
|
18
|
+
kind: 'flow_mode',
|
|
19
|
+
target: mode,
|
|
20
|
+
title: FLOW_MODE_PUBLIC_METADATA[mode].publicTitle,
|
|
21
|
+
description: FLOW_MODE_PUBLIC_METADATA[mode].description,
|
|
22
|
+
surfaces: getFlowModeSurfaces(mode),
|
|
23
|
+
reachability: 'reachable',
|
|
24
|
+
}));
|
|
25
|
+
}
|
|
26
|
+
//# sourceMappingURL=registry.js.map
|
|
@@ -3,7 +3,6 @@ import { createTaskEventBus } from '../interaction/events/bus.js';
|
|
|
3
3
|
import { createInteractionFacade } from '../interaction/orchestration/facade.js';
|
|
4
4
|
import { createA2AInteractionExecutor } from '../protocols/a2a/sdk/executor.js';
|
|
5
5
|
import { createA2ASdkExpressApp } from '../protocols/a2a/sdk/server.js';
|
|
6
|
-
import { createSidecarFastifyPlugin, } from './sidecar-fastify-plugin.js';
|
|
7
6
|
export function createAgentServerRuntime(deps) {
|
|
8
7
|
const eventBus = deps.a2a.eventBus ?? createTaskEventBus();
|
|
9
8
|
const taskStore = deps.a2a.taskStore ?? new InMemoryTaskStore();
|
|
@@ -20,67 +19,72 @@ export function createAgentServerRuntime(deps) {
|
|
|
20
19
|
taskEventBus: eventBus,
|
|
21
20
|
taskStore,
|
|
22
21
|
});
|
|
23
|
-
const
|
|
24
|
-
|
|
25
|
-
agentCard,
|
|
22
|
+
const a2aServer = (deps.createA2AServerApp ?? createA2ASdkExpressApp)({
|
|
23
|
+
agentCard: deps.a2a.buildAgentCard(),
|
|
26
24
|
agentExecutor: executor,
|
|
27
25
|
taskStore,
|
|
28
26
|
userBuilder: deps.a2a.userBuilder,
|
|
29
27
|
authMiddleware: deps.a2a.authMiddleware,
|
|
30
28
|
});
|
|
31
|
-
const sidecarPlugin = createSidecarFastifyPlugin({
|
|
32
|
-
routes: deps.sidecar.routes,
|
|
33
|
-
scope: deps.listen.sidecar.type === 'tcp' ? 'tcp' : 'uds',
|
|
34
|
-
allowConditional: deps.sidecar.allowConditional,
|
|
35
|
-
authorize: deps.sidecar.authorize,
|
|
36
|
-
baseUrl: deps.sidecar.baseUrl,
|
|
37
|
-
});
|
|
38
|
-
const sidecarServer = deps.createFastify();
|
|
39
29
|
let a2aServerInstance = null;
|
|
40
|
-
let sidecarServerInstance = null;
|
|
41
30
|
let started = false;
|
|
31
|
+
let starting = false;
|
|
42
32
|
async function start() {
|
|
43
|
-
if (started) {
|
|
33
|
+
if (started || starting) {
|
|
44
34
|
throw new Error('Runtime already started');
|
|
45
35
|
}
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
36
|
+
starting = true;
|
|
37
|
+
try {
|
|
38
|
+
if (deps.configureA2A) {
|
|
39
|
+
await deps.configureA2A(a2aServer);
|
|
40
|
+
}
|
|
41
|
+
a2aServerInstance = await new Promise((resolve, reject) => {
|
|
42
|
+
const server = a2aServer.listen(deps.listen.a2a.port, deps.listen.a2a.host ?? '0.0.0.0');
|
|
43
|
+
const cleanup = () => {
|
|
44
|
+
server.off('error', onError);
|
|
45
|
+
server.off('listening', onListening);
|
|
46
|
+
};
|
|
47
|
+
const onError = (error) => {
|
|
48
|
+
cleanup();
|
|
49
|
+
reject(error);
|
|
50
|
+
};
|
|
51
|
+
const onListening = () => {
|
|
52
|
+
cleanup();
|
|
58
53
|
resolve(server);
|
|
54
|
+
};
|
|
55
|
+
server.once('error', onError);
|
|
56
|
+
server.once('listening', onListening);
|
|
59
57
|
});
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
: { path: deps.listen.sidecar.path };
|
|
64
|
-
sidecarServerInstance = await sidecarServer.listen(sidecarListenOpts);
|
|
65
|
-
started = true;
|
|
66
|
-
}
|
|
67
|
-
async function close() {
|
|
68
|
-
if (a2aServerInstance) {
|
|
69
|
-
await new Promise((resolve) => {
|
|
70
|
-
a2aServerInstance.close(() => resolve());
|
|
71
|
-
});
|
|
58
|
+
started = true;
|
|
59
|
+
}
|
|
60
|
+
catch (error) {
|
|
72
61
|
a2aServerInstance = null;
|
|
62
|
+
throw error;
|
|
63
|
+
}
|
|
64
|
+
finally {
|
|
65
|
+
starting = false;
|
|
73
66
|
}
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
67
|
+
}
|
|
68
|
+
async function close() {
|
|
69
|
+
if (!a2aServerInstance) {
|
|
70
|
+
started = false;
|
|
71
|
+
return;
|
|
77
72
|
}
|
|
73
|
+
await new Promise((resolve, reject) => {
|
|
74
|
+
a2aServerInstance.close((error) => {
|
|
75
|
+
if (error) {
|
|
76
|
+
reject(error);
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
resolve();
|
|
80
|
+
});
|
|
81
|
+
});
|
|
82
|
+
a2aServerInstance = null;
|
|
78
83
|
started = false;
|
|
79
84
|
}
|
|
80
85
|
return {
|
|
81
86
|
eventBus,
|
|
82
|
-
a2aServer
|
|
83
|
-
sidecarServer,
|
|
87
|
+
a2aServer,
|
|
84
88
|
start,
|
|
85
89
|
close,
|
|
86
90
|
};
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { Phase } from '../types/runtime.js';
|
|
2
|
+
const RECIPE_ENTRY_PHASE = Phase.PLAN;
|
|
3
|
+
const RECIPE_PROFILES = {
|
|
4
|
+
patch: {
|
|
5
|
+
mode: 'patch',
|
|
6
|
+
driver: 'recipe',
|
|
7
|
+
readOnly: false,
|
|
8
|
+
ignoreDirtyPreflight: false,
|
|
9
|
+
failurePolicy: 'rollback',
|
|
10
|
+
verifyPolicy: 'required_before_success_if_mutated',
|
|
11
|
+
entryPhase: RECIPE_ENTRY_PHASE,
|
|
12
|
+
},
|
|
13
|
+
review: {
|
|
14
|
+
mode: 'review',
|
|
15
|
+
driver: 'recipe',
|
|
16
|
+
readOnly: true,
|
|
17
|
+
ignoreDirtyPreflight: true,
|
|
18
|
+
failurePolicy: 'rollback',
|
|
19
|
+
verifyPolicy: 'never',
|
|
20
|
+
entryPhase: RECIPE_ENTRY_PHASE,
|
|
21
|
+
},
|
|
22
|
+
debug: {
|
|
23
|
+
mode: 'debug',
|
|
24
|
+
driver: 'recipe',
|
|
25
|
+
readOnly: false,
|
|
26
|
+
ignoreDirtyPreflight: false,
|
|
27
|
+
failurePolicy: 'rollback',
|
|
28
|
+
verifyPolicy: 'required_before_success_if_mutated',
|
|
29
|
+
entryPhase: RECIPE_ENTRY_PHASE,
|
|
30
|
+
},
|
|
31
|
+
research: {
|
|
32
|
+
mode: 'research',
|
|
33
|
+
driver: 'recipe',
|
|
34
|
+
readOnly: true,
|
|
35
|
+
ignoreDirtyPreflight: true,
|
|
36
|
+
failurePolicy: 'rollback',
|
|
37
|
+
verifyPolicy: 'never',
|
|
38
|
+
entryPhase: RECIPE_ENTRY_PHASE,
|
|
39
|
+
},
|
|
40
|
+
answer: {
|
|
41
|
+
mode: 'answer',
|
|
42
|
+
driver: 'recipe',
|
|
43
|
+
readOnly: true,
|
|
44
|
+
ignoreDirtyPreflight: true,
|
|
45
|
+
failurePolicy: 'rollback',
|
|
46
|
+
verifyPolicy: 'never',
|
|
47
|
+
entryPhase: RECIPE_ENTRY_PHASE,
|
|
48
|
+
},
|
|
49
|
+
};
|
|
50
|
+
const AUTOPILOT_PROFILE = {
|
|
51
|
+
mode: 'autopilot',
|
|
52
|
+
driver: 'agent',
|
|
53
|
+
readOnly: false,
|
|
54
|
+
defaultPermissionMode: 'yolo',
|
|
55
|
+
defaultCheckpointStrategy: 'direct',
|
|
56
|
+
ignoreDirtyPreflight: true,
|
|
57
|
+
failurePolicy: 'preserve',
|
|
58
|
+
verifyPolicy: 'required_before_success_if_mutated',
|
|
59
|
+
entryPhase: Phase.AUTOPILOT,
|
|
60
|
+
};
|
|
61
|
+
export function resolveExecutionProfile(mode) {
|
|
62
|
+
if (mode === 'autopilot') {
|
|
63
|
+
return AUTOPILOT_PROFILE;
|
|
64
|
+
}
|
|
65
|
+
return RECIPE_PROFILES[mode];
|
|
66
|
+
}
|
|
67
|
+
//# sourceMappingURL=execution-profile.js.map
|