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.
Files changed (303) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +530 -0
  3. package/dist/agent/agent-client.d.ts +108 -0
  4. package/dist/agent/agent-client.d.ts.map +1 -0
  5. package/dist/agent/agent-client.js +1247 -0
  6. package/dist/agent/agent-client.js.map +1 -0
  7. package/dist/agent/agent-pool.d.ts +20 -0
  8. package/dist/agent/agent-pool.d.ts.map +1 -0
  9. package/dist/agent/agent-pool.js +217 -0
  10. package/dist/agent/agent-pool.js.map +1 -0
  11. package/dist/agent/background-awareness.d.ts +55 -0
  12. package/dist/agent/background-awareness.d.ts.map +1 -0
  13. package/dist/agent/background-awareness.js +104 -0
  14. package/dist/agent/background-awareness.js.map +1 -0
  15. package/dist/agent/command-parser.d.ts +33 -0
  16. package/dist/agent/command-parser.d.ts.map +1 -0
  17. package/dist/agent/command-parser.js +120 -0
  18. package/dist/agent/command-parser.js.map +1 -0
  19. package/dist/agent/context-budget.d.ts +91 -0
  20. package/dist/agent/context-budget.d.ts.map +1 -0
  21. package/dist/agent/context-budget.js +219 -0
  22. package/dist/agent/context-budget.js.map +1 -0
  23. package/dist/agent/conversation.d.ts +190 -0
  24. package/dist/agent/conversation.d.ts.map +1 -0
  25. package/dist/agent/conversation.js +547 -0
  26. package/dist/agent/conversation.js.map +1 -0
  27. package/dist/agent/hooks.d.ts +72 -0
  28. package/dist/agent/hooks.d.ts.map +1 -0
  29. package/dist/agent/hooks.js +214 -0
  30. package/dist/agent/hooks.js.map +1 -0
  31. package/dist/agent/mcp-bridge.d.ts +13 -0
  32. package/dist/agent/mcp-bridge.d.ts.map +1 -0
  33. package/dist/agent/mcp-bridge.js +86 -0
  34. package/dist/agent/mcp-bridge.js.map +1 -0
  35. package/dist/agent/mcp-client.d.ts +24 -0
  36. package/dist/agent/mcp-client.d.ts.map +1 -0
  37. package/dist/agent/mcp-client.js +146 -0
  38. package/dist/agent/mcp-client.js.map +1 -0
  39. package/dist/agent/mcp-manager.d.ts +13 -0
  40. package/dist/agent/mcp-manager.d.ts.map +1 -0
  41. package/dist/agent/mcp-manager.js +84 -0
  42. package/dist/agent/mcp-manager.js.map +1 -0
  43. package/dist/agent/mcp-registry.d.ts +45 -0
  44. package/dist/agent/mcp-registry.d.ts.map +1 -0
  45. package/dist/agent/mcp-registry.js +98 -0
  46. package/dist/agent/mcp-registry.js.map +1 -0
  47. package/dist/agent/orchestrator.d.ts +14 -0
  48. package/dist/agent/orchestrator.d.ts.map +1 -0
  49. package/dist/agent/orchestrator.js +118 -0
  50. package/dist/agent/orchestrator.js.map +1 -0
  51. package/dist/agent/parser-adapter.d.ts +120 -0
  52. package/dist/agent/parser-adapter.d.ts.map +1 -0
  53. package/dist/agent/parser-adapter.js +265 -0
  54. package/dist/agent/parser-adapter.js.map +1 -0
  55. package/dist/agent/parsers/imports.d.ts +11 -0
  56. package/dist/agent/parsers/imports.d.ts.map +1 -0
  57. package/dist/agent/parsers/imports.js +94 -0
  58. package/dist/agent/parsers/imports.js.map +1 -0
  59. package/dist/agent/parsers/shell.d.ts +23 -0
  60. package/dist/agent/parsers/shell.d.ts.map +1 -0
  61. package/dist/agent/parsers/shell.js +200 -0
  62. package/dist/agent/parsers/shell.js.map +1 -0
  63. package/dist/agent/parsers/symbols.d.ts +17 -0
  64. package/dist/agent/parsers/symbols.d.ts.map +1 -0
  65. package/dist/agent/parsers/symbols.js +103 -0
  66. package/dist/agent/parsers/symbols.js.map +1 -0
  67. package/dist/agent/permissions.d.ts +65 -0
  68. package/dist/agent/permissions.d.ts.map +1 -0
  69. package/dist/agent/permissions.js +219 -0
  70. package/dist/agent/permissions.js.map +1 -0
  71. package/dist/agent/predictive-gate.d.ts +69 -0
  72. package/dist/agent/predictive-gate.d.ts.map +1 -0
  73. package/dist/agent/predictive-gate.js +128 -0
  74. package/dist/agent/predictive-gate.js.map +1 -0
  75. package/dist/agent/provider-cooldown.d.ts +144 -0
  76. package/dist/agent/provider-cooldown.d.ts.map +1 -0
  77. package/dist/agent/provider-cooldown.js +300 -0
  78. package/dist/agent/provider-cooldown.js.map +1 -0
  79. package/dist/agent/providers-manager.d.ts +109 -0
  80. package/dist/agent/providers-manager.d.ts.map +1 -0
  81. package/dist/agent/providers-manager.js +464 -0
  82. package/dist/agent/providers-manager.js.map +1 -0
  83. package/dist/agent/repo-map.d.ts +6 -0
  84. package/dist/agent/repo-map.d.ts.map +1 -0
  85. package/dist/agent/repo-map.js +221 -0
  86. package/dist/agent/repo-map.js.map +1 -0
  87. package/dist/agent/retry.d.ts +103 -0
  88. package/dist/agent/retry.d.ts.map +1 -0
  89. package/dist/agent/retry.js +276 -0
  90. package/dist/agent/retry.js.map +1 -0
  91. package/dist/agent/search/index.d.ts +61 -0
  92. package/dist/agent/search/index.d.ts.map +1 -0
  93. package/dist/agent/search/index.js +314 -0
  94. package/dist/agent/search/index.js.map +1 -0
  95. package/dist/agent/single-agent.d.ts +76 -0
  96. package/dist/agent/single-agent.d.ts.map +1 -0
  97. package/dist/agent/single-agent.js +697 -0
  98. package/dist/agent/single-agent.js.map +1 -0
  99. package/dist/agent/skills.d.ts +22 -0
  100. package/dist/agent/skills.d.ts.map +1 -0
  101. package/dist/agent/skills.js +139 -0
  102. package/dist/agent/skills.js.map +1 -0
  103. package/dist/agent/stream-glue.d.ts +85 -0
  104. package/dist/agent/stream-glue.d.ts.map +1 -0
  105. package/dist/agent/stream-glue.js +120 -0
  106. package/dist/agent/stream-glue.js.map +1 -0
  107. package/dist/agent/subagent.d.ts +72 -0
  108. package/dist/agent/subagent.d.ts.map +1 -0
  109. package/dist/agent/subagent.js +193 -0
  110. package/dist/agent/subagent.js.map +1 -0
  111. package/dist/agent/telemetry.d.ts +192 -0
  112. package/dist/agent/telemetry.d.ts.map +1 -0
  113. package/dist/agent/telemetry.js +400 -0
  114. package/dist/agent/telemetry.js.map +1 -0
  115. package/dist/agent/tokenizer.d.ts +42 -0
  116. package/dist/agent/tokenizer.d.ts.map +1 -0
  117. package/dist/agent/tokenizer.js +107 -0
  118. package/dist/agent/tokenizer.js.map +1 -0
  119. package/dist/agent/tool-executor.d.ts +289 -0
  120. package/dist/agent/tool-executor.d.ts.map +1 -0
  121. package/dist/agent/tool-executor.js +2519 -0
  122. package/dist/agent/tool-executor.js.map +1 -0
  123. package/dist/agent/web-impl.d.ts +2 -0
  124. package/dist/agent/web-impl.d.ts.map +1 -0
  125. package/dist/agent/web-impl.js +34 -0
  126. package/dist/agent/web-impl.js.map +1 -0
  127. package/dist/agent/web.d.ts +8 -0
  128. package/dist/agent/web.d.ts.map +1 -0
  129. package/dist/agent/web.js +8 -0
  130. package/dist/agent/web.js.map +1 -0
  131. package/dist/agent/worker-agent.d.ts +27 -0
  132. package/dist/agent/worker-agent.d.ts.map +1 -0
  133. package/dist/agent/worker-agent.js +503 -0
  134. package/dist/agent/worker-agent.js.map +1 -0
  135. package/dist/config.d.ts +162 -0
  136. package/dist/config.d.ts.map +1 -0
  137. package/dist/config.js +138 -0
  138. package/dist/config.js.map +1 -0
  139. package/dist/context/fixo-md-watcher.d.ts +42 -0
  140. package/dist/context/fixo-md-watcher.d.ts.map +1 -0
  141. package/dist/context/fixo-md-watcher.js +126 -0
  142. package/dist/context/fixo-md-watcher.js.map +1 -0
  143. package/dist/context/fixo-md.d.ts +50 -0
  144. package/dist/context/fixo-md.d.ts.map +1 -0
  145. package/dist/context/fixo-md.js +118 -0
  146. package/dist/context/fixo-md.js.map +1 -0
  147. package/dist/context/todo.d.ts +65 -0
  148. package/dist/context/todo.d.ts.map +1 -0
  149. package/dist/context/todo.js +194 -0
  150. package/dist/context/todo.js.map +1 -0
  151. package/dist/git/git-manager.d.ts +33 -0
  152. package/dist/git/git-manager.d.ts.map +1 -0
  153. package/dist/git/git-manager.js +293 -0
  154. package/dist/git/git-manager.js.map +1 -0
  155. package/dist/git/git-ops.d.ts +10 -0
  156. package/dist/git/git-ops.d.ts.map +1 -0
  157. package/dist/git/git-ops.js +131 -0
  158. package/dist/git/git-ops.js.map +1 -0
  159. package/dist/index.d.ts +3 -0
  160. package/dist/index.d.ts.map +1 -0
  161. package/dist/index.js +352 -0
  162. package/dist/index.js.map +1 -0
  163. package/dist/indexer.d.ts +30 -0
  164. package/dist/indexer.d.ts.map +1 -0
  165. package/dist/indexer.js +273 -0
  166. package/dist/indexer.js.map +1 -0
  167. package/dist/lsp/lsp-client.d.ts +24 -0
  168. package/dist/lsp/lsp-client.d.ts.map +1 -0
  169. package/dist/lsp/lsp-client.js +205 -0
  170. package/dist/lsp/lsp-client.js.map +1 -0
  171. package/dist/lsp/lsp-manager.d.ts +17 -0
  172. package/dist/lsp/lsp-manager.d.ts.map +1 -0
  173. package/dist/lsp/lsp-manager.js +154 -0
  174. package/dist/lsp/lsp-manager.js.map +1 -0
  175. package/dist/lsp/lsp-pre-save.d.ts +137 -0
  176. package/dist/lsp/lsp-pre-save.d.ts.map +1 -0
  177. package/dist/lsp/lsp-pre-save.js +245 -0
  178. package/dist/lsp/lsp-pre-save.js.map +1 -0
  179. package/dist/lsp/syntax-fallback.d.ts +83 -0
  180. package/dist/lsp/syntax-fallback.d.ts.map +1 -0
  181. package/dist/lsp/syntax-fallback.js +275 -0
  182. package/dist/lsp/syntax-fallback.js.map +1 -0
  183. package/dist/model-outcomes.d.ts +12 -0
  184. package/dist/model-outcomes.d.ts.map +1 -0
  185. package/dist/model-outcomes.js +46 -0
  186. package/dist/model-outcomes.js.map +1 -0
  187. package/dist/planner.d.ts +32 -0
  188. package/dist/planner.d.ts.map +1 -0
  189. package/dist/planner.js +163 -0
  190. package/dist/planner.js.map +1 -0
  191. package/dist/project-memory.d.ts +29 -0
  192. package/dist/project-memory.d.ts.map +1 -0
  193. package/dist/project-memory.js +349 -0
  194. package/dist/project-memory.js.map +1 -0
  195. package/dist/review.d.ts +2 -0
  196. package/dist/review.d.ts.map +1 -0
  197. package/dist/review.js +61 -0
  198. package/dist/review.js.map +1 -0
  199. package/dist/runtime/background-jobs.d.ts +97 -0
  200. package/dist/runtime/background-jobs.d.ts.map +1 -0
  201. package/dist/runtime/background-jobs.js +331 -0
  202. package/dist/runtime/background-jobs.js.map +1 -0
  203. package/dist/runtime/credential-vault.d.ts +124 -0
  204. package/dist/runtime/credential-vault.d.ts.map +1 -0
  205. package/dist/runtime/credential-vault.js +184 -0
  206. package/dist/runtime/credential-vault.js.map +1 -0
  207. package/dist/runtime/loop-trap.d.ts +197 -0
  208. package/dist/runtime/loop-trap.d.ts.map +1 -0
  209. package/dist/runtime/loop-trap.js +420 -0
  210. package/dist/runtime/loop-trap.js.map +1 -0
  211. package/dist/runtime/policy.d.ts +15 -0
  212. package/dist/runtime/policy.d.ts.map +1 -0
  213. package/dist/runtime/policy.js +60 -0
  214. package/dist/runtime/policy.js.map +1 -0
  215. package/dist/runtime/redaction.d.ts +66 -0
  216. package/dist/runtime/redaction.d.ts.map +1 -0
  217. package/dist/runtime/redaction.js +155 -0
  218. package/dist/runtime/redaction.js.map +1 -0
  219. package/dist/runtime/session-snapshots.d.ts +76 -0
  220. package/dist/runtime/session-snapshots.d.ts.map +1 -0
  221. package/dist/runtime/session-snapshots.js +166 -0
  222. package/dist/runtime/session-snapshots.js.map +1 -0
  223. package/dist/runtime/staging.d.ts +205 -0
  224. package/dist/runtime/staging.d.ts.map +1 -0
  225. package/dist/runtime/staging.js +526 -0
  226. package/dist/runtime/staging.js.map +1 -0
  227. package/dist/runtime/task-session.d.ts +95 -0
  228. package/dist/runtime/task-session.d.ts.map +1 -0
  229. package/dist/runtime/task-session.js +263 -0
  230. package/dist/runtime/task-session.js.map +1 -0
  231. package/dist/runtime/worktree.d.ts +55 -0
  232. package/dist/runtime/worktree.d.ts.map +1 -0
  233. package/dist/runtime/worktree.js +175 -0
  234. package/dist/runtime/worktree.js.map +1 -0
  235. package/dist/setup-wizard.d.ts +8 -0
  236. package/dist/setup-wizard.d.ts.map +1 -0
  237. package/dist/setup-wizard.js +73 -0
  238. package/dist/setup-wizard.js.map +1 -0
  239. package/dist/shared/content.d.ts +43 -0
  240. package/dist/shared/content.d.ts.map +1 -0
  241. package/dist/shared/content.js +61 -0
  242. package/dist/shared/content.js.map +1 -0
  243. package/dist/shared/types.d.ts +217 -0
  244. package/dist/shared/types.d.ts.map +1 -0
  245. package/dist/shared/types.js +3 -0
  246. package/dist/shared/types.js.map +1 -0
  247. package/dist/test-runner.d.ts +5 -0
  248. package/dist/test-runner.d.ts.map +1 -0
  249. package/dist/test-runner.js +42 -0
  250. package/dist/test-runner.js.map +1 -0
  251. package/dist/types.d.ts +85 -0
  252. package/dist/types.d.ts.map +1 -0
  253. package/dist/types.js +2 -0
  254. package/dist/types.js.map +1 -0
  255. package/dist/ui/ascii.d.ts +23 -0
  256. package/dist/ui/ascii.d.ts.map +1 -0
  257. package/dist/ui/ascii.js +45 -0
  258. package/dist/ui/ascii.js.map +1 -0
  259. package/dist/ui/colors.d.ts +111 -0
  260. package/dist/ui/colors.d.ts.map +1 -0
  261. package/dist/ui/colors.js +166 -0
  262. package/dist/ui/colors.js.map +1 -0
  263. package/dist/ui/image-attach.d.ts +27 -0
  264. package/dist/ui/image-attach.d.ts.map +1 -0
  265. package/dist/ui/image-attach.js +100 -0
  266. package/dist/ui/image-attach.js.map +1 -0
  267. package/dist/ui/index.d.ts +18 -0
  268. package/dist/ui/index.d.ts.map +1 -0
  269. package/dist/ui/index.js +18 -0
  270. package/dist/ui/index.js.map +1 -0
  271. package/dist/ui/markdown-stream.d.ts +91 -0
  272. package/dist/ui/markdown-stream.d.ts.map +1 -0
  273. package/dist/ui/markdown-stream.js +524 -0
  274. package/dist/ui/markdown-stream.js.map +1 -0
  275. package/dist/ui/plan-renderer.d.ts +36 -0
  276. package/dist/ui/plan-renderer.d.ts.map +1 -0
  277. package/dist/ui/plan-renderer.js +79 -0
  278. package/dist/ui/plan-renderer.js.map +1 -0
  279. package/dist/ui/prompt.d.ts +11 -0
  280. package/dist/ui/prompt.d.ts.map +1 -0
  281. package/dist/ui/prompt.js +1960 -0
  282. package/dist/ui/prompt.js.map +1 -0
  283. package/dist/ui/render-primitives.d.ts +117 -0
  284. package/dist/ui/render-primitives.d.ts.map +1 -0
  285. package/dist/ui/render-primitives.js +322 -0
  286. package/dist/ui/render-primitives.js.map +1 -0
  287. package/dist/ui/render.d.ts +133 -0
  288. package/dist/ui/render.d.ts.map +1 -0
  289. package/dist/ui/render.js +547 -0
  290. package/dist/ui/render.js.map +1 -0
  291. package/dist/ui/session-header.d.ts +30 -0
  292. package/dist/ui/session-header.d.ts.map +1 -0
  293. package/dist/ui/session-header.js +74 -0
  294. package/dist/ui/session-header.js.map +1 -0
  295. package/dist/workspace-guard.d.ts +68 -0
  296. package/dist/workspace-guard.d.ts.map +1 -0
  297. package/dist/workspace-guard.js +168 -0
  298. package/dist/workspace-guard.js.map +1 -0
  299. package/dist/workspace-lock.d.ts +27 -0
  300. package/dist/workspace-lock.d.ts.map +1 -0
  301. package/dist/workspace-lock.js +95 -0
  302. package/dist/workspace-lock.js.map +1 -0
  303. package/package.json +63 -0
@@ -0,0 +1,74 @@
1
+ /**
2
+ * session-header.ts — The boxed session summary rendered once
3
+ * when a session starts or is resumed.
4
+ *
5
+ * The header uses the lava top/bottom border and a SNOW4 side
6
+ * border so it sits inside the same visual family as the AI
7
+ * response frame and the plan renderer.
8
+ */
9
+ import { C, providerColor } from './colors.js';
10
+ import { visLen } from './colors.js';
11
+ function frameWidth() {
12
+ return Math.max(40, Math.min(100, (process.stdout.columns ?? 100) - 4));
13
+ }
14
+ function modeColor(mode) {
15
+ switch (mode) {
16
+ case 'BUILD': return C.LAVA;
17
+ case 'PLAN': return C.PURPLE;
18
+ case 'REVIEW': return C.YELLOW;
19
+ }
20
+ }
21
+ function padInside(s, width) {
22
+ const v = visLen(s);
23
+ if (v >= width)
24
+ return s;
25
+ return s + ' '.repeat(width - v);
26
+ }
27
+ function statusLabel(s) {
28
+ switch (s) {
29
+ case 'new': return 'New session';
30
+ case 'resumed': return 'Resumed session';
31
+ case 'imported': return 'Imported session';
32
+ }
33
+ }
34
+ /**
35
+ * Print the session header box. The box width is `columns - 4`,
36
+ * capped at 100. Safe to call on a non-TTY.
37
+ */
38
+ export function renderSessionHeader(opts) {
39
+ const w = frameWidth();
40
+ const inner = w - 4; // account for the `│ ` and ` │` side padding
41
+ const top = ` ${C.LAVA}┌── SESSION ${'─'.repeat(Math.max(0, inner - 14))}┐${C.RESET}`;
42
+ const bottom = ` ${C.LAVA}└${'─'.repeat(w - 2)}┘${C.RESET}`;
43
+ const line1 = `${C.SNOW3}${statusLabel(opts.status)}${C.RESET} ${C.SNOW4}·${C.RESET} ${C.SNOW2}${formatDate(opts.startedAt)}${C.RESET}`;
44
+ const line2 = `${C.SNOW4}Provider:${C.RESET} ${C.SNOW}${providerColor(opts.provider)}${opts.provider}${C.RESET} ${C.SNOW4}·${C.RESET} ${C.SNOW4}Model:${C.RESET} ${C.BLUE}${opts.model}${C.RESET}`;
45
+ const line3 = `${C.SNOW4}Mode:${C.RESET} ${modeColor(opts.mode)}${opts.mode}${C.RESET} ${C.SNOW4}·${C.RESET} ${C.SNOW4}Routing:${C.RESET} ${C.SNOW2}${opts.routing}${C.RESET} ${C.SNOW4}·${C.RESET} ${C.SNOW4}Context:${C.RESET} ${C.SNOW2}${opts.contextWindow}${C.RESET}`;
46
+ try {
47
+ process.stdout.write(top + '\n');
48
+ process.stdout.write(` ${C.SNOW4}│${C.RESET} ${padInside(line1, inner)}${C.SNOW4}│${C.RESET}\n`);
49
+ process.stdout.write(` ${C.SNOW4}│${C.RESET} ${padInside(line2, inner)}${C.SNOW4}│${C.RESET}\n`);
50
+ process.stdout.write(` ${C.SNOW4}│${C.RESET} ${padInside(line3, inner)}${C.SNOW4}│${C.RESET}\n`);
51
+ process.stdout.write(bottom + '\n');
52
+ }
53
+ catch {
54
+ // stdout may be closed during teardown
55
+ }
56
+ }
57
+ function formatDate(iso) {
58
+ try {
59
+ const d = new Date(iso);
60
+ if (Number.isNaN(d.getTime()))
61
+ return iso;
62
+ return d.toLocaleString('en-US', {
63
+ month: 'short',
64
+ day: 'numeric',
65
+ year: 'numeric',
66
+ hour: 'numeric',
67
+ minute: '2-digit',
68
+ });
69
+ }
70
+ catch {
71
+ return iso;
72
+ }
73
+ }
74
+ //# sourceMappingURL=session-header.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session-header.js","sourceRoot":"","sources":["../../src/ui/session-header.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,68 @@
1
+ /**
2
+ * Workspace boundary guard.
3
+ *
4
+ * Pillar 5 (Self-Protection) — the WorkspaceGuard also enforces
5
+ * a System Path Lock: paths that resolve inside the platform's
6
+ * own runtime (`src/**`, `package.json`, `tsconfig.json`, and
7
+ * the lockfile) are **immutable** from any active agent loop.
8
+ * This stops an autonomous agent from corrupting its own host
9
+ * (the failure mode that produced the
10
+ * `src/agent/tool-executor.ts:983: Unexpected "catch"` incident
11
+ * during the Phase 2 release).
12
+ */
13
+ export declare class WorkspaceGuard {
14
+ readonly root: string;
15
+ private allowList;
16
+ constructor(root: string, allowList?: string[]);
17
+ private safeRealPath;
18
+ resolve(input: string | undefined, label?: string): string;
19
+ isInside(target: string): boolean;
20
+ relative(target: string): string;
21
+ ensureFile(target: string): string;
22
+ isBinaryFile(target: string, sampleBytes?: number): boolean;
23
+ /**
24
+ * File-system entries that make up the Fixo CLI platform
25
+ * itself. The agent runtime is **never** allowed to mutate
26
+ * these from an active task cycle, regardless of which
27
+ * workspace the user is operating in.
28
+ *
29
+ * The list is intentionally narrow (the platform's own
30
+ * source tree and root-level build manifests) so the lock
31
+ * does not interfere with the user's own code in
32
+ * sub-directories.
33
+ */
34
+ private static readonly PLATFORM_PATH_PATTERNS;
35
+ /**
36
+ * Return true if the relative path matches a platform-locked
37
+ * pattern. The check is case-insensitive on the extension
38
+ * because Windows and macOS Finder both silently rename
39
+ * `package.json` to `Package.json` if the user double-clicks.
40
+ */
41
+ isPlatformPath(relativePath: string): boolean;
42
+ /**
43
+ * Static form of {@link isPlatformPath}. Useful in tests and
44
+ * in places where a WorkspaceGuard instance is not yet
45
+ * available.
46
+ */
47
+ static isPlatformPath(relativePath: string): boolean;
48
+ private static isPlatformPathStatic;
49
+ /**
50
+ * Throws {@link PlatformPathLockedError} if `target` resolves
51
+ * to a path inside the platform's own runtime. This is the
52
+ * one method every mutation tool in the executor must call
53
+ * before staging a write.
54
+ */
55
+ assertNotPlatformPath(target: string): void;
56
+ }
57
+ /**
58
+ * Thrown when an agent loop attempts to mutate a path inside
59
+ * the platform's own runtime. Caught by the executor's switch
60
+ * statement and surfaced as a plain string error to the LLM,
61
+ * so the model sees the rejection in its next-turn tool result.
62
+ */
63
+ export declare class PlatformPathLockedError extends Error {
64
+ readonly resolved: string;
65
+ readonly relative: string;
66
+ constructor(resolved: string, relative: string);
67
+ }
68
+ //# sourceMappingURL=workspace-guard.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"workspace-guard.d.ts","sourceRoot":"","sources":["../src/workspace-guard.ts"],"names":[],"mappings":"AAGA;;;;;;;;;;;GAWG;AACH,qBAAa,cAAc;IACzB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,OAAO,CAAC,SAAS,CAAW;gBAEhB,IAAI,EAAE,MAAM,EAAE,SAAS,GAAE,MAAM,EAAO;IASlD,OAAO,CAAC,YAAY;IAcpB,OAAO,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,EAAE,KAAK,SAAS,GAAG,MAAM;IAS1D,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO;IAMjC,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM;IAIhC,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM;IAiBlC,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,WAAW,SAAO,GAAG,OAAO;IAgBzD;;;;;;;;;;OAUG;IACH,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,sBAAsB,CAO5C;IAEF;;;;;OAKG;IACI,cAAc,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO;IAIpD;;;;OAIG;WACW,cAAc,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO;IAI3D,OAAO,CAAC,MAAM,CAAC,oBAAoB;IAQnC;;;;;OAKG;IACI,qBAAqB,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;CASnD;AAED;;;;;GAKG;AACH,qBAAa,uBAAwB,SAAQ,KAAK;IAChD,SAAgB,QAAQ,EAAE,MAAM,CAAC;IACjC,SAAgB,QAAQ,EAAE,MAAM,CAAC;gBACrB,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM;CAS/C"}
@@ -0,0 +1,168 @@
1
+ import fs from 'fs';
2
+ import path from 'path';
3
+ /**
4
+ * Workspace boundary guard.
5
+ *
6
+ * Pillar 5 (Self-Protection) — the WorkspaceGuard also enforces
7
+ * a System Path Lock: paths that resolve inside the platform's
8
+ * own runtime (`src/**`, `package.json`, `tsconfig.json`, and
9
+ * the lockfile) are **immutable** from any active agent loop.
10
+ * This stops an autonomous agent from corrupting its own host
11
+ * (the failure mode that produced the
12
+ * `src/agent/tool-executor.ts:983: Unexpected "catch"` incident
13
+ * during the Phase 2 release).
14
+ */
15
+ export class WorkspaceGuard {
16
+ root;
17
+ allowList;
18
+ constructor(root, allowList = []) {
19
+ try {
20
+ this.root = fs.realpathSync(path.resolve(root));
21
+ }
22
+ catch {
23
+ this.root = path.resolve(root);
24
+ }
25
+ this.allowList = allowList;
26
+ }
27
+ safeRealPath(p) {
28
+ try {
29
+ return fs.realpathSync(p);
30
+ }
31
+ catch (err) {
32
+ const code = err.code;
33
+ if (code === 'ENOENT') {
34
+ const parent = path.dirname(p);
35
+ if (parent === p)
36
+ return p;
37
+ return path.join(this.safeRealPath(parent), path.basename(p));
38
+ }
39
+ throw err;
40
+ }
41
+ }
42
+ resolve(input, label = 'path') {
43
+ const raw = input?.trim() || '.';
44
+ const resolved = path.resolve(this.root, raw);
45
+ if (!this.isInside(resolved)) {
46
+ throw new Error(`${label} escapes workspace: ${input ?? '.'}`);
47
+ }
48
+ return resolved;
49
+ }
50
+ isInside(target) {
51
+ const resolvedTarget = this.safeRealPath(path.resolve(target));
52
+ const relative = path.relative(this.root, resolvedTarget);
53
+ return relative === '' || (!relative.startsWith('..') && !path.isAbsolute(relative));
54
+ }
55
+ relative(target) {
56
+ return path.relative(this.root, path.resolve(target)) || '.';
57
+ }
58
+ ensureFile(target) {
59
+ const resolved = this.resolve(target, 'file');
60
+ try {
61
+ const stat = fs.statSync(resolved);
62
+ if (!stat.isFile()) {
63
+ throw new Error(`Not a file: ${target}`);
64
+ }
65
+ }
66
+ catch (err) {
67
+ const code = err.code;
68
+ if (code === 'ENOENT') {
69
+ throw new Error(`File does not exist: ${target}`);
70
+ }
71
+ throw err;
72
+ }
73
+ return resolved;
74
+ }
75
+ isBinaryFile(target, sampleBytes = 4096) {
76
+ const fd = fs.openSync(target, 'r');
77
+ try {
78
+ const buffer = Buffer.alloc(sampleBytes);
79
+ const bytesRead = fs.readSync(fd, buffer, 0, sampleBytes, 0);
80
+ for (let i = 0; i < bytesRead; i++) {
81
+ if (buffer[i] === 0)
82
+ return true;
83
+ }
84
+ return false;
85
+ }
86
+ finally {
87
+ fs.closeSync(fd);
88
+ }
89
+ }
90
+ /* ──────────────────── System Path Lock (Pillar 5) ──────────────────── */
91
+ /**
92
+ * File-system entries that make up the Fixo CLI platform
93
+ * itself. The agent runtime is **never** allowed to mutate
94
+ * these from an active task cycle, regardless of which
95
+ * workspace the user is operating in.
96
+ *
97
+ * The list is intentionally narrow (the platform's own
98
+ * source tree and root-level build manifests) so the lock
99
+ * does not interfere with the user's own code in
100
+ * sub-directories.
101
+ */
102
+ static PLATFORM_PATH_PATTERNS = [
103
+ /(^|\/)src\/.+/,
104
+ /(^|\/)package\.json$/,
105
+ /(^|\/)package-lock\.json$/,
106
+ /(^|\/)tsconfig(\..+)?\.json$/,
107
+ /(^|\/)dist\/.+/,
108
+ /(^|\/)node_modules\/.+/,
109
+ ];
110
+ /**
111
+ * Return true if the relative path matches a platform-locked
112
+ * pattern. The check is case-insensitive on the extension
113
+ * because Windows and macOS Finder both silently rename
114
+ * `package.json` to `Package.json` if the user double-clicks.
115
+ */
116
+ isPlatformPath(relativePath) {
117
+ return WorkspaceGuard.isPlatformPathStatic(relativePath);
118
+ }
119
+ /**
120
+ * Static form of {@link isPlatformPath}. Useful in tests and
121
+ * in places where a WorkspaceGuard instance is not yet
122
+ * available.
123
+ */
124
+ static isPlatformPath(relativePath) {
125
+ return WorkspaceGuard.isPlatformPathStatic(relativePath);
126
+ }
127
+ static isPlatformPathStatic(relativePath) {
128
+ const normalised = relativePath.replace(/\\/g, '/').toLowerCase();
129
+ for (const pattern of WorkspaceGuard.PLATFORM_PATH_PATTERNS) {
130
+ if (pattern.test(normalised))
131
+ return true;
132
+ }
133
+ return false;
134
+ }
135
+ /**
136
+ * Throws {@link PlatformPathLockedError} if `target` resolves
137
+ * to a path inside the platform's own runtime. This is the
138
+ * one method every mutation tool in the executor must call
139
+ * before staging a write.
140
+ */
141
+ assertNotPlatformPath(target) {
142
+ // Resolve to an absolute path so symlinks and `..` tricks
143
+ // cannot escape the check.
144
+ const resolved = this.resolve(target, 'platform path');
145
+ const relative = this.relative(resolved);
146
+ if (this.isPlatformPath(relative)) {
147
+ throw new PlatformPathLockedError(resolved, relative);
148
+ }
149
+ }
150
+ }
151
+ /**
152
+ * Thrown when an agent loop attempts to mutate a path inside
153
+ * the platform's own runtime. Caught by the executor's switch
154
+ * statement and surfaced as a plain string error to the LLM,
155
+ * so the model sees the rejection in its next-turn tool result.
156
+ */
157
+ export class PlatformPathLockedError extends Error {
158
+ resolved;
159
+ relative;
160
+ constructor(resolved, relative) {
161
+ super(`Error: Modification of Fixo CLI core architecture files is strictly ` +
162
+ `prohibited during workspace task cycles (target: ${relative}).`);
163
+ this.name = 'PlatformPathLockedError';
164
+ this.resolved = resolved;
165
+ this.relative = relative;
166
+ }
167
+ }
168
+ //# sourceMappingURL=workspace-guard.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"workspace-guard.js","sourceRoot":"","sources":["../src/workspace-guard.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,27 @@
1
+ export interface LockState {
2
+ agentId: string;
3
+ type: 'read' | 'write';
4
+ }
5
+ export declare class WorkspaceLockManager {
6
+ private locks;
7
+ /**
8
+ * Tries to acquire a lock on a file.
9
+ * Returns true if successful, false if the lock is held by another agent.
10
+ */
11
+ acquireLock(filePath: string, agentId: string, lockType: 'read' | 'write'): boolean;
12
+ /**
13
+ * Releases a lock held by an agent on a file.
14
+ * Returns true if a lock was released, false if no lock existed for this agent.
15
+ */
16
+ releaseLock(filePath: string, agentId: string): boolean;
17
+ /**
18
+ * Releases all locks held by a specific agent.
19
+ */
20
+ releaseAllLocks(agentId: string): void;
21
+ /**
22
+ * Checks if a file is currently locked in a way that conflicts with the requested lockType.
23
+ */
24
+ isLocked(filePath: string, lockType: 'read' | 'write'): boolean;
25
+ }
26
+ export declare const workspaceLockManager: WorkspaceLockManager;
27
+ //# sourceMappingURL=workspace-lock.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"workspace-lock.d.ts","sourceRoot":"","sources":["../src/workspace-lock.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,SAAS;IACxB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED,qBAAa,oBAAoB;IAC/B,OAAO,CAAC,KAAK,CAAkC;IAE/C;;;OAGG;IACH,WAAW,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,GAAG,OAAO;IA0CnF;;;OAGG;IACH,WAAW,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO;IAkBvD;;OAEG;IACH,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAWtC;;OAEG;IACH,QAAQ,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,GAAG,OAAO;CAehE;AAED,eAAO,MAAM,oBAAoB,sBAA6B,CAAC"}
@@ -0,0 +1,95 @@
1
+ import path from 'path';
2
+ export class WorkspaceLockManager {
3
+ locks = new Map();
4
+ /**
5
+ * Tries to acquire a lock on a file.
6
+ * Returns true if successful, false if the lock is held by another agent.
7
+ */
8
+ acquireLock(filePath, agentId, lockType) {
9
+ const normalizedPath = path.resolve(filePath);
10
+ const activeLocks = this.locks.get(normalizedPath) || [];
11
+ if (activeLocks.length === 0) {
12
+ this.locks.set(normalizedPath, [{ agentId, type: lockType }]);
13
+ return true;
14
+ }
15
+ // Check if the current agent already holds a lock of the same or higher type
16
+ const agentLock = activeLocks.find(l => l.agentId === agentId);
17
+ if (agentLock) {
18
+ if (agentLock.type === lockType || agentLock.type === 'write') {
19
+ return true;
20
+ }
21
+ // Upgrade from read to write
22
+ if (lockType === 'write') {
23
+ // Can only upgrade if this agent is the ONLY reader
24
+ if (activeLocks.length === 1) {
25
+ agentLock.type = 'write';
26
+ return true;
27
+ }
28
+ return false; // Other agents hold read locks, cannot upgrade
29
+ }
30
+ }
31
+ // If any write lock is active, block all new locks
32
+ if (activeLocks.some(l => l.type === 'write')) {
33
+ return false;
34
+ }
35
+ // If new lock is write and there are existing read locks, block it
36
+ if (lockType === 'write') {
37
+ return false;
38
+ }
39
+ // Otherwise, add a shared read lock
40
+ activeLocks.push({ agentId, type: lockType });
41
+ this.locks.set(normalizedPath, activeLocks);
42
+ return true;
43
+ }
44
+ /**
45
+ * Releases a lock held by an agent on a file.
46
+ * Returns true if a lock was released, false if no lock existed for this agent.
47
+ */
48
+ releaseLock(filePath, agentId) {
49
+ const normalizedPath = path.resolve(filePath);
50
+ const activeLocks = this.locks.get(normalizedPath) || [];
51
+ const index = activeLocks.findIndex(l => l.agentId === agentId);
52
+ if (index === -1) {
53
+ return false;
54
+ }
55
+ activeLocks.splice(index, 1);
56
+ if (activeLocks.length === 0) {
57
+ this.locks.delete(normalizedPath);
58
+ }
59
+ else {
60
+ this.locks.set(normalizedPath, activeLocks);
61
+ }
62
+ return true;
63
+ }
64
+ /**
65
+ * Releases all locks held by a specific agent.
66
+ */
67
+ releaseAllLocks(agentId) {
68
+ for (const [filePath, activeLocks] of this.locks.entries()) {
69
+ const filtered = activeLocks.filter(l => l.agentId !== agentId);
70
+ if (filtered.length === 0) {
71
+ this.locks.delete(filePath);
72
+ }
73
+ else {
74
+ this.locks.set(filePath, filtered);
75
+ }
76
+ }
77
+ }
78
+ /**
79
+ * Checks if a file is currently locked in a way that conflicts with the requested lockType.
80
+ */
81
+ isLocked(filePath, lockType) {
82
+ const normalizedPath = path.resolve(filePath);
83
+ const activeLocks = this.locks.get(normalizedPath) || [];
84
+ if (activeLocks.length === 0) {
85
+ return false;
86
+ }
87
+ if (lockType === 'write') {
88
+ return true; // Any lock (read or write) blocks a new write lock
89
+ }
90
+ // For read locks, only an active write lock blocks it
91
+ return activeLocks.some(l => l.type === 'write');
92
+ }
93
+ }
94
+ export const workspaceLockManager = new WorkspaceLockManager();
95
+ //# sourceMappingURL=workspace-lock.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"workspace-lock.js","sourceRoot":"","sources":["../src/workspace-lock.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,63 @@
1
+ {
2
+ "name": "fixo-cli",
3
+ "version": "1.0.0",
4
+ "description": "FixO CLI — Autonomous Free Multi-Provider LLM Coding Tool",
5
+ "type": "module",
6
+ "bin": {
7
+ "fixo": "./dist/index.js",
8
+ "fixo-cli": "./dist/index.js"
9
+ },
10
+ "main": "./dist/index.js",
11
+ "files": [
12
+ "dist/",
13
+ "README.md"
14
+ ],
15
+ "scripts": {
16
+ "build": "tsc && chmod +x dist/index.js",
17
+ "dev": "tsx src/index.ts",
18
+ "test": "node --import tsx --test src/__tests__/*.test.ts",
19
+ "prepublishOnly": "npm run build"
20
+ },
21
+ "keywords": [
22
+ "ai",
23
+ "coding",
24
+ "agent",
25
+ "cli",
26
+ "llm",
27
+ "free",
28
+ "openai",
29
+ "groq",
30
+ "gemini",
31
+ "claude-code-alternative"
32
+ ],
33
+ "license": "Apache-2.0",
34
+ "author": "Abrar Akhunji",
35
+ "repository": {
36
+ "type": "git",
37
+ "url": "git+https://github.com/Abrar-Akhunji/FIXO_CLI.git"
38
+ },
39
+ "bugs": {
40
+ "url": "https://github.com/Abrar-Akhunji/FIXO_CLI/issues"
41
+ },
42
+ "homepage": "https://github.com/Abrar-Akhunji/FIXO_CLI#readme",
43
+ "engines": {
44
+ "node": ">=22.13.0"
45
+ },
46
+ "dependencies": {
47
+ "@clack/prompts": "^0.9.0",
48
+ "cheerio": "^1.2.0",
49
+ "gpt-tokenizer": "^3.4.0",
50
+ "js-yaml": "^4.1.0",
51
+ "tree-sitter-bash": "^0.25.0",
52
+ "turndown": "^7.2.4",
53
+ "vscode-jsonrpc": "^8.2.1",
54
+ "web-tree-sitter": "^0.25.10"
55
+ },
56
+ "devDependencies": {
57
+ "@types/js-yaml": "^4.0.9",
58
+ "@types/node": "^22.15.3",
59
+ "@types/turndown": "^5.0.6",
60
+ "tsx": "^4.19.4",
61
+ "typescript": "^5.8.3"
62
+ }
63
+ }