opencode-forge 0.1.5
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.
Potentially problematic release.
This version of opencode-forge might be problematic. Click here for more details.
- package/LICENSE +21 -0
- package/README.md +534 -0
- package/config.jsonc +47 -0
- package/dist/agents/architect.d.ts +3 -0
- package/dist/agents/architect.d.ts.map +1 -0
- package/dist/agents/architect.js +152 -0
- package/dist/agents/architect.js.map +1 -0
- package/dist/agents/auditor.d.ts +3 -0
- package/dist/agents/auditor.d.ts.map +1 -0
- package/dist/agents/auditor.js +168 -0
- package/dist/agents/auditor.js.map +1 -0
- package/dist/agents/code.d.ts +3 -0
- package/dist/agents/code.d.ts.map +1 -0
- package/dist/agents/code.js +67 -0
- package/dist/agents/code.js.map +1 -0
- package/dist/agents/index.d.ts +4 -0
- package/dist/agents/index.d.ts.map +1 -0
- package/dist/agents/index.js +9 -0
- package/dist/agents/index.js.map +1 -0
- package/dist/agents/prompts.d.ts +1 -0
- package/dist/agents/prompts.d.ts.map +1 -0
- package/dist/agents/prompts.js +4 -0
- package/dist/agents/prompts.js.map +1 -0
- package/dist/agents/types.d.ts +34 -0
- package/dist/agents/types.d.ts.map +1 -0
- package/dist/agents/types.js +2 -0
- package/dist/agents/types.js.map +1 -0
- package/dist/cache/index.d.ts +4 -0
- package/dist/cache/index.d.ts.map +1 -0
- package/dist/cache/index.js +5 -0
- package/dist/cache/index.js.map +1 -0
- package/dist/cache/memory-cache.d.ts +14 -0
- package/dist/cache/memory-cache.d.ts.map +1 -0
- package/dist/cache/memory-cache.js +51 -0
- package/dist/cache/memory-cache.js.map +1 -0
- package/dist/cache/types.d.ts +8 -0
- package/dist/cache/types.d.ts.map +1 -0
- package/dist/cache/types.js +2 -0
- package/dist/cache/types.js.map +1 -0
- package/dist/cli/commands/cancel.d.ts +15 -0
- package/dist/cli/commands/cancel.d.ts.map +1 -0
- package/dist/cli/commands/cancel.js +194 -0
- package/dist/cli/commands/cancel.js.map +1 -0
- package/dist/cli/commands/graph.d.ts +16 -0
- package/dist/cli/commands/graph.d.ts.map +1 -0
- package/dist/cli/commands/graph.js +208 -0
- package/dist/cli/commands/graph.js.map +1 -0
- package/dist/cli/commands/restart.d.ts +15 -0
- package/dist/cli/commands/restart.d.ts.map +1 -0
- package/dist/cli/commands/restart.js +268 -0
- package/dist/cli/commands/restart.js.map +1 -0
- package/dist/cli/commands/status.d.ts +17 -0
- package/dist/cli/commands/status.d.ts.map +1 -0
- package/dist/cli/commands/status.js +356 -0
- package/dist/cli/commands/status.js.map +1 -0
- package/dist/cli/commands/upgrade.d.ts +3 -0
- package/dist/cli/commands/upgrade.d.ts.map +1 -0
- package/dist/cli/commands/upgrade.js +40 -0
- package/dist/cli/commands/upgrade.js.map +1 -0
- package/dist/cli/index.d.ts +3 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +224 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/utils.d.ts +36 -0
- package/dist/cli/utils.d.ts.map +1 -0
- package/dist/cli/utils.js +163 -0
- package/dist/cli/utils.js.map +1 -0
- package/dist/command/template/review.txt +101 -0
- package/dist/config.d.ts +5 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +186 -0
- package/dist/config.js.map +1 -0
- package/dist/constants/loop.d.ts +10 -0
- package/dist/constants/loop.d.ts.map +1 -0
- package/dist/constants/loop.js +6 -0
- package/dist/constants/loop.js.map +1 -0
- package/dist/graph/cache.d.ts +17 -0
- package/dist/graph/cache.d.ts.map +1 -0
- package/dist/graph/cache.js +50 -0
- package/dist/graph/cache.js.map +1 -0
- package/dist/graph/client.d.ts +51 -0
- package/dist/graph/client.d.ts.map +1 -0
- package/dist/graph/client.js +152 -0
- package/dist/graph/client.js.map +1 -0
- package/dist/graph/clone-detection.d.ts +9 -0
- package/dist/graph/clone-detection.d.ts.map +1 -0
- package/dist/graph/clone-detection.js +148 -0
- package/dist/graph/clone-detection.js.map +1 -0
- package/dist/graph/constants.d.ts +18 -0
- package/dist/graph/constants.d.ts.map +1 -0
- package/dist/graph/constants.js +532 -0
- package/dist/graph/constants.js.map +1 -0
- package/dist/graph/database.d.ts +11 -0
- package/dist/graph/database.d.ts.map +1 -0
- package/dist/graph/database.js +250 -0
- package/dist/graph/database.js.map +1 -0
- package/dist/graph/index.d.ts +14 -0
- package/dist/graph/index.d.ts.map +1 -0
- package/dist/graph/index.js +13 -0
- package/dist/graph/index.js.map +1 -0
- package/dist/graph/repo-map.d.ts +59 -0
- package/dist/graph/repo-map.d.ts.map +1 -0
- package/dist/graph/repo-map.js +948 -0
- package/dist/graph/repo-map.js.map +1 -0
- package/dist/graph/rpc.d.ts +34 -0
- package/dist/graph/rpc.d.ts.map +1 -0
- package/dist/graph/rpc.js +139 -0
- package/dist/graph/rpc.js.map +1 -0
- package/dist/graph/service.d.ts +46 -0
- package/dist/graph/service.d.ts.map +1 -0
- package/dist/graph/service.js +329 -0
- package/dist/graph/service.js.map +1 -0
- package/dist/graph/tree-sitter.d.ts +40 -0
- package/dist/graph/tree-sitter.d.ts.map +1 -0
- package/dist/graph/tree-sitter.js +799 -0
- package/dist/graph/tree-sitter.js.map +1 -0
- package/dist/graph/types.d.ts +175 -0
- package/dist/graph/types.d.ts.map +1 -0
- package/dist/graph/types.js +105 -0
- package/dist/graph/types.js.map +1 -0
- package/dist/graph/utils.d.ts +64 -0
- package/dist/graph/utils.d.ts.map +1 -0
- package/dist/graph/utils.js +406 -0
- package/dist/graph/utils.js.map +1 -0
- package/dist/graph/worker.d.ts +2 -0
- package/dist/graph/worker.d.ts.map +1 -0
- package/dist/graph/worker.js +6043 -0
- package/dist/graph/worker.js.map +1 -0
- package/dist/hooks/compaction-utils.d.ts +21 -0
- package/dist/hooks/compaction-utils.d.ts.map +1 -0
- package/dist/hooks/compaction-utils.js +82 -0
- package/dist/hooks/compaction-utils.js.map +1 -0
- package/dist/hooks/graph-command.d.ts +27 -0
- package/dist/hooks/graph-command.d.ts.map +1 -0
- package/dist/hooks/graph-command.js +57 -0
- package/dist/hooks/graph-command.js.map +1 -0
- package/dist/hooks/graph-tools.d.ts +11 -0
- package/dist/hooks/graph-tools.d.ts.map +1 -0
- package/dist/hooks/graph-tools.js +125 -0
- package/dist/hooks/graph-tools.js.map +1 -0
- package/dist/hooks/index.d.ts +5 -0
- package/dist/hooks/index.d.ts.map +1 -0
- package/dist/hooks/index.js +5 -0
- package/dist/hooks/index.js.map +1 -0
- package/dist/hooks/loop.d.ts +23 -0
- package/dist/hooks/loop.d.ts.map +1 -0
- package/dist/hooks/loop.js +667 -0
- package/dist/hooks/loop.js.map +1 -0
- package/dist/hooks/sandbox-tools.d.ts +13 -0
- package/dist/hooks/sandbox-tools.d.ts.map +1 -0
- package/dist/hooks/sandbox-tools.js +105 -0
- package/dist/hooks/sandbox-tools.js.map +1 -0
- package/dist/hooks/session.d.ts +19 -0
- package/dist/hooks/session.d.ts.map +1 -0
- package/dist/hooks/session.js +56 -0
- package/dist/hooks/session.js.map +1 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +298 -0
- package/dist/index.js.map +1 -0
- package/dist/sandbox/context.d.ts +27 -0
- package/dist/sandbox/context.d.ts.map +1 -0
- package/dist/sandbox/context.js +18 -0
- package/dist/sandbox/context.js.map +1 -0
- package/dist/sandbox/docker.d.ts +29 -0
- package/dist/sandbox/docker.d.ts.map +1 -0
- package/dist/sandbox/docker.js +213 -0
- package/dist/sandbox/docker.js.map +1 -0
- package/dist/sandbox/manager.d.ts +23 -0
- package/dist/sandbox/manager.d.ts.map +1 -0
- package/dist/sandbox/manager.js +131 -0
- package/dist/sandbox/manager.js.map +1 -0
- package/dist/sandbox/path.d.ts +4 -0
- package/dist/sandbox/path.d.ts.map +1 -0
- package/dist/sandbox/path.js +27 -0
- package/dist/sandbox/path.js.map +1 -0
- package/dist/services/kv.d.ts +17 -0
- package/dist/services/kv.d.ts.map +1 -0
- package/dist/services/kv.js +62 -0
- package/dist/services/kv.js.map +1 -0
- package/dist/services/loop.d.ts +96 -0
- package/dist/services/loop.d.ts.map +1 -0
- package/dist/services/loop.js +315 -0
- package/dist/services/loop.js.map +1 -0
- package/dist/setup.d.ts +4 -0
- package/dist/setup.d.ts.map +1 -0
- package/dist/setup.js +118 -0
- package/dist/setup.js.map +1 -0
- package/dist/storage/database.d.ts +6 -0
- package/dist/storage/database.d.ts.map +1 -0
- package/dist/storage/database.js +90 -0
- package/dist/storage/database.js.map +1 -0
- package/dist/storage/graph-projects.d.ts +80 -0
- package/dist/storage/graph-projects.d.ts.map +1 -0
- package/dist/storage/graph-projects.js +154 -0
- package/dist/storage/graph-projects.js.map +1 -0
- package/dist/storage/index.d.ts +5 -0
- package/dist/storage/index.d.ts.map +1 -0
- package/dist/storage/index.js +3 -0
- package/dist/storage/index.js.map +1 -0
- package/dist/storage/kv-queries.d.ts +18 -0
- package/dist/storage/kv-queries.d.ts.map +1 -0
- package/dist/storage/kv-queries.js +70 -0
- package/dist/storage/kv-queries.js.map +1 -0
- package/dist/tools/graph.d.ts +9 -0
- package/dist/tools/graph.d.ts.map +1 -0
- package/dist/tools/graph.js +272 -0
- package/dist/tools/graph.js.map +1 -0
- package/dist/tools/index.d.ts +6 -0
- package/dist/tools/index.d.ts.map +1 -0
- package/dist/tools/index.js +16 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/tools/loop.d.ts +21 -0
- package/dist/tools/loop.d.ts.map +1 -0
- package/dist/tools/loop.js +570 -0
- package/dist/tools/loop.js.map +1 -0
- package/dist/tools/plan-approval.d.ts +15 -0
- package/dist/tools/plan-approval.d.ts.map +1 -0
- package/dist/tools/plan-approval.js +203 -0
- package/dist/tools/plan-approval.js.map +1 -0
- package/dist/tools/plan-execute.d.ts +4 -0
- package/dist/tools/plan-execute.d.ts.map +1 -0
- package/dist/tools/plan-execute.js +85 -0
- package/dist/tools/plan-execute.js.map +1 -0
- package/dist/tools/plan-kv.d.ts +4 -0
- package/dist/tools/plan-kv.d.ts.map +1 -0
- package/dist/tools/plan-kv.js +107 -0
- package/dist/tools/plan-kv.js.map +1 -0
- package/dist/tools/review.d.ts +4 -0
- package/dist/tools/review.d.ts.map +1 -0
- package/dist/tools/review.js +90 -0
- package/dist/tools/review.js.map +1 -0
- package/dist/tools/sandbox-fs.d.ts +22 -0
- package/dist/tools/sandbox-fs.d.ts.map +1 -0
- package/dist/tools/sandbox-fs.js +83 -0
- package/dist/tools/sandbox-fs.js.map +1 -0
- package/dist/tools/types.d.ts +26 -0
- package/dist/tools/types.d.ts.map +1 -0
- package/dist/tools/types.js +2 -0
- package/dist/tools/types.js.map +1 -0
- package/dist/tui.d.ts +3 -0
- package/dist/tui.js +2061 -0
- package/dist/types.d.ts +124 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/dist/utils/git-branch.d.ts +11 -0
- package/dist/utils/git-branch.d.ts.map +1 -0
- package/dist/utils/git-branch.js +35 -0
- package/dist/utils/git-branch.js.map +1 -0
- package/dist/utils/graph-status-store.d.ts +72 -0
- package/dist/utils/graph-status-store.d.ts.map +1 -0
- package/dist/utils/graph-status-store.js +62 -0
- package/dist/utils/graph-status-store.js.map +1 -0
- package/dist/utils/logger.d.ts +8 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +89 -0
- package/dist/utils/logger.js.map +1 -0
- package/dist/utils/loop-format.d.ts +5 -0
- package/dist/utils/loop-format.d.ts.map +1 -0
- package/dist/utils/loop-format.js +29 -0
- package/dist/utils/loop-format.js.map +1 -0
- package/dist/utils/loop-helpers.d.ts +9 -0
- package/dist/utils/loop-helpers.d.ts.map +1 -0
- package/dist/utils/loop-helpers.js +20 -0
- package/dist/utils/loop-helpers.js.map +1 -0
- package/dist/utils/loop-launch.d.ts +32 -0
- package/dist/utils/loop-launch.d.ts.map +1 -0
- package/dist/utils/loop-launch.js +162 -0
- package/dist/utils/loop-launch.js.map +1 -0
- package/dist/utils/model-fallback.d.ts +27 -0
- package/dist/utils/model-fallback.d.ts.map +1 -0
- package/dist/utils/model-fallback.js +33 -0
- package/dist/utils/model-fallback.js.map +1 -0
- package/dist/utils/partial-match.d.ts +7 -0
- package/dist/utils/partial-match.d.ts.map +1 -0
- package/dist/utils/partial-match.js +56 -0
- package/dist/utils/partial-match.js.map +1 -0
- package/dist/utils/plan-execution.d.ts +65 -0
- package/dist/utils/plan-execution.d.ts.map +1 -0
- package/dist/utils/plan-execution.js +107 -0
- package/dist/utils/plan-execution.js.map +1 -0
- package/dist/utils/session-stats.d.ts +36 -0
- package/dist/utils/session-stats.d.ts.map +1 -0
- package/dist/utils/session-stats.js +145 -0
- package/dist/utils/session-stats.js.map +1 -0
- package/dist/utils/tui-graph-status.d.ts +38 -0
- package/dist/utils/tui-graph-status.d.ts.map +1 -0
- package/dist/utils/tui-graph-status.js +95 -0
- package/dist/utils/tui-graph-status.js.map +1 -0
- package/dist/utils/tui-plan-store.d.ts +54 -0
- package/dist/utils/tui-plan-store.d.ts.map +1 -0
- package/dist/utils/tui-plan-store.js +168 -0
- package/dist/utils/tui-plan-store.js.map +1 -0
- package/dist/utils/tui-refresh-helpers.d.ts +44 -0
- package/dist/utils/tui-refresh-helpers.d.ts.map +1 -0
- package/dist/utils/tui-refresh-helpers.js +120 -0
- package/dist/utils/tui-refresh-helpers.js.map +1 -0
- package/dist/utils/upgrade.d.ts +23 -0
- package/dist/utils/upgrade.d.ts.map +1 -0
- package/dist/utils/upgrade.js +111 -0
- package/dist/utils/upgrade.js.map +1 -0
- package/dist/version.d.ts +2 -0
- package/dist/version.d.ts.map +1 -0
- package/dist/version.js +2 -0
- package/dist/version.js.map +1 -0
- package/package.json +92 -0
- package/scripts/build.ts +67 -0
- package/src/command/template/review.txt +101 -0
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
import { parseModelString, retryWithModelFallback } from '../utils/model-fallback';
|
|
2
|
+
import { setupLoop } from './loop';
|
|
3
|
+
import { DEFAULT_COMPLETION_SIGNAL } from '../services/loop';
|
|
4
|
+
import { extractPlanTitle, extractLoopNames, PLAN_EXECUTION_LABELS } from '../utils/plan-execution';
|
|
5
|
+
const LOOP_BLOCKED_TOOLS = {
|
|
6
|
+
question: 'The question tool is not available during a loop. Do not ask questions — continue working on the task autonomously.',
|
|
7
|
+
'plan-execute': 'The plan-execute tool is not available during a loop. Focus on executing the current plan.',
|
|
8
|
+
loop: 'The loop tool is not available during a loop. Focus on executing the current plan.',
|
|
9
|
+
};
|
|
10
|
+
const pendingExecutions = new Map();
|
|
11
|
+
export { LOOP_BLOCKED_TOOLS };
|
|
12
|
+
export { extractPlanTitle };
|
|
13
|
+
export function createToolExecuteBeforeHook(ctx) {
|
|
14
|
+
const { loopService, logger } = ctx;
|
|
15
|
+
return async (input, _output) => {
|
|
16
|
+
const worktreeName = loopService.resolveWorktreeName(input.sessionID);
|
|
17
|
+
const state = worktreeName ? loopService.getActiveState(worktreeName) : null;
|
|
18
|
+
if (!state?.active)
|
|
19
|
+
return;
|
|
20
|
+
if (!(input.tool in LOOP_BLOCKED_TOOLS))
|
|
21
|
+
return;
|
|
22
|
+
logger.log(`Loop: blocking ${input.tool} tool before execution in ${state.phase} phase for session ${input.sessionID}`);
|
|
23
|
+
throw new Error(LOOP_BLOCKED_TOOLS[input.tool]);
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
export function createToolExecuteAfterHook(ctx) {
|
|
27
|
+
const { loopService, logger, kvService, projectId, v2, config } = ctx;
|
|
28
|
+
return async (input, output) => {
|
|
29
|
+
if (input.tool === 'question') {
|
|
30
|
+
const args = input.args;
|
|
31
|
+
const options = args?.questions?.[0]?.options;
|
|
32
|
+
if (options) {
|
|
33
|
+
const labels = options.map((o) => o.label.toLowerCase());
|
|
34
|
+
const hasExecuteHere = labels.some((l) => l === 'execute here' || l.startsWith('execute here'));
|
|
35
|
+
const isPlanApproval = hasExecuteHere || PLAN_EXECUTION_LABELS.every((l) => labels.includes(l));
|
|
36
|
+
if (isPlanApproval) {
|
|
37
|
+
const metadata = output.metadata;
|
|
38
|
+
const answer = metadata?.answers?.[0]?.[0]?.trim() ?? output.output.trim();
|
|
39
|
+
const answerLower = answer.toLowerCase();
|
|
40
|
+
const matchedLabel = PLAN_EXECUTION_LABELS.find((l) => answerLower === l.toLowerCase() || answerLower.startsWith(l.toLowerCase()));
|
|
41
|
+
if (matchedLabel?.toLowerCase() === 'execute here') {
|
|
42
|
+
// Read plan from KV (same as "New session" path)
|
|
43
|
+
const planKey = `plan:${input.sessionID}`;
|
|
44
|
+
const planCached = kvService.get(projectId, planKey);
|
|
45
|
+
if (!planCached) {
|
|
46
|
+
output.output = `${output.output}\n\nError: No cached plan found. Please ensure the plan is written via plan-write before approval.`;
|
|
47
|
+
logger.error('Plan approval: plan not found for "Execute here"');
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
const planText = typeof planCached === 'string' ? planCached : JSON.stringify(planCached, null, 2);
|
|
51
|
+
// Delete from KV after reading (consistent with other paths)
|
|
52
|
+
kvService.delete(projectId, planKey);
|
|
53
|
+
pendingExecutions.set(input.sessionID, {
|
|
54
|
+
directory: ctx.directory,
|
|
55
|
+
executionModel: parseModelString(ctx.config.executionModel),
|
|
56
|
+
planText,
|
|
57
|
+
});
|
|
58
|
+
ctx.v2.session.abort({ sessionID: input.sessionID }).catch((err) => {
|
|
59
|
+
logger.error('Plan approval: failed to abort architect session', err);
|
|
60
|
+
});
|
|
61
|
+
output.output = `${output.output}\n\nSwitching to code agent for execution...`;
|
|
62
|
+
logger.log('Plan approval: "Execute here" — aborting architect, pending code agent switch');
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
// Programmatic dispatch for "New session" and "Loop" paths
|
|
66
|
+
const planKey = `plan:${input.sessionID}`;
|
|
67
|
+
const planCached = kvService.get(projectId, planKey);
|
|
68
|
+
if (!planCached) {
|
|
69
|
+
output.output = `${output.output}\n\nError: No cached plan found. Please ensure the plan is written via plan-write before approval.`;
|
|
70
|
+
logger.error('Plan approval: plan not found');
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
const planText = typeof planCached === 'string' ? planCached : JSON.stringify(planCached, null, 2);
|
|
74
|
+
const title = extractPlanTitle(planText);
|
|
75
|
+
if (matchedLabel === 'New session') {
|
|
76
|
+
logger.log('Plan approval: "New session" — creating new session');
|
|
77
|
+
const executionModel = parseModelString(config.executionModel);
|
|
78
|
+
v2.session.create({ title, directory: ctx.directory }).then((createResult) => {
|
|
79
|
+
if (createResult.error || !createResult.data) {
|
|
80
|
+
logger.error('Plan approval: failed to create new session', createResult.error);
|
|
81
|
+
output.output = 'Creating new session for plan execution... Failed to create session.';
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
const newSessionId = createResult.data.id;
|
|
85
|
+
kvService.delete(projectId, `plan:${input.sessionID}`);
|
|
86
|
+
retryWithModelFallback(() => v2.session.promptAsync({
|
|
87
|
+
sessionID: newSessionId,
|
|
88
|
+
directory: ctx.directory,
|
|
89
|
+
agent: 'code',
|
|
90
|
+
parts: [{ type: 'text', text: planText }],
|
|
91
|
+
...(executionModel ? { model: executionModel } : {}),
|
|
92
|
+
}), () => v2.session.promptAsync({
|
|
93
|
+
sessionID: newSessionId,
|
|
94
|
+
directory: ctx.directory,
|
|
95
|
+
agent: 'code',
|
|
96
|
+
parts: [{ type: 'text', text: planText }],
|
|
97
|
+
}), executionModel, logger).then(({ result }) => {
|
|
98
|
+
if (result.error) {
|
|
99
|
+
logger.error('Plan approval: failed to send plan to new session', result.error);
|
|
100
|
+
}
|
|
101
|
+
else {
|
|
102
|
+
v2.tui.selectSession({ sessionID: newSessionId }).catch((err) => {
|
|
103
|
+
logger.error('Plan approval: failed to navigate TUI', err);
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
});
|
|
107
|
+
}).catch((err) => {
|
|
108
|
+
logger.error('Plan approval: failed to create new session', err);
|
|
109
|
+
output.output = 'Creating new session for plan execution... Failed to create session.';
|
|
110
|
+
});
|
|
111
|
+
v2.session.abort({ sessionID: input.sessionID }).catch((err) => {
|
|
112
|
+
logger.error('Plan approval: failed to abort architect session', err);
|
|
113
|
+
});
|
|
114
|
+
return;
|
|
115
|
+
}
|
|
116
|
+
if (matchedLabel === 'Loop (worktree)' || matchedLabel === 'Loop') {
|
|
117
|
+
const isWorktree = matchedLabel === 'Loop (worktree)';
|
|
118
|
+
// Use explicit loop name from plan (or fallback to title)
|
|
119
|
+
const { executionName } = extractLoopNames(planText);
|
|
120
|
+
const uniqueWorktreeName = ctx.loopService.generateUniqueWorktreeName(executionName);
|
|
121
|
+
output.output = isWorktree
|
|
122
|
+
? 'Starting loop in worktree...'
|
|
123
|
+
: 'Starting loop in-place...';
|
|
124
|
+
logger.log(`Plan approval: "${matchedLabel}" — starting loop with worktree name "${uniqueWorktreeName}"`);
|
|
125
|
+
// Store plan under the unique worktree name (same name that setupLoop will use)
|
|
126
|
+
kvService.set(projectId, `plan:${uniqueWorktreeName}`, planText);
|
|
127
|
+
kvService.delete(projectId, `plan:${input.sessionID}`);
|
|
128
|
+
const loopModel = parseModelString(config.loop?.model) ?? parseModelString(config.executionModel);
|
|
129
|
+
setupLoop(ctx, {
|
|
130
|
+
prompt: planText,
|
|
131
|
+
sessionTitle: `Loop: ${title}`,
|
|
132
|
+
worktreeName: uniqueWorktreeName,
|
|
133
|
+
completionSignal: DEFAULT_COMPLETION_SIGNAL,
|
|
134
|
+
maxIterations: config.loop?.defaultMaxIterations ?? 0,
|
|
135
|
+
audit: config.loop?.defaultAudit ?? true,
|
|
136
|
+
agent: 'code',
|
|
137
|
+
model: loopModel,
|
|
138
|
+
worktree: isWorktree,
|
|
139
|
+
onLoopStarted: (id) => ctx.loopHandler.startWatchdog(id),
|
|
140
|
+
}).catch((err) => {
|
|
141
|
+
logger.error('Plan approval: failed to start loop', err);
|
|
142
|
+
});
|
|
143
|
+
v2.session.abort({ sessionID: input.sessionID }).catch((err) => {
|
|
144
|
+
logger.error('Plan approval: failed to abort architect session', err);
|
|
145
|
+
});
|
|
146
|
+
return;
|
|
147
|
+
}
|
|
148
|
+
// Custom answer fallback
|
|
149
|
+
output.output = `${output.output}\n\n<system-reminder>\nThe user provided a custom response instead of selecting a predefined option. Review their answer and respond accordingly. If they want to proceed with execution, use the appropriate tool (plan-execute or loop) based on their intent. If they want to cancel or revise the plan, help them with that instead.\n</system-reminder>`;
|
|
150
|
+
logger.log(`Plan approval: detected custom answer`);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
return;
|
|
154
|
+
}
|
|
155
|
+
const worktreeName = loopService.resolveWorktreeName(input.sessionID);
|
|
156
|
+
const state = worktreeName ? loopService.getActiveState(worktreeName) : null;
|
|
157
|
+
if (!state?.active)
|
|
158
|
+
return;
|
|
159
|
+
if (!(input.tool in LOOP_BLOCKED_TOOLS))
|
|
160
|
+
return;
|
|
161
|
+
logger.log(`Loop: blocked ${input.tool} tool in ${state.phase} phase for session ${input.sessionID}`);
|
|
162
|
+
output.title = 'Tool blocked';
|
|
163
|
+
output.output = LOOP_BLOCKED_TOOLS[input.tool];
|
|
164
|
+
};
|
|
165
|
+
}
|
|
166
|
+
export function createPlanApprovalEventHook(ctx) {
|
|
167
|
+
const { v2, logger } = ctx;
|
|
168
|
+
return async (eventInput) => {
|
|
169
|
+
if (eventInput.event?.type !== 'session.idle')
|
|
170
|
+
return;
|
|
171
|
+
const sessionID = eventInput.event.properties?.sessionID;
|
|
172
|
+
if (!sessionID)
|
|
173
|
+
return;
|
|
174
|
+
const pending = pendingExecutions.get(sessionID);
|
|
175
|
+
if (!pending)
|
|
176
|
+
return;
|
|
177
|
+
pendingExecutions.delete(sessionID);
|
|
178
|
+
const planRef = pending.planText
|
|
179
|
+
? `\n\nImplementation Plan:\n${pending.planText}`
|
|
180
|
+
: '\n\nPlan reference: Execute the implementation plan from this conversation. Review all phases above and implement each one.';
|
|
181
|
+
const inPlacePrompt = `The architect agent has created an implementation plan. You are now the code agent taking over this session. Your job is to execute the plan — edit files, run commands, create tests, and implement every phase. Do NOT just describe or summarize the changes. Actually make them.${planRef}`;
|
|
182
|
+
const { result: promptResult, usedModel: actualModel } = await retryWithModelFallback(() => v2.session.promptAsync({
|
|
183
|
+
sessionID,
|
|
184
|
+
directory: pending.directory,
|
|
185
|
+
agent: 'code',
|
|
186
|
+
parts: [{ type: 'text', text: inPlacePrompt }],
|
|
187
|
+
...(pending.executionModel ? { model: pending.executionModel } : {}),
|
|
188
|
+
}), () => v2.session.promptAsync({
|
|
189
|
+
sessionID,
|
|
190
|
+
directory: pending.directory,
|
|
191
|
+
agent: 'code',
|
|
192
|
+
parts: [{ type: 'text', text: inPlacePrompt }],
|
|
193
|
+
}), pending.executionModel, logger);
|
|
194
|
+
if (promptResult.error) {
|
|
195
|
+
logger.error('Plan approval: failed to switch to code agent', promptResult.error);
|
|
196
|
+
}
|
|
197
|
+
else {
|
|
198
|
+
const modelInfo = actualModel ? `${actualModel.providerID}/${actualModel.modelID}` : 'default';
|
|
199
|
+
logger.log(`Plan approval: switched to code agent (model: ${modelInfo})`);
|
|
200
|
+
}
|
|
201
|
+
};
|
|
202
|
+
}
|
|
203
|
+
//# sourceMappingURL=plan-approval.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plan-approval.js","sourceRoot":"","sources":["../../src/tools/plan-approval.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plan-execute.d.ts","sourceRoot":"","sources":["../../src/tools/plan-execute.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,qBAAqB,CAAA;AAC1C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,SAAS,CAAA;AAK1C,wBAAgB,sBAAsB,CAAC,GAAG,EAAE,WAAW,GAAG,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,OAAO,IAAI,CAAC,CAAC,CAyGhG"}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { tool } from '@opencode-ai/plugin';
|
|
2
|
+
import { parseModelString, retryWithModelFallback } from '../utils/model-fallback';
|
|
3
|
+
const z = tool.schema;
|
|
4
|
+
export function createPlanExecuteTools(ctx) {
|
|
5
|
+
const { directory, config, logger, v2, kvService, projectId } = ctx;
|
|
6
|
+
return {
|
|
7
|
+
'plan-execute': tool({
|
|
8
|
+
description: 'Send the plan to the Code agent for execution. By default creates a new session. Set inPlace to true to switch to the code agent in the current session (plan is already in context).',
|
|
9
|
+
args: {
|
|
10
|
+
plan: z.string().optional().describe('The full implementation plan. If omitted, reads from the session plan store.'),
|
|
11
|
+
title: z.string().describe('Short title for the session (shown in session list)'),
|
|
12
|
+
inPlace: z.boolean().optional().default(false).describe('Execute in the current session, instead of creating a new session'),
|
|
13
|
+
},
|
|
14
|
+
execute: async (args, context) => {
|
|
15
|
+
logger.log(`plan-execute: ${args.inPlace ? 'switching to code agent' : 'creating session'} titled "${args.title}"`);
|
|
16
|
+
let planText = args.plan;
|
|
17
|
+
if (!planText) {
|
|
18
|
+
const planKey = `plan:${context.sessionID}`;
|
|
19
|
+
const cached = kvService.get(projectId, planKey);
|
|
20
|
+
if (!cached) {
|
|
21
|
+
return 'No plan found. Write the plan via plan-write before calling this tool, or pass it directly as the plan argument.';
|
|
22
|
+
}
|
|
23
|
+
planText = typeof cached === 'string' ? cached : JSON.stringify(cached, null, 2);
|
|
24
|
+
kvService.delete(projectId, planKey);
|
|
25
|
+
}
|
|
26
|
+
const sessionTitle = args.title.length > 60 ? `${args.title.substring(0, 57)}...` : args.title;
|
|
27
|
+
const executionModel = parseModelString(config.executionModel);
|
|
28
|
+
if (args.inPlace) {
|
|
29
|
+
const inPlacePrompt = `The architect agent has created an implementation plan in this conversation above. You are now the code agent taking over this session. Your job is to execute the plan — edit files, run commands, create tests, and implement every phase. Do NOT just describe or summarize the changes. Actually make them.\n\nPlan reference: ${planText}`;
|
|
30
|
+
const { result: promptResult, usedModel: actualModel } = await retryWithModelFallback(() => v2.session.promptAsync({
|
|
31
|
+
sessionID: context.sessionID,
|
|
32
|
+
directory,
|
|
33
|
+
agent: 'code',
|
|
34
|
+
parts: [{ type: 'text', text: inPlacePrompt }],
|
|
35
|
+
...(executionModel ? { model: executionModel } : {}),
|
|
36
|
+
}), () => v2.session.promptAsync({
|
|
37
|
+
sessionID: context.sessionID,
|
|
38
|
+
directory,
|
|
39
|
+
agent: 'code',
|
|
40
|
+
parts: [{ type: 'text', text: inPlacePrompt }],
|
|
41
|
+
}), executionModel, logger);
|
|
42
|
+
if (promptResult.error) {
|
|
43
|
+
logger.error(`plan-execute: in-place agent switch failed`, promptResult.error);
|
|
44
|
+
return `Failed to switch to code agent. Error: ${JSON.stringify(promptResult.error)}`;
|
|
45
|
+
}
|
|
46
|
+
const modelInfo = actualModel ? `${actualModel.providerID}/${actualModel.modelID}` : 'default';
|
|
47
|
+
return `Switching to code agent for execution.\n\nTitle: ${sessionTitle}\nModel: ${modelInfo}\nAgent: code`;
|
|
48
|
+
}
|
|
49
|
+
const createResult = await v2.session.create({
|
|
50
|
+
title: sessionTitle,
|
|
51
|
+
directory,
|
|
52
|
+
});
|
|
53
|
+
if (createResult.error || !createResult.data) {
|
|
54
|
+
logger.error(`plan-execute: failed to create session`, createResult.error);
|
|
55
|
+
return 'Failed to create new session.';
|
|
56
|
+
}
|
|
57
|
+
const newSessionId = createResult.data.id;
|
|
58
|
+
logger.log(`plan-execute: created session=${newSessionId}`);
|
|
59
|
+
const { result: promptResult, usedModel: actualModel } = await retryWithModelFallback(() => v2.session.promptAsync({
|
|
60
|
+
sessionID: newSessionId,
|
|
61
|
+
directory,
|
|
62
|
+
parts: [{ type: 'text', text: planText }],
|
|
63
|
+
agent: 'code',
|
|
64
|
+
model: executionModel,
|
|
65
|
+
}), () => v2.session.promptAsync({
|
|
66
|
+
sessionID: newSessionId,
|
|
67
|
+
directory,
|
|
68
|
+
parts: [{ type: 'text', text: planText }],
|
|
69
|
+
agent: 'code',
|
|
70
|
+
}), executionModel, logger);
|
|
71
|
+
if (promptResult.error) {
|
|
72
|
+
logger.error(`plan-execute: failed to prompt session`, promptResult.error);
|
|
73
|
+
return `Session created (${newSessionId}) but failed to send plan. Switch to it and paste the plan manually.`;
|
|
74
|
+
}
|
|
75
|
+
logger.log(`plan-execute: prompted session=${newSessionId}`);
|
|
76
|
+
v2.tui.selectSession({ sessionID: newSessionId }).catch((err) => {
|
|
77
|
+
logger.error('plan-execute: failed to navigate TUI to new session', err);
|
|
78
|
+
});
|
|
79
|
+
const modelInfo = actualModel ? `${actualModel.providerID}/${actualModel.modelID}` : 'default';
|
|
80
|
+
return `Implementation session created and plan sent.\n\nSession: ${newSessionId}\nTitle: ${sessionTitle}\nModel: ${modelInfo}\n\nNavigated to the new session. You can change the model from the session dropdown.`;
|
|
81
|
+
},
|
|
82
|
+
}),
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
//# sourceMappingURL=plan-execute.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plan-execute.js","sourceRoot":"","sources":["../../src/tools/plan-execute.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plan-kv.d.ts","sourceRoot":"","sources":["../../src/tools/plan-kv.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,qBAAqB,CAAA;AAC1C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,SAAS,CAAA;AAI1C,wBAAgB,eAAe,CAAC,GAAG,EAAE,WAAW,GAAG,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,OAAO,IAAI,CAAC,CAAC,CA4HzF"}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import { tool } from '@opencode-ai/plugin';
|
|
2
|
+
const z = tool.schema;
|
|
3
|
+
export function createPlanTools(ctx) {
|
|
4
|
+
const { kvService, projectId, logger, loopService } = ctx;
|
|
5
|
+
function resolvePlanKey(sessionID) {
|
|
6
|
+
const worktreeName = loopService.resolveWorktreeName(sessionID);
|
|
7
|
+
if (worktreeName) {
|
|
8
|
+
return `plan:${worktreeName}`;
|
|
9
|
+
}
|
|
10
|
+
return `plan:${sessionID}`;
|
|
11
|
+
}
|
|
12
|
+
return {
|
|
13
|
+
'plan-write': tool({
|
|
14
|
+
description: 'Write or overwrite the entire plan content for the current session. Auto-resolves key to plan:{sessionID}.',
|
|
15
|
+
args: {
|
|
16
|
+
content: z.string().describe('The plan content to write'),
|
|
17
|
+
},
|
|
18
|
+
execute: async (args, context) => {
|
|
19
|
+
const key = resolvePlanKey(context.sessionID);
|
|
20
|
+
kvService.set(projectId, key, args.content);
|
|
21
|
+
const lineCount = args.content.split('\n').length;
|
|
22
|
+
logger.log(`plan-write: stored plan at ${key} (${lineCount} lines)`);
|
|
23
|
+
return `Plan stored (${lineCount} lines)`;
|
|
24
|
+
},
|
|
25
|
+
}),
|
|
26
|
+
'plan-edit': tool({
|
|
27
|
+
description: 'Edit the plan by finding old_string and replacing with new_string. Fails if old_string is not found or is not unique.',
|
|
28
|
+
args: {
|
|
29
|
+
old_string: z.string().describe('The string to find in the plan'),
|
|
30
|
+
new_string: z.string().describe('The string to replace it with'),
|
|
31
|
+
},
|
|
32
|
+
execute: async (args, context) => {
|
|
33
|
+
const key = resolvePlanKey(context.sessionID);
|
|
34
|
+
const existing = kvService.get(projectId, key);
|
|
35
|
+
if (existing === null) {
|
|
36
|
+
return `No plan found for session ${context.sessionID}`;
|
|
37
|
+
}
|
|
38
|
+
const occurrences = existing.split(args.old_string).length - 1;
|
|
39
|
+
if (occurrences === 0) {
|
|
40
|
+
return `old_string not found in plan`;
|
|
41
|
+
}
|
|
42
|
+
if (occurrences > 1) {
|
|
43
|
+
return `old_string found ${occurrences} times - must be unique`;
|
|
44
|
+
}
|
|
45
|
+
const updated = existing.replace(args.old_string, args.new_string);
|
|
46
|
+
kvService.set(projectId, key, updated);
|
|
47
|
+
const lineCount = updated.split('\n').length;
|
|
48
|
+
logger.log(`plan-edit: updated plan at ${key} (${lineCount} lines)`);
|
|
49
|
+
return `Plan updated (${lineCount} lines)`;
|
|
50
|
+
},
|
|
51
|
+
}),
|
|
52
|
+
'plan-read': tool({
|
|
53
|
+
description: 'Read the plan for the current session. Supports pagination with offset/limit and pattern search.',
|
|
54
|
+
args: {
|
|
55
|
+
offset: z.number().optional().describe('Line number to start from (1-indexed)'),
|
|
56
|
+
limit: z.number().optional().describe('Maximum number of lines to return'),
|
|
57
|
+
pattern: z.string().optional().describe('Regex pattern to search for in plan content'),
|
|
58
|
+
},
|
|
59
|
+
execute: async (args, context) => {
|
|
60
|
+
const key = resolvePlanKey(context.sessionID);
|
|
61
|
+
const value = kvService.get(projectId, key);
|
|
62
|
+
if (value === null) {
|
|
63
|
+
logger.log(`plan-read: no plan found for session ${context.sessionID}`);
|
|
64
|
+
return `No plan found for current session`;
|
|
65
|
+
}
|
|
66
|
+
logger.log(`plan-read: retrieved plan from ${key}`);
|
|
67
|
+
if (args.pattern) {
|
|
68
|
+
let regex;
|
|
69
|
+
try {
|
|
70
|
+
regex = new RegExp(args.pattern);
|
|
71
|
+
}
|
|
72
|
+
catch (e) {
|
|
73
|
+
return `Invalid regex pattern: ${e.message}`;
|
|
74
|
+
}
|
|
75
|
+
const lines = value.split('\n');
|
|
76
|
+
const matches = [];
|
|
77
|
+
for (let i = 0; i < lines.length; i++) {
|
|
78
|
+
if (regex.test(lines[i])) {
|
|
79
|
+
matches.push({ lineNum: i + 1, text: lines[i] });
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
if (matches.length === 0) {
|
|
83
|
+
return 'No matches found in plan';
|
|
84
|
+
}
|
|
85
|
+
return `Found ${matches.length} match${matches.length === 1 ? '' : 'es'}:\n\n${matches.map((m) => ` Line ${m.lineNum}: ${m.text}`).join('\n')}`;
|
|
86
|
+
}
|
|
87
|
+
const lines = value.split('\n');
|
|
88
|
+
const totalLines = lines.length;
|
|
89
|
+
let resultLines = lines;
|
|
90
|
+
if (args.offset !== undefined) {
|
|
91
|
+
const startIdx = args.offset - 1;
|
|
92
|
+
resultLines = resultLines.slice(Math.max(0, startIdx));
|
|
93
|
+
}
|
|
94
|
+
if (args.limit !== undefined) {
|
|
95
|
+
resultLines = resultLines.slice(0, args.limit);
|
|
96
|
+
}
|
|
97
|
+
const numberedLines = resultLines.map((line, i) => {
|
|
98
|
+
const originalLineNum = args.offset !== undefined ? args.offset + i : i + 1;
|
|
99
|
+
return `${originalLineNum}: ${line}`;
|
|
100
|
+
});
|
|
101
|
+
const header = `(${totalLines} lines total)`;
|
|
102
|
+
return `${header}\n${numberedLines.join('\n')}`;
|
|
103
|
+
},
|
|
104
|
+
}),
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
//# sourceMappingURL=plan-kv.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plan-kv.js","sourceRoot":"","sources":["../../src/tools/plan-kv.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"review.d.ts","sourceRoot":"","sources":["../../src/tools/review.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,qBAAqB,CAAA;AAC1C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,SAAS,CAAA;AAK1C,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,WAAW,GAAG,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,OAAO,IAAI,CAAC,CAAC,CAgG3F"}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import { tool } from '@opencode-ai/plugin';
|
|
2
|
+
import { injectBranchField } from '../utils/git-branch';
|
|
3
|
+
const z = tool.schema;
|
|
4
|
+
export function createReviewTools(ctx) {
|
|
5
|
+
const { kvService, projectId, logger, loopService } = ctx;
|
|
6
|
+
return {
|
|
7
|
+
'review-write': tool({
|
|
8
|
+
description: 'Store a code review finding with file location, severity, and description. Automatically injects branch field.',
|
|
9
|
+
args: {
|
|
10
|
+
file: z.string().describe('The file path where the finding is located'),
|
|
11
|
+
line: z.number().describe('The line number of the finding'),
|
|
12
|
+
severity: z.enum(['bug', 'warning']).describe('The severity of the finding'),
|
|
13
|
+
description: z.string().describe('Clear description of the issue'),
|
|
14
|
+
scenario: z.string().describe('The specific conditions under which this issue manifests'),
|
|
15
|
+
status: z.string().default('open').describe('The status of the finding (default: "open")'),
|
|
16
|
+
},
|
|
17
|
+
execute: async (args) => {
|
|
18
|
+
const key = `review-finding:${args.file}:${args.line}`;
|
|
19
|
+
const value = {
|
|
20
|
+
severity: args.severity,
|
|
21
|
+
file: args.file,
|
|
22
|
+
line: args.line,
|
|
23
|
+
description: args.description,
|
|
24
|
+
scenario: args.scenario,
|
|
25
|
+
status: args.status,
|
|
26
|
+
date: new Date().toISOString().split('T')[0],
|
|
27
|
+
};
|
|
28
|
+
injectBranchField(value, ctx.directory, loopService);
|
|
29
|
+
kvService.set(projectId, key, value);
|
|
30
|
+
logger.log(`review-write: stored finding at ${args.file}:${args.line} (${args.severity})`);
|
|
31
|
+
return `Stored review finding at ${args.file}:${args.line} (${args.severity})`;
|
|
32
|
+
},
|
|
33
|
+
}),
|
|
34
|
+
'review-read': tool({
|
|
35
|
+
description: 'Retrieve code review findings. No args lists all findings. Use file to filter by file path. Use pattern for regex search.',
|
|
36
|
+
args: {
|
|
37
|
+
file: z.string().optional().describe('Filter findings by file path'),
|
|
38
|
+
pattern: z.string().optional().describe('Regex pattern to search across findings'),
|
|
39
|
+
},
|
|
40
|
+
execute: async (args) => {
|
|
41
|
+
let findings = kvService.listByPrefix(projectId, 'review-finding:');
|
|
42
|
+
if (args.file) {
|
|
43
|
+
findings = findings.filter((f) => f.key.startsWith(`review-finding:${args.file}:`));
|
|
44
|
+
}
|
|
45
|
+
if (args.pattern) {
|
|
46
|
+
let regex;
|
|
47
|
+
try {
|
|
48
|
+
regex = new RegExp(args.pattern);
|
|
49
|
+
}
|
|
50
|
+
catch (e) {
|
|
51
|
+
return `Invalid regex pattern: ${e.message}`;
|
|
52
|
+
}
|
|
53
|
+
const matchedFindings = [];
|
|
54
|
+
for (const finding of findings) {
|
|
55
|
+
const valueStr = typeof finding.data === 'string'
|
|
56
|
+
? finding.data
|
|
57
|
+
: JSON.stringify(finding.data, null, 2);
|
|
58
|
+
if (regex.test(valueStr)) {
|
|
59
|
+
matchedFindings.push(finding);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
findings = matchedFindings;
|
|
63
|
+
}
|
|
64
|
+
if (findings.length === 0) {
|
|
65
|
+
return 'No review findings found.';
|
|
66
|
+
}
|
|
67
|
+
const formatted = findings.map((f) => {
|
|
68
|
+
const data = f.data;
|
|
69
|
+
return `- **${f.key}**\n - Severity: ${String(data.severity)}\n - File: ${String(data.file)}:${Number(data.line)}\n - Description: ${String(data.description)}\n - Scenario: ${String(data.scenario)}\n - Status: ${String(data.status)}\n - Branch: ${String(data.branch || 'N/A')}`;
|
|
70
|
+
});
|
|
71
|
+
logger.log(`review-read: found ${findings.length} findings`);
|
|
72
|
+
return `${findings.length} review finding${findings.length === 1 ? '' : 's'}:\n\n${formatted.join('\n\n')}`;
|
|
73
|
+
},
|
|
74
|
+
}),
|
|
75
|
+
'review-delete': tool({
|
|
76
|
+
description: 'Delete a code review finding by file and line number.',
|
|
77
|
+
args: {
|
|
78
|
+
file: z.string().describe('The file path of the finding to delete'),
|
|
79
|
+
line: z.number().describe('The line number of the finding to delete'),
|
|
80
|
+
},
|
|
81
|
+
execute: async (args) => {
|
|
82
|
+
const key = `review-finding:${args.file}:${args.line}`;
|
|
83
|
+
kvService.delete(projectId, key);
|
|
84
|
+
logger.log(`review-delete: deleted finding at ${args.file}:${args.line}`);
|
|
85
|
+
return `Deleted review finding at ${args.file}:${args.line}`;
|
|
86
|
+
},
|
|
87
|
+
}),
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
//# sourceMappingURL=review.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"review.js","sourceRoot":"","sources":["../../src/tools/review.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { DockerService } from '../sandbox/docker';
|
|
2
|
+
import type { SandboxContext } from '../sandbox/context';
|
|
3
|
+
interface SandboxExecutionDeps {
|
|
4
|
+
docker: DockerService;
|
|
5
|
+
containerName: string;
|
|
6
|
+
hostDir: string;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Execute a glob pattern search inside a sandbox container.
|
|
10
|
+
* Returns rewritten file paths with container paths converted back to host paths.
|
|
11
|
+
*/
|
|
12
|
+
export declare function executeSandboxGlob(sandbox: SandboxExecutionDeps, pattern: string, searchPath?: string): Promise<string>;
|
|
13
|
+
/**
|
|
14
|
+
* Execute a grep/regex search inside a sandbox container.
|
|
15
|
+
* Returns rewritten file paths with container paths converted back to host paths.
|
|
16
|
+
*/
|
|
17
|
+
export declare function executeSandboxGrep(sandbox: SandboxExecutionDeps, pattern: string, options?: {
|
|
18
|
+
path?: string;
|
|
19
|
+
include?: string;
|
|
20
|
+
}): Promise<string>;
|
|
21
|
+
export type { SandboxContext };
|
|
22
|
+
//# sourceMappingURL=sandbox-fs.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sandbox-fs.d.ts","sourceRoot":"","sources":["../../src/tools/sandbox-fs.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAA;AACtD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAA;AAExD,UAAU,oBAAoB;IAC5B,MAAM,EAAE,aAAa,CAAA;IACrB,aAAa,EAAE,MAAM,CAAA;IACrB,OAAO,EAAE,MAAM,CAAA;CAChB;AAED;;;GAGG;AACH,wBAAsB,kBAAkB,CACtC,OAAO,EAAE,oBAAoB,EAC7B,OAAO,EAAE,MAAM,EACf,UAAU,CAAC,EAAE,MAAM,GAClB,OAAO,CAAC,MAAM,CAAC,CA0BjB;AAOD;;;GAGG;AACH,wBAAsB,kBAAkB,CACtC,OAAO,EAAE,oBAAoB,EAC7B,OAAO,EAAE,MAAM,EACf,OAAO,CAAC,EAAE;IAAE,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE,GAC5C,OAAO,CAAC,MAAM,CAAC,CAqDjB;AAGD,YAAY,EAAE,cAAc,EAAE,CAAA"}
|