projectinator 0.3.1 → 0.4.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 (171) hide show
  1. package/README.md +7 -6
  2. package/bin/projectinator.mjs +22 -15
  3. package/dist/bakeoff.js +163 -0
  4. package/dist/bakeoff.js.map +1 -0
  5. package/dist/build-state.js +26 -0
  6. package/dist/build-state.js.map +1 -0
  7. package/dist/burndown.js +19 -0
  8. package/dist/burndown.js.map +1 -0
  9. package/dist/calibration.js +86 -0
  10. package/dist/calibration.js.map +1 -0
  11. package/dist/cli.js +289 -0
  12. package/dist/cli.js.map +1 -0
  13. package/dist/cost.js +35 -0
  14. package/dist/cost.js.map +1 -0
  15. package/dist/council.js +147 -0
  16. package/dist/council.js.map +1 -0
  17. package/dist/demo.js +93 -0
  18. package/dist/demo.js.map +1 -0
  19. package/dist/estimate.js +98 -0
  20. package/dist/estimate.js.map +1 -0
  21. package/dist/executor.js +118 -0
  22. package/dist/executor.js.map +1 -0
  23. package/dist/git.js +82 -0
  24. package/dist/git.js.map +1 -0
  25. package/dist/intake.js +98 -0
  26. package/dist/intake.js.map +1 -0
  27. package/dist/models.js +171 -0
  28. package/dist/models.js.map +1 -0
  29. package/dist/narrate.js +76 -0
  30. package/dist/narrate.js.map +1 -0
  31. package/dist/openrouter.js +112 -0
  32. package/dist/openrouter.js.map +1 -0
  33. package/dist/orchestrator.js +273 -0
  34. package/dist/orchestrator.js.map +1 -0
  35. package/dist/pm.js +245 -0
  36. package/dist/pm.js.map +1 -0
  37. package/dist/preview.js +194 -0
  38. package/dist/preview.js.map +1 -0
  39. package/dist/registry-store.js +38 -0
  40. package/dist/registry-store.js.map +1 -0
  41. package/dist/registry.js +115 -0
  42. package/dist/registry.js.map +1 -0
  43. package/dist/research.js +98 -0
  44. package/dist/research.js.map +1 -0
  45. package/dist/retro.js +83 -0
  46. package/dist/retro.js.map +1 -0
  47. package/dist/roles.js +357 -0
  48. package/dist/roles.js.map +1 -0
  49. package/dist/router.js +95 -0
  50. package/dist/router.js.map +1 -0
  51. package/dist/run-bakeoff.js +68 -0
  52. package/dist/run-bakeoff.js.map +1 -0
  53. package/dist/run-build.js +193 -0
  54. package/dist/run-build.js.map +1 -0
  55. package/{src/run-dev.ts → dist/run-dev.js} +23 -39
  56. package/dist/run-dev.js.map +1 -0
  57. package/{src/run-pm.ts → dist/run-pm.js} +34 -46
  58. package/dist/run-pm.js.map +1 -0
  59. package/{src/run-research.ts → dist/run-research.js} +19 -30
  60. package/dist/run-research.js.map +1 -0
  61. package/{src/run-scout.ts → dist/run-scout.js} +17 -27
  62. package/dist/run-scout.js.map +1 -0
  63. package/dist/run-web.js +93 -0
  64. package/dist/run-web.js.map +1 -0
  65. package/dist/scout.js +81 -0
  66. package/dist/scout.js.map +1 -0
  67. package/dist/session-cost.js +15 -0
  68. package/dist/session-cost.js.map +1 -0
  69. package/dist/stack.js +34 -0
  70. package/dist/stack.js.map +1 -0
  71. package/dist/stuck.js +21 -0
  72. package/dist/stuck.js.map +1 -0
  73. package/dist/tui/App.js +1269 -0
  74. package/dist/tui/App.js.map +1 -0
  75. package/dist/tui/BakeOff.js +95 -0
  76. package/dist/tui/BakeOff.js.map +1 -0
  77. package/dist/tui/BoardEditor.js +183 -0
  78. package/dist/tui/BoardEditor.js.map +1 -0
  79. package/dist/tui/EditableBoard.js +140 -0
  80. package/dist/tui/EditableBoard.js.map +1 -0
  81. package/dist/tui/Frame.js +78 -0
  82. package/dist/tui/Frame.js.map +1 -0
  83. package/dist/tui/Intake.js +59 -0
  84. package/dist/tui/Intake.js.map +1 -0
  85. package/dist/tui/Kanban.js +75 -0
  86. package/dist/tui/Kanban.js.map +1 -0
  87. package/dist/tui/Settings.js +299 -0
  88. package/dist/tui/Settings.js.map +1 -0
  89. package/dist/tui/StackPick.js +44 -0
  90. package/dist/tui/StackPick.js.map +1 -0
  91. package/dist/tui/WebAccounts.js +131 -0
  92. package/dist/tui/WebAccounts.js.map +1 -0
  93. package/dist/tui/components.js +178 -0
  94. package/dist/tui/components.js.map +1 -0
  95. package/dist/tui/config.js +129 -0
  96. package/dist/tui/config.js.map +1 -0
  97. package/dist/tui/deploy.js +114 -0
  98. package/dist/tui/deploy.js.map +1 -0
  99. package/dist/tui/engine.js +710 -0
  100. package/dist/tui/engine.js.map +1 -0
  101. package/dist/tui/notify.js +47 -0
  102. package/dist/tui/notify.js.map +1 -0
  103. package/dist/tui/panels.js +42 -0
  104. package/dist/tui/panels.js.map +1 -0
  105. package/dist/tui/templates.js +106 -0
  106. package/dist/tui/templates.js.map +1 -0
  107. package/dist/tui/theme.js +42 -0
  108. package/dist/tui/theme.js.map +1 -0
  109. package/dist/tui/validate.js +51 -0
  110. package/dist/tui/validate.js.map +1 -0
  111. package/{src/tui.tsx → dist/tui.js} +23 -33
  112. package/dist/tui.js.map +1 -0
  113. package/dist/types.js +19 -0
  114. package/dist/types.js.map +1 -0
  115. package/dist/web/oauth-anthropic.js +179 -0
  116. package/dist/web/oauth-anthropic.js.map +1 -0
  117. package/dist/web/session.js +274 -0
  118. package/dist/web/session.js.map +1 -0
  119. package/package.json +5 -4
  120. package/src/bakeoff.ts +0 -214
  121. package/src/build-state.ts +0 -47
  122. package/src/burndown.ts +0 -35
  123. package/src/calibration.ts +0 -88
  124. package/src/cli.ts +0 -263
  125. package/src/cost.ts +0 -43
  126. package/src/council.ts +0 -175
  127. package/src/demo.ts +0 -106
  128. package/src/estimate.ts +0 -111
  129. package/src/executor.ts +0 -169
  130. package/src/git.ts +0 -72
  131. package/src/intake.ts +0 -125
  132. package/src/models.ts +0 -175
  133. package/src/narrate.ts +0 -87
  134. package/src/openrouter.ts +0 -119
  135. package/src/orchestrator.ts +0 -310
  136. package/src/pm.ts +0 -302
  137. package/src/preview.ts +0 -206
  138. package/src/registry-store.ts +0 -41
  139. package/src/registry.ts +0 -132
  140. package/src/research.ts +0 -123
  141. package/src/retro.ts +0 -99
  142. package/src/roles.ts +0 -401
  143. package/src/router.ts +0 -120
  144. package/src/run-bakeoff.ts +0 -77
  145. package/src/run-build.ts +0 -203
  146. package/src/run-web.ts +0 -87
  147. package/src/scout.ts +0 -121
  148. package/src/session-cost.ts +0 -17
  149. package/src/stack.ts +0 -46
  150. package/src/tui/App.tsx +0 -1760
  151. package/src/tui/BakeOff.tsx +0 -190
  152. package/src/tui/BoardEditor.tsx +0 -260
  153. package/src/tui/EditableBoard.tsx +0 -179
  154. package/src/tui/Frame.tsx +0 -142
  155. package/src/tui/Intake.tsx +0 -111
  156. package/src/tui/Kanban.tsx +0 -158
  157. package/src/tui/Settings.tsx +0 -513
  158. package/src/tui/StackPick.tsx +0 -79
  159. package/src/tui/WebAccounts.tsx +0 -197
  160. package/src/tui/components.tsx +0 -340
  161. package/src/tui/config.ts +0 -150
  162. package/src/tui/deploy.ts +0 -137
  163. package/src/tui/engine.ts +0 -749
  164. package/src/tui/notify.ts +0 -21
  165. package/src/tui/panels.tsx +0 -89
  166. package/src/tui/templates.ts +0 -119
  167. package/src/tui/theme.ts +0 -44
  168. package/src/tui/validate.ts +0 -53
  169. package/src/types.ts +0 -208
  170. package/src/web/oauth-anthropic.ts +0 -206
  171. package/src/web/session.ts +0 -299
@@ -0,0 +1,98 @@
1
+ // Token estimation lives in CODE, not in the model.
2
+ // The Phase 2 live run proved models estimate their own token use terribly
3
+ // (a "high" single-file task used ~1.5k output, not the 12k a model guessed).
4
+ // So the PM only tags capability + difficulty; we map that to a token budget here.
5
+ //
6
+ // CALIBRATION (2026-07-15) — retuned against real getSessionStats from live runs:
7
+ // Phase 2 dev (code, single-file): output ~1.5k, input almost entirely cached
8
+ // (fresh 4 of ~3.3k tokens).
9
+ // Phase 4 mini: design/low, code/low ~ $0.03-0.04 each; test/trivial ~ $0.02.
10
+ // Takeaways baked in below:
11
+ // - a "task" is ONE atomic unit (a file / component / spec), not a whole feature,
12
+ // so outputs are small — and output dominates cost (priced ~5-6x input).
13
+ // - Pi caches context aggressively, so most input bills at the cheap cacheRead rate.
14
+ // These stay heuristic; wire measured actuals back in for self-calibration later.
15
+ import { calibratedTokens, modelCalibratedTokens, allSamples } from "./calibration.js";
16
+ const BUCKETS = {
17
+ plan: {
18
+ trivial: { input: 2_000, output: 800 },
19
+ low: { input: 4_000, output: 1_500 },
20
+ medium: { input: 8_000, output: 3_000 },
21
+ high: { input: 12_000, output: 5_000 },
22
+ },
23
+ design: {
24
+ trivial: { input: 4_000, output: 2_000 },
25
+ low: { input: 6_000, output: 3_500 },
26
+ medium: { input: 10_000, output: 6_000 },
27
+ high: { input: 15_000, output: 9_000 },
28
+ },
29
+ code: {
30
+ trivial: { input: 6_000, output: 1_500 },
31
+ low: { input: 10_000, output: 3_000 },
32
+ medium: { input: 25_000, output: 7_000 },
33
+ high: { input: 60_000, output: 14_000 },
34
+ },
35
+ // Review reads the same tree the tester does but never runs it — shorter output.
36
+ review: {
37
+ trivial: { input: 15_000, output: 800 },
38
+ low: { input: 25_000, output: 1_500 },
39
+ medium: { input: 50_000, output: 3_000 },
40
+ high: { input: 80_000, output: 5_000 },
41
+ },
42
+ test: {
43
+ trivial: { input: 15_000, output: 1_200 },
44
+ low: { input: 25_000, output: 2_500 },
45
+ medium: { input: 50_000, output: 5_000 },
46
+ high: { input: 80_000, output: 9_000 },
47
+ },
48
+ ops: {
49
+ trivial: { input: 10_000, output: 2_000 },
50
+ low: { input: 20_000, output: 4_000 },
51
+ medium: { input: 40_000, output: 7_000 },
52
+ high: { input: 70_000, output: 12_000 },
53
+ },
54
+ };
55
+ // Pi auto-caches system prompt + context aggressively (live run: fresh input 4 tokens
56
+ // of ~3.3k). Real cached share is often 80-99%; 0.55 is a conservative planning value.
57
+ const DEFAULT_CACHED_INPUT_FRACTION = 0.55;
58
+ export function estimateTokens(capability, difficulty) {
59
+ // Prefer the learned average once we have enough real samples; else the static bucket.
60
+ const learned = calibratedTokens(capability, difficulty);
61
+ if (learned)
62
+ return learned;
63
+ const b = BUCKETS[capability][difficulty];
64
+ return { input: b.input, output: b.output, cachedInputFraction: DEFAULT_CACHED_INPUT_FRACTION };
65
+ }
66
+ /** The static baseline (pre-calibration) token budget for a bucket. */
67
+ export function baselineTokens(capability, difficulty) {
68
+ return BUCKETS[capability][difficulty];
69
+ }
70
+ /** Baseline vs measured tokens for every bucket that has real samples — the generic
71
+ * bucket first, then each model that ran it. */
72
+ export function estimateAccuracy() {
73
+ const samples = allSamples();
74
+ const rows = [];
75
+ for (const cap of Object.keys(BUCKETS)) {
76
+ for (const diff of Object.keys(BUCKETS[cap])) {
77
+ const b = BUCKETS[cap][diff];
78
+ const prefix = `${cap}/${diff}`;
79
+ for (const k of Object.keys(samples).filter((k) => k === prefix || k.startsWith(`${prefix}/`)).sort()) {
80
+ const s = samples[k];
81
+ const model = k === prefix ? undefined : k.slice(prefix.length + 1);
82
+ rows.push({
83
+ capability: cap,
84
+ difficulty: diff,
85
+ model,
86
+ baseOutput: b.output,
87
+ actualOutput: Math.round(s.output),
88
+ baseInput: b.input,
89
+ actualInput: Math.round(s.input),
90
+ n: s.n,
91
+ active: !!(model ? modelCalibratedTokens(cap, diff, model) : calibratedTokens(cap, diff)),
92
+ });
93
+ }
94
+ }
95
+ }
96
+ return rows;
97
+ }
98
+ //# sourceMappingURL=estimate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"estimate.js","sourceRoot":"","sources":["../src/estimate.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,118 @@
1
+ // Phase 2 — the Executor. Runs ONE task on a real Pi agent session with the model
2
+ // the router chose. Writes real files to a workspace dir, then reads back Pi's own
3
+ // token usage + cost so we can compare estimated vs actual.
4
+ //
5
+ // Constructing a session and resolving models is offline + free. Only session.prompt()
6
+ // hits the provider API and spends money — that path is guarded by the caller.
7
+ import { ModelRuntime, createAgentSession, } from "@earendil-works/pi-coding-agent";
8
+ import { readdirSync, statSync } from "node:fs";
9
+ import { join, relative } from "node:path";
10
+ import { estimateCost } from "./cost.js";
11
+ import { getModel } from "./models.js";
12
+ import { addSessionCost } from "./session-cost.js";
13
+ /** Pi's model/auth runtime: built-in catalog + env keys / ~/.pi/agent/auth.json.
14
+ * Created per call on purpose — a key added in Settings must apply to the next session. */
15
+ export function piRuntime() {
16
+ return ModelRuntime.create();
17
+ }
18
+ /** Resolve a Projectinator (provider, modelId) to Pi's executable Model.
19
+ * Offline + free — reads Pi's built-in registry. Throws with a clear message
20
+ * if the id isn't one Pi knows (our ids are kept identical to Pi's on purpose). */
21
+ export function resolvePiModel(runtime, provider, modelId) {
22
+ const m = runtime.getModel(provider, modelId);
23
+ if (!m) {
24
+ throw new Error(`Pi has no model "${provider}/${modelId}". ` +
25
+ `Check src/models.ts uses Pi's exact built-in id.`);
26
+ }
27
+ return m;
28
+ }
29
+ /** Build the Developer role's instruction for a single task. */
30
+ export function buildDeveloperPrompt(task) {
31
+ return [
32
+ `You are the DEVELOPER on an autonomous build team. Complete exactly this task and nothing more.`,
33
+ ``,
34
+ `Task ${task.id}: ${task.title}`,
35
+ task.story ? `Story: ${task.story}` : ``,
36
+ ``,
37
+ `Rules:`,
38
+ `- Write real files into the current working directory using your file tools.`,
39
+ `- Keep it minimal and correct; no placeholders, no TODOs.`,
40
+ `- Do not explain at length. Build, then stop.`,
41
+ ]
42
+ .filter(Boolean)
43
+ .join("\n");
44
+ }
45
+ /**
46
+ * Execute one task on a live Pi session. THIS SPENDS MONEY (session.prompt).
47
+ * Caller is responsible for gating on a live flag + present API key.
48
+ */
49
+ export async function executeTask(task, decision, opts) {
50
+ const runtime = await piRuntime();
51
+ const model = resolvePiModel(runtime, decision.provider, decision.model.id);
52
+ const { session } = await createAgentSession({
53
+ model,
54
+ cwd: opts.workspace,
55
+ modelRuntime: runtime,
56
+ thinkingLevel: opts.thinkingLevel ?? "medium",
57
+ tools: opts.tools ?? ["read", "write", "edit", "bash", "ls", "grep", "find"],
58
+ });
59
+ let unsubscribe;
60
+ if (opts.onEvent)
61
+ unsubscribe = session.subscribe(opts.onEvent);
62
+ try {
63
+ await session.prompt(buildDeveloperPrompt(task));
64
+ const stats = session.getSessionStats();
65
+ addSessionCost(stats.cost);
66
+ const estCost = estimateCost(task.estTokens, getModel(decision.model.id));
67
+ const actualCost = round2(stats.cost);
68
+ return {
69
+ taskId: task.id,
70
+ provider: decision.provider,
71
+ modelId: decision.model.id,
72
+ files: listFiles(opts.workspace),
73
+ actual: {
74
+ input: stats.tokens.input,
75
+ output: stats.tokens.output,
76
+ cacheRead: stats.tokens.cacheRead,
77
+ cacheWrite: stats.tokens.cacheWrite,
78
+ total: stats.tokens.total,
79
+ },
80
+ actualCost,
81
+ estCost,
82
+ costDelta: round2(actualCost - estCost),
83
+ };
84
+ }
85
+ finally {
86
+ unsubscribe?.();
87
+ session.dispose();
88
+ }
89
+ }
90
+ /** List files in a workspace, skipping Pi/session/VCS noise. */
91
+ function listFiles(dir) {
92
+ const out = [];
93
+ const skip = new Set([".pi", ".git", "node_modules"]);
94
+ const walk = (d) => {
95
+ let entries;
96
+ try {
97
+ entries = readdirSync(d);
98
+ }
99
+ catch {
100
+ return;
101
+ }
102
+ for (const name of entries) {
103
+ if (skip.has(name))
104
+ continue;
105
+ const full = join(d, name);
106
+ if (statSync(full).isDirectory())
107
+ walk(full);
108
+ else
109
+ out.push(relative(dir, full));
110
+ }
111
+ };
112
+ walk(dir);
113
+ return out.sort();
114
+ }
115
+ function round2(n) {
116
+ return Math.round(n * 100) / 100;
117
+ }
118
+ //# sourceMappingURL=executor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"executor.js","sourceRoot":"","sources":["../src/executor.ts"],"names":[],"mappings":"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"}
package/dist/git.js ADDED
@@ -0,0 +1,82 @@
1
+ // Git-per-build: init a repo in the build workspace and commit after each task,
2
+ // so every build has history + diffs (and a foundation for undo). Best-effort —
3
+ // if git isn't available or a command fails, builds carry on uninterrupted.
4
+ import { spawnSync } from "node:child_process";
5
+ import { existsSync, writeFileSync } from "node:fs";
6
+ import { join } from "node:path";
7
+ function git(dir, args) {
8
+ try {
9
+ const r = spawnSync("git", args, { cwd: dir, encoding: "utf8" });
10
+ return { ok: r.status === 0, out: `${r.stdout ?? ""}${r.stderr ?? ""}`.trim() };
11
+ }
12
+ catch {
13
+ return { ok: false, out: "" };
14
+ }
15
+ }
16
+ export function isRepo(dir) {
17
+ return existsSync(join(dir, ".git"));
18
+ }
19
+ /** git init + a local identity + an initial commit. Idempotent. Returns success. */
20
+ export function initRepo(dir) {
21
+ if (isRepo(dir))
22
+ return true;
23
+ const gi = join(dir, ".gitignore");
24
+ if (!existsSync(gi))
25
+ writeFileSync(gi, ".deploy/\nbuild-state.json\nnode_modules/\n");
26
+ if (!git(dir, ["init"]).ok)
27
+ return false;
28
+ // Local identity so commits work even when the user has no global git config.
29
+ git(dir, ["config", "user.email", "bot@projectinator.local"]);
30
+ git(dir, ["config", "user.name", "Projectinator"]);
31
+ git(dir, ["add", "-A"]);
32
+ git(dir, ["commit", "-m", "chore: initial workspace", "--allow-empty"]);
33
+ return true;
34
+ }
35
+ /** Commit whatever a task produced. Returns the short hash, or null on failure. */
36
+ export function commitTask(dir, taskId, title) {
37
+ if (!isRepo(dir))
38
+ return null;
39
+ git(dir, ["add", "-A"]);
40
+ const msg = `${taskId}: ${title}`.replace(/\s+/g, " ").slice(0, 72);
41
+ const c = git(dir, ["commit", "-m", msg, "--allow-empty"]);
42
+ if (!c.ok)
43
+ return null;
44
+ const h = git(dir, ["rev-parse", "--short", "HEAD"]);
45
+ return h.ok ? h.out : null;
46
+ }
47
+ /** Hard-reset one commit back (undo the last task's file changes). Returns the
48
+ * reverted task id parsed from the commit message. Refuses to undo past the
49
+ * initial commit. */
50
+ export function undoLastCommit(dir) {
51
+ if (!isRepo(dir))
52
+ return { ok: false };
53
+ const commits = history(dir);
54
+ if (commits.length <= 1)
55
+ return { ok: false }; // nothing but the initial commit
56
+ const taskId = (commits[0]?.msg.split(":")[0] ?? "").trim() || undefined;
57
+ const r = git(dir, ["reset", "--hard", "HEAD~1"]);
58
+ return { ok: r.ok, taskId };
59
+ }
60
+ /** Commit log, newest first. */
61
+ export function history(dir) {
62
+ if (!isRepo(dir))
63
+ return [];
64
+ const r = git(dir, ["log", "--oneline", "--no-decorate", "--no-color"]);
65
+ if (!r.ok || !r.out)
66
+ return [];
67
+ return r.out.split("\n").filter(Boolean).map((line) => {
68
+ const i = line.indexOf(" ");
69
+ return i < 0 ? { hash: line, msg: "" } : { hash: line.slice(0, i), msg: line.slice(i + 1) };
70
+ });
71
+ }
72
+ /** `--stat` summary + the full patch for one commit (vs its parent). Untracked
73
+ * binaries show as "Binary files differ". Lines, not one blob, so the TUI can page. */
74
+ export function commitDiff(dir, hash) {
75
+ if (!isRepo(dir))
76
+ return { stat: [], patch: [] };
77
+ const stat = git(dir, ["show", "--stat", "--format=", "--no-color", hash]);
78
+ const patch = git(dir, ["show", "--format=", "--no-color", hash]);
79
+ const lines = (o) => (o.ok && o.out ? o.out.split("\n") : []);
80
+ return { stat: lines(stat), patch: lines(patch) };
81
+ }
82
+ //# sourceMappingURL=git.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"git.js","sourceRoot":"","sources":["../src/git.ts"],"names":[],"mappings":"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"}
package/dist/intake.js ADDED
@@ -0,0 +1,98 @@
1
+ // Intake — the PM's clarifying-questions step. Before planning a vague request,
2
+ // the PM asks 2-4 short questions (each with suggested options) to pin down what
3
+ // to build. A clear request returns no questions and skips straight to planning.
4
+ //
5
+ // Forced structured output, same discipline as pm.ts: one tool, permissive
6
+ // schema, coerced/validated in code.
7
+ import { createAgentSession, defineTool, } from "@earendil-works/pi-coding-agent";
8
+ import { Type } from "typebox";
9
+ import { findEntry } from "./registry.js";
10
+ import { piRuntime, resolvePiModel } from "./executor.js";
11
+ import { addSessionCost } from "./session-cost.js";
12
+ const IntakeSchema = Type.Object({
13
+ needsClarification: Type.Boolean({ description: "true only if the request is too vague to plan well" }),
14
+ questions: Type.Array(Type.Object({
15
+ question: Type.String({ description: "one short clarifying question" }),
16
+ options: Type.Array(Type.String(), { description: "2-4 concrete pickable answers; may be empty for free text" }),
17
+ multi: Type.Boolean({ description: "true if several options can apply at once" }),
18
+ }, { additionalProperties: true }), { description: "empty when needsClarification is false; at most 4" }),
19
+ }, { additionalProperties: true });
20
+ function buildIntakeTool() {
21
+ let captured;
22
+ const tool = defineTool({
23
+ name: "submit_intake",
24
+ label: "Submit Intake",
25
+ description: "Submit whether clarification is needed and, if so, the clarifying questions. Call exactly once.",
26
+ parameters: IntakeSchema,
27
+ execute: async (_id, params) => {
28
+ captured = params;
29
+ return { content: [{ type: "text", text: `Intake: ${params.needsClarification ? `${params.questions.length} questions` : "clear"}.` }], details: {} };
30
+ },
31
+ });
32
+ return { tool, get: () => captured };
33
+ }
34
+ const SYSTEM = [
35
+ "You are the PROJECT MANAGER doing intake for a build request.",
36
+ "If the request already has enough detail to plan and build — its purpose and the",
37
+ "must-have features are clear or reasonably inferable — set needsClarification=false",
38
+ "and questions=[].",
39
+ "If it is vague (a bare template like 'landing page', a one-liner missing the",
40
+ "essentials), set needsClarification=true and produce 2-4 SHORT questions that most",
41
+ "reduce ambiguity: what the product/business actually is, a name, must-have",
42
+ "sections/features, and style. For each question give 2-4 concrete pickable options;",
43
+ "set multi=true when several can apply (e.g. which sections). Never more than 4",
44
+ "questions. Do not ask what you can reasonably assume. Call submit_intake exactly once.",
45
+ ].join("\n");
46
+ /** Ask the PM whether the request needs clarification; returns up to 4 questions
47
+ * (empty = clear enough to plan directly). Never throws — returns [] on trouble. */
48
+ export async function assessIntake(idea, opts) {
49
+ const runtime = await piRuntime();
50
+ const { entry } = findEntry("plan", "mid");
51
+ const pick = opts.modelOverride ?? entry.byBackend[opts.backend];
52
+ try {
53
+ const model = resolvePiModel(runtime, pick.provider, pick.model);
54
+ const { tool, get } = buildIntakeTool();
55
+ const { session } = await createAgentSession({
56
+ model,
57
+ modelRuntime: runtime,
58
+ thinkingLevel: "low",
59
+ noTools: "all",
60
+ customTools: [tool],
61
+ tools: ["submit_intake"],
62
+ });
63
+ try {
64
+ await session.prompt(`${SYSTEM}\n\n--- REQUEST ---\n${idea}`);
65
+ let raw = get();
66
+ if (!raw) {
67
+ await session.prompt("Call submit_intake now.");
68
+ raw = get();
69
+ }
70
+ addSessionCost(session.getSessionStats().cost);
71
+ if (!raw || !raw.needsClarification)
72
+ return [];
73
+ return (raw.questions ?? [])
74
+ .slice(0, 4)
75
+ .map((q) => ({
76
+ question: String(q.question ?? "").trim(),
77
+ options: (q.options ?? []).map((o) => String(o).trim()).filter(Boolean).slice(0, 6),
78
+ multi: !!q.multi,
79
+ }))
80
+ .filter((q) => q.question);
81
+ }
82
+ finally {
83
+ session.dispose();
84
+ }
85
+ }
86
+ catch {
87
+ return []; // never block a build on intake — fall through to planning
88
+ }
89
+ }
90
+ /** Fold the collected answers into the brief the PM will plan from. */
91
+ export function enrichBrief(idea, answers) {
92
+ const kept = answers.filter((a) => a.answer.trim());
93
+ if (!kept.length)
94
+ return idea;
95
+ const lines = kept.map((a) => `- ${a.question} ${a.answer.trim()}`);
96
+ return `${idea}\n\nClarifications from the requester:\n${lines.join("\n")}`;
97
+ }
98
+ //# sourceMappingURL=intake.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"intake.js","sourceRoot":"","sources":["../src/intake.ts"],"names":[],"mappings":"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"}
package/dist/models.js ADDED
@@ -0,0 +1,171 @@
1
+ // Model pricing table. Rates USD per 1,000,000 tokens — copied verbatim from Pi's
2
+ // bundled catalog (pi-coding-agent 0.85.1, Sept 2026); test/executor.test.ts pins every
3
+ // entry against it. Shape mirrors Pi's models.json `cost` block.
4
+ import { findOpenRouterModel } from "./openrouter.js";
5
+ export const MODELS = {
6
+ // ---- OpenAI: GPT-5.6 family (prices cut Sept 2026; past 272k input costs 2x) ----
7
+ "gpt-5.6-sol": {
8
+ id: "gpt-5.6-sol",
9
+ provider: "openai",
10
+ name: "GPT-5.6 Sol",
11
+ contextWindow: 272_000,
12
+ cost: { input: 4, output: 20, cacheRead: 0.4, cacheWrite: 5, tiers: [{ inputTokensAbove: 272_000, input: 8, output: 30, cacheRead: 0.8, cacheWrite: 10 }] },
13
+ },
14
+ "gpt-5.6-terra": {
15
+ id: "gpt-5.6-terra",
16
+ provider: "openai",
17
+ name: "GPT-5.6 Terra",
18
+ contextWindow: 272_000,
19
+ cost: { input: 2, output: 12, cacheRead: 0.2, cacheWrite: 2.5, tiers: [{ inputTokensAbove: 272_000, input: 4, output: 18, cacheRead: 0.4, cacheWrite: 5 }] },
20
+ },
21
+ "gpt-5.6-luna": {
22
+ id: "gpt-5.6-luna",
23
+ provider: "openai",
24
+ name: "GPT-5.6 Luna",
25
+ contextWindow: 272_000,
26
+ cost: { input: 0.2, output: 1.2, cacheRead: 0.02, cacheWrite: 0.25, tiers: [{ inputTokensAbove: 272_000, input: 0.4, output: 1.8, cacheRead: 0.04, cacheWrite: 0.5 }] },
27
+ },
28
+ // ---- Anthropic: Claude ----
29
+ "claude-fable-5-1": {
30
+ id: "claude-fable-5-1",
31
+ provider: "anthropic",
32
+ name: "Claude Fable 5.1",
33
+ contextWindow: 1_000_000,
34
+ cost: { input: 10, output: 50, cacheRead: 0.25, cacheWrite: 12.5 },
35
+ },
36
+ "claude-fable-5": {
37
+ id: "claude-fable-5",
38
+ provider: "anthropic",
39
+ name: "Claude Fable 5",
40
+ contextWindow: 1_000_000,
41
+ cost: { input: 10, output: 50, cacheRead: 1, cacheWrite: 12.5 },
42
+ },
43
+ "claude-opus-5": {
44
+ id: "claude-opus-5",
45
+ provider: "anthropic",
46
+ name: "Claude Opus 5",
47
+ contextWindow: 1_000_000,
48
+ cost: { input: 5, output: 25, cacheRead: 0.5, cacheWrite: 6.25 },
49
+ },
50
+ "claude-opus-4-8": {
51
+ id: "claude-opus-4-8",
52
+ provider: "anthropic",
53
+ name: "Claude Opus 4.8",
54
+ contextWindow: 1_000_000,
55
+ cost: { input: 5, output: 25, cacheRead: 0.5, cacheWrite: 6.25 },
56
+ },
57
+ "claude-sonnet-5": {
58
+ id: "claude-sonnet-5",
59
+ provider: "anthropic",
60
+ name: "Claude Sonnet 5",
61
+ contextWindow: 1_000_000,
62
+ cost: { input: 2, output: 10, cacheRead: 0.2, cacheWrite: 2.5 },
63
+ },
64
+ "claude-sonnet-4-6": {
65
+ id: "claude-sonnet-4-6",
66
+ provider: "anthropic",
67
+ name: "Claude Sonnet 4.6",
68
+ contextWindow: 1_000_000,
69
+ cost: { input: 3, output: 15, cacheRead: 0.3, cacheWrite: 3.75 },
70
+ },
71
+ "claude-haiku-4-5": {
72
+ id: "claude-haiku-4-5",
73
+ provider: "anthropic",
74
+ name: "Claude Haiku 4.5",
75
+ contextWindow: 200_000,
76
+ cost: { input: 1, output: 5, cacheRead: 0.1, cacheWrite: 1.25 },
77
+ },
78
+ // ---- Google: Gemini ----
79
+ // NOTE: ids match Pi's built-in registry exactly (provider "google"), so they
80
+ // resolve directly via ModelRegistry.find() with no alias layer.
81
+ "gemini-3.1-pro-preview": {
82
+ id: "gemini-3.1-pro-preview",
83
+ provider: "google",
84
+ name: "Gemini 3.1 Pro",
85
+ contextWindow: 1_000_000,
86
+ cost: {
87
+ input: 2,
88
+ output: 12,
89
+ cacheRead: 0.2,
90
+ cacheWrite: 2.5,
91
+ // Google charges more past 200k input tokens.
92
+ tiers: [{ inputTokensAbove: 200_000, input: 4, output: 18, cacheRead: 0.4, cacheWrite: 5 }],
93
+ },
94
+ },
95
+ "gemini-3.8-flash": {
96
+ id: "gemini-3.8-flash",
97
+ provider: "google",
98
+ name: "Gemini 3.8 Flash",
99
+ contextWindow: 1_000_000,
100
+ cost: { input: 0.75, output: 3.75, cacheRead: 0.075 },
101
+ },
102
+ "gemini-3-flash-preview": {
103
+ id: "gemini-3-flash-preview",
104
+ provider: "google",
105
+ name: "Gemini 3 Flash",
106
+ contextWindow: 1_000_000,
107
+ cost: { input: 0.5, output: 3, cacheRead: 0.05, cacheWrite: 0.625 },
108
+ },
109
+ // ---- OpenRouter (one key → frontier models). ids are Pi's OpenRouter-catalog
110
+ // slugs (vendor/model). Pricing mirrors the underlying model (OpenRouter passes
111
+ // it through, ~small margin); ACTUAL cost still comes from Pi per run.
112
+ "anthropic/claude-opus-5": {
113
+ id: "anthropic/claude-opus-5",
114
+ provider: "openrouter",
115
+ name: "Claude Opus 5 (OpenRouter)",
116
+ contextWindow: 1_000_000,
117
+ cost: { input: 5, output: 25, cacheRead: 0.5, cacheWrite: 6.25 },
118
+ },
119
+ "anthropic/claude-opus-4.8": {
120
+ id: "anthropic/claude-opus-4.8",
121
+ provider: "openrouter",
122
+ name: "Claude Opus 4.8 (OpenRouter)",
123
+ contextWindow: 1_000_000,
124
+ cost: { input: 5, output: 25, cacheRead: 0.5, cacheWrite: 6.25 },
125
+ },
126
+ "anthropic/claude-sonnet-5": {
127
+ id: "anthropic/claude-sonnet-5",
128
+ provider: "openrouter",
129
+ name: "Claude Sonnet 5 (OpenRouter)",
130
+ contextWindow: 1_000_000,
131
+ cost: { input: 2, output: 10, cacheRead: 0.2, cacheWrite: 2.5 },
132
+ },
133
+ "anthropic/claude-sonnet-4.6": {
134
+ id: "anthropic/claude-sonnet-4.6",
135
+ provider: "openrouter",
136
+ name: "Claude Sonnet 4.6 (OpenRouter)",
137
+ contextWindow: 1_000_000,
138
+ cost: { input: 3, output: 15, cacheRead: 0.3, cacheWrite: 3.75 },
139
+ },
140
+ "google/gemini-3.8-flash": {
141
+ id: "google/gemini-3.8-flash",
142
+ provider: "openrouter",
143
+ name: "Gemini 3.8 Flash (OpenRouter)",
144
+ contextWindow: 1_000_000,
145
+ cost: { input: 0.75, output: 3.75, cacheRead: 0.075 },
146
+ },
147
+ "openai/gpt-5.6-luna": {
148
+ id: "openai/gpt-5.6-luna",
149
+ provider: "openrouter",
150
+ name: "GPT-5.6 Luna (OpenRouter)",
151
+ contextWindow: 1_050_000,
152
+ cost: { input: 0.2, output: 1.2, cacheRead: 0.02, cacheWrite: 0.25 },
153
+ },
154
+ };
155
+ export function getModel(id) {
156
+ const m = MODELS[id];
157
+ if (m)
158
+ return m;
159
+ // OpenRouter slugs (vendor/model) aren't in the static table — price them from
160
+ // the OpenRouter catalog (live cache or Pi's built-in list). Fall back to a
161
+ // rough estimate so a build never crashes on an unpriced model (actual cost
162
+ // still comes from Pi per run).
163
+ if (id.includes("/")) {
164
+ const or = findOpenRouterModel(id);
165
+ if (or)
166
+ return { ...or, provider: "openrouter" };
167
+ return { id, provider: "openrouter", name: id, contextWindow: 200_000, cost: { input: 1, output: 3, cacheRead: 0.1, cacheWrite: 1.25 } };
168
+ }
169
+ throw new Error(`Unknown model id: "${id}". Add it to src/models.ts.`);
170
+ }
171
+ //# sourceMappingURL=models.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"models.js","sourceRoot":"","sources":["../src/models.ts"],"names":[],"mappings":"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"}