@burtson-labs/agent-core 1.6.13
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/LICENSE +201 -0
- package/README.md +88 -0
- package/dist/index.d.ts +16 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +52 -0
- package/dist/index.js.map +1 -0
- package/dist/mcp/activation.d.ts +60 -0
- package/dist/mcp/activation.d.ts.map +1 -0
- package/dist/mcp/activation.js +139 -0
- package/dist/mcp/activation.js.map +1 -0
- package/dist/mcp/clientPool.d.ts +202 -0
- package/dist/mcp/clientPool.d.ts.map +1 -0
- package/dist/mcp/clientPool.js +469 -0
- package/dist/mcp/clientPool.js.map +1 -0
- package/dist/mcp/index.d.ts +18 -0
- package/dist/mcp/index.d.ts.map +1 -0
- package/dist/mcp/index.js +28 -0
- package/dist/mcp/index.js.map +1 -0
- package/dist/mcp/server.d.ts +43 -0
- package/dist/mcp/server.d.ts.map +1 -0
- package/dist/mcp/server.js +130 -0
- package/dist/mcp/server.js.map +1 -0
- package/dist/mcp/toolAdapter.d.ts +57 -0
- package/dist/mcp/toolAdapter.d.ts.map +1 -0
- package/dist/mcp/toolAdapter.js +223 -0
- package/dist/mcp/toolAdapter.js.map +1 -0
- package/dist/mcp/types.d.ts +122 -0
- package/dist/mcp/types.d.ts.map +1 -0
- package/dist/mcp/types.js +15 -0
- package/dist/mcp/types.js.map +1 -0
- package/dist/providers/deterministic-provider.d.ts +21 -0
- package/dist/providers/deterministic-provider.d.ts.map +1 -0
- package/dist/providers/deterministic-provider.js +80 -0
- package/dist/providers/deterministic-provider.js.map +1 -0
- package/dist/providers/provider-client.d.ts +12 -0
- package/dist/providers/provider-client.d.ts.map +1 -0
- package/dist/providers/provider-client.js +11 -0
- package/dist/providers/provider-client.js.map +1 -0
- package/dist/runtime/AgentRuntime.d.ts +67 -0
- package/dist/runtime/AgentRuntime.d.ts.map +1 -0
- package/dist/runtime/AgentRuntime.js +382 -0
- package/dist/runtime/AgentRuntime.js.map +1 -0
- package/dist/security/secretPatterns.d.ts +76 -0
- package/dist/security/secretPatterns.d.ts.map +1 -0
- package/dist/security/secretPatterns.js +290 -0
- package/dist/security/secretPatterns.js.map +1 -0
- package/dist/tools/ask-user-tool.d.ts +19 -0
- package/dist/tools/ask-user-tool.d.ts.map +1 -0
- package/dist/tools/ask-user-tool.js +148 -0
- package/dist/tools/ask-user-tool.js.map +1 -0
- package/dist/tools/compactMessages.d.ts +52 -0
- package/dist/tools/compactMessages.d.ts.map +1 -0
- package/dist/tools/compactMessages.js +158 -0
- package/dist/tools/compactMessages.js.map +1 -0
- package/dist/tools/core-tools.d.ts +29 -0
- package/dist/tools/core-tools.d.ts.map +1 -0
- package/dist/tools/core-tools.js +2214 -0
- package/dist/tools/core-tools.js.map +1 -0
- package/dist/tools/git-tools.d.ts +32 -0
- package/dist/tools/git-tools.d.ts.map +1 -0
- package/dist/tools/git-tools.js +330 -0
- package/dist/tools/git-tools.js.map +1 -0
- package/dist/tools/index.d.ts +15 -0
- package/dist/tools/index.d.ts.map +1 -0
- package/dist/tools/index.js +31 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/tools/language-adapters.d.ts +48 -0
- package/dist/tools/language-adapters.d.ts.map +1 -0
- package/dist/tools/language-adapters.js +299 -0
- package/dist/tools/language-adapters.js.map +1 -0
- package/dist/tools/loop/compactionTrigger.d.ts +47 -0
- package/dist/tools/loop/compactionTrigger.d.ts.map +1 -0
- package/dist/tools/loop/compactionTrigger.js +32 -0
- package/dist/tools/loop/compactionTrigger.js.map +1 -0
- package/dist/tools/loop/finalAnswerNudges.d.ts +68 -0
- package/dist/tools/loop/finalAnswerNudges.d.ts.map +1 -0
- package/dist/tools/loop/finalAnswerNudges.js +87 -0
- package/dist/tools/loop/finalAnswerNudges.js.map +1 -0
- package/dist/tools/loop/goalAnchor.d.ts +72 -0
- package/dist/tools/loop/goalAnchor.d.ts.map +1 -0
- package/dist/tools/loop/goalAnchor.js +76 -0
- package/dist/tools/loop/goalAnchor.js.map +1 -0
- package/dist/tools/loop/llmStream.d.ts +70 -0
- package/dist/tools/loop/llmStream.d.ts.map +1 -0
- package/dist/tools/loop/llmStream.js +181 -0
- package/dist/tools/loop/llmStream.js.map +1 -0
- package/dist/tools/loop/parallelExecute.d.ts +57 -0
- package/dist/tools/loop/parallelExecute.d.ts.map +1 -0
- package/dist/tools/loop/parallelExecute.js +54 -0
- package/dist/tools/loop/parallelExecute.js.map +1 -0
- package/dist/tools/loop/singleToolExecute.d.ts +71 -0
- package/dist/tools/loop/singleToolExecute.d.ts.map +1 -0
- package/dist/tools/loop/singleToolExecute.js +139 -0
- package/dist/tools/loop/singleToolExecute.js.map +1 -0
- package/dist/tools/loop/toolCallNormalize.d.ts +57 -0
- package/dist/tools/loop/toolCallNormalize.d.ts.map +1 -0
- package/dist/tools/loop/toolCallNormalize.js +99 -0
- package/dist/tools/loop/toolCallNormalize.js.map +1 -0
- package/dist/tools/loop/turnSetup.d.ts +43 -0
- package/dist/tools/loop/turnSetup.d.ts.map +1 -0
- package/dist/tools/loop/turnSetup.js +48 -0
- package/dist/tools/loop/turnSetup.js.map +1 -0
- package/dist/tools/ocr.d.ts +52 -0
- package/dist/tools/ocr.d.ts.map +1 -0
- package/dist/tools/ocr.js +238 -0
- package/dist/tools/ocr.js.map +1 -0
- package/dist/tools/post-edit-checks.d.ts +46 -0
- package/dist/tools/post-edit-checks.d.ts.map +1 -0
- package/dist/tools/post-edit-checks.js +236 -0
- package/dist/tools/post-edit-checks.js.map +1 -0
- package/dist/tools/skill-loader.d.ts +94 -0
- package/dist/tools/skill-loader.d.ts.map +1 -0
- package/dist/tools/skill-loader.js +422 -0
- package/dist/tools/skill-loader.js.map +1 -0
- package/dist/tools/skill-registry.d.ts +44 -0
- package/dist/tools/skill-registry.d.ts.map +1 -0
- package/dist/tools/skill-registry.js +118 -0
- package/dist/tools/skill-registry.js.map +1 -0
- package/dist/tools/skill-types.d.ts +38 -0
- package/dist/tools/skill-types.d.ts.map +1 -0
- package/dist/tools/skill-types.js +10 -0
- package/dist/tools/skill-types.js.map +1 -0
- package/dist/tools/skills/code-review-skill.d.ts +9 -0
- package/dist/tools/skills/code-review-skill.d.ts.map +1 -0
- package/dist/tools/skills/code-review-skill.js +66 -0
- package/dist/tools/skills/code-review-skill.js.map +1 -0
- package/dist/tools/skills/core-skill.d.ts +13 -0
- package/dist/tools/skills/core-skill.d.ts.map +1 -0
- package/dist/tools/skills/core-skill.js +23 -0
- package/dist/tools/skills/core-skill.js.map +1 -0
- package/dist/tools/skills/git-skill.d.ts +10 -0
- package/dist/tools/skills/git-skill.d.ts.map +1 -0
- package/dist/tools/skills/git-skill.js +30 -0
- package/dist/tools/skills/git-skill.js.map +1 -0
- package/dist/tools/skills/index.d.ts +17 -0
- package/dist/tools/skills/index.d.ts.map +1 -0
- package/dist/tools/skills/index.js +49 -0
- package/dist/tools/skills/index.js.map +1 -0
- package/dist/tools/skills/interaction-skill.d.ts +14 -0
- package/dist/tools/skills/interaction-skill.d.ts.map +1 -0
- package/dist/tools/skills/interaction-skill.js +24 -0
- package/dist/tools/skills/interaction-skill.js.map +1 -0
- package/dist/tools/skills/mail-search-skill.d.ts +25 -0
- package/dist/tools/skills/mail-search-skill.d.ts.map +1 -0
- package/dist/tools/skills/mail-search-skill.js +343 -0
- package/dist/tools/skills/mail-search-skill.js.map +1 -0
- package/dist/tools/skills/plan-skill.d.ts +10 -0
- package/dist/tools/skills/plan-skill.d.ts.map +1 -0
- package/dist/tools/skills/plan-skill.js +126 -0
- package/dist/tools/skills/plan-skill.js.map +1 -0
- package/dist/tools/skills/semantic-search-skill.d.ts +22 -0
- package/dist/tools/skills/semantic-search-skill.d.ts.map +1 -0
- package/dist/tools/skills/semantic-search-skill.js +244 -0
- package/dist/tools/skills/semantic-search-skill.js.map +1 -0
- package/dist/tools/skills/test-gen-skill.d.ts +9 -0
- package/dist/tools/skills/test-gen-skill.d.ts.map +1 -0
- package/dist/tools/skills/test-gen-skill.js +123 -0
- package/dist/tools/skills/test-gen-skill.js.map +1 -0
- package/dist/tools/tool-registry.d.ts +60 -0
- package/dist/tools/tool-registry.d.ts.map +1 -0
- package/dist/tools/tool-registry.js +200 -0
- package/dist/tools/tool-registry.js.map +1 -0
- package/dist/tools/tool-types.d.ts +281 -0
- package/dist/tools/tool-types.d.ts.map +1 -0
- package/dist/tools/tool-types.js +10 -0
- package/dist/tools/tool-types.js.map +1 -0
- package/dist/tools/tool-use-loop.d.ts +231 -0
- package/dist/tools/tool-use-loop.d.ts.map +1 -0
- package/dist/tools/tool-use-loop.js +2057 -0
- package/dist/tools/tool-use-loop.js.map +1 -0
- package/dist/tools/tool-use-parser.d.ts +78 -0
- package/dist/tools/tool-use-parser.d.ts.map +1 -0
- package/dist/tools/tool-use-parser.js +427 -0
- package/dist/tools/tool-use-parser.js.map +1 -0
- package/dist/tools/toolAvailabilityDetector.d.ts +48 -0
- package/dist/tools/toolAvailabilityDetector.d.ts.map +1 -0
- package/dist/tools/toolAvailabilityDetector.js +156 -0
- package/dist/tools/toolAvailabilityDetector.js.map +1 -0
- package/dist/tools/unified-patch.d.ts +87 -0
- package/dist/tools/unified-patch.d.ts.map +1 -0
- package/dist/tools/unified-patch.js +217 -0
- package/dist/tools/unified-patch.js.map +1 -0
- package/dist/types/agent.d.ts +69 -0
- package/dist/types/agent.d.ts.map +1 -0
- package/dist/types/agent.js +54 -0
- package/dist/types/agent.js.map +1 -0
- package/dist/types/tasks.d.ts +22 -0
- package/dist/types/tasks.d.ts.map +1 -0
- package/dist/types/tasks.js +3 -0
- package/dist/types/tasks.js.map +1 -0
- package/dist/utils/event-emitter.d.ts +13 -0
- package/dist/utils/event-emitter.d.ts.map +1 -0
- package/dist/utils/event-emitter.js +54 -0
- package/dist/utils/event-emitter.js.map +1 -0
- package/package.json +33 -0
|
@@ -0,0 +1,382 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.AgentRuntime = void 0;
|
|
4
|
+
const event_emitter_1 = require("../utils/event-emitter");
|
|
5
|
+
const defaultLogger = {
|
|
6
|
+
debug: (...args) => {
|
|
7
|
+
const env = typeof process !== "undefined" ? process.env : undefined;
|
|
8
|
+
if (env?.BANDIT_AGENT_DEBUG) {
|
|
9
|
+
console.debug("[agent-core]", ...args);
|
|
10
|
+
}
|
|
11
|
+
},
|
|
12
|
+
info: (...args) => console.info("[agent-core]", ...args),
|
|
13
|
+
warn: (...args) => console.warn("[agent-core]", ...args),
|
|
14
|
+
error: (...args) => console.error("[agent-core]", ...args)
|
|
15
|
+
};
|
|
16
|
+
const defaultStepExecutor = async ({ step }) => {
|
|
17
|
+
return {
|
|
18
|
+
status: step.status === "failed" ? "failed" : "completed",
|
|
19
|
+
logs: [`No-op executor completed step "${step.title}".`]
|
|
20
|
+
};
|
|
21
|
+
};
|
|
22
|
+
class AgentRuntime extends event_emitter_1.AgentEventEmitter {
|
|
23
|
+
constructor(options) {
|
|
24
|
+
super();
|
|
25
|
+
this.activePlan = null;
|
|
26
|
+
this.executionResults = [];
|
|
27
|
+
this.planStartedAt = null;
|
|
28
|
+
this.executeStartedAt = null;
|
|
29
|
+
this.provider = options.provider;
|
|
30
|
+
this.context =
|
|
31
|
+
options.context ??
|
|
32
|
+
{
|
|
33
|
+
files: [],
|
|
34
|
+
goals: []
|
|
35
|
+
};
|
|
36
|
+
this.logger = options.logger ?? defaultLogger;
|
|
37
|
+
this.telemetry = options.telemetry;
|
|
38
|
+
this.clock = options.clock ?? (() => Date.now());
|
|
39
|
+
this.configuredStepExecutor = options.stepExecutor;
|
|
40
|
+
}
|
|
41
|
+
getContext() {
|
|
42
|
+
return this.context;
|
|
43
|
+
}
|
|
44
|
+
setContext(context) {
|
|
45
|
+
this.context = context;
|
|
46
|
+
this.emitAgentEvent("context:updated", { context });
|
|
47
|
+
}
|
|
48
|
+
updateContext(patch) {
|
|
49
|
+
this.context = { ...this.context, ...patch };
|
|
50
|
+
this.emitAgentEvent("context:updated", { context: this.context });
|
|
51
|
+
}
|
|
52
|
+
getPlan() {
|
|
53
|
+
return this.activePlan;
|
|
54
|
+
}
|
|
55
|
+
getExecutionResults() {
|
|
56
|
+
return this.executionResults.slice();
|
|
57
|
+
}
|
|
58
|
+
async plan(goal, options = {}) {
|
|
59
|
+
this.logger.info("Starting plan for goal:", goal);
|
|
60
|
+
this.planStartedAt = this.clock();
|
|
61
|
+
this.executionResults = [];
|
|
62
|
+
const mergedContext = {
|
|
63
|
+
...this.context,
|
|
64
|
+
...options.context,
|
|
65
|
+
goals: Array.from(new Set([...(this.context.goals ?? []), goal]))
|
|
66
|
+
};
|
|
67
|
+
this.context = mergedContext;
|
|
68
|
+
this.emitAgentEvent("plan:start", { goal, context: mergedContext });
|
|
69
|
+
const modelTier = options.metadata?.modelTier;
|
|
70
|
+
const prompt = buildPlanPrompt(goal, mergedContext, modelTier);
|
|
71
|
+
const providerOptions = {
|
|
72
|
+
mode: "plan",
|
|
73
|
+
metadata: options.metadata,
|
|
74
|
+
context: mergedContext
|
|
75
|
+
};
|
|
76
|
+
const stream = this.provider.chat(prompt, providerOptions);
|
|
77
|
+
let aggregated = "";
|
|
78
|
+
for await (const chunk of stream) {
|
|
79
|
+
aggregated += chunk;
|
|
80
|
+
this.emitAgentEvent("plan:chunk", { chunk });
|
|
81
|
+
}
|
|
82
|
+
let plan = tryParsePlan(aggregated, goal, this.clock);
|
|
83
|
+
// If plan parsing failed (version "0.1.0" = fallback), retry once with schema reminder
|
|
84
|
+
if (plan.version === "0.1.0") {
|
|
85
|
+
this.logger.warn("Plan parse failed on first attempt — retrying with schema reminder.");
|
|
86
|
+
this.emitAgentEvent("plan:parse_retry", { goal, rawResponse: aggregated });
|
|
87
|
+
const retryPrompt = buildPlanPromptWithReminder(goal, mergedContext, aggregated, modelTier);
|
|
88
|
+
const retryStream = this.provider.chat(retryPrompt, providerOptions);
|
|
89
|
+
let retryAggregated = "";
|
|
90
|
+
for await (const chunk of retryStream) {
|
|
91
|
+
retryAggregated += chunk;
|
|
92
|
+
this.emitAgentEvent("plan:chunk", { chunk });
|
|
93
|
+
}
|
|
94
|
+
const retryPlan = tryParsePlan(retryAggregated, goal, this.clock);
|
|
95
|
+
if (retryPlan.version !== "0.1.0") {
|
|
96
|
+
plan = retryPlan;
|
|
97
|
+
}
|
|
98
|
+
else {
|
|
99
|
+
this.logger.error("Plan parse failed after retry. Using heuristic fallback.");
|
|
100
|
+
this.emitAgentEvent("plan:parse_failed", {
|
|
101
|
+
goal,
|
|
102
|
+
rawResponse: retryAggregated,
|
|
103
|
+
error: "Model did not return valid JSON plan after 2 attempts."
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
this.activePlan = plan;
|
|
108
|
+
this.emitAgentEvent("plan:complete", { plan });
|
|
109
|
+
await this.trackTelemetry("plan:complete", { goal, provider: this.provider.name });
|
|
110
|
+
return plan;
|
|
111
|
+
}
|
|
112
|
+
async execute(options = {}) {
|
|
113
|
+
if (!this.activePlan) {
|
|
114
|
+
throw new Error("Cannot execute without an existing plan. Call plan() first.");
|
|
115
|
+
}
|
|
116
|
+
this.executeStartedAt = this.clock();
|
|
117
|
+
this.executionResults = [];
|
|
118
|
+
const executor = options.stepExecutor ?? this.configuredStepExecutor ?? defaultStepExecutor;
|
|
119
|
+
const results = [];
|
|
120
|
+
for (const step of this.activePlan.steps) {
|
|
121
|
+
const start = this.clock();
|
|
122
|
+
this.emitAgentEvent("step:start", { step });
|
|
123
|
+
this.logger.info(`Executing step ${step.id}: ${step.title}`);
|
|
124
|
+
let output;
|
|
125
|
+
try {
|
|
126
|
+
output = await executor({
|
|
127
|
+
step,
|
|
128
|
+
plan: this.activePlan,
|
|
129
|
+
context: this.context,
|
|
130
|
+
metadata: options.metadata,
|
|
131
|
+
emitEvent: (type, payload) => this.emitAgentEvent(type, payload),
|
|
132
|
+
logger: this.logger
|
|
133
|
+
});
|
|
134
|
+
}
|
|
135
|
+
catch (error) {
|
|
136
|
+
this.logger.error(`Step ${step.id} failed`, error);
|
|
137
|
+
output = {
|
|
138
|
+
status: "failed",
|
|
139
|
+
logs: [String(error instanceof Error ? error.message : error)]
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
const status = output.status ?? "completed";
|
|
143
|
+
const executionResult = {
|
|
144
|
+
stepId: step.id,
|
|
145
|
+
status,
|
|
146
|
+
diff: output.diff,
|
|
147
|
+
logs: output.logs,
|
|
148
|
+
metadata: {
|
|
149
|
+
...(output.metadata ?? {}),
|
|
150
|
+
durationMs: this.clock() - start
|
|
151
|
+
}
|
|
152
|
+
};
|
|
153
|
+
results.push(executionResult);
|
|
154
|
+
this.executionResults.push(executionResult);
|
|
155
|
+
if (executionResult.diff?.length) {
|
|
156
|
+
this.emitAgentEvent("diff:apply", { step, diff: executionResult.diff });
|
|
157
|
+
}
|
|
158
|
+
this.emitAgentEvent("step:complete", { step, result: executionResult });
|
|
159
|
+
}
|
|
160
|
+
await this.trackTelemetry("execute:complete", {
|
|
161
|
+
planId: this.activePlan.id,
|
|
162
|
+
provider: this.provider.name,
|
|
163
|
+
results
|
|
164
|
+
});
|
|
165
|
+
return results;
|
|
166
|
+
}
|
|
167
|
+
async report(metadata = {}) {
|
|
168
|
+
if (!this.activePlan) {
|
|
169
|
+
throw new Error("Cannot report without a plan. Call plan() before report().");
|
|
170
|
+
}
|
|
171
|
+
const startedAt = this.planStartedAt ?? this.clock();
|
|
172
|
+
const completedAt = this.clock();
|
|
173
|
+
const providerStream = this.provider.chat(buildReportPrompt(this.activePlan, this.executionResults), {
|
|
174
|
+
mode: "report",
|
|
175
|
+
metadata,
|
|
176
|
+
context: this.context
|
|
177
|
+
});
|
|
178
|
+
let summary = "";
|
|
179
|
+
for await (const chunk of providerStream) {
|
|
180
|
+
summary += chunk;
|
|
181
|
+
this.emitAgentEvent("report:chunk", { chunk });
|
|
182
|
+
}
|
|
183
|
+
if (!summary.trim()) {
|
|
184
|
+
summary = `Report for goal "${this.activePlan.goal}" generated without provider output.`;
|
|
185
|
+
}
|
|
186
|
+
const report = {
|
|
187
|
+
goal: this.activePlan.goal,
|
|
188
|
+
summary,
|
|
189
|
+
steps: this.executionResults,
|
|
190
|
+
startedAt,
|
|
191
|
+
completedAt,
|
|
192
|
+
metadata: {
|
|
193
|
+
...metadata,
|
|
194
|
+
provider: this.provider.name
|
|
195
|
+
}
|
|
196
|
+
};
|
|
197
|
+
this.emitAgentEvent("report:complete", { report });
|
|
198
|
+
await this.trackTelemetry("report:complete", { goal: this.activePlan.goal });
|
|
199
|
+
return report;
|
|
200
|
+
}
|
|
201
|
+
emitAgentEvent(type, payload) {
|
|
202
|
+
const event = {
|
|
203
|
+
type,
|
|
204
|
+
payload,
|
|
205
|
+
timestamp: this.clock()
|
|
206
|
+
};
|
|
207
|
+
this.emit(type, event);
|
|
208
|
+
}
|
|
209
|
+
async trackTelemetry(type, payload) {
|
|
210
|
+
const event = {
|
|
211
|
+
type,
|
|
212
|
+
payload,
|
|
213
|
+
timestamp: this.clock()
|
|
214
|
+
};
|
|
215
|
+
try {
|
|
216
|
+
await this.telemetry?.track(event);
|
|
217
|
+
}
|
|
218
|
+
catch (error) {
|
|
219
|
+
this.logger.warn("Telemetry dispatch failed", error);
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
exports.AgentRuntime = AgentRuntime;
|
|
224
|
+
function buildPlanPrompt(goal, context, modelTier) {
|
|
225
|
+
if (modelTier === "small") {
|
|
226
|
+
// Small / 4B models: minimal prompt — every token is precious and brevity
|
|
227
|
+
// reduces the chance of the model producing prose instead of JSON.
|
|
228
|
+
return [
|
|
229
|
+
"Respond with JSON only. Start with { and end with }. No other text.",
|
|
230
|
+
"",
|
|
231
|
+
'Schema: {"goal":string,"summary":string,"steps":[{"id":string,"title":string}]}',
|
|
232
|
+
"",
|
|
233
|
+
'Example: {"goal":"Fix login","summary":"Patch auth handler","steps":[{"id":"step-1","title":"Edit auth.ts"}]}',
|
|
234
|
+
"",
|
|
235
|
+
`Goal: ${goal}`,
|
|
236
|
+
].join("\n");
|
|
237
|
+
}
|
|
238
|
+
// Medium / large models: fuller prompt with description field and file context.
|
|
239
|
+
const fileLimit = modelTier === "large" ? 8 : 5;
|
|
240
|
+
const files = context.files?.slice(0, fileLimit).join(", ") || "none";
|
|
241
|
+
return [
|
|
242
|
+
"You are Bandit Agent Runtime planner. Respond with JSON only — no markdown, no explanation.",
|
|
243
|
+
"",
|
|
244
|
+
"Return a JSON object exactly matching this schema:",
|
|
245
|
+
'{ "goal": string, "summary": string, "steps": [ { "id": string, "title": string, "description": string } ] }',
|
|
246
|
+
"",
|
|
247
|
+
"Example:",
|
|
248
|
+
'{ "goal": "Add TypeScript support", "summary": "Install TS and create tsconfig", "steps": [',
|
|
249
|
+
' { "id": "step-1", "title": "Install TypeScript", "description": "Run npm install -D typescript" },',
|
|
250
|
+
' { "id": "step-2", "title": "Create tsconfig.json", "description": "Write default tsconfig" }',
|
|
251
|
+
"]}",
|
|
252
|
+
"",
|
|
253
|
+
`Goal: ${goal}`,
|
|
254
|
+
`Relevant files: ${files}`,
|
|
255
|
+
].join("\n");
|
|
256
|
+
}
|
|
257
|
+
function buildPlanPromptWithReminder(goal, context, previousResponse, modelTier) {
|
|
258
|
+
const snippet = previousResponse.slice(0, 200).replace(/\n/g, " ");
|
|
259
|
+
if (modelTier === "small") {
|
|
260
|
+
return [
|
|
261
|
+
"JSON only. No explanation. Your last response was not valid JSON.",
|
|
262
|
+
`Bad response: ${snippet}`,
|
|
263
|
+
"",
|
|
264
|
+
'Schema: {"goal":string,"summary":string,"steps":[{"id":string,"title":string}]}',
|
|
265
|
+
"",
|
|
266
|
+
`Goal: ${goal}`,
|
|
267
|
+
"Start with { and end with }",
|
|
268
|
+
].join("\n");
|
|
269
|
+
}
|
|
270
|
+
const fileLimit = modelTier === "large" ? 8 : 5;
|
|
271
|
+
const files = context.files?.slice(0, fileLimit).join(", ") || "none";
|
|
272
|
+
return [
|
|
273
|
+
"You are Bandit Agent Runtime planner. Your previous response was not valid JSON.",
|
|
274
|
+
`Previous response (first 200 chars): ${snippet}`,
|
|
275
|
+
"",
|
|
276
|
+
"You MUST respond with ONLY a JSON object. No markdown code fences. No explanation. No other text.",
|
|
277
|
+
"Required schema:",
|
|
278
|
+
'{ "goal": string, "summary": string, "steps": [ { "id": string, "title": string, "description": string } ] }',
|
|
279
|
+
"",
|
|
280
|
+
`Goal: ${goal}`,
|
|
281
|
+
`Relevant files: ${files}`,
|
|
282
|
+
"",
|
|
283
|
+
"JSON only. Start your response with { and end with }",
|
|
284
|
+
].join("\n");
|
|
285
|
+
}
|
|
286
|
+
function buildReportPrompt(plan, results) {
|
|
287
|
+
return [
|
|
288
|
+
"You are Bandit Agent Runtime reporter.",
|
|
289
|
+
"Generate a concise execution summary as markdown.",
|
|
290
|
+
"Focus on what changed and next steps.",
|
|
291
|
+
"Plan:",
|
|
292
|
+
JSON.stringify(plan, null, 2),
|
|
293
|
+
"Results:",
|
|
294
|
+
JSON.stringify(results, null, 2)
|
|
295
|
+
].join("\n");
|
|
296
|
+
}
|
|
297
|
+
/**
|
|
298
|
+
* Attempt to extract and parse a JSON plan from a raw LLM response.
|
|
299
|
+
* Handles: clean JSON, JSON wrapped in markdown code fences, JSON with leading/trailing text.
|
|
300
|
+
* Returns null on failure instead of silently falling back.
|
|
301
|
+
*/
|
|
302
|
+
function extractJsonFromResponse(raw) {
|
|
303
|
+
const trimmed = raw.trim();
|
|
304
|
+
// Direct JSON parse
|
|
305
|
+
try {
|
|
306
|
+
return JSON.parse(trimmed);
|
|
307
|
+
}
|
|
308
|
+
catch { /* continue */ }
|
|
309
|
+
// Strip markdown code fences: ```json ... ``` or ``` ... ```
|
|
310
|
+
const fenceMatch = trimmed.match(/```(?:json)?\s*([\s\S]*?)```/);
|
|
311
|
+
if (fenceMatch?.[1]) {
|
|
312
|
+
try {
|
|
313
|
+
return JSON.parse(fenceMatch[1].trim());
|
|
314
|
+
}
|
|
315
|
+
catch { /* continue */ }
|
|
316
|
+
}
|
|
317
|
+
// Find first { ... } block in the response
|
|
318
|
+
const jsonStart = trimmed.indexOf('{');
|
|
319
|
+
const jsonEnd = trimmed.lastIndexOf('}');
|
|
320
|
+
if (jsonStart !== -1 && jsonEnd > jsonStart) {
|
|
321
|
+
try {
|
|
322
|
+
return JSON.parse(trimmed.slice(jsonStart, jsonEnd + 1));
|
|
323
|
+
}
|
|
324
|
+
catch { /* continue */ }
|
|
325
|
+
}
|
|
326
|
+
return null;
|
|
327
|
+
}
|
|
328
|
+
function tryParsePlan(raw, goal, clock) {
|
|
329
|
+
const now = clock();
|
|
330
|
+
const parsed = extractJsonFromResponse(raw);
|
|
331
|
+
if (!parsed || typeof parsed !== "object" || !Array.isArray(parsed.steps)) {
|
|
332
|
+
return buildFallbackPlan(goal, now);
|
|
333
|
+
}
|
|
334
|
+
const data = parsed;
|
|
335
|
+
const steps = data.steps.map((step, index) => ({
|
|
336
|
+
id: step.id ?? `step-${index + 1}`,
|
|
337
|
+
title: step.title ?? `Step ${index + 1}`,
|
|
338
|
+
description: step.description ?? "",
|
|
339
|
+
status: step.status ?? "pending",
|
|
340
|
+
metadata: step.metadata
|
|
341
|
+
}));
|
|
342
|
+
return {
|
|
343
|
+
id: typeof data.id === "string" ? data.id : `plan-${now}`,
|
|
344
|
+
goal: typeof data.goal === "string" ? data.goal : goal,
|
|
345
|
+
summary: typeof data.summary === "string" ? data.summary : `Plan for goal: ${goal}`,
|
|
346
|
+
steps,
|
|
347
|
+
createdAt: now,
|
|
348
|
+
version: "1.0.0"
|
|
349
|
+
};
|
|
350
|
+
}
|
|
351
|
+
function buildFallbackPlan(goal, timestamp) {
|
|
352
|
+
const steps = heuristicallyBreakGoal(goal).map((description, index) => ({
|
|
353
|
+
id: `step-${index + 1}`,
|
|
354
|
+
title: titleCase(description),
|
|
355
|
+
description,
|
|
356
|
+
status: "pending"
|
|
357
|
+
}));
|
|
358
|
+
return {
|
|
359
|
+
id: `plan-${timestamp}`,
|
|
360
|
+
goal,
|
|
361
|
+
summary: `Fallback plan generated for goal: ${goal}`,
|
|
362
|
+
steps,
|
|
363
|
+
createdAt: timestamp,
|
|
364
|
+
version: "0.1.0"
|
|
365
|
+
};
|
|
366
|
+
}
|
|
367
|
+
function heuristicallyBreakGoal(goal) {
|
|
368
|
+
const delimiters = [/ and /i, / then /i, /, /, / -> /];
|
|
369
|
+
for (const delimiter of delimiters) {
|
|
370
|
+
if (delimiter.test(goal)) {
|
|
371
|
+
return goal.split(delimiter).map((part) => part.trim()).filter(Boolean);
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
return [goal];
|
|
375
|
+
}
|
|
376
|
+
function titleCase(input) {
|
|
377
|
+
return input
|
|
378
|
+
.split(" ")
|
|
379
|
+
.map((word) => word.charAt(0).toUpperCase() + word.slice(1))
|
|
380
|
+
.join(" ");
|
|
381
|
+
}
|
|
382
|
+
//# sourceMappingURL=AgentRuntime.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AgentRuntime.js","sourceRoot":"","sources":["../../src/runtime/AgentRuntime.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Secret-leak protection. Tool output (file reads, command
|
|
3
|
+
* stdout, search results) routinely surfaces API keys, OAuth tokens,
|
|
4
|
+
* and private keys when the user asks the agent to inspect dotfiles,
|
|
5
|
+
* environment variables, or anything else that touches credentials.
|
|
6
|
+
* Without redaction, those tokens land in:
|
|
7
|
+
*
|
|
8
|
+
* 1. The model's context window → the model may echo them in its
|
|
9
|
+
* next response, embed them in a tool call, or hallucinate
|
|
10
|
+
* surrounding prose that quotes them verbatim
|
|
11
|
+
* 2. The user's terminal → secrets sit in the scrollback,
|
|
12
|
+
* visible to over-shoulder readers and any screen-sharing flow
|
|
13
|
+
* 3. The session log on disk → ~/.bandit/sessions/*.jsonl
|
|
14
|
+
* persists raw secrets indefinitely, becoming a target if
|
|
15
|
+
* that file is ever shared (bug reports, etc.)
|
|
16
|
+
*
|
|
17
|
+
* The redactor is the single source of truth for "what looks like a
|
|
18
|
+
* secret." Patterns target high-confidence formats (known prefixes,
|
|
19
|
+
* stable lengths) — we deliberately do NOT redact generic
|
|
20
|
+
* high-entropy strings because false positives are corrosive (the
|
|
21
|
+
* agent loses the ability to reason about real data that happens to
|
|
22
|
+
* look secret-shaped).
|
|
23
|
+
*
|
|
24
|
+
* Each pattern has a `kind` label so the redaction replaces the match
|
|
25
|
+
* with a typed token like `<REDACTED:github-pat>` — preserves enough
|
|
26
|
+
* structure for the model (and the user) to understand what kind of
|
|
27
|
+
* thing was hidden without leaking the value.
|
|
28
|
+
*/
|
|
29
|
+
export interface SecretPattern {
|
|
30
|
+
/** Stable identifier used in the replacement token + telemetry. */
|
|
31
|
+
kind: string;
|
|
32
|
+
/** Human-readable label used in user-facing summaries. */
|
|
33
|
+
label: string;
|
|
34
|
+
/** Detection regex. MUST use the `g` flag (replace-all). */
|
|
35
|
+
re: RegExp;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Built-in secret patterns. Each entry is a high-confidence format with
|
|
39
|
+
* either a recognized prefix or a strict length/charset constraint.
|
|
40
|
+
*
|
|
41
|
+
* Order matters: longer / more-specific patterns must match BEFORE
|
|
42
|
+
* shorter / more-generic ones, otherwise a fine-grained PAT would be
|
|
43
|
+
* partially matched by the classic-PAT pattern. We rely on the regex
|
|
44
|
+
* engine matching in source order via the array iteration below.
|
|
45
|
+
*/
|
|
46
|
+
export declare const BUILTIN_SECRET_PATTERNS: SecretPattern[];
|
|
47
|
+
/**
|
|
48
|
+
* Result of a redaction pass. The text is the masked output; counts
|
|
49
|
+
* and kinds tell the host how many secrets were found so it can show
|
|
50
|
+
* a small "redacted N secrets" footer if it wants to.
|
|
51
|
+
*/
|
|
52
|
+
export interface RedactionResult {
|
|
53
|
+
text: string;
|
|
54
|
+
redactionCount: number;
|
|
55
|
+
/** Kinds detected, deduplicated. Order matches first-occurrence. */
|
|
56
|
+
kinds: string[];
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Apply all built-in patterns to a string. Replaces each match with
|
|
60
|
+
* `<REDACTED:{kind}>`. The replacement is intentionally short so the
|
|
61
|
+
* model can still reason about the surrounding text without burning
|
|
62
|
+
* context on long placeholder tokens.
|
|
63
|
+
*
|
|
64
|
+
* The `env-secret` pattern is special: it preserves the variable name
|
|
65
|
+
* and only redacts the value. So `GITHUB_TOKEN=ghp_abc...` becomes
|
|
66
|
+
* `GITHUB_TOKEN=<REDACTED:env-secret>` — the model can still see WHAT
|
|
67
|
+
* variable was set without seeing its value. For all other patterns
|
|
68
|
+
* the whole match is replaced.
|
|
69
|
+
*/
|
|
70
|
+
export declare function redactSecrets(text: string, patterns?: SecretPattern[]): RedactionResult;
|
|
71
|
+
/**
|
|
72
|
+
* Convenience helper used by callers that don't need the metadata —
|
|
73
|
+
* just want the masked string. Equivalent to redactSecrets(text).text.
|
|
74
|
+
*/
|
|
75
|
+
export declare function redactSecretsString(text: string): string;
|
|
76
|
+
//# sourceMappingURL=secretPatterns.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"secretPatterns.d.ts","sourceRoot":"","sources":["../../src/security/secretPatterns.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AAEH,MAAM,WAAW,aAAa;IAC5B,mEAAmE;IACnE,IAAI,EAAE,MAAM,CAAC;IACb,0DAA0D;IAC1D,KAAK,EAAE,MAAM,CAAC;IACd,4DAA4D;IAC5D,EAAE,EAAE,MAAM,CAAC;CACZ;AAED;;;;;;;;GAQG;AACH,eAAO,MAAM,uBAAuB,EAAE,aAAa,EAiLlD,CAAC;AAEF;;;;GAIG;AACH,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,cAAc,EAAE,MAAM,CAAC;IACvB,oEAAoE;IACpE,KAAK,EAAE,MAAM,EAAE,CAAC;CACjB;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,aAAa,CAC3B,IAAI,EAAE,MAAM,EACZ,QAAQ,GAAE,aAAa,EAA4B,GAClD,eAAe,CAuDjB;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAExD"}
|