fixo-cli 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +201 -0
- package/README.md +530 -0
- package/dist/agent/agent-client.d.ts +108 -0
- package/dist/agent/agent-client.d.ts.map +1 -0
- package/dist/agent/agent-client.js +1247 -0
- package/dist/agent/agent-client.js.map +1 -0
- package/dist/agent/agent-pool.d.ts +20 -0
- package/dist/agent/agent-pool.d.ts.map +1 -0
- package/dist/agent/agent-pool.js +217 -0
- package/dist/agent/agent-pool.js.map +1 -0
- package/dist/agent/background-awareness.d.ts +55 -0
- package/dist/agent/background-awareness.d.ts.map +1 -0
- package/dist/agent/background-awareness.js +104 -0
- package/dist/agent/background-awareness.js.map +1 -0
- package/dist/agent/command-parser.d.ts +33 -0
- package/dist/agent/command-parser.d.ts.map +1 -0
- package/dist/agent/command-parser.js +120 -0
- package/dist/agent/command-parser.js.map +1 -0
- package/dist/agent/context-budget.d.ts +91 -0
- package/dist/agent/context-budget.d.ts.map +1 -0
- package/dist/agent/context-budget.js +219 -0
- package/dist/agent/context-budget.js.map +1 -0
- package/dist/agent/conversation.d.ts +190 -0
- package/dist/agent/conversation.d.ts.map +1 -0
- package/dist/agent/conversation.js +547 -0
- package/dist/agent/conversation.js.map +1 -0
- package/dist/agent/hooks.d.ts +72 -0
- package/dist/agent/hooks.d.ts.map +1 -0
- package/dist/agent/hooks.js +214 -0
- package/dist/agent/hooks.js.map +1 -0
- package/dist/agent/mcp-bridge.d.ts +13 -0
- package/dist/agent/mcp-bridge.d.ts.map +1 -0
- package/dist/agent/mcp-bridge.js +86 -0
- package/dist/agent/mcp-bridge.js.map +1 -0
- package/dist/agent/mcp-client.d.ts +24 -0
- package/dist/agent/mcp-client.d.ts.map +1 -0
- package/dist/agent/mcp-client.js +146 -0
- package/dist/agent/mcp-client.js.map +1 -0
- package/dist/agent/mcp-manager.d.ts +13 -0
- package/dist/agent/mcp-manager.d.ts.map +1 -0
- package/dist/agent/mcp-manager.js +84 -0
- package/dist/agent/mcp-manager.js.map +1 -0
- package/dist/agent/mcp-registry.d.ts +45 -0
- package/dist/agent/mcp-registry.d.ts.map +1 -0
- package/dist/agent/mcp-registry.js +98 -0
- package/dist/agent/mcp-registry.js.map +1 -0
- package/dist/agent/orchestrator.d.ts +14 -0
- package/dist/agent/orchestrator.d.ts.map +1 -0
- package/dist/agent/orchestrator.js +118 -0
- package/dist/agent/orchestrator.js.map +1 -0
- package/dist/agent/parser-adapter.d.ts +120 -0
- package/dist/agent/parser-adapter.d.ts.map +1 -0
- package/dist/agent/parser-adapter.js +265 -0
- package/dist/agent/parser-adapter.js.map +1 -0
- package/dist/agent/parsers/imports.d.ts +11 -0
- package/dist/agent/parsers/imports.d.ts.map +1 -0
- package/dist/agent/parsers/imports.js +94 -0
- package/dist/agent/parsers/imports.js.map +1 -0
- package/dist/agent/parsers/shell.d.ts +23 -0
- package/dist/agent/parsers/shell.d.ts.map +1 -0
- package/dist/agent/parsers/shell.js +200 -0
- package/dist/agent/parsers/shell.js.map +1 -0
- package/dist/agent/parsers/symbols.d.ts +17 -0
- package/dist/agent/parsers/symbols.d.ts.map +1 -0
- package/dist/agent/parsers/symbols.js +103 -0
- package/dist/agent/parsers/symbols.js.map +1 -0
- package/dist/agent/permissions.d.ts +65 -0
- package/dist/agent/permissions.d.ts.map +1 -0
- package/dist/agent/permissions.js +219 -0
- package/dist/agent/permissions.js.map +1 -0
- package/dist/agent/predictive-gate.d.ts +69 -0
- package/dist/agent/predictive-gate.d.ts.map +1 -0
- package/dist/agent/predictive-gate.js +128 -0
- package/dist/agent/predictive-gate.js.map +1 -0
- package/dist/agent/provider-cooldown.d.ts +144 -0
- package/dist/agent/provider-cooldown.d.ts.map +1 -0
- package/dist/agent/provider-cooldown.js +300 -0
- package/dist/agent/provider-cooldown.js.map +1 -0
- package/dist/agent/providers-manager.d.ts +109 -0
- package/dist/agent/providers-manager.d.ts.map +1 -0
- package/dist/agent/providers-manager.js +464 -0
- package/dist/agent/providers-manager.js.map +1 -0
- package/dist/agent/repo-map.d.ts +6 -0
- package/dist/agent/repo-map.d.ts.map +1 -0
- package/dist/agent/repo-map.js +221 -0
- package/dist/agent/repo-map.js.map +1 -0
- package/dist/agent/retry.d.ts +103 -0
- package/dist/agent/retry.d.ts.map +1 -0
- package/dist/agent/retry.js +276 -0
- package/dist/agent/retry.js.map +1 -0
- package/dist/agent/search/index.d.ts +61 -0
- package/dist/agent/search/index.d.ts.map +1 -0
- package/dist/agent/search/index.js +314 -0
- package/dist/agent/search/index.js.map +1 -0
- package/dist/agent/single-agent.d.ts +76 -0
- package/dist/agent/single-agent.d.ts.map +1 -0
- package/dist/agent/single-agent.js +697 -0
- package/dist/agent/single-agent.js.map +1 -0
- package/dist/agent/skills.d.ts +22 -0
- package/dist/agent/skills.d.ts.map +1 -0
- package/dist/agent/skills.js +139 -0
- package/dist/agent/skills.js.map +1 -0
- package/dist/agent/stream-glue.d.ts +85 -0
- package/dist/agent/stream-glue.d.ts.map +1 -0
- package/dist/agent/stream-glue.js +120 -0
- package/dist/agent/stream-glue.js.map +1 -0
- package/dist/agent/subagent.d.ts +72 -0
- package/dist/agent/subagent.d.ts.map +1 -0
- package/dist/agent/subagent.js +193 -0
- package/dist/agent/subagent.js.map +1 -0
- package/dist/agent/telemetry.d.ts +192 -0
- package/dist/agent/telemetry.d.ts.map +1 -0
- package/dist/agent/telemetry.js +400 -0
- package/dist/agent/telemetry.js.map +1 -0
- package/dist/agent/tokenizer.d.ts +42 -0
- package/dist/agent/tokenizer.d.ts.map +1 -0
- package/dist/agent/tokenizer.js +107 -0
- package/dist/agent/tokenizer.js.map +1 -0
- package/dist/agent/tool-executor.d.ts +289 -0
- package/dist/agent/tool-executor.d.ts.map +1 -0
- package/dist/agent/tool-executor.js +2519 -0
- package/dist/agent/tool-executor.js.map +1 -0
- package/dist/agent/web-impl.d.ts +2 -0
- package/dist/agent/web-impl.d.ts.map +1 -0
- package/dist/agent/web-impl.js +34 -0
- package/dist/agent/web-impl.js.map +1 -0
- package/dist/agent/web.d.ts +8 -0
- package/dist/agent/web.d.ts.map +1 -0
- package/dist/agent/web.js +8 -0
- package/dist/agent/web.js.map +1 -0
- package/dist/agent/worker-agent.d.ts +27 -0
- package/dist/agent/worker-agent.d.ts.map +1 -0
- package/dist/agent/worker-agent.js +503 -0
- package/dist/agent/worker-agent.js.map +1 -0
- package/dist/config.d.ts +162 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +138 -0
- package/dist/config.js.map +1 -0
- package/dist/context/fixo-md-watcher.d.ts +42 -0
- package/dist/context/fixo-md-watcher.d.ts.map +1 -0
- package/dist/context/fixo-md-watcher.js +126 -0
- package/dist/context/fixo-md-watcher.js.map +1 -0
- package/dist/context/fixo-md.d.ts +50 -0
- package/dist/context/fixo-md.d.ts.map +1 -0
- package/dist/context/fixo-md.js +118 -0
- package/dist/context/fixo-md.js.map +1 -0
- package/dist/context/todo.d.ts +65 -0
- package/dist/context/todo.d.ts.map +1 -0
- package/dist/context/todo.js +194 -0
- package/dist/context/todo.js.map +1 -0
- package/dist/git/git-manager.d.ts +33 -0
- package/dist/git/git-manager.d.ts.map +1 -0
- package/dist/git/git-manager.js +293 -0
- package/dist/git/git-manager.js.map +1 -0
- package/dist/git/git-ops.d.ts +10 -0
- package/dist/git/git-ops.d.ts.map +1 -0
- package/dist/git/git-ops.js +131 -0
- package/dist/git/git-ops.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +352 -0
- package/dist/index.js.map +1 -0
- package/dist/indexer.d.ts +30 -0
- package/dist/indexer.d.ts.map +1 -0
- package/dist/indexer.js +273 -0
- package/dist/indexer.js.map +1 -0
- package/dist/lsp/lsp-client.d.ts +24 -0
- package/dist/lsp/lsp-client.d.ts.map +1 -0
- package/dist/lsp/lsp-client.js +205 -0
- package/dist/lsp/lsp-client.js.map +1 -0
- package/dist/lsp/lsp-manager.d.ts +17 -0
- package/dist/lsp/lsp-manager.d.ts.map +1 -0
- package/dist/lsp/lsp-manager.js +154 -0
- package/dist/lsp/lsp-manager.js.map +1 -0
- package/dist/lsp/lsp-pre-save.d.ts +137 -0
- package/dist/lsp/lsp-pre-save.d.ts.map +1 -0
- package/dist/lsp/lsp-pre-save.js +245 -0
- package/dist/lsp/lsp-pre-save.js.map +1 -0
- package/dist/lsp/syntax-fallback.d.ts +83 -0
- package/dist/lsp/syntax-fallback.d.ts.map +1 -0
- package/dist/lsp/syntax-fallback.js +275 -0
- package/dist/lsp/syntax-fallback.js.map +1 -0
- package/dist/model-outcomes.d.ts +12 -0
- package/dist/model-outcomes.d.ts.map +1 -0
- package/dist/model-outcomes.js +46 -0
- package/dist/model-outcomes.js.map +1 -0
- package/dist/planner.d.ts +32 -0
- package/dist/planner.d.ts.map +1 -0
- package/dist/planner.js +163 -0
- package/dist/planner.js.map +1 -0
- package/dist/project-memory.d.ts +29 -0
- package/dist/project-memory.d.ts.map +1 -0
- package/dist/project-memory.js +349 -0
- package/dist/project-memory.js.map +1 -0
- package/dist/review.d.ts +2 -0
- package/dist/review.d.ts.map +1 -0
- package/dist/review.js +61 -0
- package/dist/review.js.map +1 -0
- package/dist/runtime/background-jobs.d.ts +97 -0
- package/dist/runtime/background-jobs.d.ts.map +1 -0
- package/dist/runtime/background-jobs.js +331 -0
- package/dist/runtime/background-jobs.js.map +1 -0
- package/dist/runtime/credential-vault.d.ts +124 -0
- package/dist/runtime/credential-vault.d.ts.map +1 -0
- package/dist/runtime/credential-vault.js +184 -0
- package/dist/runtime/credential-vault.js.map +1 -0
- package/dist/runtime/loop-trap.d.ts +197 -0
- package/dist/runtime/loop-trap.d.ts.map +1 -0
- package/dist/runtime/loop-trap.js +420 -0
- package/dist/runtime/loop-trap.js.map +1 -0
- package/dist/runtime/policy.d.ts +15 -0
- package/dist/runtime/policy.d.ts.map +1 -0
- package/dist/runtime/policy.js +60 -0
- package/dist/runtime/policy.js.map +1 -0
- package/dist/runtime/redaction.d.ts +66 -0
- package/dist/runtime/redaction.d.ts.map +1 -0
- package/dist/runtime/redaction.js +155 -0
- package/dist/runtime/redaction.js.map +1 -0
- package/dist/runtime/session-snapshots.d.ts +76 -0
- package/dist/runtime/session-snapshots.d.ts.map +1 -0
- package/dist/runtime/session-snapshots.js +166 -0
- package/dist/runtime/session-snapshots.js.map +1 -0
- package/dist/runtime/staging.d.ts +205 -0
- package/dist/runtime/staging.d.ts.map +1 -0
- package/dist/runtime/staging.js +526 -0
- package/dist/runtime/staging.js.map +1 -0
- package/dist/runtime/task-session.d.ts +95 -0
- package/dist/runtime/task-session.d.ts.map +1 -0
- package/dist/runtime/task-session.js +263 -0
- package/dist/runtime/task-session.js.map +1 -0
- package/dist/runtime/worktree.d.ts +55 -0
- package/dist/runtime/worktree.d.ts.map +1 -0
- package/dist/runtime/worktree.js +175 -0
- package/dist/runtime/worktree.js.map +1 -0
- package/dist/setup-wizard.d.ts +8 -0
- package/dist/setup-wizard.d.ts.map +1 -0
- package/dist/setup-wizard.js +73 -0
- package/dist/setup-wizard.js.map +1 -0
- package/dist/shared/content.d.ts +43 -0
- package/dist/shared/content.d.ts.map +1 -0
- package/dist/shared/content.js +61 -0
- package/dist/shared/content.js.map +1 -0
- package/dist/shared/types.d.ts +217 -0
- package/dist/shared/types.d.ts.map +1 -0
- package/dist/shared/types.js +3 -0
- package/dist/shared/types.js.map +1 -0
- package/dist/test-runner.d.ts +5 -0
- package/dist/test-runner.d.ts.map +1 -0
- package/dist/test-runner.js +42 -0
- package/dist/test-runner.js.map +1 -0
- package/dist/types.d.ts +85 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/dist/ui/ascii.d.ts +23 -0
- package/dist/ui/ascii.d.ts.map +1 -0
- package/dist/ui/ascii.js +45 -0
- package/dist/ui/ascii.js.map +1 -0
- package/dist/ui/colors.d.ts +111 -0
- package/dist/ui/colors.d.ts.map +1 -0
- package/dist/ui/colors.js +166 -0
- package/dist/ui/colors.js.map +1 -0
- package/dist/ui/image-attach.d.ts +27 -0
- package/dist/ui/image-attach.d.ts.map +1 -0
- package/dist/ui/image-attach.js +100 -0
- package/dist/ui/image-attach.js.map +1 -0
- package/dist/ui/index.d.ts +18 -0
- package/dist/ui/index.d.ts.map +1 -0
- package/dist/ui/index.js +18 -0
- package/dist/ui/index.js.map +1 -0
- package/dist/ui/markdown-stream.d.ts +91 -0
- package/dist/ui/markdown-stream.d.ts.map +1 -0
- package/dist/ui/markdown-stream.js +524 -0
- package/dist/ui/markdown-stream.js.map +1 -0
- package/dist/ui/plan-renderer.d.ts +36 -0
- package/dist/ui/plan-renderer.d.ts.map +1 -0
- package/dist/ui/plan-renderer.js +79 -0
- package/dist/ui/plan-renderer.js.map +1 -0
- package/dist/ui/prompt.d.ts +11 -0
- package/dist/ui/prompt.d.ts.map +1 -0
- package/dist/ui/prompt.js +1960 -0
- package/dist/ui/prompt.js.map +1 -0
- package/dist/ui/render-primitives.d.ts +117 -0
- package/dist/ui/render-primitives.d.ts.map +1 -0
- package/dist/ui/render-primitives.js +322 -0
- package/dist/ui/render-primitives.js.map +1 -0
- package/dist/ui/render.d.ts +133 -0
- package/dist/ui/render.d.ts.map +1 -0
- package/dist/ui/render.js +547 -0
- package/dist/ui/render.js.map +1 -0
- package/dist/ui/session-header.d.ts +30 -0
- package/dist/ui/session-header.d.ts.map +1 -0
- package/dist/ui/session-header.js +74 -0
- package/dist/ui/session-header.js.map +1 -0
- package/dist/workspace-guard.d.ts +68 -0
- package/dist/workspace-guard.d.ts.map +1 -0
- package/dist/workspace-guard.js +168 -0
- package/dist/workspace-guard.js.map +1 -0
- package/dist/workspace-lock.d.ts +27 -0
- package/dist/workspace-lock.d.ts.map +1 -0
- package/dist/workspace-lock.js +95 -0
- package/dist/workspace-lock.js.map +1 -0
- package/package.json +63 -0
|
@@ -0,0 +1,263 @@
|
|
|
1
|
+
import crypto from 'crypto';
|
|
2
|
+
import fs from 'fs';
|
|
3
|
+
import path from 'path';
|
|
4
|
+
import { execFileSync } from 'child_process';
|
|
5
|
+
import { WorkspaceGuard } from '../workspace-guard.js';
|
|
6
|
+
import { redactSecrets } from './redaction.js';
|
|
7
|
+
export class TaskSession {
|
|
8
|
+
id;
|
|
9
|
+
cwd;
|
|
10
|
+
guard;
|
|
11
|
+
policy;
|
|
12
|
+
runDir;
|
|
13
|
+
startedAt;
|
|
14
|
+
readFiles = new Map();
|
|
15
|
+
changedFiles = new Map();
|
|
16
|
+
/**
|
|
17
|
+
* Tracks which files the agent has done a *structural* pre-scan on
|
|
18
|
+
* (via `extract_symbols` / `extract_imports`). The map is read by
|
|
19
|
+
* Pillar 3 (Context-Budget Guard) to verify that a large file the
|
|
20
|
+
* LLM wants to read was first reduced to its declarations. The
|
|
21
|
+
* `noteStructuralMap` and `hasStructuralMap` helpers below are
|
|
22
|
+
* intentionally side-effect-free for tests.
|
|
23
|
+
*/
|
|
24
|
+
structuralMaps = new Map();
|
|
25
|
+
summary;
|
|
26
|
+
constructor(opts) {
|
|
27
|
+
this.id = `${new Date().toISOString().replace(/[:.]/g, '-')}-${crypto.randomBytes(4).toString('hex')}`;
|
|
28
|
+
this.cwd = path.resolve(opts.cwd);
|
|
29
|
+
this.guard = new WorkspaceGuard(this.cwd);
|
|
30
|
+
this.policy = opts.policy ?? 'shell-confirm';
|
|
31
|
+
this.startedAt = new Date().toISOString();
|
|
32
|
+
this.runDir = path.join(this.cwd, '.fixo', 'runs', this.id);
|
|
33
|
+
fs.mkdirSync(this.runDir, { recursive: true });
|
|
34
|
+
fs.mkdirSync(path.join(this.runDir, 'snapshots'), { recursive: true });
|
|
35
|
+
this.summary = {
|
|
36
|
+
id: this.id,
|
|
37
|
+
task: opts.task,
|
|
38
|
+
model: opts.model,
|
|
39
|
+
cwd: this.cwd,
|
|
40
|
+
startedAt: this.startedAt,
|
|
41
|
+
status: 'running',
|
|
42
|
+
modifiedFiles: [],
|
|
43
|
+
verification: [],
|
|
44
|
+
};
|
|
45
|
+
this.writeSummary();
|
|
46
|
+
this.record('run_started', { task: opts.task, model: opts.model, policy: this.policy });
|
|
47
|
+
gcRuns(this.cwd, 50);
|
|
48
|
+
}
|
|
49
|
+
record(type, data = {}) {
|
|
50
|
+
const event = redactSecrets(JSON.stringify({ type, timestamp: new Date().toISOString(), ...data }));
|
|
51
|
+
fs.appendFileSync(path.join(this.runDir, 'events.jsonl'), `${event}\n`, 'utf-8');
|
|
52
|
+
}
|
|
53
|
+
noteRead(file) {
|
|
54
|
+
const resolved = this.guard.resolve(file, 'file');
|
|
55
|
+
this.readFiles.set(resolved, hashFile(resolved));
|
|
56
|
+
this.record('file_read', { file: this.guard.relative(resolved), hash: this.readFiles.get(resolved) });
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Mark a file as having been pre-scanned structurally. The
|
|
60
|
+
* `flags` object records which dimensions were extracted so
|
|
61
|
+
* Pillar 3 can decide whether the LLM is still missing
|
|
62
|
+
* information when it later calls `read_file` on the same path.
|
|
63
|
+
*/
|
|
64
|
+
noteStructuralMap(file, flags) {
|
|
65
|
+
const resolved = this.guard.resolve(file, 'file');
|
|
66
|
+
const existing = this.structuralMaps.get(resolved) ?? {
|
|
67
|
+
symbols: false,
|
|
68
|
+
imports: false,
|
|
69
|
+
};
|
|
70
|
+
this.structuralMaps.set(resolved, {
|
|
71
|
+
symbols: existing.symbols || flags.symbols,
|
|
72
|
+
imports: existing.imports || flags.imports,
|
|
73
|
+
});
|
|
74
|
+
this.record('structural_map', {
|
|
75
|
+
file: this.guard.relative(resolved),
|
|
76
|
+
...flags,
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Returns the structural pre-scan flags recorded for a file.
|
|
81
|
+
* Returns `null` if the file has never been pre-scanned — the
|
|
82
|
+
* caller should treat this as a hard-fail for the
|
|
83
|
+
* Context-Budget Guard rule.
|
|
84
|
+
*/
|
|
85
|
+
hasStructuralMap(file) {
|
|
86
|
+
const resolved = this.guard.resolve(file, 'file');
|
|
87
|
+
return this.structuralMaps.get(resolved) ?? null;
|
|
88
|
+
}
|
|
89
|
+
captureBefore(file) {
|
|
90
|
+
const resolved = this.guard.resolve(file, 'file');
|
|
91
|
+
if (this.changedFiles.has(resolved))
|
|
92
|
+
return;
|
|
93
|
+
const beforeHash = hashFile(resolved);
|
|
94
|
+
const beforeExists = beforeHash !== null;
|
|
95
|
+
let beforeSnapshot;
|
|
96
|
+
if (beforeExists) {
|
|
97
|
+
beforeSnapshot = path.join('snapshots', `${crypto.randomBytes(6).toString('hex')}.before`);
|
|
98
|
+
fs.copyFileSync(resolved, path.join(this.runDir, beforeSnapshot));
|
|
99
|
+
}
|
|
100
|
+
const record = {
|
|
101
|
+
file: this.guard.relative(resolved),
|
|
102
|
+
beforeHash,
|
|
103
|
+
afterHash: beforeHash,
|
|
104
|
+
beforeExists,
|
|
105
|
+
afterExists: beforeExists,
|
|
106
|
+
beforeSnapshot,
|
|
107
|
+
};
|
|
108
|
+
this.changedFiles.set(resolved, record);
|
|
109
|
+
this.writeChanges();
|
|
110
|
+
}
|
|
111
|
+
noteChange(file) {
|
|
112
|
+
const resolved = this.guard.resolve(file, 'file');
|
|
113
|
+
if (!this.changedFiles.has(resolved))
|
|
114
|
+
this.captureBefore(resolved);
|
|
115
|
+
const existing = this.changedFiles.get(resolved);
|
|
116
|
+
const after = hashFile(resolved);
|
|
117
|
+
existing.afterHash = after;
|
|
118
|
+
existing.afterExists = after !== null;
|
|
119
|
+
this.changedFiles.set(resolved, existing);
|
|
120
|
+
this.summary.modifiedFiles = Array.from(this.changedFiles.keys()).map(f => this.guard.relative(f));
|
|
121
|
+
this.writeChanges();
|
|
122
|
+
this.writeSummary();
|
|
123
|
+
this.record('file_changed', { file: this.guard.relative(resolved), before: existing.beforeHash, after });
|
|
124
|
+
}
|
|
125
|
+
canMutate(file) {
|
|
126
|
+
const resolved = this.guard.resolve(file, 'file');
|
|
127
|
+
if (!fs.existsSync(resolved))
|
|
128
|
+
return { ok: true };
|
|
129
|
+
const readHash = this.readFiles.get(resolved);
|
|
130
|
+
if (readHash === undefined) {
|
|
131
|
+
return { ok: false, reason: `Refusing to modify unread file: ${this.guard.relative(resolved)}` };
|
|
132
|
+
}
|
|
133
|
+
const currentHash = hashFile(resolved);
|
|
134
|
+
if (readHash !== currentHash) {
|
|
135
|
+
return { ok: false, reason: `Refusing stale edit; file changed since read: ${this.guard.relative(resolved)}` };
|
|
136
|
+
}
|
|
137
|
+
return { ok: true };
|
|
138
|
+
}
|
|
139
|
+
addVerification(message) {
|
|
140
|
+
this.summary.verification.push(redactSecrets(message));
|
|
141
|
+
this.writeSummary();
|
|
142
|
+
this.record('verification', { message });
|
|
143
|
+
}
|
|
144
|
+
finish(status, response) {
|
|
145
|
+
this.summary.status = status;
|
|
146
|
+
this.summary.endedAt = new Date().toISOString();
|
|
147
|
+
this.summary.response = redactSecrets(response);
|
|
148
|
+
this.writeSummary();
|
|
149
|
+
this.record('run_finished', { status });
|
|
150
|
+
}
|
|
151
|
+
writeSummary() {
|
|
152
|
+
fs.writeFileSync(path.join(this.runDir, 'run.json'), JSON.stringify(this.summary, null, 2) + '\n', 'utf-8');
|
|
153
|
+
}
|
|
154
|
+
writeChanges() {
|
|
155
|
+
fs.writeFileSync(path.join(this.runDir, 'changes.json'), JSON.stringify(Array.from(this.changedFiles.values()), null, 2) + '\n', 'utf-8');
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
export function hashFile(file) {
|
|
159
|
+
if (!fs.existsSync(file))
|
|
160
|
+
return null;
|
|
161
|
+
const stat = fs.statSync(file);
|
|
162
|
+
if (!stat.isFile())
|
|
163
|
+
return null;
|
|
164
|
+
return crypto.createHash('sha256').update(fs.readFileSync(file)).digest('hex');
|
|
165
|
+
}
|
|
166
|
+
export function gcRuns(cwd, keepLimit = 50) {
|
|
167
|
+
try {
|
|
168
|
+
const root = path.join(cwd, '.fixo', 'runs');
|
|
169
|
+
if (!fs.existsSync(root))
|
|
170
|
+
return;
|
|
171
|
+
const runs = fs.readdirSync(root).sort().reverse();
|
|
172
|
+
if (runs.length <= keepLimit)
|
|
173
|
+
return;
|
|
174
|
+
const toDelete = runs.slice(keepLimit);
|
|
175
|
+
for (const run of toDelete) {
|
|
176
|
+
fs.rmSync(path.join(root, run), { recursive: true, force: true });
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
catch (err) {
|
|
180
|
+
console.error('[TaskSession] Warning: failed to garbage collect old runs', err);
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
export function listRuns(cwd, limit = 10) {
|
|
184
|
+
const root = path.join(cwd, '.fixo', 'runs');
|
|
185
|
+
if (!fs.existsSync(root))
|
|
186
|
+
return [];
|
|
187
|
+
return fs.readdirSync(root)
|
|
188
|
+
.sort()
|
|
189
|
+
.reverse()
|
|
190
|
+
.slice(0, limit)
|
|
191
|
+
.map(id => {
|
|
192
|
+
const file = path.join(root, id, 'run.json');
|
|
193
|
+
if (!fs.existsSync(file))
|
|
194
|
+
return null;
|
|
195
|
+
return JSON.parse(fs.readFileSync(file, 'utf-8'));
|
|
196
|
+
})
|
|
197
|
+
.filter((run) => run !== null);
|
|
198
|
+
}
|
|
199
|
+
export function showRun(cwd, id) {
|
|
200
|
+
const file = path.join(cwd, '.fixo', 'runs', id, 'run.json');
|
|
201
|
+
if (!fs.existsSync(file))
|
|
202
|
+
return `Run not found: ${id}`;
|
|
203
|
+
const run = JSON.parse(fs.readFileSync(file, 'utf-8'));
|
|
204
|
+
return [
|
|
205
|
+
`Run ${run.id}`,
|
|
206
|
+
`Status: ${run.status}`,
|
|
207
|
+
`Task: ${run.task}`,
|
|
208
|
+
`Model: ${run.model}`,
|
|
209
|
+
`Started: ${run.startedAt}`,
|
|
210
|
+
`Ended: ${run.endedAt ?? 'running'}`,
|
|
211
|
+
`Files: ${run.modifiedFiles.length ? run.modifiedFiles.join(', ') : '(none)'}`,
|
|
212
|
+
`Verification: ${run.verification.length ? run.verification.join(' | ') : '(none)'}`,
|
|
213
|
+
].join('\n');
|
|
214
|
+
}
|
|
215
|
+
export function undoRun(cwd, id) {
|
|
216
|
+
const file = path.join(cwd, '.fixo', 'runs', id, 'run.json');
|
|
217
|
+
if (!fs.existsSync(file))
|
|
218
|
+
return `Run not found: ${id}`;
|
|
219
|
+
const runDir = path.dirname(file);
|
|
220
|
+
const changesFile = path.join(runDir, 'changes.json');
|
|
221
|
+
if (!fs.existsSync(changesFile))
|
|
222
|
+
return `Undo refused: run ${id} has no change ledger.`;
|
|
223
|
+
const guard = new WorkspaceGuard(cwd);
|
|
224
|
+
const changes = JSON.parse(fs.readFileSync(changesFile, 'utf-8'));
|
|
225
|
+
const conflicts = [];
|
|
226
|
+
for (const change of changes) {
|
|
227
|
+
const target = guard.resolve(change.file, 'rollback file');
|
|
228
|
+
const currentHash = hashFile(target);
|
|
229
|
+
if (currentHash !== change.afterHash) {
|
|
230
|
+
conflicts.push(`${change.file} changed after run (expected ${change.afterHash ?? 'missing'}, got ${currentHash ?? 'missing'})`);
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
if (conflicts.length > 0) {
|
|
234
|
+
return `Undo refused because files changed after the run:\n${conflicts.join('\n')}`;
|
|
235
|
+
}
|
|
236
|
+
for (const change of changes.slice().reverse()) {
|
|
237
|
+
const target = guard.resolve(change.file, 'rollback file');
|
|
238
|
+
if (change.beforeExists) {
|
|
239
|
+
if (!change.beforeSnapshot)
|
|
240
|
+
return `Undo failed: missing snapshot for ${change.file}`;
|
|
241
|
+
fs.mkdirSync(path.dirname(target), { recursive: true });
|
|
242
|
+
fs.copyFileSync(path.join(runDir, change.beforeSnapshot), target);
|
|
243
|
+
}
|
|
244
|
+
else if (fs.existsSync(target)) {
|
|
245
|
+
fs.unlinkSync(target);
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
return `Undid ${changes.length} file change(s) from run ${id}.`;
|
|
249
|
+
}
|
|
250
|
+
export function revertAgentCommit(cwd) {
|
|
251
|
+
try {
|
|
252
|
+
const message = execFileSync('git', ['log', '-1', '--format=%s'], { cwd, encoding: 'utf-8' }).trim();
|
|
253
|
+
if (!message.includes('[fixo-run:')) {
|
|
254
|
+
return 'Undo refused: last commit is not marked as a FixO-owned commit.';
|
|
255
|
+
}
|
|
256
|
+
execFileSync('git', ['revert', '--no-edit', 'HEAD'], { cwd, encoding: 'utf-8' });
|
|
257
|
+
return 'Performed a safe git revert of the last FixO-owned commit.';
|
|
258
|
+
}
|
|
259
|
+
catch (error) {
|
|
260
|
+
return `Undo failed: ${error instanceof Error ? error.message : String(error)}`;
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
//# sourceMappingURL=task-session.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"task-session.js","sourceRoot":"","sources":["../../src/runtime/task-session.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
export interface CreateWorktreeInput {
|
|
2
|
+
/** Branch to create (and check out in the new worktree). */
|
|
3
|
+
branch: string;
|
|
4
|
+
/** Base branch / ref to fork from. Default: 'HEAD'. */
|
|
5
|
+
base?: string;
|
|
6
|
+
/** Where to put the worktree directory. Default: `<cwd>/.fixo/worktrees/<branch>`. */
|
|
7
|
+
path?: string;
|
|
8
|
+
}
|
|
9
|
+
export interface WorktreeResult {
|
|
10
|
+
ok: boolean;
|
|
11
|
+
/** Path to the new worktree (create) / merged branch name (merge) / removed path (remove). */
|
|
12
|
+
detail: string;
|
|
13
|
+
/** Captured git output. */
|
|
14
|
+
output: string;
|
|
15
|
+
/** Error message, if any. */
|
|
16
|
+
error?: string;
|
|
17
|
+
}
|
|
18
|
+
/** Create a new worktree at `path` on `branch` forked from `base`. */
|
|
19
|
+
export declare function createWorktree(cwd: string, input: CreateWorktreeInput): WorktreeResult;
|
|
20
|
+
/** Merge the worktree's branch back into the current branch of `cwd`. */
|
|
21
|
+
export declare function mergeWorktree(cwd: string, branch: string, targetBranch?: string): WorktreeResult;
|
|
22
|
+
/** Remove a worktree at `worktreePath` and (optionally) delete its branch. */
|
|
23
|
+
export declare function removeWorktree(cwd: string, worktreePath: string, opts?: {
|
|
24
|
+
deleteBranch?: boolean;
|
|
25
|
+
branch?: string;
|
|
26
|
+
}): WorktreeResult;
|
|
27
|
+
export type WorktreeAnnotation = {
|
|
28
|
+
op: 'create';
|
|
29
|
+
branch: string;
|
|
30
|
+
base?: string;
|
|
31
|
+
path?: string;
|
|
32
|
+
} | {
|
|
33
|
+
op: 'merge';
|
|
34
|
+
branch: string;
|
|
35
|
+
} | {
|
|
36
|
+
op: 'remove';
|
|
37
|
+
path: string;
|
|
38
|
+
deleteBranch?: boolean;
|
|
39
|
+
branch?: string;
|
|
40
|
+
};
|
|
41
|
+
/**
|
|
42
|
+
* Extract all worktree annotations from `text`. Annotations
|
|
43
|
+
* are returned in the order they appear. The text is not
|
|
44
|
+
* mutated.
|
|
45
|
+
*/
|
|
46
|
+
export declare function parseWorktreeAnnotations(text: string): WorktreeAnnotation[];
|
|
47
|
+
/**
|
|
48
|
+
* Apply a list of worktree annotations. Each annotation runs
|
|
49
|
+
* in order; failures are returned but do not stop the chain.
|
|
50
|
+
* Returns a list of results, one per annotation.
|
|
51
|
+
*/
|
|
52
|
+
export declare function applyWorktreeAnnotations(cwd: string, annotations: WorktreeAnnotation[]): WorktreeResult[];
|
|
53
|
+
/** Strip worktree annotations from a string (used to clean the assistant output). */
|
|
54
|
+
export declare function stripWorktreeAnnotations(text: string): string;
|
|
55
|
+
//# sourceMappingURL=worktree.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"worktree.d.ts","sourceRoot":"","sources":["../../src/runtime/worktree.ts"],"names":[],"mappings":"AAoCA,MAAM,WAAW,mBAAmB;IAClC,4DAA4D;IAC5D,MAAM,EAAE,MAAM,CAAC;IACf,uDAAuD;IACvD,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,sFAAsF;IACtF,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,OAAO,CAAC;IACZ,8FAA8F;IAC9F,MAAM,EAAE,MAAM,CAAC;IACf,2BAA2B;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,6BAA6B;IAC7B,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAOD,sEAAsE;AACtE,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,mBAAmB,GAAG,cAAc,CAYtF;AAED,yEAAyE;AACzE,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,YAAY,CAAC,EAAE,MAAM,GAAG,cAAc,CAUhG;AAED,8EAA8E;AAC9E,wBAAgB,cAAc,CAC5B,GAAG,EAAE,MAAM,EACX,YAAY,EAAE,MAAM,EACpB,IAAI,GAAE;IAAE,YAAY,CAAC,EAAE,OAAO,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAO,GACrD,cAAc,CAkBhB;AAID,MAAM,MAAM,kBAAkB,GAC1B;IAAE,EAAE,EAAE,QAAQ,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,GAC9D;IAAE,EAAE,EAAE,OAAO,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GAC/B;IAAE,EAAE,EAAE,QAAQ,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,YAAY,CAAC,EAAE,OAAO,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AA0C5E;;;;GAIG;AACH,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,MAAM,GAAG,kBAAkB,EAAE,CAY3E;AAED;;;;GAIG;AACH,wBAAgB,wBAAwB,CACtC,GAAG,EAAE,MAAM,EACX,WAAW,EAAE,kBAAkB,EAAE,GAChC,cAAc,EAAE,CAclB;AAED,qFAAqF;AACrF,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAE7D"}
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* worktree.ts — Git worktree management + annotation parser.
|
|
3
|
+
*
|
|
4
|
+
* Phase 3.6 spec:
|
|
5
|
+
* - Three operations: create / merge / remove.
|
|
6
|
+
* - NOT exposed as a tool. Instead, the SingleAgent scans
|
|
7
|
+
* its final assistant message for inline annotations of
|
|
8
|
+
* the form `[worktree:create branch=x]` / `[worktree:merge]`
|
|
9
|
+
* / `[worktree:remove]` and dispatches the corresponding
|
|
10
|
+
* worktree operation.
|
|
11
|
+
* - All operations are guarded by `git isGitRepo(cwd)` and
|
|
12
|
+
* use `execFileSync('git', ...)` so we never go through a
|
|
13
|
+
* shell.
|
|
14
|
+
*
|
|
15
|
+
* Annotation format (single line, anywhere in assistant text):
|
|
16
|
+
* [worktree:create branch=foo]
|
|
17
|
+
* [worktree:create branch=foo base=main]
|
|
18
|
+
* [worktree:merge]
|
|
19
|
+
* [worktree:remove path=<absolute path to worktree>]
|
|
20
|
+
*/
|
|
21
|
+
import { execFileSync } from 'node:child_process';
|
|
22
|
+
function runGit(cwd, args) {
|
|
23
|
+
try {
|
|
24
|
+
return execFileSync('git', args, {
|
|
25
|
+
cwd,
|
|
26
|
+
encoding: 'utf-8',
|
|
27
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
28
|
+
}).trim();
|
|
29
|
+
}
|
|
30
|
+
catch (error) {
|
|
31
|
+
const err = error;
|
|
32
|
+
const stderr = typeof err.stderr === 'string' ? err.stderr : (err.stderr ? err.stderr.toString() : err.message ?? '');
|
|
33
|
+
throw new Error(`Git error (git ${args.join(' ')}): ${stderr.trim()}`);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
function defaultWorktreePath(cwd, branch) {
|
|
37
|
+
const safe = branch.replace(/[^A-Za-z0-9._/-]/g, '-');
|
|
38
|
+
return `${cwd}/.fixo/worktrees/${safe}`;
|
|
39
|
+
}
|
|
40
|
+
/** Create a new worktree at `path` on `branch` forked from `base`. */
|
|
41
|
+
export function createWorktree(cwd, input) {
|
|
42
|
+
if (!input.branch || typeof input.branch !== 'string') {
|
|
43
|
+
return { ok: false, detail: '', output: '', error: 'createWorktree: branch is required' };
|
|
44
|
+
}
|
|
45
|
+
const worktreePath = input.path ?? defaultWorktreePath(cwd, input.branch);
|
|
46
|
+
const base = input.base ?? 'HEAD';
|
|
47
|
+
try {
|
|
48
|
+
const out = runGit(cwd, ['worktree', 'add', '-b', input.branch, worktreePath, base]);
|
|
49
|
+
return { ok: true, detail: worktreePath, output: out };
|
|
50
|
+
}
|
|
51
|
+
catch (err) {
|
|
52
|
+
return { ok: false, detail: worktreePath, output: '', error: err.message };
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
/** Merge the worktree's branch back into the current branch of `cwd`. */
|
|
56
|
+
export function mergeWorktree(cwd, branch, targetBranch) {
|
|
57
|
+
if (!branch) {
|
|
58
|
+
return { ok: false, detail: '', output: '', error: 'mergeWorktree: branch is required' };
|
|
59
|
+
}
|
|
60
|
+
try {
|
|
61
|
+
const out = runGit(cwd, ['merge', '--no-ff', branch, '-m', `Merge worktree branch ${branch}`]);
|
|
62
|
+
return { ok: true, detail: targetBranch ?? branch, output: out };
|
|
63
|
+
}
|
|
64
|
+
catch (err) {
|
|
65
|
+
return { ok: false, detail: branch, output: '', error: err.message };
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
/** Remove a worktree at `worktreePath` and (optionally) delete its branch. */
|
|
69
|
+
export function removeWorktree(cwd, worktreePath, opts = {}) {
|
|
70
|
+
if (!worktreePath) {
|
|
71
|
+
return { ok: false, detail: '', output: '', error: 'removeWorktree: worktreePath is required' };
|
|
72
|
+
}
|
|
73
|
+
try {
|
|
74
|
+
const out = runGit(cwd, ['worktree', 'remove', worktreePath, '--force']);
|
|
75
|
+
let extra = '';
|
|
76
|
+
if (opts.deleteBranch && opts.branch) {
|
|
77
|
+
try {
|
|
78
|
+
extra = '\n' + runGit(cwd, ['branch', '-D', opts.branch]);
|
|
79
|
+
}
|
|
80
|
+
catch {
|
|
81
|
+
// Branch may already be gone or merged — non-fatal.
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
return { ok: true, detail: worktreePath, output: out + extra };
|
|
85
|
+
}
|
|
86
|
+
catch (err) {
|
|
87
|
+
return { ok: false, detail: worktreePath, output: '', error: err.message };
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
const ANNOTATION_RE = /\[worktree:(\w+)([^\]]*)\]/g;
|
|
91
|
+
/**
|
|
92
|
+
* Extract a single annotation from a `[worktree:op key=value ...]`
|
|
93
|
+
* token. Returns null if the token is malformed.
|
|
94
|
+
*/
|
|
95
|
+
function parseOneAnnotation(op, body) {
|
|
96
|
+
// Parse key=value pairs (values may be quoted; we accept
|
|
97
|
+
// any non-whitespace token).
|
|
98
|
+
const pairs = {};
|
|
99
|
+
const re = /(\w+)=(?:"([^"]*)"|(\S+))/g;
|
|
100
|
+
let m;
|
|
101
|
+
while ((m = re.exec(body)) !== null) {
|
|
102
|
+
pairs[m[1]] = m[2] ?? m[3] ?? '';
|
|
103
|
+
}
|
|
104
|
+
if (op === 'create') {
|
|
105
|
+
if (!pairs.branch)
|
|
106
|
+
return null;
|
|
107
|
+
return {
|
|
108
|
+
op: 'create',
|
|
109
|
+
branch: pairs.branch,
|
|
110
|
+
base: pairs.base,
|
|
111
|
+
path: pairs.path,
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
if (op === 'merge') {
|
|
115
|
+
if (!pairs.branch)
|
|
116
|
+
return null;
|
|
117
|
+
return { op: 'merge', branch: pairs.branch };
|
|
118
|
+
}
|
|
119
|
+
if (op === 'remove') {
|
|
120
|
+
if (!pairs.path)
|
|
121
|
+
return null;
|
|
122
|
+
return {
|
|
123
|
+
op: 'remove',
|
|
124
|
+
path: pairs.path,
|
|
125
|
+
deleteBranch: pairs.deleteBranch === 'true' || pairs.deleteBranch === '1',
|
|
126
|
+
branch: pairs.branch,
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
return null;
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Extract all worktree annotations from `text`. Annotations
|
|
133
|
+
* are returned in the order they appear. The text is not
|
|
134
|
+
* mutated.
|
|
135
|
+
*/
|
|
136
|
+
export function parseWorktreeAnnotations(text) {
|
|
137
|
+
if (typeof text !== 'string' || text.length === 0)
|
|
138
|
+
return [];
|
|
139
|
+
const out = [];
|
|
140
|
+
ANNOTATION_RE.lastIndex = 0;
|
|
141
|
+
let m;
|
|
142
|
+
while ((m = ANNOTATION_RE.exec(text)) !== null) {
|
|
143
|
+
const op = m[1];
|
|
144
|
+
const body = m[2] ?? '';
|
|
145
|
+
const parsed = parseOneAnnotation(op, body);
|
|
146
|
+
if (parsed)
|
|
147
|
+
out.push(parsed);
|
|
148
|
+
}
|
|
149
|
+
return out;
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* Apply a list of worktree annotations. Each annotation runs
|
|
153
|
+
* in order; failures are returned but do not stop the chain.
|
|
154
|
+
* Returns a list of results, one per annotation.
|
|
155
|
+
*/
|
|
156
|
+
export function applyWorktreeAnnotations(cwd, annotations) {
|
|
157
|
+
return annotations.map(ann => {
|
|
158
|
+
if (ann.op === 'create') {
|
|
159
|
+
return createWorktree(cwd, { branch: ann.branch, base: ann.base, path: ann.path });
|
|
160
|
+
}
|
|
161
|
+
if (ann.op === 'merge') {
|
|
162
|
+
return mergeWorktree(cwd, ann.branch);
|
|
163
|
+
}
|
|
164
|
+
// remove
|
|
165
|
+
return removeWorktree(cwd, ann.path, {
|
|
166
|
+
deleteBranch: ann.deleteBranch,
|
|
167
|
+
branch: ann.branch,
|
|
168
|
+
});
|
|
169
|
+
});
|
|
170
|
+
}
|
|
171
|
+
/** Strip worktree annotations from a string (used to clean the assistant output). */
|
|
172
|
+
export function stripWorktreeAnnotations(text) {
|
|
173
|
+
return text.replace(ANNOTATION_RE, '').replace(/[ \t]{2,}/g, ' ').trim();
|
|
174
|
+
}
|
|
175
|
+
//# sourceMappingURL=worktree.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"worktree.js","sourceRoot":"","sources":["../../src/runtime/worktree.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { FreeLLMConfig } from './config.js';
|
|
2
|
+
/**
|
|
3
|
+
* Runs the interactive first-run setup wizard for FixO CLI.
|
|
4
|
+
* Links the CLI terminal to the FreeLLMAPI SaaS cloud by prompting
|
|
5
|
+
* for the master API key, destination URL, and saving it to the configuration.
|
|
6
|
+
*/
|
|
7
|
+
export declare function runSetupWizard(): Promise<FreeLLMConfig>;
|
|
8
|
+
//# sourceMappingURL=setup-wizard.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"setup-wizard.d.ts","sourceRoot":"","sources":["../src/setup-wizard.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAGjD;;;;GAIG;AACH,wBAAsB,cAAc,IAAI,OAAO,CAAC,aAAa,CAAC,CA0E7D"}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import * as p from '@clack/prompts';
|
|
2
|
+
import { getDefaultConfig, saveConfig, DEFAULT_API_URL } from './config.js';
|
|
3
|
+
/**
|
|
4
|
+
* Runs the interactive first-run setup wizard for FixO CLI.
|
|
5
|
+
* Links the CLI terminal to the FreeLLMAPI SaaS cloud by prompting
|
|
6
|
+
* for the master API key, destination URL, and saving it to the configuration.
|
|
7
|
+
*/
|
|
8
|
+
export async function runSetupWizard() {
|
|
9
|
+
p.intro('🚀 Welcome to FixO CLI Setup');
|
|
10
|
+
console.log(`┌────────────────────────────────────────────────────────────────┐
|
|
11
|
+
│ 🚀 Welcome to FixO CLI! │
|
|
12
|
+
│ Let's link your CLI terminal to your FreeLLMAPI SaaS cloud. │
|
|
13
|
+
│ │
|
|
14
|
+
│ 1. Open your web browser and navigate to your dashboard. │
|
|
15
|
+
│ 2. Sign in to your account. │
|
|
16
|
+
│ 3. Navigate to the Profile / API Keys section. │
|
|
17
|
+
│ 4. Copy your master 'FreeLLMAPI' API key. │
|
|
18
|
+
└────────────────────────────────────────────────────────────────┘\n`);
|
|
19
|
+
const serverChoice = await p.select({
|
|
20
|
+
message: 'Select your FreeLLMAPI server endpoint:',
|
|
21
|
+
options: [
|
|
22
|
+
{ value: DEFAULT_API_URL, label: 'Cloud Hosted SaaS (Default)' },
|
|
23
|
+
{ value: 'http://localhost:3001/v1', label: 'Local Development Server (http://localhost:3001/v1)' },
|
|
24
|
+
{ value: 'custom', label: 'Custom Endpoint URL' },
|
|
25
|
+
],
|
|
26
|
+
});
|
|
27
|
+
if (p.isCancel(serverChoice)) {
|
|
28
|
+
p.outro('Setup cancelled.');
|
|
29
|
+
process.exit(1);
|
|
30
|
+
}
|
|
31
|
+
let apiUrl = serverChoice;
|
|
32
|
+
if (serverChoice === 'custom') {
|
|
33
|
+
const customUrl = await p.text({
|
|
34
|
+
message: 'Enter your custom FreeLLMAPI Endpoint URL:',
|
|
35
|
+
placeholder: 'https://api.custom-domain.com/v1',
|
|
36
|
+
validate: (val) => {
|
|
37
|
+
if (!val.trim())
|
|
38
|
+
return 'URL is required';
|
|
39
|
+
return;
|
|
40
|
+
},
|
|
41
|
+
});
|
|
42
|
+
if (p.isCancel(customUrl)) {
|
|
43
|
+
p.outro('Setup cancelled.');
|
|
44
|
+
process.exit(1);
|
|
45
|
+
}
|
|
46
|
+
apiUrl = customUrl.trim();
|
|
47
|
+
}
|
|
48
|
+
const apiKeyInput = await p.text({
|
|
49
|
+
message: 'Enter your FreeLLMAPI API key:',
|
|
50
|
+
placeholder: 'freellmapi-user-sk-...',
|
|
51
|
+
validate: (val) => {
|
|
52
|
+
if (!val.trim()) {
|
|
53
|
+
return 'API key is required';
|
|
54
|
+
}
|
|
55
|
+
if (!val.trim().startsWith('freellmapi-')) {
|
|
56
|
+
return 'API key must start with "freellmapi-"';
|
|
57
|
+
}
|
|
58
|
+
return;
|
|
59
|
+
},
|
|
60
|
+
});
|
|
61
|
+
if (p.isCancel(apiKeyInput)) {
|
|
62
|
+
p.outro('Setup cancelled. FixO CLI requires an API key to function.');
|
|
63
|
+
process.exit(1);
|
|
64
|
+
}
|
|
65
|
+
const config = getDefaultConfig();
|
|
66
|
+
config.freellmapi_api_key = apiKeyInput.trim();
|
|
67
|
+
config.apiUrl = apiUrl;
|
|
68
|
+
config._firstRunComplete = true;
|
|
69
|
+
saveConfig(config);
|
|
70
|
+
p.outro('✓ Configuration saved to ~/.fixocli/config.json');
|
|
71
|
+
return config;
|
|
72
|
+
}
|
|
73
|
+
//# sourceMappingURL=setup-wizard.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"setup-wizard.js","sourceRoot":"","sources":["../src/setup-wizard.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,CAAC,MAAM,gBAAgB,CAAC;AAEpC,OAAO,EAAE,gBAAgB,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAE5E;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc;IAClC,CAAC,CAAC,KAAK,CAAC,8BAA8B,CAAC,CAAC;IAExC,OAAO,CAAC,GAAG,CAAC;;;;;;;;qEAQuD,CAAC,CAAC;IAErE,MAAM,YAAY,GAAG,MAAM,CAAC,CAAC,MAAM,CAAC;QAClC,OAAO,EAAE,yCAAyC;QAClD,OAAO,EAAE;YACP,EAAE,KAAK,EAAE,eAAe,EAAE,KAAK,EAAE,6BAA6B,EAAE;YAChE,EAAE,KAAK,EAAE,0BAA0B,EAAE,KAAK,EAAE,qDAAqD,EAAE;YACnG,EAAE,KAAK,EAAE,QAAQ,EAAE,KAAK,EAAE,qBAAqB,EAAE;SAClD;KACF,CAAC,CAAC;IAEH,IAAI,CAAC,CAAC,QAAQ,CAAC,YAAY,CAAC,EAAE,CAAC;QAC7B,CAAC,CAAC,KAAK,CAAC,kBAAkB,CAAC,CAAC;QAC5B,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,IAAI,MAAM,GAAG,YAAsB,CAAC;IACpC,IAAI,YAAY,KAAK,QAAQ,EAAE,CAAC;QAC9B,MAAM,SAAS,GAAG,MAAM,CAAC,CAAC,IAAI,CAAC;YAC7B,OAAO,EAAE,4CAA4C;YACrD,WAAW,EAAE,kCAAkC;YAC/C,QAAQ,EAAE,CAAC,GAAG,EAAE,EAAE;gBAChB,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE;oBAAE,OAAO,iBAAiB,CAAC;gBAC1C,OAAO;YACT,CAAC;SACF,CAAC,CAAC;QAEH,IAAI,CAAC,CAAC,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC;YAC1B,CAAC,CAAC,KAAK,CAAC,kBAAkB,CAAC,CAAC;YAC5B,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QACD,MAAM,GAAG,SAAS,CAAC,IAAI,EAAE,CAAC;IAC5B,CAAC;IAED,MAAM,WAAW,GAAG,MAAM,CAAC,CAAC,IAAI,CAAC;QAC/B,OAAO,EAAE,gCAAgC;QACzC,WAAW,EAAE,wBAAwB;QACrC,QAAQ,EAAE,CAAC,GAAG,EAAE,EAAE;YAChB,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,EAAE,CAAC;gBAChB,OAAO,qBAAqB,CAAC;YAC/B,CAAC;YACD,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,UAAU,CAAC,aAAa,CAAC,EAAE,CAAC;gBAC1C,OAAO,uCAAuC,CAAC;YACjD,CAAC;YACD,OAAO;QACT,CAAC;KACF,CAAC,CAAC;IAEH,IAAI,CAAC,CAAC,QAAQ,CAAC,WAAW,CAAC,EAAE,CAAC;QAC5B,CAAC,CAAC,KAAK,CAAC,4DAA4D,CAAC,CAAC;QACtE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,MAAM,MAAM,GAAG,gBAAgB,EAAE,CAAC;IAClC,MAAM,CAAC,kBAAkB,GAAG,WAAW,CAAC,IAAI,EAAE,CAAC;IAC/C,MAAM,CAAC,MAAM,GAAG,MAAM,CAAC;IACvB,MAAM,CAAC,iBAAiB,GAAG,IAAI,CAAC;IAEhC,UAAU,CAAC,MAAM,CAAC,CAAC;IAEnB,CAAC,CAAC,KAAK,CAAC,iDAAiD,CAAC,CAAC;IAE3D,OAAO,MAAM,CAAC;AAChB,CAAC"}
|