salmon-loop 0.3.2 → 0.5.0
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 +9 -13
- package/dist/cli/authorization/provider.js +2 -10
- package/dist/cli/chat.js +12 -6
- package/dist/cli/commands/allowlist.js +1 -1
- package/dist/cli/commands/chat.js +13 -13
- package/dist/cli/commands/config.js +2 -2
- package/dist/cli/commands/mode.js +2 -2
- package/dist/cli/commands/parallel.js +1 -1
- package/dist/cli/commands/run/handler.js +9 -4
- package/dist/cli/commands/run/loop-params.js +2 -0
- package/dist/cli/commands/run/parse-options.js +14 -26
- package/dist/cli/commands/run/runtime-llm.js +15 -12
- package/dist/cli/commands/run/runtime-options.js +3 -1
- package/dist/cli/config.js +0 -8
- package/dist/cli/headless/openai-responses-canonical-applier.js +1 -7
- package/dist/cli/locales/en.js +2 -2
- package/dist/cli/reporters/standard.js +12 -3
- package/dist/cli/reporters/stream-json.js +2 -1
- package/dist/cli/slash/runtime.js +2 -2
- package/dist/cli/ui/hooks/useLoopEvents.js +1 -1
- package/dist/cli/ui/hooks/useLoopState.js +1 -1
- package/dist/core/adapters/fs/file-adapter.js +3 -1
- package/dist/core/adapters/git/git-adapter.js +6 -3
- package/dist/core/adapters/git/git-runner.js +5 -2
- package/dist/core/adapters/git/lock-manager.js +7 -4
- package/dist/core/ast/parser.js +18 -9
- package/dist/core/checkpoint-domain/manifest-store.js +21 -13
- package/dist/core/checkpoint-domain/service.js +3 -1
- package/dist/core/config/limits.js +1 -1
- package/dist/core/config/model-pricing.js +61 -0
- package/dist/core/config/schema.js +738 -0
- package/dist/core/config/validate.js +11 -922
- package/dist/core/context/ast/skeleton-extractor.js +225 -0
- package/dist/core/context/ast/source-outline.js +24 -1
- package/dist/core/context/budget/dynamic-adjuster.js +20 -5
- package/dist/core/context/builder.js +7 -3
- package/dist/core/context/cache/store-factory.js +3 -1
- package/dist/core/context/dependencies.js +2 -1
- package/dist/core/context/effectiveness/persistence.js +50 -0
- package/dist/core/context/effectiveness/tracker.js +24 -0
- package/dist/core/context/gatherers/architecture-gatherer.js +2 -1
- package/dist/core/context/gatherers/artifact-gatherer.js +7 -4
- package/dist/core/context/gatherers/ast-gatherer.js +34 -40
- package/dist/core/context/gatherers/ghost-dependency-gatherer.js +0 -1
- package/dist/core/context/gatherers/git-history-gatherer.js +3 -1
- package/dist/core/context/gatherers/knowledge-gatherer.js +21 -2
- package/dist/core/context/gatherers/metadata-gatherer.js +12 -7
- package/dist/core/context/gatherers/ripgrep-gatherer.js +6 -3
- package/dist/core/context/service.js +12 -2
- package/dist/core/context/steps/context-gather.js +14 -3
- package/dist/core/context/steps/context-targets.js +1 -0
- package/dist/core/context/targeting/target-resolver.js +29 -11
- package/dist/core/context/token/cache.js +5 -2
- package/dist/core/context/token/encoding-registry.js +7 -6
- package/dist/core/context/truncation/strategies/json.js +5 -2
- package/dist/core/context/truncation/type-detector.js +3 -1
- package/dist/core/extensions/index.js +48 -3
- package/dist/core/extensions/load.js +3 -2
- package/dist/core/extensions/merge.js +5 -1
- package/dist/core/extensions/paths.js +8 -2
- package/dist/core/extensions/schemas.js +21 -0
- package/dist/core/facades/cli-authorization-provider.js +1 -0
- package/dist/core/facades/cli-command-chat.js +2 -0
- package/dist/core/facades/cli-run-handler.js +1 -0
- package/dist/core/facades/cli-utils-serialize.js +2 -0
- package/dist/core/feedback/parsers.js +290 -1
- package/dist/core/grizzco/dsl/llm-strategy.js +4 -3
- package/dist/core/grizzco/engine/observability/loop-telemetry.js +5 -2
- package/dist/core/grizzco/engine/outcome/loop-result-mapper.js +30 -13
- package/dist/core/grizzco/engine/pipeline/pipeline.js +149 -240
- package/dist/core/grizzco/engine/transaction/attempt-failure.js +49 -24
- package/dist/core/grizzco/engine/transaction/authorization-summary.js +2 -1
- package/dist/core/grizzco/engine/transaction/transaction-runner.js +40 -34
- package/dist/core/grizzco/execution/RejectionManager.js +7 -5
- package/dist/core/grizzco/runtime/apply-back-runtime.js +5 -2
- package/dist/core/grizzco/services/implementations/default/GitConfigService.js +2 -1
- package/dist/core/grizzco/services/registry.js +18 -0
- package/dist/core/grizzco/steps/audit.js +20 -10
- package/dist/core/grizzco/steps/autopilot.js +21 -32
- package/dist/core/grizzco/steps/display-report.js +4 -11
- package/dist/core/grizzco/steps/explore.js +14 -4
- package/dist/core/grizzco/steps/generateReview.js +3 -1
- package/dist/core/grizzco/steps/patch/prompt-input.js +4 -1
- package/dist/core/grizzco/steps/patch.js +1 -0
- package/dist/core/grizzco/steps/plan.js +58 -49
- package/dist/core/grizzco/steps/research.js +3 -1
- package/dist/core/grizzco/steps/tool-runtime.js +3 -0
- package/dist/core/grizzco/steps/verify.js +7 -1
- package/dist/core/grizzco/validation/AstValidationService.js +3 -1
- package/dist/core/grizzco/workers/strata-sync-worker.js +2 -1
- package/dist/core/history/input-history.js +3 -1
- package/dist/core/intent/chat-intent.js +3 -1
- package/dist/core/llm/ai-sdk/message-mapper.js +37 -26
- package/dist/core/llm/ai-sdk/request-params.js +2 -6
- package/dist/core/llm/ai-sdk/result-mapper.js +14 -8
- package/dist/core/llm/ai-sdk/retry-classifier.js +17 -7
- package/dist/core/llm/ai-sdk/retry-executor.js +1 -1
- package/dist/core/llm/contracts/repair.js +16 -8
- package/dist/core/llm/errors.js +18 -14
- package/dist/core/llm/output-policy.js +8 -0
- package/dist/core/llm/redact.js +1 -3
- package/dist/core/llm/retry-utils.js +8 -2
- package/dist/core/llm/stream-utils.js +5 -3
- package/dist/core/llm/sub-agent-factory.js +51 -0
- package/dist/core/llm/tool-calling-stub.js +48 -0
- package/dist/core/llm/utils.js +17 -6
- package/dist/core/mcp/bridge/prompt-command-provider.js +4 -3
- package/dist/core/mcp/bridge/resource-context-provider.js +3 -1
- package/dist/core/mcp/bridge/tool-bridge.js +5 -14
- package/dist/core/mcp/catalog/discovery.js +3 -1
- package/dist/core/mcp/client/connection-manager.js +7 -4
- package/dist/core/mcp/client/transport-factory.js +7 -3
- package/dist/core/mcp/host/sampling-provider.js +1 -1
- package/dist/core/mcp/schema/json-schema-to-zod.js +2 -1
- package/dist/core/memory/relevant-retrieval.js +6 -4
- package/dist/core/observability/audit-file.js +2 -1
- package/dist/core/observability/audit-trail.js +3 -1
- package/dist/core/observability/authorization-decisions.js +13 -12
- package/dist/core/observability/error-mapping.js +2 -1
- package/dist/core/observability/logger.js +2 -1
- package/dist/core/observability/monitor.js +24 -0
- package/dist/core/observability/run-outcome-reporter.js +1 -0
- package/dist/core/observability/token-usage.js +5 -4
- package/dist/core/permission-gate/default-gate.js +5 -8
- package/dist/core/plan/storage.js +7 -4
- package/dist/core/plugin/loader.js +8 -5
- package/dist/core/prompts/registry.js +12 -30
- package/dist/core/prompts/runtime.js +3 -1
- package/dist/core/prompts/templates/system/autopilot_system.hbs +28 -4
- package/dist/core/protocols/a2a/sdk/executor.js +3 -1
- package/dist/core/protocols/a2a/sdk/server.js +5 -4
- package/dist/core/protocols/acp/acp-command-runner.js +7 -6
- package/dist/core/protocols/acp/acp-session-persistence.js +13 -10
- package/dist/core/protocols/acp/formal-agent.js +13 -6
- package/dist/core/protocols/acp/permission-provider.js +3 -2
- package/dist/core/protocols/acp/stdio-server.js +6 -6
- package/dist/core/reflection/engine.js +114 -14
- package/dist/core/runtime/agent-server-runtime.js +3 -2
- package/dist/core/runtime/batch-runner.js +81 -0
- package/dist/core/runtime/initialize.js +71 -6
- package/dist/core/runtime/loop-finalize.js +3 -0
- package/dist/core/runtime/loop-session-runner.js +5 -0
- package/dist/core/runtime/loop.js +4 -0
- package/dist/core/runtime/paths.js +9 -6
- package/dist/core/runtime/spawn-interactive.js +5 -4
- package/dist/core/security/redaction.js +3 -2
- package/dist/core/session/compaction/index.js +4 -3
- package/dist/core/session/compression.js +3 -1
- package/dist/core/session/manager.js +26 -38
- package/dist/core/session/pruning-strategy.js +2 -1
- package/dist/core/session/token-tracker.js +27 -9
- package/dist/core/skills/parser.js +3 -2
- package/dist/core/skills/permissions.js +2 -2
- package/dist/core/skills/runtime/MicroTaskRunner.js +1 -1
- package/dist/core/skills/runtime/SkillRunner.js +5 -2
- package/dist/core/slash/steps/slash-execute.js +7 -5
- package/dist/core/slash/strategy.js +1 -1
- package/dist/core/strata/checkpoint/manager.js +16 -10
- package/dist/core/strata/checkpoint/snapshot-create.js +5 -4
- package/dist/core/strata/checkpoint/snapshot-write-tree.js +7 -3
- package/dist/core/strata/engine/shadow-merge-engine.js +4 -2
- package/dist/core/strata/interaction/file-system-provider.js +2 -1
- package/dist/core/strata/layers/file-state-resolver.js +9 -7
- package/dist/core/strata/layers/immutable-git-layer.js +3 -1
- package/dist/core/strata/layers/shadow-driver/readonly-lock.js +8 -6
- package/dist/core/strata/layers/shadow-driver/shadow-driver.js +2 -1
- package/dist/core/strata/layers/worktree.js +9 -10
- package/dist/core/strata/runtime/environment.js +2 -1
- package/dist/core/strata/runtime/synchronizer.js +28 -26
- package/dist/core/streaming/canonical/parts-from-llm-stream-chunk.js +1 -11
- package/dist/core/structured-output/json-extract.js +3 -1
- package/dist/core/structured-output/json-schema-validator.js +1 -13
- package/dist/core/sub-agent/artifacts/store.js +2 -1
- package/dist/core/sub-agent/context-snapshot.js +12 -6
- package/dist/core/sub-agent/controller.js +70 -1
- package/dist/core/sub-agent/core/loop.js +25 -3
- package/dist/core/sub-agent/core/manager.js +343 -117
- package/dist/core/sub-agent/registry-defaults.js +12 -0
- package/dist/core/sub-agent/registry.js +8 -0
- package/dist/core/sub-agent/summary.js +96 -0
- package/dist/core/sub-agent/team.js +98 -0
- package/dist/core/sub-agent/tools/task-await.js +109 -0
- package/dist/core/sub-agent/tools/task-spawn.js +52 -7
- package/dist/core/sub-agent/tools/team.js +92 -0
- package/dist/core/sub-agent/types.js +11 -2
- package/dist/core/target-runtime/profile.js +3 -1
- package/dist/core/tools/audit.js +3 -2
- package/dist/core/tools/budget.js +7 -12
- package/dist/core/tools/builtin/ast.js +144 -0
- package/dist/core/tools/builtin/code-search/backends/powershell.js +3 -1
- package/dist/core/tools/builtin/code-search/backends/rg.js +3 -1
- package/dist/core/tools/builtin/code-search/executor.js +46 -43
- package/dist/core/tools/builtin/code-search/parse/plain-grep.js +3 -1
- package/dist/core/tools/builtin/code-search/parse/rg-json.js +3 -1
- package/dist/core/tools/builtin/fs.js +90 -7
- package/dist/core/tools/builtin/git.js +242 -0
- package/dist/core/tools/builtin/glob.js +79 -0
- package/dist/core/tools/builtin/index.js +53 -111
- package/dist/core/tools/builtin/interaction.js +13 -15
- package/dist/core/tools/builtin/knowledge.js +146 -4
- package/dist/core/tools/builtin/proposal.js +14 -3
- package/dist/core/tools/builtin/verify.js +35 -3
- package/dist/core/tools/capability/executor.js +5 -5
- package/dist/core/tools/headless-payload.js +1 -3
- package/dist/core/tools/mapper.js +8 -42
- package/dist/core/tools/parallel/persistence.js +17 -5
- package/dist/core/tools/parallel/scheduler.js +23 -21
- package/dist/core/tools/permissions/permission-rules.js +69 -115
- package/dist/core/tools/plugins/loader.js +4 -3
- package/dist/core/tools/router.js +112 -58
- package/dist/core/tools/session.js +64 -102
- package/dist/core/tools/streaming/ToolCallAccumulator.js +1 -3
- package/dist/core/tools/tool-visibility.js +2 -1
- package/dist/core/tools/types.js +10 -0
- package/dist/core/types/batch.js +2 -0
- package/dist/core/utils/error.js +79 -0
- package/dist/core/utils/sanitizer.js +5 -2
- package/dist/core/utils/serialize.js +66 -0
- package/dist/core/utils/zod.js +29 -0
- package/dist/core/verification/detect-runner.js +86 -0
- package/dist/core/verification/runner.js +76 -0
- package/dist/core/version.js +3 -1
- package/dist/core/workspace/capabilities.js +3 -2
- package/dist/integrations/langfuse/litellm-langfuse-outcome-reporter.js +9 -8
- package/dist/languages/python/index.js +154 -0
- package/dist/locales/en.js +8 -1
- package/package.json +2 -1
|
@@ -93,19 +93,16 @@ class DefaultPermissionGate {
|
|
|
93
93
|
};
|
|
94
94
|
}
|
|
95
95
|
mapAuthorizationDecision(decision) {
|
|
96
|
+
const source = decision.source === 'auto' || decision.source === 'allowlist' ? 'policy' : decision.source;
|
|
96
97
|
if (decision.outcome === 'deny') {
|
|
97
|
-
return {
|
|
98
|
-
kind: 'deny',
|
|
99
|
-
reason: decision.reason ?? 'denied',
|
|
100
|
-
source: decision.source === 'auto' || decision.source === 'allowlist'
|
|
101
|
-
? 'policy'
|
|
102
|
-
: decision.source,
|
|
103
|
-
};
|
|
98
|
+
return { kind: 'deny', reason: decision.reason ?? 'denied', source };
|
|
104
99
|
}
|
|
105
100
|
return {
|
|
106
101
|
kind: 'allow',
|
|
107
102
|
reason: decision.reason,
|
|
108
|
-
source
|
|
103
|
+
source,
|
|
104
|
+
ttlMs: decision.ttlMs,
|
|
105
|
+
persist: decision.persist,
|
|
109
106
|
};
|
|
110
107
|
}
|
|
111
108
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { randomBytes, createHash } from 'crypto';
|
|
2
2
|
import path from 'path';
|
|
3
3
|
import { mkdir, readFile, rename, stat, writeFile } from '../adapters/fs/node-fs.js';
|
|
4
|
+
import { getLogger } from '../observability/logger.js';
|
|
4
5
|
const SESSION_ID_RE = /^[a-zA-Z0-9_-]{6,64}$/;
|
|
5
6
|
export function assertValidSessionId(sessionId) {
|
|
6
7
|
if (!SESSION_ID_RE.test(sessionId)) {
|
|
@@ -31,8 +32,8 @@ async function resolveGitDir(repoRoot) {
|
|
|
31
32
|
if (st.isDirectory())
|
|
32
33
|
return dotGit;
|
|
33
34
|
}
|
|
34
|
-
catch {
|
|
35
|
-
|
|
35
|
+
catch (error) {
|
|
36
|
+
getLogger().debug(`[PlanStorage] .git stat failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
36
37
|
}
|
|
37
38
|
try {
|
|
38
39
|
const raw = await readFile(dotGit, 'utf-8');
|
|
@@ -43,7 +44,8 @@ async function resolveGitDir(repoRoot) {
|
|
|
43
44
|
const gitdir = m[1].trim();
|
|
44
45
|
return path.isAbsolute(gitdir) ? gitdir : path.resolve(repoRoot, gitdir);
|
|
45
46
|
}
|
|
46
|
-
catch {
|
|
47
|
+
catch (error) {
|
|
48
|
+
getLogger().debug(`[PlanStorage] .git read failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
47
49
|
return null;
|
|
48
50
|
}
|
|
49
51
|
}
|
|
@@ -61,7 +63,8 @@ export async function ensureSalmonloopIgnored(repoRoot) {
|
|
|
61
63
|
try {
|
|
62
64
|
existing = await readFile(excludePath, 'utf-8');
|
|
63
65
|
}
|
|
64
|
-
catch {
|
|
66
|
+
catch (error) {
|
|
67
|
+
getLogger().debug(`[PlanStorage] Failed to read git exclude file: ${error instanceof Error ? error.message : String(error)}`);
|
|
65
68
|
existing = '';
|
|
66
69
|
}
|
|
67
70
|
if (existing.split('\n').some((l) => l.trim() === '.salmonloop/'))
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import { join } from 'path';
|
|
2
|
+
import { pythonPlugin } from '../../languages/python/index.js';
|
|
2
3
|
import { typescriptPlugin, tsxPlugin, javascriptPlugin } from '../../languages/typescript/index.js';
|
|
3
4
|
import { readdir } from '../adapters/fs/node-fs.js';
|
|
4
5
|
import { getLogger } from '../observability/logger.js';
|
|
6
|
+
import { errorMessage } from '../utils/error.js';
|
|
5
7
|
import { validateQueryPack } from './validator.js';
|
|
6
8
|
// Import built-in plugins (Phase 1: explicit import)
|
|
7
9
|
export class PluginLoader {
|
|
@@ -18,10 +20,11 @@ export class PluginLoader {
|
|
|
18
20
|
try {
|
|
19
21
|
// Phase 1: Manually register TypeScript/JavaScript plugins
|
|
20
22
|
getLogger().debug('Loading built-in plugins...');
|
|
23
|
+
this.registerWithValidation(registry, pythonPlugin);
|
|
21
24
|
this.registerWithValidation(registry, typescriptPlugin);
|
|
22
25
|
this.registerWithValidation(registry, tsxPlugin);
|
|
23
26
|
this.registerWithValidation(registry, javascriptPlugin);
|
|
24
|
-
getLogger().debug(`Plugins loaded: ${typescriptPlugin.meta.name}, ${tsxPlugin.meta.name}, ${javascriptPlugin.meta.name}`);
|
|
27
|
+
getLogger().debug(`Plugins loaded: ${pythonPlugin.meta.name}, ${typescriptPlugin.meta.name}, ${tsxPlugin.meta.name}, ${javascriptPlugin.meta.name}`);
|
|
25
28
|
// Phase 2: Load user plugins from .salmonloop/languages/
|
|
26
29
|
if (repoPath) {
|
|
27
30
|
await this.loadUserPlugins(registry, repoPath);
|
|
@@ -31,11 +34,11 @@ export class PluginLoader {
|
|
|
31
34
|
catch (error) {
|
|
32
35
|
// In test environment, we want to know why it failed
|
|
33
36
|
if (process.env.NODE_ENV === 'test') {
|
|
34
|
-
const errorMsg =
|
|
37
|
+
const errorMsg = errorMessage(error);
|
|
35
38
|
getLogger().error(`CRITICAL: Failed to load plugins: ${errorMsg}`);
|
|
36
39
|
throw error;
|
|
37
40
|
}
|
|
38
|
-
getLogger().error(`Failed to load plugins: ${
|
|
41
|
+
getLogger().error(`Failed to load plugins: ${errorMessage(error)}`);
|
|
39
42
|
}
|
|
40
43
|
}
|
|
41
44
|
/**
|
|
@@ -70,7 +73,7 @@ export class PluginLoader {
|
|
|
70
73
|
}
|
|
71
74
|
catch (err) {
|
|
72
75
|
if (err && typeof err === 'object' && 'code' in err && err.code !== 'ENOENT') {
|
|
73
|
-
getLogger().warn(`Failed to load user plugin from ${dirName}: ${
|
|
76
|
+
getLogger().warn(`Failed to load user plugin from ${dirName}: ${errorMessage(err)}`);
|
|
74
77
|
}
|
|
75
78
|
}
|
|
76
79
|
}
|
|
@@ -78,7 +81,7 @@ export class PluginLoader {
|
|
|
78
81
|
catch (err) {
|
|
79
82
|
// Ignore if directory doesn't exist
|
|
80
83
|
if (err && typeof err === 'object' && 'code' in err && err.code !== 'ENOENT') {
|
|
81
|
-
getLogger().debug(`Error scanning for user plugins: ${
|
|
84
|
+
getLogger().debug(`Error scanning for user plugins: ${errorMessage(err)}`);
|
|
82
85
|
}
|
|
83
86
|
}
|
|
84
87
|
}
|
|
@@ -2,6 +2,7 @@ import { fileURLToPath } from 'node:url';
|
|
|
2
2
|
import Handlebars from 'handlebars';
|
|
3
3
|
import { z } from 'zod';
|
|
4
4
|
import { readFile } from '../adapters/fs/node-fs.js';
|
|
5
|
+
import { unwrapZodSchema } from '../utils/zod.js';
|
|
5
6
|
const TEMPLATE_URLS = {
|
|
6
7
|
'system/_tool_defs.hbs': new URL('./templates/system/_tool_defs.hbs', import.meta.url),
|
|
7
8
|
'system/main_system.hbs': new URL('./templates/system/main_system.hbs', import.meta.url),
|
|
@@ -60,8 +61,8 @@ export class PromptRegistry {
|
|
|
60
61
|
if (!url) {
|
|
61
62
|
throw new Error(`Unknown prompt template path: ${relativePath}`);
|
|
62
63
|
}
|
|
63
|
-
const
|
|
64
|
-
const bun =
|
|
64
|
+
const bunGlobal = globalThis;
|
|
65
|
+
const bun = bunGlobal.Bun;
|
|
65
66
|
if (bun?.file) {
|
|
66
67
|
return bun.file(url).text();
|
|
67
68
|
}
|
|
@@ -113,34 +114,15 @@ export class PromptRegistry {
|
|
|
113
114
|
if (!zodSchema) {
|
|
114
115
|
return { type: 'object', description: 'Schema details unavailable' };
|
|
115
116
|
}
|
|
116
|
-
const unwrapForJsonSchema = (schema) => {
|
|
117
|
-
let current = schema;
|
|
118
|
-
for (let depth = 0; depth < 20; depth++) {
|
|
119
|
-
const ZodEffects = z.ZodEffects;
|
|
120
|
-
if (ZodEffects && current instanceof ZodEffects) {
|
|
121
|
-
current = current._def.schema;
|
|
122
|
-
continue;
|
|
123
|
-
}
|
|
124
|
-
if (current instanceof z.ZodPipe) {
|
|
125
|
-
current = current._def.out;
|
|
126
|
-
continue;
|
|
127
|
-
}
|
|
128
|
-
if (current instanceof z.ZodOptional ||
|
|
129
|
-
current instanceof z.ZodNullable ||
|
|
130
|
-
current instanceof z.ZodDefault) {
|
|
131
|
-
current = current._def.innerType;
|
|
132
|
-
continue;
|
|
133
|
-
}
|
|
134
|
-
break;
|
|
135
|
-
}
|
|
136
|
-
return current;
|
|
137
|
-
};
|
|
138
117
|
try {
|
|
139
|
-
const unwrapped =
|
|
140
|
-
const
|
|
141
|
-
if (
|
|
142
|
-
const
|
|
143
|
-
|
|
118
|
+
const unwrapped = unwrapZodSchema(zodSchema);
|
|
119
|
+
const zWithJson = z;
|
|
120
|
+
if (zWithJson.toJSONSchema) {
|
|
121
|
+
const schema = zWithJson.toJSONSchema(unwrapped);
|
|
122
|
+
if (schema && typeof schema === 'object') {
|
|
123
|
+
const { $schema: _ignored, ...rest } = schema;
|
|
124
|
+
return rest;
|
|
125
|
+
}
|
|
144
126
|
}
|
|
145
127
|
}
|
|
146
128
|
catch (_e) {
|
|
@@ -174,7 +156,7 @@ export class PromptRegistry {
|
|
|
174
156
|
return this.render('explore_system', { tools: this.getToolsForTemplate() });
|
|
175
157
|
}
|
|
176
158
|
renderAutopilotSystem() {
|
|
177
|
-
return this.render('autopilot_system', {});
|
|
159
|
+
return this.render('autopilot_system', { tools: this.getToolsForTemplate() });
|
|
178
160
|
}
|
|
179
161
|
renderAnswerSystem() {
|
|
180
162
|
return this.render('answer_system', {});
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { getLogger } from '../observability/logger.js';
|
|
1
2
|
import { resolvePhaseVisibleTools } from '../tools/tool-visibility.js';
|
|
2
3
|
import { Phase } from '../types/runtime.js';
|
|
3
4
|
import { getPromptRegistry } from './registry.js';
|
|
@@ -16,7 +17,8 @@ function extractTargetFiles(plan) {
|
|
|
16
17
|
const files = parsed.files.filter((f) => typeof f === 'string');
|
|
17
18
|
return files.length > 0 ? files.join(', ') : undefined;
|
|
18
19
|
}
|
|
19
|
-
catch {
|
|
20
|
+
catch (error) {
|
|
21
|
+
getLogger().debug(`[PromptRuntime] Failed to extract target files from plan JSON: ${error instanceof Error ? error.message : String(error)}`);
|
|
20
22
|
return undefined;
|
|
21
23
|
}
|
|
22
24
|
}
|
|
@@ -1,11 +1,35 @@
|
|
|
1
1
|
You are a coding assistant running in "autopilot" mode.
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
2
|
+
Your job is to complete the given task by using the available tools to inspect and modify the repository.
|
|
3
|
+
You MUST use tools to accomplish the task — do not just describe what needs to be done, actually do it.
|
|
4
|
+
|
|
5
|
+
## Problem-Solving Strategy
|
|
6
|
+
|
|
7
|
+
1. **Understand**: Read the problem statement carefully. Identify what is failing and what the expected behavior should be.
|
|
8
|
+
2. **Locate**: Find the source file to fix AND all test files that will be affected. Use `code.search` to search for the rule name, function name, or error message across the entire codebase. Pay special attention to CLI integration tests, snapshot tests, and end-to-end tests that assert on the behavior you are changing. Read ALL affected test files before writing any code.
|
|
9
|
+
3. **Diagnose**: Understand the root cause before writing any code. Read surrounding context, not just the error site.
|
|
10
|
+
4. **Fix**: Write the minimal change that fixes the issue. Update ALL affected test files to match the new behavior. Do not refactor unrelated code.
|
|
11
|
+
5. **Verify**: Run the FULL test suite with `shell.exec` (e.g. `pytest`). If tests fail, analyze the output and iterate. Do NOT run only targeted tests — behavioral changes cascade to other tests.
|
|
12
|
+
|
|
13
|
+
## Efficiency Rules
|
|
14
|
+
- Do NOT reproduce the bug. The problem statement already describes it. Go straight from understanding to fixing.
|
|
15
|
+
- Do NOT run multiple exploratory shell commands. Read the source code, understand the logic, write the fix.
|
|
16
|
+
- If you understand the root cause after reading the source, write the fix immediately. Do not verify the bug first.
|
|
17
|
+
- IMPORTANT: The Locate step is not optional. Spending time finding all affected tests upfront saves rounds later.
|
|
18
|
+
|
|
19
|
+
## Rules
|
|
20
|
+
- After writing code, you MUST run tests with `shell.exec` to verify your changes. This is not optional — a fix without verification is incomplete.
|
|
21
|
+
- If tests fail, read the failure output carefully, diagnose the issue, and fix it. Do not stop until tests pass. A failing test means your fix is incomplete — find all affected tests and update them.
|
|
22
|
+
- Read test files before modifying code — tests define the expected behavior.
|
|
23
|
+
- Do not modify test files unless the test itself is incorrect. If your fix changes behavior correctly, update the test's expected output to match.
|
|
24
|
+
- Before writing any code, use `code.search` to find ALL tests that reference the changed behavior. Search for: the rule name (e.g. "L031"), the function name, error messages, and expected test output. CLI integration tests and snapshot tests often contain hardcoded expected output that must be updated when behavior changes.
|
|
25
|
+
- Make the smallest possible change. Avoid unrelated refactoring or style changes.
|
|
26
|
+
- Drive the task forward autonomously and answer in the same language as the user.
|
|
27
|
+
|
|
6
28
|
Treat simple repo-relative paths like "smoke.txt", "README.md", or "src/index.ts" as valid paths from the repository root.
|
|
7
29
|
Do not ask the user to validate a path that is already a valid relative path or can be inferred directly from the instruction.
|
|
8
30
|
Use `interaction.ask_user` only when the task is genuinely ambiguous and you cannot safely infer the next action.
|
|
9
31
|
When calling `interaction.ask_user`, the arguments MUST be valid JSON with exactly this shape: {"questions":[{"header":"Short header","question":"One clear question","options":[{"label":"Option 1","description":"Why pick it"},{"label":"Option 2","description":"Why pick it"}],"multiSelect":false}]}.
|
|
10
32
|
Do not call `interaction.ask_user` with free-form strings, a single question field, string-only options, or empty options arrays.
|
|
11
33
|
For simple file creation or edits, call `fs.write_file` directly with {"file":"relative/path.ext","content":"..."} instead of asking the user for the path again.
|
|
34
|
+
|
|
35
|
+
{{> tool_defs}}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { InMemoryTaskStore } from '@a2a-js/sdk/server';
|
|
2
|
+
import { getLogger } from '../../../observability/logger.js';
|
|
2
3
|
import { buildCanonicalExecutionRequest, buildInstructionFromParts, } from '../../shared/execution-request.js';
|
|
3
4
|
import { parseA2ASkillFlowMode } from '../../shared/flow-mode-mapping.js';
|
|
4
5
|
export function createA2AInteractionExecutor(deps) {
|
|
@@ -346,7 +347,8 @@ export function createA2AInteractionExecutor(deps) {
|
|
|
346
347
|
data: JSON.parse(artifact.content),
|
|
347
348
|
};
|
|
348
349
|
}
|
|
349
|
-
catch {
|
|
350
|
+
catch (error) {
|
|
351
|
+
getLogger().debug(`[A2AExecutor] Failed to parse artifact content as JSON: ${error instanceof Error ? error.message : String(error)}`);
|
|
350
352
|
// Fall through to text
|
|
351
353
|
}
|
|
352
354
|
}
|
|
@@ -406,9 +406,9 @@ const normalizeA2AExtensionHeadersByVersion = (req, res, next) => {
|
|
|
406
406
|
});
|
|
407
407
|
next();
|
|
408
408
|
};
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
409
|
+
import { getLogger } from '../../../observability/logger.js';
|
|
410
|
+
import { isRecord } from '../../../utils/serialize.js';
|
|
411
|
+
const isObjectRecord = isRecord;
|
|
412
412
|
function looksLikeTask(result) {
|
|
413
413
|
return typeof result.id === 'string' && 'status' in result;
|
|
414
414
|
}
|
|
@@ -826,7 +826,8 @@ function normalizeSseJsonRpcChunkByMethod(chunk, method) {
|
|
|
826
826
|
const payload = JSON.parse(line.slice('data: '.length));
|
|
827
827
|
return `data: ${JSON.stringify(normalizeJsonRpcPayloadByMethod(method, payload))}`;
|
|
828
828
|
}
|
|
829
|
-
catch {
|
|
829
|
+
catch (error) {
|
|
830
|
+
getLogger().debug(`[A2AServer] Failed to parse SSE JSON-RPC chunk: ${error instanceof Error ? error.message : String(error)}`);
|
|
830
831
|
return line;
|
|
831
832
|
}
|
|
832
833
|
})
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { getLogger } from '../../observability/logger.js';
|
|
1
2
|
function sleep(ms) {
|
|
2
3
|
if (ms <= 0)
|
|
3
4
|
return Promise.resolve();
|
|
@@ -72,8 +73,8 @@ async function safeRelease(terminal) {
|
|
|
72
73
|
try {
|
|
73
74
|
await terminal.release();
|
|
74
75
|
}
|
|
75
|
-
catch {
|
|
76
|
-
|
|
76
|
+
catch (error) {
|
|
77
|
+
getLogger().debug(`[AcpCommandRunner] Failed to release terminal: ${error instanceof Error ? error.message : String(error)}`);
|
|
77
78
|
}
|
|
78
79
|
}
|
|
79
80
|
export function createAcpCommandRunner(params) {
|
|
@@ -134,8 +135,8 @@ export function createAcpCommandRunner(params) {
|
|
|
134
135
|
try {
|
|
135
136
|
await terminal.kill();
|
|
136
137
|
}
|
|
137
|
-
catch {
|
|
138
|
-
|
|
138
|
+
catch (error) {
|
|
139
|
+
getLogger().debug(`[AcpCommandRunner] Failed to kill terminal on abort: ${error instanceof Error ? error.message : String(error)}`);
|
|
139
140
|
}
|
|
140
141
|
break;
|
|
141
142
|
}
|
|
@@ -144,8 +145,8 @@ export function createAcpCommandRunner(params) {
|
|
|
144
145
|
try {
|
|
145
146
|
await terminal.kill();
|
|
146
147
|
}
|
|
147
|
-
catch {
|
|
148
|
-
|
|
148
|
+
catch (error) {
|
|
149
|
+
getLogger().debug(`[AcpCommandRunner] Failed to kill terminal on timeout: ${error instanceof Error ? error.message : String(error)}`);
|
|
149
150
|
}
|
|
150
151
|
break;
|
|
151
152
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { mkdir, open, readFile, rename, stat, unlink, writeFile, } from '../../adapters/fs/node-fs.js';
|
|
2
2
|
import { defaultPathAdapter } from '../../adapters/path/path-adapter.js';
|
|
3
3
|
import { recordAuditEvent } from '../../observability/audit-trail.js';
|
|
4
|
+
import { getLogger } from '../../observability/logger.js';
|
|
4
5
|
import { hashRepoPath, isPermissionPolicyValue, parseTimestamp, } from './acp-types.js';
|
|
5
6
|
export function createAcpSessionPersistence(options) {
|
|
6
7
|
const deletedSessionIds = new Map();
|
|
@@ -219,7 +220,8 @@ export function createAcpSessionPersistence(options) {
|
|
|
219
220
|
phase: 'PREFLIGHT',
|
|
220
221
|
});
|
|
221
222
|
}
|
|
222
|
-
catch {
|
|
223
|
+
catch (error) {
|
|
224
|
+
getLogger().debug(`[AcpSessionPersistence] Failed to parse stale lock file: ${error instanceof Error ? error.message : String(error)}`);
|
|
223
225
|
try {
|
|
224
226
|
const lockStat = await stat(lockPath);
|
|
225
227
|
const ageMs = Date.now() - lockStat.mtimeMs;
|
|
@@ -231,8 +233,8 @@ export function createAcpSessionPersistence(options) {
|
|
|
231
233
|
}, { source: 'acp', severity: 'medium', scope: 'session', phase: 'PREFLIGHT' });
|
|
232
234
|
}
|
|
233
235
|
}
|
|
234
|
-
catch {
|
|
235
|
-
|
|
236
|
+
catch (innerError) {
|
|
237
|
+
getLogger().debug(`[AcpSessionPersistence] Failed to stat lock file for age check: ${innerError instanceof Error ? innerError.message : String(innerError)}`);
|
|
236
238
|
}
|
|
237
239
|
}
|
|
238
240
|
};
|
|
@@ -246,7 +248,8 @@ export function createAcpSessionPersistence(options) {
|
|
|
246
248
|
await lockHandle.writeFile(JSON.stringify({ pid: process.pid, createdAtMs: Date.now() }), 'utf8');
|
|
247
249
|
break;
|
|
248
250
|
}
|
|
249
|
-
catch {
|
|
251
|
+
catch (error) {
|
|
252
|
+
getLogger().debug(`[AcpSessionPersistence] Lock acquire attempt failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
250
253
|
await tryClearStaleLock();
|
|
251
254
|
const delayMs = Math.min(250, 20 * (attempt + 1));
|
|
252
255
|
await new Promise((resolve) => setTimeout(resolve, delayMs));
|
|
@@ -271,8 +274,8 @@ export function createAcpSessionPersistence(options) {
|
|
|
271
274
|
const existingRaw = await readFile(options.path, 'utf8');
|
|
272
275
|
existing = normalizePersistedSessionStore(JSON.parse(existingRaw));
|
|
273
276
|
}
|
|
274
|
-
catch {
|
|
275
|
-
|
|
277
|
+
catch (error) {
|
|
278
|
+
getLogger().debug(`[AcpSessionPersistence] Failed to read existing session store for merge: ${error instanceof Error ? error.message : String(error)}`);
|
|
276
279
|
}
|
|
277
280
|
const merged = new Map();
|
|
278
281
|
const mergedDeletedSessions = pruneDeletedSessionRecords([
|
|
@@ -311,14 +314,14 @@ export function createAcpSessionPersistence(options) {
|
|
|
311
314
|
try {
|
|
312
315
|
await lockHandle.close();
|
|
313
316
|
}
|
|
314
|
-
catch {
|
|
315
|
-
|
|
317
|
+
catch (error) {
|
|
318
|
+
getLogger().debug(`[AcpSessionPersistence] Failed to close lock handle: ${error instanceof Error ? error.message : String(error)}`);
|
|
316
319
|
}
|
|
317
320
|
try {
|
|
318
321
|
await unlink(lockPath);
|
|
319
322
|
}
|
|
320
|
-
catch {
|
|
321
|
-
|
|
323
|
+
catch (error) {
|
|
324
|
+
getLogger().debug(`[AcpSessionPersistence] Failed to unlink lock file: ${error instanceof Error ? error.message : String(error)}`);
|
|
322
325
|
}
|
|
323
326
|
}
|
|
324
327
|
}
|
|
@@ -3,10 +3,12 @@ import { text } from '../../../locales/index.js';
|
|
|
3
3
|
import { defaultPathAdapter } from '../../adapters/path/path-adapter.js';
|
|
4
4
|
import { inferTurnStopReasonFromFailure } from '../../interaction/turn-stop-reason.js';
|
|
5
5
|
import { recordAuditEvent } from '../../observability/audit-trail.js';
|
|
6
|
+
import { getLogger } from '../../observability/logger.js';
|
|
6
7
|
import { toAcpPublicModes } from '../../public-capabilities/projections.js';
|
|
7
8
|
import { buildPublicCapabilityRegistry } from '../../public-capabilities/registry.js';
|
|
8
9
|
import { parseSlashInput } from '../../slash/parser.js';
|
|
9
10
|
import { Phase } from '../../types/runtime.js';
|
|
11
|
+
import { isRecord } from '../../utils/serialize.js';
|
|
10
12
|
import { buildCanonicalExecutionRequest } from '../shared/execution-request.js';
|
|
11
13
|
import { parseAcpFlowMode } from '../shared/flow-mode-mapping.js';
|
|
12
14
|
import { probeCheckpoint, probeCheckpointForNewSession, } from './acp-checkpoint-probe.js';
|
|
@@ -18,7 +20,7 @@ import { createAcpSessionStore, isTerminalTaskEvent } from './handlers.js';
|
|
|
18
20
|
import { createAcpToolAuthorizationProvider } from './permission-provider.js';
|
|
19
21
|
import { mapToolKind } from './tool-kind-mapping.js';
|
|
20
22
|
function formatInputRequiredMessage(inputRequired) {
|
|
21
|
-
if (!inputRequired || !Array.isArray(inputRequired.questions))
|
|
23
|
+
if (!inputRequired || !isRecord(inputRequired) || !Array.isArray(inputRequired.questions))
|
|
22
24
|
return null;
|
|
23
25
|
const questions = inputRequired.questions;
|
|
24
26
|
if (questions.length === 0)
|
|
@@ -525,6 +527,7 @@ function acpMcpServersToExtensions(mcpServers) {
|
|
|
525
527
|
mcpServers: resolvedServers,
|
|
526
528
|
toolPlugins: [],
|
|
527
529
|
skillDiscovery: { paths: [], scope: 'repo' },
|
|
530
|
+
agentProfiles: [],
|
|
528
531
|
};
|
|
529
532
|
}
|
|
530
533
|
function validateAcpMcpServers(mcpServers) {
|
|
@@ -569,12 +572,13 @@ function isPersistableSession(session) {
|
|
|
569
572
|
async function awaitTerminalEvent(params) {
|
|
570
573
|
if (!params.eventBus)
|
|
571
574
|
return null;
|
|
572
|
-
const
|
|
575
|
+
const { eventBus } = params;
|
|
576
|
+
const history = eventBus.list(params.taskId);
|
|
573
577
|
const terminal = history.find(isTerminalTaskEvent);
|
|
574
578
|
if (terminal)
|
|
575
579
|
return terminal;
|
|
576
580
|
return await new Promise((resolve) => {
|
|
577
|
-
const unsubscribe =
|
|
581
|
+
const unsubscribe = eventBus.subscribe((event) => {
|
|
578
582
|
if (event.taskId !== params.taskId)
|
|
579
583
|
return;
|
|
580
584
|
if (!isTerminalTaskEvent(event))
|
|
@@ -638,8 +642,8 @@ export function createAcpFormalAgent(deps) {
|
|
|
638
642
|
try {
|
|
639
643
|
await emitSessionUpdate(sessionId, update);
|
|
640
644
|
}
|
|
641
|
-
catch {
|
|
642
|
-
|
|
645
|
+
catch (error) {
|
|
646
|
+
getLogger().debug(`[AcpFormalAgent] Best-effort session info update failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
643
647
|
}
|
|
644
648
|
}
|
|
645
649
|
async function emitRuntimePlanUpdateIfNeeded(params) {
|
|
@@ -1092,7 +1096,10 @@ export function createAcpFormalAgent(deps) {
|
|
|
1092
1096
|
...current,
|
|
1093
1097
|
history: [
|
|
1094
1098
|
...current.history,
|
|
1095
|
-
{
|
|
1099
|
+
{
|
|
1100
|
+
role: 'assistant',
|
|
1101
|
+
content: [buildTextContentBlock(responseText)],
|
|
1102
|
+
},
|
|
1096
1103
|
],
|
|
1097
1104
|
}));
|
|
1098
1105
|
await sessionPersistence.persist();
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { text } from '../../../locales/index.js';
|
|
2
|
+
import { getLogger } from '../../observability/logger.js';
|
|
2
3
|
import { mapToolKind } from './tool-kind-mapping.js';
|
|
3
4
|
function buildPermissionOptions() {
|
|
4
5
|
return [
|
|
@@ -45,8 +46,8 @@ export function createAcpToolAuthorizationProvider(params) {
|
|
|
45
46
|
};
|
|
46
47
|
await params.conn.sessionUpdate({ sessionId: params.sessionId, update });
|
|
47
48
|
}
|
|
48
|
-
catch {
|
|
49
|
-
|
|
49
|
+
catch (error) {
|
|
50
|
+
getLogger().debug(`[AcpPermissionProvider] Best-effort in_progress update failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
50
51
|
}
|
|
51
52
|
};
|
|
52
53
|
return {
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { Readable, Writable } from 'node:stream';
|
|
2
2
|
import { AgentSideConnection } from '@agentclientprotocol/sdk';
|
|
3
3
|
import { tryGetLogger } from '../../observability/logger.js';
|
|
4
|
+
import { errorMessage } from '../../utils/error.js';
|
|
5
|
+
import { isRecord } from '../../utils/serialize.js';
|
|
4
6
|
const INVALID_REQUEST = {
|
|
5
7
|
jsonrpc: '2.0',
|
|
6
8
|
id: null,
|
|
@@ -11,9 +13,7 @@ const PARSE_ERROR = {
|
|
|
11
13
|
id: null,
|
|
12
14
|
error: { code: -32700, message: 'Parse error' },
|
|
13
15
|
};
|
|
14
|
-
|
|
15
|
-
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
16
|
-
}
|
|
16
|
+
const isJsonObject = isRecord;
|
|
17
17
|
function hasOwn(value, key) {
|
|
18
18
|
return Object.prototype.hasOwnProperty.call(value, key);
|
|
19
19
|
}
|
|
@@ -50,9 +50,9 @@ function createNdjsonWriter(output) {
|
|
|
50
50
|
.catch(() => undefined)
|
|
51
51
|
.then(() => writer.write(data))
|
|
52
52
|
.catch((error) => {
|
|
53
|
-
const detail =
|
|
53
|
+
const detail = errorMessage(error);
|
|
54
54
|
safeWarn(`ACP stdio failed to write NDJSON line. reason="${detail}"`);
|
|
55
|
-
lastError =
|
|
55
|
+
lastError = new Error(detail);
|
|
56
56
|
});
|
|
57
57
|
await tail;
|
|
58
58
|
},
|
|
@@ -83,7 +83,7 @@ async function processStdioLine(line, ndjson, controller) {
|
|
|
83
83
|
controller.enqueue(parsed);
|
|
84
84
|
}
|
|
85
85
|
catch (error) {
|
|
86
|
-
const detail =
|
|
86
|
+
const detail = errorMessage(error);
|
|
87
87
|
safeWarn(`ACP stdio failed to parse JSON line. reason="${detail}"`);
|
|
88
88
|
await ndjson.write(PARSE_ERROR);
|
|
89
89
|
}
|