pi-daddy 0.41.1 → 0.43.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 (133) hide show
  1. package/CHANGELOG.md +31 -0
  2. package/contracts/ledger-record/v1/fixtures/capability-decision.json +3 -1
  3. package/contracts/ledger-record/v1/fixtures/child-lifecycle.json +25 -0
  4. package/contracts/ledger-record/v1/fixtures/episode-cost-gate.json +14 -0
  5. package/contracts/ledger-record/v1/fixtures/episode-outcome.json +12 -0
  6. package/contracts/ledger-record/v1/fixtures/ledger-record.jsonl +6 -3
  7. package/contracts/ledger-record/v1/fixtures/session-config.json +14 -0
  8. package/contracts/ledger-record/v1/governance-event.schema.json +356 -0
  9. package/dist/advisors/advisor.d.ts +24 -1
  10. package/dist/advisors/advisor.d.ts.map +1 -1
  11. package/dist/advisors/advisor.js +19 -1
  12. package/dist/advisors/advisor.js.map +1 -1
  13. package/dist/advisors/decider.d.ts +11 -0
  14. package/dist/advisors/decider.d.ts.map +1 -1
  15. package/dist/advisors/decider.js.map +1 -1
  16. package/dist/advisors/jev.d.ts.map +1 -1
  17. package/dist/advisors/jev.js +32 -1
  18. package/dist/advisors/jev.js.map +1 -1
  19. package/dist/cli.d.ts +7 -1
  20. package/dist/cli.d.ts.map +1 -1
  21. package/dist/cli.js +87 -1
  22. package/dist/cli.js.map +1 -1
  23. package/dist/executors/activity-session.d.ts +13 -0
  24. package/dist/executors/activity-session.d.ts.map +1 -1
  25. package/dist/executors/activity-session.js +44 -2
  26. package/dist/executors/activity-session.js.map +1 -1
  27. package/dist/governance/episode-cost-gate.d.ts +31 -0
  28. package/dist/governance/episode-cost-gate.d.ts.map +1 -0
  29. package/dist/governance/episode-cost-gate.js +112 -0
  30. package/dist/governance/episode-cost-gate.js.map +1 -0
  31. package/dist/governance/ledger-events.d.ts +108 -1
  32. package/dist/governance/ledger-events.d.ts.map +1 -1
  33. package/dist/governance/ledger-events.js +64 -0
  34. package/dist/governance/ledger-events.js.map +1 -1
  35. package/dist/governance/ledger-v3-validation.d.ts.map +1 -1
  36. package/dist/governance/ledger-v3-validation.js +124 -0
  37. package/dist/governance/ledger-v3-validation.js.map +1 -1
  38. package/dist/governance/ledger.d.ts +8 -2
  39. package/dist/governance/ledger.d.ts.map +1 -1
  40. package/dist/governance/ledger.js +18 -2
  41. package/dist/governance/ledger.js.map +1 -1
  42. package/dist/kernel/definitions.d.ts +5 -0
  43. package/dist/kernel/definitions.d.ts.map +1 -1
  44. package/dist/kernel/definitions.js +30 -1
  45. package/dist/kernel/definitions.js.map +1 -1
  46. package/dist/kernel/delegate-types.d.ts +4 -0
  47. package/dist/kernel/delegate-types.d.ts.map +1 -1
  48. package/dist/kernel/delegate-types.js.map +1 -1
  49. package/dist/kernel/delegate.d.ts.map +1 -1
  50. package/dist/kernel/delegate.js +20 -5
  51. package/dist/kernel/delegate.js.map +1 -1
  52. package/dist/kernel/env-names.d.ts +5 -0
  53. package/dist/kernel/env-names.d.ts.map +1 -1
  54. package/dist/kernel/env-names.js +9 -0
  55. package/dist/kernel/env-names.js.map +1 -1
  56. package/dist/kernel/grant-env.d.ts +2 -0
  57. package/dist/kernel/grant-env.d.ts.map +1 -1
  58. package/dist/kernel/grant-env.js +1 -0
  59. package/dist/kernel/grant-env.js.map +1 -1
  60. package/dist/kernel/propagation.d.ts +2 -2
  61. package/dist/kernel/propagation.d.ts.map +1 -1
  62. package/dist/kernel/propagation.js +7 -2
  63. package/dist/kernel/propagation.js.map +1 -1
  64. package/dist/products/dashboard-cli.d.ts +4 -0
  65. package/dist/products/dashboard-cli.d.ts.map +1 -1
  66. package/dist/products/dashboard-cli.js +32 -4
  67. package/dist/products/dashboard-cli.js.map +1 -1
  68. package/dist/products/dashboard-handshake.d.ts +8 -0
  69. package/dist/products/dashboard-handshake.d.ts.map +1 -1
  70. package/dist/products/dashboard-handshake.js +3 -0
  71. package/dist/products/dashboard-handshake.js.map +1 -1
  72. package/dist/products/dashboard-herdr.d.ts +4 -0
  73. package/dist/products/dashboard-herdr.d.ts.map +1 -1
  74. package/dist/products/dashboard-herdr.js +10 -2
  75. package/dist/products/dashboard-herdr.js.map +1 -1
  76. package/dist/products/dashboard-projection.d.ts.map +1 -1
  77. package/dist/products/dashboard-projection.js +13 -6
  78. package/dist/products/dashboard-projection.js.map +1 -1
  79. package/dist/products/dashboard-render.d.ts +10 -0
  80. package/dist/products/dashboard-render.d.ts.map +1 -1
  81. package/dist/products/dashboard-render.js +9 -0
  82. package/dist/products/dashboard-render.js.map +1 -1
  83. package/dist/products/dashboard-session-client.d.ts +17 -0
  84. package/dist/products/dashboard-session-client.d.ts.map +1 -0
  85. package/dist/products/dashboard-session-client.js +28 -0
  86. package/dist/products/dashboard-session-client.js.map +1 -0
  87. package/dist/products/episode-outcomes.d.ts +32 -0
  88. package/dist/products/episode-outcomes.d.ts.map +1 -0
  89. package/dist/products/episode-outcomes.js +280 -0
  90. package/dist/products/episode-outcomes.js.map +1 -0
  91. package/dist/products/episode-report.d.ts +59 -0
  92. package/dist/products/episode-report.d.ts.map +1 -0
  93. package/dist/products/episode-report.js +311 -0
  94. package/dist/products/episode-report.js.map +1 -0
  95. package/extensions/chain-ledger.ts +2 -0
  96. package/extensions/chain-plan.ts +4 -2
  97. package/extensions/dashboard-session-server.ts +86 -0
  98. package/extensions/definition-runtime.ts +93 -0
  99. package/extensions/delegate-chain.ts +31 -2
  100. package/extensions/delegation-ledger.ts +2 -0
  101. package/extensions/delegation.ts +24 -0
  102. package/extensions/effort-advice.ts +12 -0
  103. package/extensions/execute-child.ts +148 -9
  104. package/extensions/grants-command.ts +32 -2
  105. package/extensions/grants.ts +23 -1
  106. package/extensions/pruning-advice.ts +3 -1
  107. package/extensions/run-delegation.ts +54 -6
  108. package/extensions/session-model-prompt.ts +179 -0
  109. package/extensions/session.ts +104 -3
  110. package/package.json +1 -1
  111. package/src/advisors/advisor.ts +45 -2
  112. package/src/advisors/decider.ts +8 -0
  113. package/src/advisors/jev.ts +34 -1
  114. package/src/cli.ts +90 -2
  115. package/src/executors/activity-session.ts +56 -2
  116. package/src/governance/episode-cost-gate.ts +128 -0
  117. package/src/governance/ledger-events.ts +173 -1
  118. package/src/governance/ledger-v3-validation.ts +146 -0
  119. package/src/governance/ledger.ts +29 -1
  120. package/src/kernel/definitions.ts +32 -1
  121. package/src/kernel/delegate-types.ts +4 -0
  122. package/src/kernel/delegate.ts +22 -5
  123. package/src/kernel/env-names.ts +10 -0
  124. package/src/kernel/grant-env.ts +3 -0
  125. package/src/kernel/propagation.ts +7 -0
  126. package/src/products/dashboard-cli.ts +32 -4
  127. package/src/products/dashboard-handshake.ts +5 -0
  128. package/src/products/dashboard-herdr.ts +15 -1
  129. package/src/products/dashboard-projection.ts +13 -6
  130. package/src/products/dashboard-render.ts +11 -0
  131. package/src/products/dashboard-session-client.ts +35 -0
  132. package/src/products/episode-outcomes.ts +317 -0
  133. package/src/products/episode-report.ts +372 -0
@@ -0,0 +1,311 @@
1
+ /** Read-only episode accounting over the governance ledger and activity timeline. */
2
+ import { execFile } from "node:child_process";
3
+ import { promisify } from "node:util";
4
+ import { readRecords } from "../governance/record.js";
5
+ const execFileAsync = promisify(execFile);
6
+ const TERMINAL = new Set(["completed", "failed"]);
7
+ const object = (value) => value !== null && typeof value === "object" && !Array.isArray(value);
8
+ const number = (value) => (typeof value === "number" && Number.isFinite(value) ? value : 0);
9
+ const text = (value) => (typeof value === "string" ? value : "");
10
+ const joined = (values) => [...values].filter(Boolean).sort().join(",");
11
+ function timestamp(value, fallback) {
12
+ const parsed = Date.parse(typeof value === "string" ? value : fallback);
13
+ return Number.isFinite(parsed) ? parsed : Date.parse(fallback);
14
+ }
15
+ function episodeOf(episodes, id, at) {
16
+ const existing = episodes.get(id);
17
+ if (existing) {
18
+ existing.startedMs = Math.min(existing.startedMs, at);
19
+ existing.endedMs = Math.max(existing.endedMs, at);
20
+ return existing;
21
+ }
22
+ const episode = {
23
+ episode: id,
24
+ startedMs: at,
25
+ endedMs: at,
26
+ definitions: new Set(),
27
+ hashes: new Set(),
28
+ models: new Set(),
29
+ modelIds: new Set(),
30
+ modelSources: new Set(),
31
+ thinkingLevels: new Set(),
32
+ thinkingSources: new Set(),
33
+ inputTokens: 0,
34
+ outputTokens: 0,
35
+ cacheReadTokens: 0,
36
+ reasoningTokens: 0,
37
+ cost: 0,
38
+ compactions: 0,
39
+ turns: 0,
40
+ children: new Set(),
41
+ terminalExecutions: new Set(),
42
+ };
43
+ episodes.set(id, episode);
44
+ return episode;
45
+ }
46
+ function percentile(values, fraction) {
47
+ if (values.length === 0)
48
+ return 0;
49
+ const sorted = [...values].sort((a, b) => a - b);
50
+ return sorted[Math.ceil(sorted.length * fraction) - 1] ?? 0;
51
+ }
52
+ export function reportEpisodes(input) {
53
+ const episodes = new Map();
54
+ const outcomes = new Map();
55
+ const ledger = readRecords(input.ledgerText);
56
+ if (ledger.damage)
57
+ throw new Error(`grants ledger damaged at line ${ledger.damage.line}: ${ledger.damage.reason}`);
58
+ for (const record of ledger.records) {
59
+ if (!object(record.body))
60
+ continue;
61
+ const body = record.body;
62
+ const episodeId = text(body.episodeId);
63
+ if (!episodeId)
64
+ continue;
65
+ if (body.event === "episode_outcome") {
66
+ if (["positive", "negative", "unknown"].includes(text(body.label)))
67
+ outcomes.set(episodeId, body.label);
68
+ continue;
69
+ }
70
+ const episode = episodeOf(episodes, episodeId, timestamp(body.ts, record.at));
71
+ if (text(body.definitionHash))
72
+ episode.hashes.add(text(body.definitionHash).slice(0, 12));
73
+ if (body.event === "capability_decision") {
74
+ if (body.agentType !== "delegate")
75
+ episode.definitions.add(text(body.agentType));
76
+ continue;
77
+ }
78
+ if (body.event !== "child_lifecycle")
79
+ continue;
80
+ const executionId = text(body.executionId);
81
+ if (executionId)
82
+ episode.children.add(executionId);
83
+ if (!TERMINAL.has(text(body.state)) || episode.terminalExecutions.has(executionId))
84
+ continue;
85
+ episode.terminalExecutions.add(executionId);
86
+ if (object(body.resolvedModel)) {
87
+ const provider = text(body.resolvedModel.provider), modelId = text(body.resolvedModel.modelId);
88
+ if (modelId) {
89
+ episode.modelIds.add(modelId);
90
+ episode.models.add(provider ? `${provider}/${modelId}` : modelId);
91
+ }
92
+ }
93
+ if (text(body.modelSource))
94
+ episode.modelSources.add(text(body.modelSource));
95
+ if (object(body.thinkingLevel)) {
96
+ if (text(body.thinkingLevel.level))
97
+ episode.thinkingLevels.add(text(body.thinkingLevel.level));
98
+ if (text(body.thinkingLevel.source))
99
+ episode.thinkingSources.add(text(body.thinkingLevel.source));
100
+ }
101
+ if (text(body.thinkingSource))
102
+ episode.thinkingSources.add(text(body.thinkingSource));
103
+ const usage = object(body.usage) ? body.usage : undefined;
104
+ if (object(body.tokenDetail)) {
105
+ episode.inputTokens += number(body.tokenDetail.inputTokens);
106
+ episode.outputTokens += number(body.tokenDetail.outputTokens);
107
+ episode.cacheReadTokens += number(body.tokenDetail.cacheReadTokens);
108
+ episode.reasoningTokens += number(body.tokenDetail.reasoningTokens);
109
+ }
110
+ else if (usage) {
111
+ episode.inputTokens += number(usage.input);
112
+ episode.outputTokens += number(usage.output);
113
+ episode.cacheReadTokens += number(usage.cacheRead);
114
+ episode.reasoningTokens += number(usage.reasoning);
115
+ }
116
+ if (usage && object(usage.cost))
117
+ episode.cost += number(usage.cost.total);
118
+ episode.compactions += number(body.compactionCount);
119
+ }
120
+ const activity = readRecords(input.activityText);
121
+ if (activity.damage)
122
+ throw new Error(`activity ledger damaged at line ${activity.damage.line}: ${activity.damage.reason}`);
123
+ for (const record of activity.records) {
124
+ if (record.kind !== "activity" || !object(record.body))
125
+ continue;
126
+ const event = record.body;
127
+ const episodeId = text(event.episodeId);
128
+ if (!episodeId)
129
+ continue;
130
+ const episode = episodeOf(episodes, episodeId, timestamp(event.at, record.at));
131
+ if (event.kind === "task_started" && !text(event.agentId))
132
+ episode.turns += 1;
133
+ }
134
+ const since = input.options.since ? Date.parse(input.options.since) : Number.NEGATIVE_INFINITY;
135
+ let rows = [...episodes.values()]
136
+ .map((episode) => ({
137
+ episode: episode.episode,
138
+ started: new Date(episode.startedMs).toISOString(),
139
+ definition: joined(episode.definitions),
140
+ definitionHash: joined(episode.hashes),
141
+ resolvedModel: joined(episode.models),
142
+ modelSource: joined(episode.modelSources),
143
+ thinkingLevel: joined(episode.thinkingLevels),
144
+ thinkingSource: joined(episode.thinkingSources),
145
+ inputTokens: episode.inputTokens,
146
+ outputTokens: episode.outputTokens,
147
+ cacheReadTokens: episode.cacheReadTokens,
148
+ reasoningTokens: episode.reasoningTokens,
149
+ cost: episode.cost,
150
+ compactions: episode.compactions,
151
+ turns: episode.turns,
152
+ durationMs: Math.max(0, episode.endedMs - episode.startedMs),
153
+ children: episode.children.size,
154
+ commit: input.commitByEpisode.get(episode.episode) ?? "",
155
+ outcome: outcomes.get(episode.episode) ?? "",
156
+ }))
157
+ .filter((row) => Date.parse(row.started) >= since)
158
+ .filter((row) => !input.options.definition || row.definition.split(",").includes(input.options.definition))
159
+ .filter((row) => {
160
+ if (!input.options.model)
161
+ return true;
162
+ const source = episodes.get(row.episode);
163
+ return source.modelIds.has(input.options.model) || source.models.has(input.options.model);
164
+ })
165
+ .sort((a, b) => Date.parse(a.started) - Date.parse(b.started) || a.episode.localeCompare(b.episode));
166
+ if (input.options.groupBy) {
167
+ const field = input.options.groupBy === "thinking"
168
+ ? "thinkingLevel"
169
+ : input.options.groupBy === "model"
170
+ ? "resolvedModel"
171
+ : "definition";
172
+ const groups = new Map();
173
+ for (const row of rows) {
174
+ const value = row[field] || "(none)";
175
+ const group = groups.get(value) ?? {
176
+ value,
177
+ count: 0,
178
+ inputTokens: 0,
179
+ outputTokens: 0,
180
+ cacheReadTokens: 0,
181
+ reasoningTokens: 0,
182
+ cost: 0,
183
+ };
184
+ group.count += 1;
185
+ group.inputTokens += row.inputTokens;
186
+ group.outputTokens += row.outputTokens;
187
+ group.cacheReadTokens += row.cacheReadTokens;
188
+ group.reasoningTokens += row.reasoningTokens;
189
+ group.cost += row.cost;
190
+ groups.set(value, group);
191
+ }
192
+ return {
193
+ rows: [],
194
+ groups: [...groups.values()].sort((a, b) => a.value.localeCompare(b.value)),
195
+ groupBy: input.options.groupBy,
196
+ };
197
+ }
198
+ const costs = rows.map((row) => row.cost);
199
+ return {
200
+ rows,
201
+ totals: {
202
+ episodes: rows.length,
203
+ cost: costs.reduce((sum, value) => sum + value, 0),
204
+ tokens: rows.reduce((sum, row) => sum + row.inputTokens + row.outputTokens, 0),
205
+ p50EpisodeCost: percentile(costs, 0.5),
206
+ p95EpisodeCost: percentile(costs, 0.95),
207
+ },
208
+ };
209
+ }
210
+ const escapeCell = (value) => String(value).replaceAll("|", "\\|").replaceAll("\n", " ");
211
+ const cost = (value) => value.toFixed(6).replace(/\.?0+$/, "") || "0";
212
+ function duration(ms) {
213
+ const seconds = Math.round(ms / 1000);
214
+ const minutes = Math.floor(seconds / 60);
215
+ return minutes ? `${minutes}m ${seconds % 60}s` : `${seconds}s`;
216
+ }
217
+ function table(headers, rows) {
218
+ return [
219
+ `| ${headers.join(" | ")} |`,
220
+ `| ${headers.map(() => "---").join(" | ")} |`,
221
+ ...rows.map((row) => `| ${row.map(escapeCell).join(" | ")} |`),
222
+ ].join("\n");
223
+ }
224
+ export function renderEpisodeReport(report, json) {
225
+ if (json)
226
+ return `${JSON.stringify(report, null, 2)}\n`;
227
+ if (report.groups && report.groupBy) {
228
+ const headers = [
229
+ report.groupBy,
230
+ "count",
231
+ "inputTokens",
232
+ "outputTokens",
233
+ "cacheReadTokens",
234
+ "reasoningTokens",
235
+ "cost",
236
+ ];
237
+ return `${table(headers, report.groups.map((group) => [
238
+ group.value,
239
+ group.count,
240
+ group.inputTokens,
241
+ group.outputTokens,
242
+ group.cacheReadTokens,
243
+ group.reasoningTokens,
244
+ cost(group.cost),
245
+ ]))}\n`;
246
+ }
247
+ const headers = [
248
+ "episode",
249
+ "started",
250
+ "definition",
251
+ "definitionHash",
252
+ "resolvedModel",
253
+ "modelSource",
254
+ "thinkingLevel",
255
+ "thinkingSource",
256
+ "inputTokens",
257
+ "outputTokens",
258
+ "cacheReadTokens",
259
+ "reasoningTokens",
260
+ "cost",
261
+ "compactions",
262
+ "turns",
263
+ "duration",
264
+ "children",
265
+ "commit",
266
+ "outcome",
267
+ ];
268
+ const rows = report.rows.map((row) => [
269
+ row.episode,
270
+ row.started,
271
+ row.definition,
272
+ row.definitionHash,
273
+ row.resolvedModel,
274
+ row.modelSource,
275
+ row.thinkingLevel,
276
+ row.thinkingSource,
277
+ row.inputTokens,
278
+ row.outputTokens,
279
+ row.cacheReadTokens,
280
+ row.reasoningTokens,
281
+ cost(row.cost),
282
+ row.compactions,
283
+ row.turns,
284
+ duration(row.durationMs),
285
+ row.children,
286
+ row.commit,
287
+ row.outcome,
288
+ ]);
289
+ const totals = report.totals;
290
+ const totalsTable = table(["episodes", "cost", "tokens", "p50 episode cost", "p95 episode cost"], [[totals.episodes, cost(totals.cost), totals.tokens, cost(totals.p50EpisodeCost), cost(totals.p95EpisodeCost)]]);
291
+ return `${table(headers, rows)}\n\n${totalsTable}\n`;
292
+ }
293
+ export function commitsFromGitLog(log) {
294
+ const commits = new Map();
295
+ for (const entry of log.split("\u001e")) {
296
+ const [sha, ...body] = entry.trim().split("\n");
297
+ if (!/^[a-f0-9]{8,40}$/i.test(sha ?? ""))
298
+ continue;
299
+ for (const match of body.join("\n").matchAll(/^Pi-Episode:\s*(\S+)\s*$/gim)) {
300
+ const episode = match[1].startsWith("episode:") ? match[1] : `episode:${match[1]}`;
301
+ if (!commits.has(episode))
302
+ commits.set(episode, sha.slice(0, 8));
303
+ }
304
+ }
305
+ return commits;
306
+ }
307
+ export async function commitsForRepo(cwd) {
308
+ const { stdout } = await execFileAsync("git", ["log", "--format=%H%n%B%x1e"], { cwd, maxBuffer: 16 * 1024 * 1024 });
309
+ return commitsFromGitLog(stdout);
310
+ }
311
+ //# sourceMappingURL=episode-report.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"episode-report.js","sourceRoot":"","sources":["../../src/products/episode-report.ts"],"names":[],"mappings":"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"}
@@ -41,6 +41,8 @@ export async function recordChainRefusal(input: {
41
41
  humanDenied: input.approval?.humanDenied,
42
42
  gateOutcome: input.approval?.gateOutcome,
43
43
  definitionDigest: input.plan.definitionDigest,
44
+ definitionHash: input.plan.definitionHash,
45
+ definitionPackageVersion: input.plan.definitionPackageVersion,
44
46
  taskDigest: input.plan.taskDigest,
45
47
  correlation: input.plan.correlation,
46
48
  // An approval banked before a later chain decline is a yes that led to no spawn, not the stale
@@ -37,6 +37,7 @@ export async function planChain(
37
37
  steps: ChainStep[],
38
38
  executionIds: readonly string[],
39
39
  preflightModel?: (model: string | undefined) => StructuredRefusal | undefined,
40
+ resolveModel?: (step: ChainStep) => string | undefined,
40
41
  ): Promise<ChainPlan> {
41
42
  const requests: GateRequest[] = [];
42
43
  const uses = new Map<number, Set<string>>();
@@ -49,12 +50,13 @@ export async function planChain(
49
50
  const { stageHandoff: _stageHandoff, ...context } = await session.delegationContext();
50
51
 
51
52
  for (const [index, step] of steps.entries()) {
53
+ const model = resolveModel?.(step) ?? step.model;
52
54
  const plan = planDelegation(
53
55
  {
54
56
  task: step.task,
55
57
  agent: step.agent,
56
58
  tools: step.tools,
57
- model: step.model,
59
+ model,
58
60
  thinking: step.thinking,
59
61
  context: step.context,
60
62
  correlation: step.workspace
@@ -71,7 +73,7 @@ export async function planChain(
71
73
  },
72
74
  );
73
75
 
74
- const modelRefusal = preflightModel?.(step.model);
76
+ const modelRefusal = preflightModel?.(model);
75
77
  if (modelRefusal) {
76
78
  return {
77
79
  requests: [],
@@ -0,0 +1,86 @@
1
+ import { randomBytes } from "node:crypto";
2
+ import { chmod, rm } from "node:fs/promises";
3
+ import { createServer, type Server } from "node:net";
4
+ import { tmpdir } from "node:os";
5
+ import { join } from "node:path";
6
+ import type { GrantsSession } from "./session.ts";
7
+ import { saveSessionModelEdits, sessionModelRows } from "./session-model-prompt.ts";
8
+
9
+ export interface DashboardSessionEndpoint {
10
+ socketPath: string;
11
+ token: string;
12
+ close(): Promise<void>;
13
+ }
14
+
15
+ const endpoints = new WeakMap<GrantsSession, Promise<DashboardSessionEndpoint>>();
16
+
17
+ export function ensureDashboardSessionServer(session: GrantsSession): Promise<DashboardSessionEndpoint> {
18
+ const existing = endpoints.get(session);
19
+ if (existing) return existing;
20
+ const started = start(session);
21
+ endpoints.set(session, started);
22
+ return started;
23
+ }
24
+
25
+ async function start(session: GrantsSession): Promise<DashboardSessionEndpoint> {
26
+ const socketPath = join(tmpdir(), `pi-daddy-${process.pid}-${randomBytes(8).toString("hex")}.sock`);
27
+ const token = randomBytes(24).toString("hex");
28
+ const server = createServer((socket) => {
29
+ let input = "";
30
+ socket.setEncoding("utf8");
31
+ socket.on("data", (chunk) => {
32
+ input += chunk;
33
+ if (input.length > 16 * 1024) socket.destroy(new Error("dashboard request too large"));
34
+ if (!input.includes("\n")) return;
35
+ const line = input.slice(0, input.indexOf("\n"));
36
+ void respond(session, token, line)
37
+ .then((value) => socket.end(`${JSON.stringify(value)}\n`))
38
+ .catch((error) => socket.end(`${JSON.stringify({ ok: false, error: String(error) })}\n`));
39
+ });
40
+ });
41
+ await new Promise<void>((resolve, reject) => {
42
+ server.once("error", reject);
43
+ server.listen(socketPath, () => resolve());
44
+ });
45
+ await chmod(socketPath, 0o600);
46
+ const cleanup = () => {
47
+ close(server, socketPath);
48
+ };
49
+ process.once("exit", cleanup);
50
+ server.unref();
51
+ return {
52
+ socketPath,
53
+ token,
54
+ close: async () => {
55
+ process.off("exit", cleanup);
56
+ await new Promise<void>((resolve) => server.close(() => resolve()));
57
+ await rm(socketPath, { force: true });
58
+ },
59
+ };
60
+ }
61
+
62
+ async function respond(session: GrantsSession, token: string, line: string): Promise<Record<string, unknown>> {
63
+ const request = JSON.parse(line) as { token?: unknown; action?: unknown; edits?: unknown };
64
+ if (request.token !== token) return { ok: false, error: "unauthorised dashboard request" };
65
+ if (request.action === "set") {
66
+ if (typeof request.edits !== "string") return { ok: false, error: "dashboard edits must be a string" };
67
+ const invalid = await saveSessionModelEdits(
68
+ session,
69
+ request.edits,
70
+ [...session.definitions.keys()].sort(),
71
+ "grants-models",
72
+ );
73
+ if (invalid) return { ok: false, error: invalid };
74
+ } else if (request.action !== "get") return { ok: false, error: "unknown dashboard action" };
75
+ return {
76
+ ok: true,
77
+ rows: sessionModelRows(session, [...session.definitions.keys()].sort()),
78
+ cost: session.episodeCostGate.cost,
79
+ ceiling: session.episodeCostGate.ceiling,
80
+ };
81
+ }
82
+
83
+ function close(server: Server, socketPath: string): void {
84
+ server.close();
85
+ void rm(socketPath, { force: true });
86
+ }
@@ -0,0 +1,93 @@
1
+ /** Per-definition child model and thinking configuration, resolved before a delegation is planned. */
2
+
3
+ export const THINKING_LEVELS = ["off", "minimal", "low", "medium", "high", "xhigh", "max"] as const;
4
+ export type ThinkingLevel = (typeof THINKING_LEVELS)[number];
5
+ export type ModelSource = "explicit" | "session" | "definition" | "global" | "pi";
6
+ export type ThinkingSource = ModelSource | "advisor";
7
+ export interface DefinitionRuntimeChoice {
8
+ model?: string;
9
+ thinking?: ThinkingLevel;
10
+ }
11
+ export interface DefinitionRuntimeSettings {
12
+ defaults: DefinitionRuntimeChoice;
13
+ definitions: Map<string, DefinitionRuntimeChoice>;
14
+ }
15
+ export interface ResolvedDefinitionRuntime {
16
+ model?: string;
17
+ modelSource: ModelSource;
18
+ thinking?: ThinkingLevel;
19
+ thinkingSource: ThinkingSource;
20
+ }
21
+
22
+ const isObject = (value: unknown): value is Record<string, unknown> =>
23
+ value !== null && typeof value === "object" && !Array.isArray(value);
24
+ export const parseThinkingLevel = (value: unknown): ThinkingLevel | undefined =>
25
+ typeof value === "string" && (THINKING_LEVELS as readonly string[]).includes(value)
26
+ ? (value as ThinkingLevel)
27
+ : undefined;
28
+ export const parseConfiguredModel = (value: unknown): string | undefined => {
29
+ if (typeof value !== "string") return undefined;
30
+ const colon = value.indexOf(":");
31
+ if (colon <= 0 || colon === value.length - 1 || /\s/.test(value)) return undefined;
32
+ return `${value.slice(0, colon)}/${value.slice(colon + 1)}`;
33
+ };
34
+ const choice = (value: unknown): DefinitionRuntimeChoice => {
35
+ if (!isObject(value)) return {};
36
+ return {
37
+ ...(parseConfiguredModel(value.model) ? { model: parseConfiguredModel(value.model) } : {}),
38
+ ...(parseThinkingLevel(value.thinking) ? { thinking: parseThinkingLevel(value.thinking) } : {}),
39
+ };
40
+ };
41
+
42
+ export function definitionRuntimeSettingsFrom(raw: unknown): DefinitionRuntimeSettings {
43
+ const definitions = new Map<string, DefinitionRuntimeChoice>();
44
+ if (isObject(raw) && Array.isArray(raw.definitions)) {
45
+ for (const entry of raw.definitions) {
46
+ if (!isObject(entry) || typeof entry.name !== "string") continue;
47
+ definitions.set(entry.name, choice(entry));
48
+ }
49
+ }
50
+ return { defaults: isObject(raw) ? choice(raw.defaults) : {}, definitions };
51
+ }
52
+
53
+ export function resolvedModelOf(value: string | undefined): { provider: string; modelId: string } | null {
54
+ if (!value) return null;
55
+ const slash = value.indexOf("/");
56
+ return slash > 0 && slash < value.length - 1
57
+ ? { provider: value.slice(0, slash), modelId: value.slice(slash + 1) }
58
+ : null;
59
+ }
60
+
61
+ export function resolveDefinitionRuntime(input: {
62
+ definition?: string;
63
+ explicit: { model?: string; thinking?: string };
64
+ session: ReadonlyMap<string, DefinitionRuntimeChoice>;
65
+ settings: DefinitionRuntimeSettings;
66
+ piModel?: string;
67
+ advisorThinking?: string;
68
+ }): ResolvedDefinitionRuntime {
69
+ const session = input.definition ? input.session.get(input.definition) : undefined;
70
+ const definition = input.definition ? input.settings.definitions.get(input.definition) : undefined;
71
+ const modelCandidates: Array<[string | undefined, ModelSource]> = [
72
+ [input.explicit.model, "explicit"],
73
+ [session?.model, "session"],
74
+ [definition?.model, "definition"],
75
+ [input.settings.defaults.model, "global"],
76
+ [input.piModel, "pi"],
77
+ ];
78
+ const thinkingCandidates: Array<[string | undefined, ThinkingSource]> = [
79
+ [input.explicit.thinking, "explicit"],
80
+ [session?.thinking, "session"],
81
+ [input.advisorThinking, "advisor"],
82
+ [definition?.thinking, "definition"],
83
+ [input.settings.defaults.thinking, "global"],
84
+ ];
85
+ const selectedModel = modelCandidates.find(([value]) => value !== undefined) ?? [undefined, "pi" as const];
86
+ const selectedThinking = thinkingCandidates.find(([value]) => value !== undefined) ?? [undefined, "pi" as const];
87
+ return {
88
+ model: selectedModel[0],
89
+ modelSource: selectedModel[1],
90
+ thinking: parseThinkingLevel(selectedThinking[0]),
91
+ thinkingSource: selectedThinking[1],
92
+ };
93
+ }
@@ -43,6 +43,8 @@ import { newExecutionId } from "../src/kernel/execution-id.ts";
43
43
  import { planChain, type GateRequest } from "./chain-plan.ts";
44
44
  import { contextShape } from "./context-shape.ts";
45
45
  import { preflightModel } from "../src/kernel/model-preflight.ts";
46
+ import { resolveDefinitionRuntime } from "./definition-runtime.ts";
47
+ import { ensureSessionModelPrompt } from "./session-model-prompt.ts";
46
48
  import { assertDelegationAuthority } from "./delegation-authority.ts";
47
49
 
48
50
  /** One chain step is one execution occurrence, however many capability dialogs contributed to its answer. */
@@ -100,6 +102,9 @@ export function registerChainTool(pi: ExtensionAPI, session: GrantsSession): voi
100
102
  maxItems: MAX_CHAIN_STEPS,
101
103
  description: "The steps to run IN ORDER. Each one sees the previous one's output.",
102
104
  }),
105
+ episodeCostCeiling: Type.Optional(
106
+ Type.Number({ exclusiveMinimum: 0, description: "Override the USD ceiling for this whole episode." }),
107
+ ),
103
108
  });
104
109
 
105
110
  pi.registerTool({
@@ -130,12 +135,35 @@ export function registerChainTool(pi: ExtensionAPI, session: GrantsSession): voi
130
135
  const split = splitBudget(session.fanoutBudget, steps.length);
131
136
  if (!split.ok) throw new GovernanceRefusal(refusal("FANOUT_EXCEEDED", `chain refused: ${split.reason}`));
132
137
 
138
+ await ensureSessionModelPrompt(
139
+ session,
140
+ steps.flatMap((step) => (step.agent ? [step.agent] : [])),
141
+ {
142
+ hasUI: ctx.hasUI && typeof ctx.ui.input === "function",
143
+ input: (title, placeholder) => ctx.ui.input(title, placeholder),
144
+ notify: (message, type) => ctx.ui.notify(message, type),
145
+ },
146
+ );
147
+
133
148
  // Plan every step first. A step that can never run refuses the chain HERE, before anyone is asked — see
134
149
  // `planChain`.
135
150
  const executionIds = steps.map(() => newExecutionId());
136
151
  const parentExecutionId = session.ownExecutionId ?? null;
137
- const chainPlan = await planChain(session, steps, executionIds, (model) =>
138
- preflightModel(model, ctx.modelRegistry, session.modelResolutionCache, session.allowUnresolvedModels),
152
+ const piModel = ctx.model ? `${ctx.model.provider}/${ctx.model.id}` : undefined;
153
+ const chainPlan = await planChain(
154
+ session,
155
+ steps,
156
+ executionIds,
157
+ (model) =>
158
+ preflightModel(model, ctx.modelRegistry, session.modelResolutionCache, session.allowUnresolvedModels),
159
+ (step) =>
160
+ resolveDefinitionRuntime({
161
+ definition: step.agent,
162
+ explicit: { model: step.model, thinking: step.thinking },
163
+ session: session.definitionRuntimeOverrides,
164
+ settings: session.definitionRuntimeSettings,
165
+ piModel,
166
+ }).model,
139
167
  );
140
168
  if (chainPlan.doomed) {
141
169
  const message =
@@ -274,6 +302,7 @@ export function registerChainTool(pi: ExtensionAPI, session: GrantsSession): voi
274
302
  */
275
303
  let available = [...preApproved];
276
304
 
305
+ if (args.episodeCostCeiling !== undefined) session.episodeCostGate.setCeiling(args.episodeCostCeiling);
277
306
  for (const [index, step] of steps.entries()) {
278
307
  const childId = childSpawnId(session.ownSpawnId, index);
279
308
  const availableForStep = available.filter((approval) => {
@@ -54,6 +54,8 @@ export async function recordDelegationDecision(input: {
54
54
  humanDenied: approval?.humanDenied ?? approvalFacts?.humanDenied,
55
55
  gateOutcome: approval?.gateOutcome,
56
56
  definitionDigest: plan.definitionDigest,
57
+ definitionHash: plan.definitionHash,
58
+ definitionPackageVersion: plan.definitionPackageVersion,
57
59
  taskDigest: plan.taskDigest,
58
60
  correlation: plan.correlation,
59
61
  refusal: plan.refusal,