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
|
@@ -0,0 +1,334 @@
|
|
|
1
|
+
import { createHash } from 'crypto';
|
|
2
|
+
import { getPromptCachingManager } from '../context/cache/prompt-caching.js';
|
|
3
|
+
function isArtifactHandle(value) {
|
|
4
|
+
if (!value || typeof value !== 'object')
|
|
5
|
+
return false;
|
|
6
|
+
const candidate = value;
|
|
7
|
+
return (typeof candidate.handle === 'string' &&
|
|
8
|
+
typeof candidate.mimeType === 'string' &&
|
|
9
|
+
typeof candidate.sha256 === 'string' &&
|
|
10
|
+
typeof candidate.size === 'number');
|
|
11
|
+
}
|
|
12
|
+
function mergeArtifactHandles(existing, incoming, limit = 4) {
|
|
13
|
+
const merged = [];
|
|
14
|
+
const seen = new Set();
|
|
15
|
+
for (const artifact of [...(existing ?? []), ...(incoming ?? [])]) {
|
|
16
|
+
if (!artifact || seen.has(artifact.handle))
|
|
17
|
+
continue;
|
|
18
|
+
seen.add(artifact.handle);
|
|
19
|
+
merged.push(artifact);
|
|
20
|
+
}
|
|
21
|
+
if (merged.length === 0)
|
|
22
|
+
return undefined;
|
|
23
|
+
return merged.slice(-limit);
|
|
24
|
+
}
|
|
25
|
+
function mergeReadArtifactRefs(existing, incoming, limit = 6) {
|
|
26
|
+
const merged = [];
|
|
27
|
+
const seen = new Set();
|
|
28
|
+
for (const item of [...(existing ?? []), ...(incoming ?? [])]) {
|
|
29
|
+
if (!item?.path || !item.artifact?.handle)
|
|
30
|
+
continue;
|
|
31
|
+
const key = `${item.path}::${item.artifact.handle}`;
|
|
32
|
+
if (seen.has(key))
|
|
33
|
+
continue;
|
|
34
|
+
seen.add(key);
|
|
35
|
+
merged.push(item);
|
|
36
|
+
}
|
|
37
|
+
if (merged.length === 0)
|
|
38
|
+
return undefined;
|
|
39
|
+
return merged.slice(-limit);
|
|
40
|
+
}
|
|
41
|
+
function mergePreviewArtifactRefs(existing, incoming, limit = 6) {
|
|
42
|
+
const merged = [];
|
|
43
|
+
const seen = new Set();
|
|
44
|
+
for (const item of [...(existing ?? []), ...(incoming ?? [])]) {
|
|
45
|
+
if (!item?.label || !item.artifact?.handle)
|
|
46
|
+
continue;
|
|
47
|
+
const key = `${item.label}::${item.artifact.handle}`;
|
|
48
|
+
if (seen.has(key))
|
|
49
|
+
continue;
|
|
50
|
+
seen.add(key);
|
|
51
|
+
merged.push(item);
|
|
52
|
+
}
|
|
53
|
+
if (merged.length === 0)
|
|
54
|
+
return undefined;
|
|
55
|
+
return merged.slice(-limit);
|
|
56
|
+
}
|
|
57
|
+
export function resolveRequestArtifactHints(params) {
|
|
58
|
+
const direct = params.artifactHints;
|
|
59
|
+
const auditEntries = params.toolCallingAudit ?? [];
|
|
60
|
+
const auditPatchArtifacts = [];
|
|
61
|
+
const auditAuditArtifacts = [];
|
|
62
|
+
const auditReadArtifacts = [];
|
|
63
|
+
const auditPreviewArtifacts = [];
|
|
64
|
+
for (const entry of auditEntries) {
|
|
65
|
+
if (entry?.toolResultStatus === 'ok' && entry.toolName === 'agent_dispatch') {
|
|
66
|
+
if (isArtifactHandle(entry.toolResultPatchArtifact)) {
|
|
67
|
+
auditPatchArtifacts.push(entry.toolResultPatchArtifact);
|
|
68
|
+
}
|
|
69
|
+
if (isArtifactHandle(entry.toolResultAuditArtifact)) {
|
|
70
|
+
auditAuditArtifacts.push(entry.toolResultAuditArtifact);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
if (typeof entry.toolResultReadArtifactPath === 'string' &&
|
|
74
|
+
isArtifactHandle(entry.toolResultReadArtifact)) {
|
|
75
|
+
auditReadArtifacts.push({
|
|
76
|
+
path: entry.toolResultReadArtifactPath,
|
|
77
|
+
artifact: entry.toolResultReadArtifact,
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
if (typeof entry.toolResultPreviewLabel === 'string' &&
|
|
81
|
+
isArtifactHandle(entry.toolResultPreviewArtifact)) {
|
|
82
|
+
auditPreviewArtifacts.push({
|
|
83
|
+
label: entry.toolResultPreviewLabel,
|
|
84
|
+
artifact: entry.toolResultPreviewArtifact,
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
const resolved = {
|
|
89
|
+
verifyArtifact: direct?.verifyArtifact,
|
|
90
|
+
subAgentPatchArtifacts: mergeArtifactHandles(direct?.subAgentPatchArtifacts, auditPatchArtifacts),
|
|
91
|
+
subAgentAuditArtifacts: mergeArtifactHandles(direct?.subAgentAuditArtifacts, auditAuditArtifacts),
|
|
92
|
+
recentReadArtifacts: mergeReadArtifactRefs(direct?.recentReadArtifacts, auditReadArtifacts),
|
|
93
|
+
toolResultPreviewArtifacts: mergePreviewArtifactRefs(params.previewProvider?.getPreviewHints(), auditPreviewArtifacts),
|
|
94
|
+
};
|
|
95
|
+
if (!resolved.verifyArtifact &&
|
|
96
|
+
!resolved.subAgentPatchArtifacts?.length &&
|
|
97
|
+
!resolved.subAgentAuditArtifacts?.length &&
|
|
98
|
+
!resolved.recentReadArtifacts?.length &&
|
|
99
|
+
!resolved.toolResultPreviewArtifacts?.length) {
|
|
100
|
+
return undefined;
|
|
101
|
+
}
|
|
102
|
+
return resolved;
|
|
103
|
+
}
|
|
104
|
+
function toSafeMessage(message) {
|
|
105
|
+
if (!message || typeof message !== 'object')
|
|
106
|
+
return null;
|
|
107
|
+
if (message.role !== 'system' && message.role !== 'user' && message.role !== 'assistant') {
|
|
108
|
+
return null;
|
|
109
|
+
}
|
|
110
|
+
if (typeof message.content !== 'string')
|
|
111
|
+
return null;
|
|
112
|
+
const content = message.content.trimEnd();
|
|
113
|
+
if (!content)
|
|
114
|
+
return null;
|
|
115
|
+
return {
|
|
116
|
+
role: message.role,
|
|
117
|
+
content,
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
function estimateTokens(text) {
|
|
121
|
+
return Math.ceil(text.length / 4);
|
|
122
|
+
}
|
|
123
|
+
function resolvePromptCacheMode(mode) {
|
|
124
|
+
return mode === 'strict_full_prompt' ? 'strict_full_prompt' : 'cache_safe_only';
|
|
125
|
+
}
|
|
126
|
+
function serializeAttachmentForFingerprint(item) {
|
|
127
|
+
return [
|
|
128
|
+
item.key,
|
|
129
|
+
item.kind,
|
|
130
|
+
item.label ?? '',
|
|
131
|
+
item.content ?? '',
|
|
132
|
+
item.artifactHandle ?? '',
|
|
133
|
+
item.mimeType ?? '',
|
|
134
|
+
typeof item.size === 'number' ? String(item.size) : '',
|
|
135
|
+
].join('\u001f');
|
|
136
|
+
}
|
|
137
|
+
function createFingerprint(parts) {
|
|
138
|
+
if (parts.length === 0)
|
|
139
|
+
return undefined;
|
|
140
|
+
const hash = createHash('sha256');
|
|
141
|
+
for (const [index, part] of parts.entries()) {
|
|
142
|
+
hash.update(`part:${index}:${part.length}\n`);
|
|
143
|
+
hash.update(part);
|
|
144
|
+
hash.update('\n');
|
|
145
|
+
}
|
|
146
|
+
return hash.digest('hex');
|
|
147
|
+
}
|
|
148
|
+
function toArtifactAttachment(args) {
|
|
149
|
+
return {
|
|
150
|
+
key: args.key,
|
|
151
|
+
kind: 'artifact',
|
|
152
|
+
label: args.label,
|
|
153
|
+
content: '',
|
|
154
|
+
artifactHandle: args.artifact.handle,
|
|
155
|
+
mimeType: args.artifact.mimeType,
|
|
156
|
+
size: args.artifact.size,
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
export function buildArtifactHintAttachments(hints) {
|
|
160
|
+
if (!hints)
|
|
161
|
+
return [];
|
|
162
|
+
const attachments = [];
|
|
163
|
+
if (hints.verifyArtifact) {
|
|
164
|
+
attachments.push(toArtifactAttachment({
|
|
165
|
+
key: 'previous-verify-output',
|
|
166
|
+
label: 'Previous verify output',
|
|
167
|
+
artifact: hints.verifyArtifact,
|
|
168
|
+
}));
|
|
169
|
+
}
|
|
170
|
+
for (const [index, artifact] of (hints.subAgentPatchArtifacts ?? []).entries()) {
|
|
171
|
+
attachments.push(toArtifactAttachment({
|
|
172
|
+
key: `previous-subagent-patch-${index}`,
|
|
173
|
+
label: `Previous sub-agent patch artifact ${index + 1}`,
|
|
174
|
+
artifact,
|
|
175
|
+
}));
|
|
176
|
+
}
|
|
177
|
+
for (const [index, artifact] of (hints.subAgentAuditArtifacts ?? []).entries()) {
|
|
178
|
+
attachments.push(toArtifactAttachment({
|
|
179
|
+
key: `previous-subagent-audit-${index}`,
|
|
180
|
+
label: `Previous sub-agent audit artifact ${index + 1}`,
|
|
181
|
+
artifact,
|
|
182
|
+
}));
|
|
183
|
+
}
|
|
184
|
+
for (const [index, item] of (hints.recentReadArtifacts ?? []).entries()) {
|
|
185
|
+
attachments.push(toArtifactAttachment({
|
|
186
|
+
key: `recent-read-${index}`,
|
|
187
|
+
label: `Recent file read: ${item.path}`,
|
|
188
|
+
artifact: item.artifact,
|
|
189
|
+
}));
|
|
190
|
+
}
|
|
191
|
+
for (const [index, item] of (hints.toolResultPreviewArtifacts ?? []).entries()) {
|
|
192
|
+
attachments.push(toArtifactAttachment({
|
|
193
|
+
key: `tool-result-preview-${index}`,
|
|
194
|
+
label: item.label,
|
|
195
|
+
artifact: item.artifact,
|
|
196
|
+
}));
|
|
197
|
+
}
|
|
198
|
+
return attachments;
|
|
199
|
+
}
|
|
200
|
+
function buildPromptCachingHints(surface) {
|
|
201
|
+
const policy = {
|
|
202
|
+
mode: surface.mode,
|
|
203
|
+
eligibility: surface.cacheEligibility,
|
|
204
|
+
namespace: surface.namespace,
|
|
205
|
+
contextHash: surface.contextHash,
|
|
206
|
+
cacheSafeFingerprint: surface.cacheSafeFingerprint,
|
|
207
|
+
lateInjectionFingerprint: surface.lateInjectionFingerprint,
|
|
208
|
+
};
|
|
209
|
+
if (surface.cacheEligibility !== 'eligible' ||
|
|
210
|
+
!surface.contextHash ||
|
|
211
|
+
!surface.cacheSafeFingerprint) {
|
|
212
|
+
return {
|
|
213
|
+
openAICachePolicy: policy,
|
|
214
|
+
};
|
|
215
|
+
}
|
|
216
|
+
const components = [surface.contextHash, `stable:${surface.cacheSafeFingerprint}`];
|
|
217
|
+
if (surface.mode === 'strict_full_prompt' && surface.lateInjectionFingerprint) {
|
|
218
|
+
components.push(`late:${surface.lateInjectionFingerprint}`);
|
|
219
|
+
}
|
|
220
|
+
const manager = getPromptCachingManager();
|
|
221
|
+
return {
|
|
222
|
+
openAICacheHint: manager.generateOpenAICacheHint(surface.namespace ?? 'request-envelope', components),
|
|
223
|
+
openAICachePolicy: policy,
|
|
224
|
+
};
|
|
225
|
+
}
|
|
226
|
+
export function buildRequestEnvelope(params) {
|
|
227
|
+
const systemSections = (Array.isArray(params.system) ? params.system : [params.system]).map((item) => String(item ?? '').trimEnd());
|
|
228
|
+
const attachments = Array.isArray(params.attachments)
|
|
229
|
+
? params.attachments
|
|
230
|
+
.filter((item) => item && (typeof item.content === 'string' || typeof item.artifactHandle === 'string'))
|
|
231
|
+
.map((item) => ({
|
|
232
|
+
...item,
|
|
233
|
+
content: typeof item.content === 'string' ? item.content.trimEnd() : '',
|
|
234
|
+
}))
|
|
235
|
+
.filter((item) => item.content.length > 0 || typeof item.artifactHandle === 'string')
|
|
236
|
+
: [];
|
|
237
|
+
const userMetaMessages = [];
|
|
238
|
+
const conversationMessages = [];
|
|
239
|
+
if (Array.isArray(params.conversationContext)) {
|
|
240
|
+
for (const message of params.conversationContext) {
|
|
241
|
+
const safe = toSafeMessage(message);
|
|
242
|
+
if (!safe)
|
|
243
|
+
continue;
|
|
244
|
+
if (safe.role === 'system') {
|
|
245
|
+
userMetaMessages.push(safe);
|
|
246
|
+
continue;
|
|
247
|
+
}
|
|
248
|
+
conversationMessages.push(safe);
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
const cacheMode = resolvePromptCacheMode(params.cacheSafeSurface?.mode);
|
|
252
|
+
const cacheSafeAttachments = attachments.filter((item) => item.cacheSafe);
|
|
253
|
+
const lateInjectionAttachments = attachments.filter((item) => !item.cacheSafe);
|
|
254
|
+
const cacheSafeFingerprint = createFingerprint([
|
|
255
|
+
...systemSections.map((section, index) => `system:${index}\u001f${section}`),
|
|
256
|
+
...cacheSafeAttachments.map((item, index) => `attachment:${index}\u001f${serializeAttachmentForFingerprint(item)}`),
|
|
257
|
+
]);
|
|
258
|
+
const lateInjectionFingerprint = createFingerprint([
|
|
259
|
+
`userPrompt\u001f${String(params.user ?? '').trimEnd()}`,
|
|
260
|
+
...userMetaMessages.map((message, index) => `meta:${index}\u001f${message.content}`),
|
|
261
|
+
...conversationMessages.map((message, index) => `conversation:${index}\u001f${message.role}\u001f${message.content}`),
|
|
262
|
+
...lateInjectionAttachments.map((item, index) => `late-attachment:${index}\u001f${serializeAttachmentForFingerprint(item)}`),
|
|
263
|
+
]);
|
|
264
|
+
const cacheSafeText = [...systemSections, ...cacheSafeAttachments.map((item) => item.content)]
|
|
265
|
+
.filter(Boolean)
|
|
266
|
+
.join('\n\n');
|
|
267
|
+
const manager = getPromptCachingManager();
|
|
268
|
+
const cacheEligibility = !params.cacheSafeSurface?.contextHash
|
|
269
|
+
? 'missing_context_hash'
|
|
270
|
+
: !cacheSafeText.trim()
|
|
271
|
+
? 'empty_cache_safe_surface'
|
|
272
|
+
: !manager.shouldCache(estimateTokens(cacheSafeText))
|
|
273
|
+
? 'below_min_tokens'
|
|
274
|
+
: 'eligible';
|
|
275
|
+
const cacheSafeSurface = {
|
|
276
|
+
systemSections,
|
|
277
|
+
attachments: cacheSafeAttachments,
|
|
278
|
+
contextHash: params.cacheSafeSurface?.contextHash,
|
|
279
|
+
namespace: params.cacheSafeSurface?.namespace,
|
|
280
|
+
mode: cacheMode,
|
|
281
|
+
cacheEligibility,
|
|
282
|
+
cacheSafeFingerprint,
|
|
283
|
+
lateInjectionFingerprint,
|
|
284
|
+
};
|
|
285
|
+
return {
|
|
286
|
+
systemSections,
|
|
287
|
+
userPrompt: String(params.user ?? ''),
|
|
288
|
+
userMetaMessages,
|
|
289
|
+
conversationMessages,
|
|
290
|
+
attachments,
|
|
291
|
+
providerHints: {
|
|
292
|
+
...buildPromptCachingHints(cacheSafeSurface),
|
|
293
|
+
...(params.providerHints ?? {}),
|
|
294
|
+
},
|
|
295
|
+
cacheSafeSurface,
|
|
296
|
+
};
|
|
297
|
+
}
|
|
298
|
+
export function materializeRequestEnvelope(envelope) {
|
|
299
|
+
const artifactSection = (() => {
|
|
300
|
+
const artifactAttachments = envelope.attachments.filter((item) => item.kind === 'artifact' && typeof item.artifactHandle === 'string' && item.artifactHandle);
|
|
301
|
+
if (artifactAttachments.length === 0)
|
|
302
|
+
return '';
|
|
303
|
+
const lines = [
|
|
304
|
+
'# Available Artifacts',
|
|
305
|
+
'Use `artifact.read` with these handles when you need the full artifact contents.',
|
|
306
|
+
];
|
|
307
|
+
for (const item of artifactAttachments) {
|
|
308
|
+
const suffix = [
|
|
309
|
+
item.mimeType ? `mime=${item.mimeType}` : undefined,
|
|
310
|
+
typeof item.size === 'number' ? `size=${item.size}` : undefined,
|
|
311
|
+
]
|
|
312
|
+
.filter(Boolean)
|
|
313
|
+
.join(', ');
|
|
314
|
+
lines.push(`- ${item.label ?? item.key}: ${item.artifactHandle}${suffix ? ` (${suffix})` : ''}`);
|
|
315
|
+
}
|
|
316
|
+
return lines.join('\n');
|
|
317
|
+
})();
|
|
318
|
+
const out = [
|
|
319
|
+
{
|
|
320
|
+
role: 'system',
|
|
321
|
+
content: envelope.systemSections.filter(Boolean).join('\n\n'),
|
|
322
|
+
},
|
|
323
|
+
];
|
|
324
|
+
out.push(...envelope.userMetaMessages);
|
|
325
|
+
out.push(...envelope.conversationMessages);
|
|
326
|
+
out.push({
|
|
327
|
+
role: 'user',
|
|
328
|
+
content: artifactSection.trim().length > 0
|
|
329
|
+
? `${String(envelope.userPrompt ?? '')}\n\n${artifactSection}`
|
|
330
|
+
: String(envelope.userPrompt ?? ''),
|
|
331
|
+
});
|
|
332
|
+
return out;
|
|
333
|
+
}
|
|
334
|
+
//# sourceMappingURL=request-envelope.js.map
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { buildArtifactHintAttachments, buildRequestEnvelope, materializeRequestEnvelope, resolveRequestArtifactHints, } from './request-envelope.js';
|
|
2
|
+
export function buildSharedRequestEnvelope(args) {
|
|
3
|
+
const cacheSurface = {
|
|
4
|
+
namespace: args.defaultNamespace,
|
|
5
|
+
contextHash: args.contextHash,
|
|
6
|
+
};
|
|
7
|
+
const resolvedArtifactHints = resolveRequestArtifactHints({
|
|
8
|
+
artifactHints: args.artifactHints,
|
|
9
|
+
toolCallingAudit: args.toolCallingAudit,
|
|
10
|
+
previewProvider: args.previewProvider,
|
|
11
|
+
});
|
|
12
|
+
const envelope = buildRequestEnvelope({
|
|
13
|
+
system: args.systemPrompt,
|
|
14
|
+
user: args.userPrompt,
|
|
15
|
+
conversationContext: args.conversationContext,
|
|
16
|
+
attachments: [
|
|
17
|
+
...(args.attachments ?? []),
|
|
18
|
+
...buildArtifactHintAttachments(resolvedArtifactHints),
|
|
19
|
+
],
|
|
20
|
+
providerHints: args.providerHints,
|
|
21
|
+
cacheSafeSurface: {
|
|
22
|
+
contextHash: cacheSurface.contextHash,
|
|
23
|
+
namespace: cacheSurface.namespace,
|
|
24
|
+
mode: 'cache_safe_only',
|
|
25
|
+
},
|
|
26
|
+
});
|
|
27
|
+
const baseMessages = materializeRequestEnvelope(envelope);
|
|
28
|
+
return {
|
|
29
|
+
cacheSurface,
|
|
30
|
+
resolvedArtifactHints,
|
|
31
|
+
envelope,
|
|
32
|
+
baseMessages,
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
//# sourceMappingURL=shared-request-assembly.js.map
|
|
@@ -33,12 +33,20 @@ export function mapAiSdkStreamPartToChunk(part) {
|
|
|
33
33
|
return null;
|
|
34
34
|
}
|
|
35
35
|
switch (part.type) {
|
|
36
|
-
case 'text-delta':
|
|
37
|
-
|
|
38
|
-
if (typeof
|
|
39
|
-
return { role: 'assistant', source: 'provider', contentDelta:
|
|
36
|
+
case 'text-delta': {
|
|
37
|
+
const text = typeof part.text === 'string' ? part.text : part.delta;
|
|
38
|
+
if (typeof text === 'string' && text) {
|
|
39
|
+
return { role: 'assistant', source: 'provider', contentDelta: text };
|
|
40
40
|
}
|
|
41
41
|
return null;
|
|
42
|
+
}
|
|
43
|
+
case 'reasoning-delta': {
|
|
44
|
+
const text = typeof part.text === 'string' ? part.text : part.delta;
|
|
45
|
+
if (typeof text === 'string' && text) {
|
|
46
|
+
return { role: 'assistant', source: 'provider', reasoningDelta: text };
|
|
47
|
+
}
|
|
48
|
+
return null;
|
|
49
|
+
}
|
|
42
50
|
case 'tool-call':
|
|
43
51
|
return {
|
|
44
52
|
role: 'assistant',
|
|
@@ -51,6 +59,7 @@ export function mapAiSdkStreamPartToChunk(part) {
|
|
|
51
59
|
name: part.toolName || 'unknown',
|
|
52
60
|
arguments: JSON.stringify(normalizeToolInput(part.input ?? {})),
|
|
53
61
|
},
|
|
62
|
+
...(part.providerMetadata ? { providerMetadata: part.providerMetadata } : {}),
|
|
54
63
|
},
|
|
55
64
|
],
|
|
56
65
|
};
|
package/dist/core/llm/utils.js
CHANGED
|
@@ -10,32 +10,22 @@ export function formatContextForPrompt(context, options = {}) {
|
|
|
10
10
|
}
|
|
11
11
|
return formatContextForXmlPrompt(context);
|
|
12
12
|
}
|
|
13
|
-
export function
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
try {
|
|
18
|
-
return JSON.parse(jsonBlockMatch[1]);
|
|
19
|
-
}
|
|
20
|
-
catch (__e) {
|
|
21
|
-
// Fallback to raw content if block is invalid
|
|
22
|
-
}
|
|
13
|
+
export function parsePlanFromLLMContent(content) {
|
|
14
|
+
const trimmed = String(content ?? '').trim();
|
|
15
|
+
if (!trimmed.startsWith('{') || !trimmed.endsWith('}')) {
|
|
16
|
+
throw new Error(text.llm.planInvalidJson);
|
|
23
17
|
}
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
try {
|
|
28
|
-
return JSON.parse(jsonMatch[0]);
|
|
29
|
-
}
|
|
30
|
-
catch (__e) {
|
|
31
|
-
// Fallback
|
|
32
|
-
}
|
|
18
|
+
let parsed;
|
|
19
|
+
try {
|
|
20
|
+
parsed = JSON.parse(trimmed);
|
|
33
21
|
}
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
|
|
22
|
+
catch {
|
|
23
|
+
throw new Error(text.llm.planInvalidJson);
|
|
24
|
+
}
|
|
25
|
+
if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {
|
|
26
|
+
throw new Error(text.llm.planInvalidJson);
|
|
27
|
+
}
|
|
28
|
+
const plan = parsed;
|
|
39
29
|
if (!plan.goal || !Array.isArray(plan.files) || !Array.isArray(plan.changes) || !plan.verify) {
|
|
40
30
|
throw new Error(text.llm.planInvalid);
|
|
41
31
|
}
|
|
@@ -46,10 +36,9 @@ export function extractUnifiedDiffFromLLMContent(content) {
|
|
|
46
36
|
throw wrapPatchEmpty();
|
|
47
37
|
}
|
|
48
38
|
const looksLikeUnifiedDiff = (text) => {
|
|
49
|
-
return /^\s*
|
|
39
|
+
return /^\s*diff --git /m.test(text);
|
|
50
40
|
};
|
|
51
|
-
// 1) Prefer fenced code blocks and always pick the LAST diff
|
|
52
|
-
// Accept both git-style (`diff --git`) and minimal unified diffs (`--- a/...` + `+++ b/...`).
|
|
41
|
+
// 1) Prefer fenced code blocks and always pick the LAST canonical diff block (LLM may generate multiple attempts).
|
|
53
42
|
const fencedBlocks = [];
|
|
54
43
|
const fenceRegex = /```(?:diff)?\s*\n([\s\S]*?)\n```/gi;
|
|
55
44
|
let fenceMatch = null;
|
|
@@ -62,10 +51,10 @@ export function extractUnifiedDiffFromLLMContent(content) {
|
|
|
62
51
|
if (fencedBlocks.length > 0) {
|
|
63
52
|
return fencedBlocks[fencedBlocks.length - 1].trim();
|
|
64
53
|
}
|
|
65
|
-
// 2) Raw diff without markdown: keep the first diff
|
|
54
|
+
// 2) Raw diff without markdown: keep the first canonical diff section.
|
|
66
55
|
// In "pure diff" mode, LLMs typically return only the patch, so selecting the first marker
|
|
67
56
|
// avoids accidentally dropping the leading `diff --git` header.
|
|
68
|
-
const rawStart = content.search(/^\s*
|
|
57
|
+
const rawStart = content.search(/^\s*diff --git /m);
|
|
69
58
|
if (rawStart !== -1)
|
|
70
59
|
return content.slice(rawStart).trim();
|
|
71
60
|
// Final fallback: original simple cleanup
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
import { extractKeywords } from '../context/keywords.js';
|
|
2
|
+
const DEFAULT_MAX_ITEMS = 3;
|
|
3
|
+
const DEFAULT_MAX_SUMMARY_CHARS = 220;
|
|
4
|
+
function trimToUndefined(value) {
|
|
5
|
+
if (typeof value !== 'string')
|
|
6
|
+
return undefined;
|
|
7
|
+
const trimmed = value.trim();
|
|
8
|
+
return trimmed ? trimmed : undefined;
|
|
9
|
+
}
|
|
10
|
+
function clampText(value, maxChars) {
|
|
11
|
+
if (value.length <= maxChars)
|
|
12
|
+
return value;
|
|
13
|
+
return `${value.slice(0, Math.max(0, maxChars - 1)).trimEnd()}…`;
|
|
14
|
+
}
|
|
15
|
+
function normalizeCandidate(candidate, maxSummaryChars) {
|
|
16
|
+
const path = trimToUndefined(candidate.path);
|
|
17
|
+
const title = trimToUndefined(candidate.title);
|
|
18
|
+
const summary = trimToUndefined(candidate.summary);
|
|
19
|
+
if (!path || !title || !summary)
|
|
20
|
+
return undefined;
|
|
21
|
+
const tags = Array.isArray(candidate.tags)
|
|
22
|
+
? candidate.tags
|
|
23
|
+
.map((tag) => trimToUndefined(tag)?.toLowerCase())
|
|
24
|
+
.filter((tag) => Boolean(tag))
|
|
25
|
+
: undefined;
|
|
26
|
+
return {
|
|
27
|
+
path,
|
|
28
|
+
title,
|
|
29
|
+
summary: clampText(summary, maxSummaryChars),
|
|
30
|
+
tags,
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
function buildAlreadySurfacedHaystack(values) {
|
|
34
|
+
return (values ?? []).join('\n').toLowerCase();
|
|
35
|
+
}
|
|
36
|
+
function hasToolConflict(candidate, activeToolNames) {
|
|
37
|
+
const toolTags = (candidate.tags ?? []).filter((tag) => tag.startsWith('tool:'));
|
|
38
|
+
if (toolTags.length === 0)
|
|
39
|
+
return false;
|
|
40
|
+
const active = new Set(activeToolNames.map((name) => name.trim().toLowerCase()).filter(Boolean));
|
|
41
|
+
if (active.size === 0)
|
|
42
|
+
return false;
|
|
43
|
+
return toolTags.some((tag) => active.has(tag.slice('tool:'.length)));
|
|
44
|
+
}
|
|
45
|
+
function computeCandidateScore(candidate, keywords) {
|
|
46
|
+
if (keywords.length === 0)
|
|
47
|
+
return 0;
|
|
48
|
+
const pathLower = candidate.path.toLowerCase();
|
|
49
|
+
const titleLower = candidate.title.toLowerCase();
|
|
50
|
+
const summaryLower = candidate.summary.toLowerCase();
|
|
51
|
+
const tagsLower = candidate.tags ?? [];
|
|
52
|
+
let score = 0;
|
|
53
|
+
for (const keyword of keywords) {
|
|
54
|
+
const normalized = keyword.trim().toLowerCase();
|
|
55
|
+
if (!normalized)
|
|
56
|
+
continue;
|
|
57
|
+
if (pathLower.includes(normalized))
|
|
58
|
+
score += 6;
|
|
59
|
+
if (titleLower.includes(normalized))
|
|
60
|
+
score += 5;
|
|
61
|
+
if (summaryLower.includes(normalized))
|
|
62
|
+
score += 4;
|
|
63
|
+
if (tagsLower.some((tag) => tag.includes(normalized)))
|
|
64
|
+
score += 3;
|
|
65
|
+
}
|
|
66
|
+
return score;
|
|
67
|
+
}
|
|
68
|
+
export function buildRelevantMemoryCandidates(context) {
|
|
69
|
+
const candidates = [];
|
|
70
|
+
const knowledge = context.knowledgeBase;
|
|
71
|
+
const metadata = context.projectMetadata;
|
|
72
|
+
if (Array.isArray(knowledge?.project_rules) && knowledge.project_rules.length > 0) {
|
|
73
|
+
candidates.push({
|
|
74
|
+
path: '.salmonloop/knowledge/project_rules',
|
|
75
|
+
title: 'Project rules',
|
|
76
|
+
summary: knowledge.project_rules.join('; '),
|
|
77
|
+
tags: ['rules', 'project'],
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
if (trimToUndefined(knowledge?.user_preferences)) {
|
|
81
|
+
candidates.push({
|
|
82
|
+
path: '.salmonloop/knowledge/user_preferences',
|
|
83
|
+
title: 'User preferences',
|
|
84
|
+
summary: knowledge.user_preferences,
|
|
85
|
+
tags: ['preferences', 'user'],
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
for (const [index, decision] of (knowledge?.architectural_decisions ?? []).entries()) {
|
|
89
|
+
const summary = trimToUndefined(decision?.decision);
|
|
90
|
+
if (!summary)
|
|
91
|
+
continue;
|
|
92
|
+
candidates.push({
|
|
93
|
+
path: `.salmonloop/knowledge/architectural_decisions/${index + 1}`,
|
|
94
|
+
title: `Architectural decision ${index + 1}`,
|
|
95
|
+
summary,
|
|
96
|
+
tags: ['architecture', ...(decision.related_files ?? []).map((file) => file.toLowerCase())],
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
if (trimToUndefined(metadata?.aiInstructions)) {
|
|
100
|
+
candidates.push({
|
|
101
|
+
path: '.salmonloop/project/ai-instructions',
|
|
102
|
+
title: 'Project AI instructions',
|
|
103
|
+
summary: metadata.aiInstructions,
|
|
104
|
+
tags: ['instructions', 'project'],
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
return candidates;
|
|
108
|
+
}
|
|
109
|
+
export function selectRelevantMemory(args) {
|
|
110
|
+
const maxItems = Math.max(1, Math.floor(args.maxItems ?? DEFAULT_MAX_ITEMS));
|
|
111
|
+
const maxSummaryChars = Math.max(48, Math.floor(args.maxSummaryChars ?? DEFAULT_MAX_SUMMARY_CHARS));
|
|
112
|
+
const haystack = buildAlreadySurfacedHaystack(args.alreadySurfacedText);
|
|
113
|
+
const activeToolNames = args.activeToolNames ?? [];
|
|
114
|
+
const keywords = extractKeywords(args.instruction ?? '');
|
|
115
|
+
const deduped = new Map();
|
|
116
|
+
for (const rawCandidate of args.candidates) {
|
|
117
|
+
const candidate = normalizeCandidate(rawCandidate, maxSummaryChars);
|
|
118
|
+
if (!candidate)
|
|
119
|
+
continue;
|
|
120
|
+
if (deduped.has(candidate.path))
|
|
121
|
+
continue;
|
|
122
|
+
if (haystack.includes(candidate.path.toLowerCase()) ||
|
|
123
|
+
haystack.includes(candidate.title.toLowerCase()) ||
|
|
124
|
+
haystack.includes(candidate.summary.toLowerCase())) {
|
|
125
|
+
continue;
|
|
126
|
+
}
|
|
127
|
+
if (hasToolConflict(candidate, activeToolNames))
|
|
128
|
+
continue;
|
|
129
|
+
deduped.set(candidate.path, candidate);
|
|
130
|
+
}
|
|
131
|
+
const scored = [...deduped.values()].map((candidate) => ({
|
|
132
|
+
candidate,
|
|
133
|
+
score: computeCandidateScore(candidate, keywords),
|
|
134
|
+
}));
|
|
135
|
+
const ranked = scored
|
|
136
|
+
.filter((entry) => entry.score > 0 || keywords.length === 0)
|
|
137
|
+
.sort((left, right) => {
|
|
138
|
+
if (left.score !== right.score)
|
|
139
|
+
return right.score - left.score;
|
|
140
|
+
return left.candidate.path.localeCompare(right.candidate.path);
|
|
141
|
+
});
|
|
142
|
+
return ranked.slice(0, maxItems).map((entry) => entry.candidate);
|
|
143
|
+
}
|
|
144
|
+
//# sourceMappingURL=relevant-retrieval.js.map
|
|
@@ -3,6 +3,17 @@ import { FileAdapter } from '../adapters/fs/index.js';
|
|
|
3
3
|
import { sanitizeObject, sanitizeErrorMessage } from '../utils/sanitizer.js';
|
|
4
4
|
import { recordAuditEvent } from './audit-trail.js';
|
|
5
5
|
import { mapErrorForDisplay } from './error-mapping.js';
|
|
6
|
+
/**
|
|
7
|
+
* Reporter for machine-readable modes where stdout/stderr are protocol channels.
|
|
8
|
+
*/
|
|
9
|
+
export class SilentReporter {
|
|
10
|
+
log(_level, _message, _metadata) {
|
|
11
|
+
// Intentionally empty.
|
|
12
|
+
}
|
|
13
|
+
clear() {
|
|
14
|
+
// Intentionally empty.
|
|
15
|
+
}
|
|
16
|
+
}
|
|
6
17
|
/**
|
|
7
18
|
* Standard Console Reporter
|
|
8
19
|
*/
|
|
@@ -418,8 +429,6 @@ export class Logger {
|
|
|
418
429
|
const auditMeta = typeof meta === 'string' ? { source: meta } : meta;
|
|
419
430
|
recordAuditEvent(action, sanitizedDetails, auditMeta);
|
|
420
431
|
this.writeToLog('audit', formatted);
|
|
421
|
-
if (!this.silent)
|
|
422
|
-
this.reporter.log('audit', formatted);
|
|
423
432
|
}
|
|
424
433
|
sanitizeLogMessage(message) {
|
|
425
434
|
let result = '';
|