@aligndottech/cli 0.67.1 → 0.68.1

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 (143) hide show
  1. package/README.md +28 -7
  2. package/dist/cli.d.ts.map +1 -1
  3. package/dist/cli.js +5 -2
  4. package/dist/cli.js.map +1 -1
  5. package/dist/commands/capture.d.ts.map +1 -1
  6. package/dist/commands/capture.js +4 -0
  7. package/dist/commands/capture.js.map +1 -1
  8. package/dist/commands/check.d.ts +1 -5
  9. package/dist/commands/check.d.ts.map +1 -1
  10. package/dist/commands/check.js +1 -33
  11. package/dist/commands/check.js.map +1 -1
  12. package/dist/commands/connect-agents.d.ts +8 -18
  13. package/dist/commands/connect-agents.d.ts.map +1 -1
  14. package/dist/commands/connect-agents.js +32 -19
  15. package/dist/commands/connect-agents.js.map +1 -1
  16. package/dist/commands/default-action.d.ts.map +1 -1
  17. package/dist/commands/default-action.js +18 -7
  18. package/dist/commands/default-action.js.map +1 -1
  19. package/dist/commands/local.js +2 -2
  20. package/dist/commands/local.js.map +1 -1
  21. package/dist/commands/mcp.d.ts.map +1 -1
  22. package/dist/commands/mcp.js +4 -2
  23. package/dist/commands/mcp.js.map +1 -1
  24. package/dist/commands/setup.d.ts.map +1 -1
  25. package/dist/commands/setup.js +24 -15
  26. package/dist/commands/setup.js.map +1 -1
  27. package/dist/lib/agent/agent-guidance.d.ts +8 -0
  28. package/dist/lib/agent/agent-guidance.d.ts.map +1 -0
  29. package/dist/lib/agent/agent-guidance.js +8 -0
  30. package/dist/lib/agent/agent-guidance.js.map +1 -0
  31. package/dist/lib/agent/edit-gate.d.ts +30 -0
  32. package/dist/lib/agent/edit-gate.d.ts.map +1 -0
  33. package/dist/lib/agent/edit-gate.js +67 -0
  34. package/dist/lib/agent/edit-gate.js.map +1 -0
  35. package/dist/lib/agent/edit-text.d.ts +14 -0
  36. package/dist/lib/agent/edit-text.d.ts.map +1 -0
  37. package/dist/lib/agent/edit-text.js +34 -0
  38. package/dist/lib/agent/edit-text.js.map +1 -0
  39. package/dist/lib/agent/engines/claude-code-protocol.d.ts +24 -0
  40. package/dist/lib/agent/engines/claude-code-protocol.d.ts.map +1 -0
  41. package/dist/lib/agent/engines/claude-code-protocol.js +127 -0
  42. package/dist/lib/agent/engines/claude-code-protocol.js.map +1 -0
  43. package/dist/lib/agent/engines/claude-code.d.ts +17 -0
  44. package/dist/lib/agent/engines/claude-code.d.ts.map +1 -0
  45. package/dist/lib/agent/engines/claude-code.js +122 -0
  46. package/dist/lib/agent/engines/claude-code.js.map +1 -0
  47. package/dist/lib/agent/engines/pi-models.d.ts +46 -0
  48. package/dist/lib/agent/engines/pi-models.d.ts.map +1 -0
  49. package/dist/lib/agent/engines/pi-models.js +91 -0
  50. package/dist/lib/agent/engines/pi-models.js.map +1 -0
  51. package/dist/lib/agent/engines/pi-sdk.d.ts +39 -0
  52. package/dist/lib/agent/engines/pi-sdk.d.ts.map +1 -0
  53. package/dist/lib/agent/engines/pi-sdk.js +105 -0
  54. package/dist/lib/agent/engines/pi-sdk.js.map +1 -0
  55. package/dist/lib/agent/engines/pi.d.ts +44 -0
  56. package/dist/lib/agent/engines/pi.d.ts.map +1 -0
  57. package/dist/lib/agent/engines/pi.js +189 -0
  58. package/dist/lib/agent/engines/pi.js.map +1 -0
  59. package/dist/lib/agent/failure-tail.d.ts +9 -0
  60. package/dist/lib/agent/failure-tail.d.ts.map +1 -0
  61. package/dist/lib/agent/failure-tail.js +42 -0
  62. package/dist/lib/agent/failure-tail.js.map +1 -0
  63. package/dist/lib/agent/git-runs-programs.d.ts +11 -0
  64. package/dist/lib/agent/git-runs-programs.d.ts.map +1 -0
  65. package/dist/lib/agent/git-runs-programs.js +25 -0
  66. package/dist/lib/agent/git-runs-programs.js.map +1 -0
  67. package/dist/lib/agent/graph-tools.d.ts +23 -0
  68. package/dist/lib/agent/graph-tools.d.ts.map +1 -0
  69. package/dist/lib/agent/graph-tools.js +33 -0
  70. package/dist/lib/agent/graph-tools.js.map +1 -0
  71. package/dist/lib/agent/permission-broker.d.ts +27 -0
  72. package/dist/lib/agent/permission-broker.d.ts.map +1 -0
  73. package/dist/lib/agent/permission-broker.js +56 -0
  74. package/dist/lib/agent/permission-broker.js.map +1 -0
  75. package/dist/lib/agent/read-only-command.d.ts +15 -0
  76. package/dist/lib/agent/read-only-command.d.ts.map +1 -0
  77. package/dist/lib/agent/read-only-command.js +102 -0
  78. package/dist/lib/agent/read-only-command.js.map +1 -0
  79. package/dist/lib/agent/run-agent-session.d.ts +45 -0
  80. package/dist/lib/agent/run-agent-session.d.ts.map +1 -0
  81. package/dist/lib/agent/run-agent-session.js +139 -0
  82. package/dist/lib/agent/run-agent-session.js.map +1 -0
  83. package/dist/lib/agent/select-engine.d.ts +28 -0
  84. package/dist/lib/agent/select-engine.d.ts.map +1 -0
  85. package/dist/lib/agent/select-engine.js +14 -0
  86. package/dist/lib/agent/select-engine.js.map +1 -0
  87. package/dist/lib/agent/tui/app.d.ts +12 -0
  88. package/dist/lib/agent/tui/app.d.ts.map +1 -0
  89. package/dist/lib/agent/tui/app.js +122 -0
  90. package/dist/lib/agent/tui/app.js.map +1 -0
  91. package/dist/lib/agent/tui/cards.d.ts +17 -0
  92. package/dist/lib/agent/tui/cards.d.ts.map +1 -0
  93. package/dist/lib/agent/tui/cards.js +48 -0
  94. package/dist/lib/agent/tui/cards.js.map +1 -0
  95. package/dist/lib/agent/tui/controller.d.ts +21 -0
  96. package/dist/lib/agent/tui/controller.d.ts.map +1 -0
  97. package/dist/lib/agent/tui/controller.js +29 -0
  98. package/dist/lib/agent/tui/controller.js.map +1 -0
  99. package/dist/lib/agent/tui/theme.d.ts +11 -0
  100. package/dist/lib/agent/tui/theme.d.ts.map +1 -0
  101. package/dist/lib/agent/tui/theme.js +13 -0
  102. package/dist/lib/agent/tui/theme.js.map +1 -0
  103. package/dist/lib/agent/types.d.ts +84 -0
  104. package/dist/lib/agent/types.d.ts.map +1 -0
  105. package/dist/lib/agent/types.js +2 -0
  106. package/dist/lib/agent/types.js.map +1 -0
  107. package/dist/lib/config.d.ts +4 -0
  108. package/dist/lib/config.d.ts.map +1 -1
  109. package/dist/lib/config.js +17 -0
  110. package/dist/lib/config.js.map +1 -1
  111. package/dist/lib/doctor.d.ts +1 -1
  112. package/dist/lib/doctor.js +2 -2
  113. package/dist/lib/launch/config-writes.d.ts +5 -3
  114. package/dist/lib/launch/config-writes.d.ts.map +1 -1
  115. package/dist/lib/launch/config-writes.js +39 -8
  116. package/dist/lib/launch/config-writes.js.map +1 -1
  117. package/dist/lib/launch/launch.d.ts +4 -0
  118. package/dist/lib/launch/launch.d.ts.map +1 -1
  119. package/dist/lib/launch/launch.js +14 -6
  120. package/dist/lib/launch/launch.js.map +1 -1
  121. package/dist/lib/launch/mcp-child-env.js +1 -1
  122. package/dist/lib/launch/mcp-child-env.js.map +1 -1
  123. package/dist/lib/launch/prompts.d.ts +6 -0
  124. package/dist/lib/launch/prompts.d.ts.map +1 -1
  125. package/dist/lib/launch/prompts.js +12 -0
  126. package/dist/lib/launch/prompts.js.map +1 -1
  127. package/dist/lib/personal-import.d.ts +4 -0
  128. package/dist/lib/personal-import.d.ts.map +1 -1
  129. package/dist/lib/personal-import.js +4 -0
  130. package/dist/lib/personal-import.js.map +1 -1
  131. package/dist/lib/scope-real.d.ts +12 -0
  132. package/dist/lib/scope-real.d.ts.map +1 -1
  133. package/dist/lib/sync/real-env.d.ts +12 -0
  134. package/dist/lib/sync/real-env.d.ts.map +1 -1
  135. package/dist/lib/usage-telemetry.d.ts +1 -1
  136. package/dist/lib/usage-telemetry.d.ts.map +1 -1
  137. package/dist/lib/usage-telemetry.js +20 -2
  138. package/dist/lib/usage-telemetry.js.map +1 -1
  139. package/dist/lib/write-confirm.d.ts +14 -5
  140. package/dist/lib/write-confirm.d.ts.map +1 -1
  141. package/dist/lib/write-confirm.js +29 -10
  142. package/dist/lib/write-confirm.js.map +1 -1
  143. package/package.json +5 -2
@@ -0,0 +1,127 @@
1
+ import { failureTail } from '../failure-tail.js';
2
+ const asRecord = (v) => (v && typeof v === 'object' && !Array.isArray(v) ? v : null);
3
+ const str = (v) => (typeof v === 'string' ? v : undefined);
4
+ const line = (o) => `${JSON.stringify(o)}\n`;
5
+ /** `manual` + host prompts: every permission question comes to us. Never bypassPermissions. */
6
+ export function buildArgs(extra = []) {
7
+ return ['-p', '--input-format', 'stream-json', '--output-format', 'stream-json', '--verbose',
8
+ '--include-partial-messages', '--permission-mode', 'manual', '--permission-prompts', 'host',
9
+ '--permission-prompt-tool', 'stdio',
10
+ // The user's own settings only. A repo's .claude/settings.json could otherwise run its hooks and
11
+ // pre-approve tools before Align is asked, and headless claude shows no trust prompt for it.
12
+ '--setting-sources', 'user', ...extra];
13
+ }
14
+ export const initializeLine = (requestId) => line({ type: 'control_request', request_id: requestId, request: { subtype: 'initialize' } });
15
+ export const userMessageLine = (text) => line({ type: 'user', message: { role: 'user', content: text } });
16
+ export const interruptLine = (requestId) => line({ type: 'control_request', request_id: requestId, request: { subtype: 'interrupt' } });
17
+ export function controlResponse(requestId, verdict, input) {
18
+ const response = verdict.allow ? { behavior: 'allow', updatedInput: input } : { behavior: 'deny', message: verdict.message };
19
+ return line({ type: 'control_response', response: { subtype: 'success', request_id: requestId, response } });
20
+ }
21
+ const EDIT_TOOLS = new Set(['Write', 'Edit', 'MultiEdit', 'NotebookEdit']);
22
+ const COMMAND_TOOLS = new Set(['Bash', 'PowerShell']);
23
+ const READ_TOOLS = new Set(['Read', 'Glob', 'Grep', 'LS', 'TodoWrite']);
24
+ function kindOf(tool) {
25
+ if (EDIT_TOOLS.has(tool))
26
+ return 'edit';
27
+ if (COMMAND_TOOLS.has(tool))
28
+ return 'command';
29
+ return READ_TOOLS.has(tool) ? 'read' : 'other';
30
+ }
31
+ /** Only the fields the hook check reads, so the gate sees the same shape from every engine. */
32
+ function toEdit(input) {
33
+ const out = {};
34
+ const path = str(input['file_path']) ?? str(input['notebook_path']);
35
+ if (path !== undefined)
36
+ out.file_path = path;
37
+ if (str(input['content']) !== undefined)
38
+ out.content = str(input['content']);
39
+ if (str(input['old_string']) !== undefined)
40
+ out.old_string = str(input['old_string']);
41
+ const next = str(input['new_string']) ?? str(input['new_source']);
42
+ if (next !== undefined)
43
+ out.new_string = next;
44
+ if (Array.isArray(input['edits']))
45
+ out.edits = input['edits'];
46
+ return out;
47
+ }
48
+ function toAsk(id, tool, input) {
49
+ const kind = kindOf(tool);
50
+ const ask = { id, tool, kind };
51
+ if (kind === 'edit')
52
+ ask.edit = toEdit(input);
53
+ if (kind === 'command')
54
+ ask.command = str(input['command']) ?? '';
55
+ if (kind === 'other')
56
+ ask.detail = JSON.stringify(input);
57
+ return ask;
58
+ }
59
+ function summaryOf(tool, input) {
60
+ const kind = kindOf(tool);
61
+ if (kind === 'command')
62
+ return str(input['command']) ?? tool;
63
+ if (kind === 'edit')
64
+ return str(input['file_path']) ?? tool;
65
+ return tool;
66
+ }
67
+ function contentBlocks(msg) {
68
+ const content = asRecord(msg['message'])?.['content'];
69
+ return Array.isArray(content) ? content.map(asRecord).filter((b) => b !== null) : [];
70
+ }
71
+ export function parseLine(raw) {
72
+ let msg;
73
+ try {
74
+ msg = asRecord(JSON.parse(raw));
75
+ }
76
+ catch {
77
+ return { events: [] };
78
+ }
79
+ if (!msg)
80
+ return { events: [] };
81
+ switch (msg['type']) {
82
+ case 'system':
83
+ return msg['subtype'] === 'init' ? { events: [], init: true } : { events: [] };
84
+ case 'result': {
85
+ // An error result ("Not logged in", a refused request) must show, not read as an empty turn.
86
+ const failed = msg['is_error'] === true ? str(msg['result']) : undefined;
87
+ return { events: failed ? [{ type: 'error', message: failed }, { type: 'turn-end' }] : [{ type: 'turn-end' }] };
88
+ }
89
+ case 'stream_event': {
90
+ const delta = asRecord(asRecord(msg['event'])?.['delta']);
91
+ const text = delta?.['type'] === 'text_delta' ? str(delta['text']) : undefined;
92
+ return { events: text === undefined ? [] : [{ type: 'text', delta: text }] };
93
+ }
94
+ case 'assistant': {
95
+ const events = [];
96
+ for (const b of contentBlocks(msg)) {
97
+ if (b['type'] !== 'tool_use')
98
+ continue;
99
+ const tool = str(b['name']) ?? '';
100
+ events.push({ type: 'tool-start', id: str(b['id']) ?? '', tool, summary: summaryOf(tool, asRecord(b['input']) ?? {}) });
101
+ }
102
+ return { events };
103
+ }
104
+ case 'user': {
105
+ const events = [];
106
+ for (const b of contentBlocks(msg)) {
107
+ if (b['type'] !== 'tool_result')
108
+ continue;
109
+ const ok = b['is_error'] !== true;
110
+ const detail = ok ? undefined : failureTail(b['content']);
111
+ events.push({ type: 'tool-end', id: str(b['tool_use_id']) ?? '', ok, ...(detail === undefined ? {} : { detail }) });
112
+ }
113
+ return { events };
114
+ }
115
+ case 'control_request': {
116
+ const req = asRecord(msg['request']);
117
+ if (req?.['subtype'] !== 'can_use_tool')
118
+ return { events: [] };
119
+ const input = asRecord(req['input']) ?? {};
120
+ const tool = str(req['tool_name']) ?? '';
121
+ return { events: [], permission: { requestId: str(msg['request_id']) ?? '', ask: toAsk(str(req['tool_use_id']) ?? '', tool, input), input } };
122
+ }
123
+ default:
124
+ return { events: [] };
125
+ }
126
+ }
127
+ //# sourceMappingURL=claude-code-protocol.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"claude-code-protocol.js","sourceRoot":"","sources":["../../../../src/lib/agent/engines/claude-code-protocol.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ import { spawn as nodeSpawn } from 'node:child_process';
2
+ import type { AgentEngine } from '../types.js';
3
+ export interface ClaudeCodeOpts {
4
+ cwd: string;
5
+ bin?: string;
6
+ extraArgs?: string[];
7
+ /** Exactly the child's env. The caller passes the user's startup env so a key Align saved never reaches `claude`. */
8
+ env: Record<string, string | undefined>;
9
+ spawn?: typeof nodeSpawn;
10
+ firstEventTimeoutMs?: number;
11
+ }
12
+ /**
13
+ * Drives the user's own, unmodified `claude` over stream-json. Align never touches its auth or
14
+ * model: it only answers the permission questions `claude` asks the host.
15
+ */
16
+ export declare function createClaudeCodeEngine(opts: ClaudeCodeOpts): AgentEngine;
17
+ //# sourceMappingURL=claude-code.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"claude-code.d.ts","sourceRoot":"","sources":["../../../../src/lib/agent/engines/claude-code.ts"],"names":[],"mappings":"AAAA,OAAO,EAAuC,KAAK,IAAI,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAC7F,OAAO,KAAK,EAAE,WAAW,EAAwC,MAAM,aAAa,CAAC;AAGrF,MAAM,WAAW,cAAc;IAC7B,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;IACrB,qHAAqH;IACrH,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC;IACxC,KAAK,CAAC,EAAE,OAAO,SAAS,CAAC;IACzB,mBAAmB,CAAC,EAAE,MAAM,CAAC;CAC9B;AAKD;;;GAGG;AACH,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,cAAc,GAAG,WAAW,CAyGxE"}
@@ -0,0 +1,122 @@
1
+ import { spawn as nodeSpawn } from 'node:child_process';
2
+ import { buildArgs, controlResponse, initializeLine, interruptLine, parseLine, userMessageLine } from './claude-code-protocol.js';
3
+ const NOT_INSTALLED = 'Claude Code is not installed (no `claude` on PATH)';
4
+ const KILL_AFTER_MS = 2000;
5
+ /**
6
+ * Drives the user's own, unmodified `claude` over stream-json. Align never touches its auth or
7
+ * model: it only answers the permission questions `claude` asks the host.
8
+ */
9
+ export function createClaudeCodeEngine(opts) {
10
+ const spawnFn = opts.spawn ?? nodeSpawn;
11
+ const firstEventTimeoutMs = opts.firstEventTimeoutMs ?? 20000;
12
+ let child;
13
+ let exitMessage;
14
+ let pending;
15
+ let emit = () => { };
16
+ let broker = async () => ({ allow: true });
17
+ let stderrTail = '';
18
+ let initTimer;
19
+ let buffer = '';
20
+ let interrupts = 0;
21
+ const send = (text) => { child?.stdin.write(text); };
22
+ async function answer(requestId, ask, input) {
23
+ let verdict;
24
+ try {
25
+ verdict = await broker(ask);
26
+ }
27
+ catch (err) {
28
+ // Never leave `claude` waiting on a question nobody will answer.
29
+ verdict = { allow: false, message: `Align could not check this action (${err instanceof Error ? err.message : String(err)}). Do not retry it.` };
30
+ }
31
+ send(controlResponse(requestId, verdict, input));
32
+ }
33
+ function onLine(raw) {
34
+ if (!raw.trim())
35
+ return;
36
+ const parsed = parseLine(raw);
37
+ if (parsed.init)
38
+ clearTimeout(initTimer);
39
+ for (const e of parsed.events) {
40
+ emit(e);
41
+ if (e.type === 'turn-end') {
42
+ pending?.resolve();
43
+ pending = undefined;
44
+ }
45
+ }
46
+ if (parsed.permission)
47
+ void answer(parsed.permission.requestId, parsed.permission.ask, parsed.permission.input);
48
+ }
49
+ return {
50
+ label: 'Claude Code',
51
+ start(onEvent, onAsk) {
52
+ emit = onEvent;
53
+ broker = onAsk;
54
+ return new Promise((resolve, reject) => {
55
+ const c = spawnFn(opts.bin ?? 'claude', buildArgs(opts.extraArgs), { cwd: opts.cwd, env: opts.env, stdio: ['pipe', 'pipe', 'pipe'] });
56
+ child = c;
57
+ c.stdout.on('data', (d) => {
58
+ buffer += String(d);
59
+ let i;
60
+ while ((i = buffer.indexOf('\n')) >= 0) {
61
+ const l = buffer.slice(0, i);
62
+ buffer = buffer.slice(i + 1);
63
+ onLine(l);
64
+ }
65
+ });
66
+ c.stderr.on('data', (d) => { stderrTail = (stderrTail + String(d)).slice(-500); });
67
+ // A claude that died mid-write breaks the pipe. The 'exit' handler reports the death;
68
+ // an unhandled stream error here would crash Align instead.
69
+ c.stdin.on('error', () => { });
70
+ c.once('error', (err) => {
71
+ const message = err.code === 'ENOENT' ? NOT_INSTALLED : err.message;
72
+ emit({ type: 'error', message });
73
+ reject(new Error(message));
74
+ });
75
+ c.once('exit', (code, signal) => {
76
+ clearTimeout(initTimer);
77
+ exitMessage = `Claude Code exited (${signal ? `signal ${signal}` : `code ${code}`})${stderrTail.trim() ? `: ${stderrTail.trim()}` : ''}`;
78
+ if (pending) {
79
+ emit({ type: 'error', message: exitMessage });
80
+ pending.reject(new Error(exitMessage));
81
+ pending = undefined;
82
+ }
83
+ });
84
+ c.once('spawn', () => {
85
+ send(initializeLine(`init-${Date.now()}`));
86
+ // A claude that never starts ends the run: the waiting turn fails, the child is stopped,
87
+ // and later prompts are refused with the same reason, so the screen never hangs.
88
+ initTimer = setTimeout(() => {
89
+ exitMessage = `Claude Code did not start within ${Math.round(firstEventTimeoutMs / 1000)}s. Run \`claude --version\` to check it works.`;
90
+ emit({ type: 'error', message: exitMessage });
91
+ pending?.reject(new Error(exitMessage));
92
+ pending = undefined;
93
+ c.kill();
94
+ }, firstEventTimeoutMs);
95
+ resolve();
96
+ });
97
+ });
98
+ },
99
+ prompt(text) {
100
+ if (exitMessage)
101
+ return Promise.reject(new Error(exitMessage));
102
+ return new Promise((resolve, reject) => {
103
+ pending = { resolve, reject };
104
+ send(userMessageLine(text));
105
+ });
106
+ },
107
+ // Verified against claude 2.1.318: it answers with a result line (error_during_execution), which
108
+ // ends the turn through the normal path, and the process stays up for the next prompt.
109
+ abort() { send(interruptLine(`int-${++interrupts}`)); },
110
+ close() {
111
+ const c = child;
112
+ if (!c || exitMessage)
113
+ return Promise.resolve();
114
+ return new Promise((resolve) => {
115
+ const killer = setTimeout(() => c.kill(), KILL_AFTER_MS);
116
+ c.once('exit', () => { clearTimeout(killer); resolve(); });
117
+ c.stdin.end();
118
+ });
119
+ },
120
+ };
121
+ }
122
+ //# sourceMappingURL=claude-code.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"claude-code.js","sourceRoot":"","sources":["../../../../src/lib/agent/engines/claude-code.ts"],"names":[],"mappings":"AAAA,OAAO,EAAuC,KAAK,IAAI,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAE7F,OAAO,EAAE,SAAS,EAAE,eAAe,EAAE,cAAc,EAAE,aAAa,EAAE,SAAS,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAC;AAYlI,MAAM,aAAa,GAAG,oDAAoD,CAAC;AAC3E,MAAM,aAAa,GAAG,IAAI,CAAC;AAE3B;;;GAGG;AACH,MAAM,UAAU,sBAAsB,CAAC,IAAoB;IACzD,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,IAAI,SAAS,CAAC;IACxC,MAAM,mBAAmB,GAAG,IAAI,CAAC,mBAAmB,IAAI,KAAK,CAAC;IAC9D,IAAI,KAAiD,CAAC;IACtD,IAAI,WAA+B,CAAC;IACpC,IAAI,OAAwE,CAAC;IAC7E,IAAI,IAAI,GAA8B,GAAG,EAAE,GAAE,CAAC,CAAC;IAC/C,IAAI,MAAM,GAA6C,KAAK,IAAI,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IACrF,IAAI,UAAU,GAAG,EAAE,CAAC;IACpB,IAAI,SAAoD,CAAC;IACzD,IAAI,MAAM,GAAG,EAAE,CAAC;IAChB,IAAI,UAAU,GAAG,CAAC,CAAC;IAEnB,MAAM,IAAI,GAAG,CAAC,IAAY,EAAE,EAAE,GAAG,KAAK,EAAE,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;IAE7D,KAAK,UAAU,MAAM,CAAC,SAAiB,EAAE,GAAY,EAAE,KAA8B;QACnF,IAAI,OAAsB,CAAC;QAC3B,IAAI,CAAC;YAAC,OAAO,GAAG,MAAM,MAAM,CAAC,GAAG,CAAC,CAAC;QAAC,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YAChD,iEAAiE;YACjE,OAAO,GAAG,EAAE,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,sCAAsC,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,qBAAqB,EAAE,CAAC;QACnJ,CAAC;QACD,IAAI,CAAC,eAAe,CAAC,SAAS,EAAE,OAAO,EAAE,KAAK,CAAC,CAAC,CAAC;IACnD,CAAC;IAED,SAAS,MAAM,CAAC,GAAW;QACzB,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE;YAAE,OAAO;QACxB,MAAM,MAAM,GAAG,SAAS,CAAC,GAAG,CAAC,CAAC;QAC9B,IAAI,MAAM,CAAC,IAAI;YAAE,YAAY,CAAC,SAAS,CAAC,CAAC;QACzC,KAAK,MAAM,CAAC,IAAI,MAAM,CAAC,MAAM,EAAE,CAAC;YAC9B,IAAI,CAAC,CAAC,CAAC,CAAC;YACR,IAAI,CAAC,CAAC,IAAI,KAAK,UAAU,EAAE,CAAC;gBAAC,OAAO,EAAE,OAAO,EAAE,CAAC;gBAAC,OAAO,GAAG,SAAS,CAAC;YAAC,CAAC;QACzE,CAAC;QACD,IAAI,MAAM,CAAC,UAAU;YAAE,KAAK,MAAM,CAAC,MAAM,CAAC,UAAU,CAAC,SAAS,EAAE,MAAM,CAAC,UAAU,CAAC,GAAG,EAAE,MAAM,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC;IAClH,CAAC;IAED,OAAO;QACL,KAAK,EAAE,aAAa;QAEpB,KAAK,CAAC,OAAO,EAAE,KAAK;YAClB,IAAI,GAAG,OAAO,CAAC;YACf,MAAM,GAAG,KAAK,CAAC;YACf,OAAO,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;gBAC3C,MAAM,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,QAAQ,EAAE,SAAS,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,EAAE,GAAG,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,EAAE,IAAI,CAAC,GAAG,EAAE,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,CAAmC,CAAC;gBACxK,KAAK,GAAG,CAAC,CAAC;gBACV,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,CAAS,EAAE,EAAE;oBAChC,MAAM,IAAI,MAAM,CAAC,CAAC,CAAC,CAAC;oBACpB,IAAI,CAAS,CAAC;oBACd,OAAO,CAAC,CAAC,GAAG,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC;wBAAC,MAAM,CAAC,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;wBAAC,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;wBAAC,MAAM,CAAC,CAAC,CAAC,CAAC;oBAAC,CAAC;gBACpH,CAAC,CAAC,CAAC;gBACH,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,CAAS,EAAE,EAAE,GAAG,UAAU,GAAG,CAAC,UAAU,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;gBAC3F,sFAAsF;gBACtF,4DAA4D;gBAC5D,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;gBAC9B,CAAC,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,GAA8B,EAAE,EAAE;oBACjD,MAAM,OAAO,GAAG,GAAG,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC;oBACpE,IAAI,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC,CAAC;oBACjC,MAAM,CAAC,IAAI,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC;gBAC7B,CAAC,CAAC,CAAC;gBACH,CAAC,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE;oBAC9B,YAAY,CAAC,SAAS,CAAC,CAAC;oBACxB,WAAW,GAAG,uBAAuB,MAAM,CAAC,CAAC,CAAC,UAAU,MAAM,EAAE,CAAC,CAAC,CAAC,QAAQ,IAAI,EAAE,IAAI,UAAU,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,KAAK,UAAU,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;oBACzI,IAAI,OAAO,EAAE,CAAC;wBACZ,IAAI,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,WAAW,EAAE,CAAC,CAAC;wBAC9C,OAAO,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,WAAW,CAAC,CAAC,CAAC;wBACvC,OAAO,GAAG,SAAS,CAAC;oBACtB,CAAC;gBACH,CAAC,CAAC,CAAC;gBACH,CAAC,CAAC,IAAI,CAAC,OAAO,EAAE,GAAG,EAAE;oBACnB,IAAI,CAAC,cAAc,CAAC,QAAQ,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,CAAC;oBAC3C,yFAAyF;oBACzF,iFAAiF;oBACjF,SAAS,GAAG,UAAU,CAAC,GAAG,EAAE;wBAC1B,WAAW,GAAG,oCAAoC,IAAI,CAAC,KAAK,CAAC,mBAAmB,GAAG,IAAI,CAAC,gDAAgD,CAAC;wBACzI,IAAI,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,WAAW,EAAE,CAAC,CAAC;wBAC9C,OAAO,EAAE,MAAM,CAAC,IAAI,KAAK,CAAC,WAAW,CAAC,CAAC,CAAC;wBACxC,OAAO,GAAG,SAAS,CAAC;wBACpB,CAAC,CAAC,IAAI,EAAE,CAAC;oBACX,CAAC,EAAE,mBAAmB,CAAC,CAAC;oBACxB,OAAO,EAAE,CAAC;gBACZ,CAAC,CAAC,CAAC;YACL,CAAC,CAAC,CAAC;QACL,CAAC;QAED,MAAM,CAAC,IAAI;YACT,IAAI,WAAW;gBAAE,OAAO,OAAO,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,WAAW,CAAC,CAAC,CAAC;YAC/D,OAAO,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;gBAC3C,OAAO,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC;gBAC9B,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC,CAAC;YAC9B,CAAC,CAAC,CAAC;QACL,CAAC;QAED,iGAAiG;QACjG,uFAAuF;QACvF,KAAK,KAAK,IAAI,CAAC,aAAa,CAAC,OAAO,EAAE,UAAU,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;QAEvD,KAAK;YACH,MAAM,CAAC,GAAG,KAAK,CAAC;YAChB,IAAI,CAAC,CAAC,IAAI,WAAW;gBAAE,OAAO,OAAO,CAAC,OAAO,EAAE,CAAC;YAChD,OAAO,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,EAAE;gBACnC,MAAM,MAAM,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,EAAE,aAAa,CAAC,CAAC;gBACzD,CAAC,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,EAAE,GAAG,YAAY,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;gBAC3D,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC;YAChB,CAAC,CAAC,CAAC;QACL,CAAC;KACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,46 @@
1
+ import { type SavedLlmConfig } from '../../local-llm.js';
2
+ /**
3
+ * Which model the Align engine runs, and the key to run it with. No Pi types here: the result is
4
+ * plain data and pi.ts builds Pi's model from it.
5
+ *
6
+ * Keys come from what the user already gave Align (an exported variable, or a key saved with
7
+ * `align ai`) and travel in-process only (H1): they are never put into process.env, so a child
8
+ * process cannot inherit them.
9
+ *
10
+ * NEVER a subscription login. Anthropic's terms forbid a Claude subscription login in third-party
11
+ * apps, and Pi's other OAuth providers (openai-codex, github-copilot, ...) are partner-only. Nothing
12
+ * here, or in pi.ts, calls or offers Pi's login; an override naming one is refused.
13
+ */
14
+ export interface ResolvedPiModel {
15
+ /** Pi's provider id, which is not always Align's (Align says gemini and grok; Pi says google and xai). */
16
+ provider: string;
17
+ modelId: string;
18
+ apiKey?: string;
19
+ /** Set for Ollama only: its OpenAI-compatible endpoint. */
20
+ baseUrl?: string;
21
+ /** Shown in the header, e.g. "Anthropic claude-sonnet-5-5". */
22
+ label: string;
23
+ }
24
+ /**
25
+ * The default coding-grade model per Align provider, read from Pi 1.5.0's catalogue (the test
26
+ * asserts every entry exists there, so a Pi bump that drops one fails loudly).
27
+ * - anthropic: Sonnet 5.5, the model the engine was built and tried against.
28
+ * - openai: gpt-6.1-sol, the newest non-pro flagship, priced like Sonnet 5.5 ($2/$10 per Mtok).
29
+ * - gemini: gemini-3.1-pro-preview, the only Pro-tier model in the catalogue (the rest are Flash).
30
+ * - grok: grok-4.7, the newest Grok. groq: gpt-oss-120b, its largest tool-calling model.
31
+ * - mistral: mistral-large-4, the newest large model with reasoning. deepseek: deepseek-v4-pro.
32
+ * Other Align providers (OpenRouter, a custom endpoint, the long tail) have no default: pick one
33
+ * with ALIGN_AGENT_MODEL, because a guess at a model on a gateway we cannot enumerate is worse than asking.
34
+ */
35
+ export declare const DEFAULT_PI_MODELS: Record<string, {
36
+ provider: string;
37
+ modelId: string;
38
+ }>;
39
+ export interface ResolvePiModelOptions {
40
+ /** Keys saved by `align ai`. The caller reads them from the config store; they never touch process.env. */
41
+ saved?: SavedLlmConfig;
42
+ /** Injected so tests need no network. Returns the model a reachable Ollama would use, or null. */
43
+ probeOllama?: () => Promise<string | null>;
44
+ }
45
+ export declare function resolvePiModel(opts?: ResolvePiModelOptions): Promise<ResolvedPiModel | undefined>;
46
+ //# sourceMappingURL=pi-models.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pi-models.d.ts","sourceRoot":"","sources":["../../../../src/lib/agent/engines/pi-models.ts"],"names":[],"mappings":"AACA,OAAO,EAAsD,KAAK,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAE7G;;;;;;;;;;;GAWG;AACH,MAAM,WAAW,eAAe;IAC9B,0GAA0G;IAC1G,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,2DAA2D;IAC3D,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,+DAA+D;IAC/D,KAAK,EAAE,MAAM,CAAC;CACf;AAED;;;;;;;;;;GAUG;AACH,eAAO,MAAM,iBAAiB,EAAE,MAAM,CAAC,MAAM,EAAE;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAQnF,CAAC;AAOF,MAAM,WAAW,qBAAqB;IACpC,2GAA2G;IAC3G,KAAK,CAAC,EAAE,cAAc,CAAC;IACvB,kGAAkG;IAClG,WAAW,CAAC,EAAE,MAAM,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;CAC5C;AAuBD,wBAAsB,cAAc,CAAC,IAAI,GAAE,qBAA0B,GAAG,OAAO,CAAC,eAAe,GAAG,SAAS,CAAC,CA2C3G"}
@@ -0,0 +1,91 @@
1
+ import { NAMED_PROVIDERS, namedProvider } from '../../llm-providers.js';
2
+ import { preferredProvider, probeOllama as probeLocalOllama } from '../../local-llm.js';
3
+ /**
4
+ * The default coding-grade model per Align provider, read from Pi 1.5.0's catalogue (the test
5
+ * asserts every entry exists there, so a Pi bump that drops one fails loudly).
6
+ * - anthropic: Sonnet 5.5, the model the engine was built and tried against.
7
+ * - openai: gpt-6.1-sol, the newest non-pro flagship, priced like Sonnet 5.5 ($2/$10 per Mtok).
8
+ * - gemini: gemini-3.1-pro-preview, the only Pro-tier model in the catalogue (the rest are Flash).
9
+ * - grok: grok-4.7, the newest Grok. groq: gpt-oss-120b, its largest tool-calling model.
10
+ * - mistral: mistral-large-4, the newest large model with reasoning. deepseek: deepseek-v4-pro.
11
+ * Other Align providers (OpenRouter, a custom endpoint, the long tail) have no default: pick one
12
+ * with ALIGN_AGENT_MODEL, because a guess at a model on a gateway we cannot enumerate is worse than asking.
13
+ */
14
+ export const DEFAULT_PI_MODELS = {
15
+ anthropic: { provider: 'anthropic', modelId: 'claude-sonnet-5-5' },
16
+ openai: { provider: 'openai', modelId: 'gpt-6.1-sol' },
17
+ gemini: { provider: 'google', modelId: 'gemini-3.1-pro-preview' },
18
+ grok: { provider: 'xai', modelId: 'grok-4.7' },
19
+ groq: { provider: 'groq', modelId: 'openai/gpt-oss-120b' },
20
+ mistral: { provider: 'mistral', modelId: 'mistral-large-4' },
21
+ deepseek: { provider: 'deepseek', modelId: 'deepseek-v4-pro' },
22
+ };
23
+ /** Pi providers that sign in with a subscription. Refused outright (see the header). */
24
+ const SUBSCRIPTION_PROVIDERS = new Set([
25
+ 'openai-codex', 'openai-chatgpt', 'github-copilot', 'google-gemini-cli', 'google-antigravity',
26
+ ]);
27
+ const label = (alignId, modelId) => `${namedProvider(alignId)?.label ?? alignId} ${modelId}`;
28
+ /** The key for one Align provider: a saved key, or an exported one that Align is allowed to use. */
29
+ function keyFor(alignId, saved, preferred) {
30
+ const p = namedProvider(alignId);
31
+ if (!p)
32
+ return undefined;
33
+ const exported = p.keyEnv.map((n) => process.env[n]).find(Boolean);
34
+ const saveKey = saved.keys[alignId];
35
+ // Same rule as local-llm's credentials(): an exported key beyond the original six may be there for
36
+ // another tool, so it counts only when the user also saved one or chose the provider.
37
+ if (exported && (p.autoFromEnv || preferred === alignId || saveKey))
38
+ return exported;
39
+ return saveKey;
40
+ }
41
+ /** A local Ollama model. `||`, not `??`: OLLAMA_HOST='' must not make a relative URL (local-llm's ollamaHost says why). */
42
+ function ollamaModel(model) {
43
+ const host = (process.env['OLLAMA_HOST'] || 'http://localhost:11434').replace(/\/+$/, '');
44
+ return { provider: 'ollama', modelId: model, apiKey: 'ollama', baseUrl: `${host}/v1`, label: `Ollama ${model}` };
45
+ }
46
+ export async function resolvePiModel(opts = {}) {
47
+ const saved = opts.saved ?? { keys: {} };
48
+ const preferred = preferredProvider(saved);
49
+ const override = process.env['ALIGN_AGENT_MODEL'];
50
+ if (override) {
51
+ const slash = override.indexOf('/');
52
+ if (slash < 1 || slash === override.length - 1) {
53
+ throw new Error(`ALIGN_AGENT_MODEL must be provider/model-id (for example anthropic/claude-sonnet-5-5), got "${override}".`);
54
+ }
55
+ const provider = override.slice(0, slash);
56
+ const modelId = override.slice(slash + 1);
57
+ // Ollama needs no key: the override names the local model to run.
58
+ if (provider === 'ollama')
59
+ return ollamaModel(modelId);
60
+ if (SUBSCRIPTION_PROVIDERS.has(provider)) {
61
+ throw new Error(`ALIGN_AGENT_MODEL names ${provider}, which signs in with a subscription. Align runs on API keys only: use a provider you have a key for.`);
62
+ }
63
+ const alignId = Object.entries(DEFAULT_PI_MODELS).find(([, d]) => d.provider === provider)?.[0] ?? provider;
64
+ const apiKey = namedProvider(alignId) ? keyFor(alignId, saved, preferred) : undefined;
65
+ if (!apiKey)
66
+ throw new Error(`ALIGN_AGENT_MODEL names ${provider}, but there is no key for it. Export its key or run align ai.`);
67
+ return { provider, modelId, apiKey, label: label(alignId, modelId) };
68
+ }
69
+ const probe = opts.probeOllama ?? probeLocalOllama;
70
+ // A user who chose Ollama gets Ollama when it runs, before any exported key: a local choice must
71
+ // not quietly become a paid API call.
72
+ if (preferred === 'ollama') {
73
+ const local = await probe();
74
+ if (local)
75
+ return ollamaModel(local);
76
+ }
77
+ // The preference goes first, then the fixed provider order, so the answer does not depend on which
78
+ // shell variable happens to be set.
79
+ const order = [preferred, ...NAMED_PROVIDERS.map((p) => p.id)].filter((id) => Boolean(id) && id !== 'ollama' && id !== 'custom' && id !== 'openrouter');
80
+ for (const alignId of order) {
81
+ const def = DEFAULT_PI_MODELS[alignId];
82
+ const apiKey = def ? keyFor(alignId, saved, preferred) : undefined;
83
+ if (def && apiKey)
84
+ return { provider: def.provider, modelId: def.modelId, apiKey, label: label(alignId, def.modelId) };
85
+ }
86
+ if (preferred === 'ollama')
87
+ return undefined; // already probed above, and it is not running
88
+ const model = await probe();
89
+ return model ? ollamaModel(model) : undefined;
90
+ }
91
+ //# sourceMappingURL=pi-models.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pi-models.js","sourceRoot":"","sources":["../../../../src/lib/agent/engines/pi-models.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,39 @@
1
+ import type { PiSdk } from './pi.js';
2
+ /**
3
+ * Where Align's own engine comes from.
4
+ *
5
+ * The engine is Pi's SDK plus the provider SDKs it pulls in, about 110 MB, so it is not in the
6
+ * npm install (install-smoke caps that at 100 MB; the UI library, ~3 MB, is). It is used from
7
+ * the bundle where there is one (the compiled binary, a dev checkout), else from a copy
8
+ * downloaded earlier, else downloaded once now with the person's yes - the same shape as the
9
+ * on-device embedding runtime. Users on their own Claude Code never download it.
10
+ */
11
+ export declare const PI_ENGINE_PACKAGES: readonly ["@earendil-works/pi-coding-agent", "@earendil-works/pi-ai"];
12
+ export declare const PI_ENGINE_VERSION: string;
13
+ export interface PiSdkDeps {
14
+ engineDir: string;
15
+ /** The engine bundled with this build, and its version when it can be read. */
16
+ importBundled: () => Promise<{
17
+ sdk: PiSdk;
18
+ version?: string;
19
+ }>;
20
+ importInstalled: (engineDir: string) => Promise<PiSdk>;
21
+ confirm: (message: string) => Promise<boolean>;
22
+ runNpm: (args: string[]) => Promise<number>;
23
+ out: (line: string) => void;
24
+ }
25
+ export declare function loadPiSdk(deps: PiSdkDeps): Promise<PiSdk>;
26
+ /**
27
+ * How to run npm. On Windows npm is npm.cmd, which needs a shell, and cmd.exe splits an unquoted
28
+ * argument at a space - a home directory like "Jo Smith" would break the install path.
29
+ */
30
+ export declare function npmCommand(platform: string, args: string[]): {
31
+ cmd: string;
32
+ args: string[];
33
+ shell: boolean;
34
+ };
35
+ export declare function defaultPiSdkDeps(o: {
36
+ engineDir: string;
37
+ confirm: (message: string) => Promise<boolean>;
38
+ }): PiSdkDeps;
39
+ //# sourceMappingURL=pi-sdk.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pi-sdk.d.ts","sourceRoot":"","sources":["../../../../src/lib/agent/engines/pi-sdk.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAErC;;;;;;;;GAQG;AAEH,eAAO,MAAM,kBAAkB,uEAAwE,CAAC;AAQxG,eAAO,MAAM,iBAAiB,QAAgC,CAAC;AAE/D,MAAM,WAAW,SAAS;IACxB,SAAS,EAAE,MAAM,CAAC;IAClB,+EAA+E;IAC/E,aAAa,EAAE,MAAM,OAAO,CAAC;QAAE,GAAG,EAAE,KAAK,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC/D,eAAe,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,OAAO,CAAC,KAAK,CAAC,CAAC;IACvD,OAAO,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IAC/C,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IAC5C,GAAG,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;CAC7B;AAMD,wBAAsB,SAAS,CAAC,IAAI,EAAE,SAAS,GAAG,OAAO,CAAC,KAAK,CAAC,CAgB/D;AA6BD;;;GAGG;AACH,wBAAgB,UAAU,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,EAAE,CAAC;IAAC,KAAK,EAAE,OAAO,CAAA;CAAE,CAG5G;AAED,wBAAgB,gBAAgB,CAAC,CAAC,EAAE;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAA;CAAE,GAAG,SAAS,CAepH"}
@@ -0,0 +1,105 @@
1
+ import { spawn } from 'node:child_process';
2
+ import { readFileSync } from 'node:fs';
3
+ import { dirname, join } from 'node:path';
4
+ import { fileURLToPath, pathToFileURL } from 'node:url';
5
+ import pkg from '../../../../package.json' with { type: 'json' };
6
+ /**
7
+ * Where Align's own engine comes from.
8
+ *
9
+ * The engine is Pi's SDK plus the provider SDKs it pulls in, about 110 MB, so it is not in the
10
+ * npm install (install-smoke caps that at 100 MB; the UI library, ~3 MB, is). It is used from
11
+ * the bundle where there is one (the compiled binary, a dev checkout), else from a copy
12
+ * downloaded earlier, else downloaded once now with the person's yes - the same shape as the
13
+ * on-device embedding runtime. Users on their own Claude Code never download it.
14
+ */
15
+ export const PI_ENGINE_PACKAGES = ['@earendil-works/pi-coding-agent', '@earendil-works/pi-ai'];
16
+ /** The exact versions this CLI was tested against: the devDependencies pins, one writer of each. */
17
+ function pinned(name) {
18
+ const version = pkg.devDependencies[name];
19
+ if (!version)
20
+ throw new Error(`package.json pins no version of ${name}`);
21
+ return version;
22
+ }
23
+ export const PI_ENGINE_VERSION = pinned(PI_ENGINE_PACKAGES[0]);
24
+ const attempt = async (load) => {
25
+ try {
26
+ return await load();
27
+ }
28
+ catch {
29
+ return undefined;
30
+ }
31
+ };
32
+ export async function loadPiSdk(deps) {
33
+ // A bundled Pi of another version (one installed beside Align, say) may lack what the engine
34
+ // uses, so only the pinned version counts. A build that cannot report its version (the compiled
35
+ // binary) counts when it has the API, so binary users are not sent to download what they have.
36
+ const bundled = await attempt(deps.importBundled);
37
+ const usable = bundled && (bundled.version === PI_ENGINE_VERSION || (bundled.version === undefined && typeof bundled.sdk.ModelRuntime === 'function'));
38
+ const ready = (usable ? bundled.sdk : undefined) ?? (await attempt(() => deps.importInstalled(deps.engineDir)));
39
+ if (ready)
40
+ return ready;
41
+ const yes = await deps.confirm('Align\'s own engine is a one-time download, about 110 MB. Download it now?');
42
+ if (!yes)
43
+ throw new Error('Align\'s own engine was not downloaded. Run align again to download it, or use --engine claude.');
44
+ deps.out(`Downloading Align's engine into ${deps.engineDir} ...`);
45
+ const code = await deps.runNpm(['install', '--prefix', deps.engineDir, '--no-audit', '--no-fund', '--loglevel=error',
46
+ ...PI_ENGINE_PACKAGES.map((name) => `${name}@${pinned(name)}`)]);
47
+ if (code !== 0)
48
+ throw new Error(`The engine download failed (npm exited ${code}). Check your connection and run align again.`);
49
+ return deps.importInstalled(deps.engineDir);
50
+ }
51
+ /** The ESM entry of a package installed under `engineDir`, read from its own exports map. */
52
+ function installedEntry(engineDir, name) {
53
+ const dir = join(engineDir, 'node_modules', ...name.split('/'));
54
+ const manifest = JSON.parse(readFileSync(join(dir, 'package.json'), 'utf8'));
55
+ const root = manifest.exports?.['.'];
56
+ const entry = typeof root === 'string' ? root
57
+ : root?.['import'] ?? root?.['default'] ?? manifest.main;
58
+ const file = typeof entry === 'string' ? entry : entry?.['default'];
59
+ if (typeof file !== 'string')
60
+ throw new Error(`${name} in ${engineDir} has no entry point`);
61
+ return join(dir, file);
62
+ }
63
+ /** The version of the bundled engine, read from its package.json; undefined when it cannot be found. */
64
+ function bundledVersion() {
65
+ try {
66
+ let dir = dirname(fileURLToPath(import.meta.resolve(PI_ENGINE_PACKAGES[0])));
67
+ for (let i = 0; i < 6; i++) {
68
+ try {
69
+ const m = JSON.parse(readFileSync(join(dir, 'package.json'), 'utf8'));
70
+ if (m.name === PI_ENGINE_PACKAGES[0])
71
+ return m.version;
72
+ }
73
+ catch { /* keep walking up */ }
74
+ dir = dirname(dir);
75
+ }
76
+ }
77
+ catch { /* not resolvable here */ }
78
+ return undefined;
79
+ }
80
+ /**
81
+ * How to run npm. On Windows npm is npm.cmd, which needs a shell, and cmd.exe splits an unquoted
82
+ * argument at a space - a home directory like "Jo Smith" would break the install path.
83
+ */
84
+ export function npmCommand(platform, args) {
85
+ if (platform !== 'win32')
86
+ return { cmd: 'npm', args, shell: false };
87
+ return { cmd: 'npm.cmd', args: args.map((a) => (/[\s"&|<>^]/.test(a) ? `"${a.replace(/"/g, '""')}"` : a)), shell: true };
88
+ }
89
+ export function defaultPiSdkDeps(o) {
90
+ return {
91
+ engineDir: o.engineDir,
92
+ // A literal specifier, so the compiled binary bundles the engine and never downloads it.
93
+ importBundled: async () => ({ sdk: await import('@earendil-works/pi-coding-agent'), version: bundledVersion() }),
94
+ importInstalled: async (dir) => (await import(pathToFileURL(installedEntry(dir, PI_ENGINE_PACKAGES[0])).href)),
95
+ confirm: o.confirm,
96
+ runNpm: (args) => new Promise((resolve) => {
97
+ const npm = npmCommand(process.platform, args);
98
+ const child = spawn(npm.cmd, npm.args, { stdio: 'inherit', shell: npm.shell });
99
+ child.on('error', () => resolve(127));
100
+ child.on('exit', (code) => resolve(code ?? 1));
101
+ }),
102
+ out: (l) => process.stderr.write(`${l}\n`),
103
+ };
104
+ }
105
+ //# sourceMappingURL=pi-sdk.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pi-sdk.js","sourceRoot":"","sources":["../../../../src/lib/agent/engines/pi-sdk.ts"],"names":[],"mappings":"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"}