@pi-unipi/background-tasks 2.16.0 → 2.17.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +21 -27
- package/package.json +3 -4
- package/src/cards.ts +76 -0
- package/src/child-process.ts +1 -1
- package/src/config.ts +0 -42
- package/src/context-visible-conversation-v2.ts +1 -1
- package/src/delegate/artifacts.ts +1 -1
- package/src/delegate/launch.ts +17 -30
- package/src/delegate/result-package.ts +1 -1
- package/src/delegate/runner.ts +1 -20
- package/src/delegate/seed.ts +1 -1
- package/src/delegate-extension.ts +16 -168
- package/src/index.ts +53 -25
- package/src/json-utils.ts +56 -0
- package/src/package-assets.ts +51 -0
- package/src/registry.ts +8 -459
- package/src/task-manager.ts +13 -2
- package/src/tools.ts +4 -189
- package/src/types.ts +17 -70
- package/extensions/anthropic-attribution.ts +0 -1
- package/extensions/fusion-child.ts +0 -1
- package/src/anthropic-attribution-path.ts +0 -21
- package/src/anthropic-attribution.ts +0 -1983
- package/src/attested-pi-run.ts +0 -612
- package/src/fixtures/fusion-golden-bytes.json +0 -310
- package/src/fixtures/fusion-validate-golden-bytes.json +0 -282
- package/src/fusion/artifacts.ts +0 -967
- package/src/fusion/budget.ts +0 -1162
- package/src/fusion/child-protocol.ts +0 -305
- package/src/fusion/claude-cache.ts +0 -207
- package/src/fusion/clean-context.ts +0 -91
- package/src/fusion/config.ts +0 -449
- package/src/fusion/context.ts +0 -265
- package/src/fusion/evaluation.ts +0 -800
- package/src/fusion/orchestrator.ts +0 -1288
- package/src/fusion/output-contract.ts +0 -34
- package/src/fusion/pi-child.ts +0 -2373
- package/src/fusion/prompts.ts +0 -345
- package/src/fusion/result-package.ts +0 -959
- package/src/fusion/source-policy.ts +0 -257
- package/src/fusion/types.ts +0 -1139
- package/src/fusion/web-fetch.ts +0 -1060
- package/src/fusion/workflows.ts +0 -184
- package/src/fusion-child-extension.ts +0 -1052
- package/src/fusion-extension.ts +0 -1293
- package/src/ui/fusion-model-selector.ts +0 -322
package/src/tools.ts
CHANGED
|
@@ -6,9 +6,7 @@
|
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
8
|
import { Text } from "@earendil-works/pi-tui";
|
|
9
|
-
import {
|
|
10
|
-
import { dirname } from "node:path";
|
|
11
|
-
import { fileURLToPath } from "node:url";
|
|
9
|
+
import { renderCompletionCard, renderLaunchCard } from "./cards.js";
|
|
12
10
|
import { Type, type Static } from "typebox";
|
|
13
11
|
import {
|
|
14
12
|
COMMAND_PREVIEW_CHARS,
|
|
@@ -27,7 +25,6 @@ import {
|
|
|
27
25
|
type BgRunDetails,
|
|
28
26
|
type BgStatusDetails,
|
|
29
27
|
type BgTaskSnapshot,
|
|
30
|
-
type StartAttestedPiTaskOptions,
|
|
31
28
|
type StartTaskOptions,
|
|
32
29
|
} from "./types.js";
|
|
33
30
|
import type { BackgroundTaskRegistry } from "./registry.js";
|
|
@@ -88,31 +85,12 @@ export const BgKillParams = Type.Object({
|
|
|
88
85
|
taskId: Type.String({ description: "Task ID or unambiguous prefix of a running task" }),
|
|
89
86
|
});
|
|
90
87
|
|
|
91
|
-
export const BgPiAttestedParams = Type.Object({
|
|
92
|
-
name: Type.String({ description: "Short human-readable task name" }),
|
|
93
|
-
provider: Type.String({ description: "Pi provider id (e.g. anthropic)" }),
|
|
94
|
-
model: Type.String({ description: "Model id under the provider" }),
|
|
95
|
-
prompt: Type.String({ description: "Final user prompt for the child Pi run" }),
|
|
96
|
-
reportPath: Type.String({
|
|
97
|
-
description: "Relative path (inside cwd) where the child must write its report before exit",
|
|
98
|
-
}),
|
|
99
|
-
extraPiArgs: Type.Optional(
|
|
100
|
-
Type.Array(Type.String(), { description: "Extra literal pi CLI args (restricted)" }),
|
|
101
|
-
),
|
|
102
|
-
thinking: Type.Optional(Type.String({ description: "Thinking level passed as --thinking" })),
|
|
103
|
-
timeoutSeconds: Type.Optional(Type.Number({ description: "Kill after this many seconds" })),
|
|
104
|
-
});
|
|
105
|
-
|
|
106
88
|
// ── Registration ────────────────────────────────────────────────────────────
|
|
107
89
|
|
|
108
90
|
export interface RegisterSurfaceOptions {
|
|
109
91
|
pi: import("@earendil-works/pi-coding-agent").ExtensionAPI;
|
|
110
92
|
registry: BackgroundTaskRegistry;
|
|
111
93
|
startTask: (ctx: any, command: string, options?: StartTaskOptions) => Promise<any>;
|
|
112
|
-
startAttestedPiTask: (
|
|
113
|
-
ctx: any,
|
|
114
|
-
options: StartAttestedPiTaskOptions,
|
|
115
|
-
) => Promise<any>;
|
|
116
94
|
openTaskManager: (ctx: any, initialTaskId?: string) => Promise<void>;
|
|
117
95
|
clearFinishedNotices: (ctx: any) => number;
|
|
118
96
|
openSettings: (ctx: any) => Promise<void>;
|
|
@@ -135,25 +113,6 @@ export function registerToolsAndCommands(options: RegisterSurfaceOptions): void
|
|
|
135
113
|
|
|
136
114
|
// ── Commands (/unipi:* namespace — ours) ──────────────────────────────────
|
|
137
115
|
|
|
138
|
-
// Update info lives with OUR updater module; this only reports versions.
|
|
139
|
-
pi.registerCommand("unipi:bg-update", {
|
|
140
|
-
description: "Show the installed background-tasks version and how to update",
|
|
141
|
-
handler: (_args, ctx) => {
|
|
142
|
-
const here = dirname(fileURLToPath(import.meta.url));
|
|
143
|
-
const current = getInstalledPackageVersion(here, "@pi-unipi/background-tasks");
|
|
144
|
-
const lines = [
|
|
145
|
-
`@pi-unipi/background-tasks ${current} is installed.`,
|
|
146
|
-
"Background tasks ship inside the @pi-unipi/unipi umbrella package.",
|
|
147
|
-
"Update from npm:",
|
|
148
|
-
" pi install npm:@pi-unipi/unipi@latest",
|
|
149
|
-
"Or use /unipi:updater-settings to check for updates.",
|
|
150
|
-
"This command only prints update instructions; it does not install or self-update.",
|
|
151
|
-
];
|
|
152
|
-
ctx.ui.notify(lines.join("\n"), "info");
|
|
153
|
-
return Promise.resolve();
|
|
154
|
-
},
|
|
155
|
-
});
|
|
156
|
-
|
|
157
116
|
pi.registerCommand("unipi:bg", {
|
|
158
117
|
description:
|
|
159
118
|
'Start a shell command as a tracked background task: /unipi:bg [--agent] [--name "Task name"] <command>',
|
|
@@ -180,14 +139,6 @@ export function registerToolsAndCommands(options: RegisterSurfaceOptions): void
|
|
|
180
139
|
},
|
|
181
140
|
});
|
|
182
141
|
|
|
183
|
-
pi.registerCommand("unipi:tasks", {
|
|
184
|
-
description: "Open the background task manager UI",
|
|
185
|
-
handler: async (args, ctx) => {
|
|
186
|
-
const taskId = typeof args === "string" ? args.trim() : "";
|
|
187
|
-
await options.openTaskManager(ctx, taskId || undefined);
|
|
188
|
-
},
|
|
189
|
-
});
|
|
190
|
-
|
|
191
142
|
pi.registerCommand("unipi:bg-tasks", {
|
|
192
143
|
description: "Open the background task manager UI",
|
|
193
144
|
handler: async (args, ctx) => {
|
|
@@ -196,86 +147,6 @@ export function registerToolsAndCommands(options: RegisterSurfaceOptions): void
|
|
|
196
147
|
},
|
|
197
148
|
});
|
|
198
149
|
|
|
199
|
-
pi.registerCommand("unipi:bg-clear", {
|
|
200
|
-
description: "Clear finished background task footer notices",
|
|
201
|
-
handler: (_args, ctx) => {
|
|
202
|
-
options.clearFinishedNotices(ctx);
|
|
203
|
-
return Promise.resolve();
|
|
204
|
-
},
|
|
205
|
-
});
|
|
206
|
-
|
|
207
|
-
pi.registerCommand("unipi:jobs", {
|
|
208
|
-
description: "List running and recent background tasks",
|
|
209
|
-
handler: (_args, ctx) => {
|
|
210
|
-
ctx.ui.notify(
|
|
211
|
-
formatSnapshotList(registry.allTasks().map((task) => registry.snapshot(task))),
|
|
212
|
-
"info",
|
|
213
|
-
);
|
|
214
|
-
return Promise.resolve();
|
|
215
|
-
},
|
|
216
|
-
});
|
|
217
|
-
|
|
218
|
-
pi.registerCommand("unipi:logs", {
|
|
219
|
-
description: "Show bounded output from a background task: /unipi:logs <id> [maxBytes]",
|
|
220
|
-
getArgumentCompletions: (prefix: string) => {
|
|
221
|
-
const matches = registry
|
|
222
|
-
.allTasks()
|
|
223
|
-
.filter((task) => task.id.startsWith(prefix.trim()))
|
|
224
|
-
.slice(0, 20)
|
|
225
|
-
.map((task) => ({
|
|
226
|
-
value: task.id,
|
|
227
|
-
label: `${task.id} ${taskDisplayName(task)}`,
|
|
228
|
-
description: `${task.status} — ${truncateChars(task.command, 60)}`,
|
|
229
|
-
}));
|
|
230
|
-
return matches.length > 0 ? matches : null;
|
|
231
|
-
},
|
|
232
|
-
handler: async (args, ctx) => {
|
|
233
|
-
try {
|
|
234
|
-
const [id, bytes] = args.trim().split(/\s+/, 2);
|
|
235
|
-
const task = registry.resolveTask(id ?? "");
|
|
236
|
-
const maxBytes = normalizeMaxBytes(Number(bytes), DEFAULT_LOG_BYTES);
|
|
237
|
-
const logs = await registry.getTaskLogs(task, maxBytes, true);
|
|
238
|
-
ctx.ui.notify(logs.text, "info");
|
|
239
|
-
} catch (error) {
|
|
240
|
-
ctx.ui.notify(
|
|
241
|
-
`Background logs error: ${error instanceof Error ? error.message : String(error)}`,
|
|
242
|
-
"error",
|
|
243
|
-
);
|
|
244
|
-
}
|
|
245
|
-
},
|
|
246
|
-
});
|
|
247
|
-
|
|
248
|
-
pi.registerCommand("unipi:kill", {
|
|
249
|
-
description: "Stop a running background task: /unipi:kill <id>",
|
|
250
|
-
getArgumentCompletions: (prefix: string) => {
|
|
251
|
-
const matches = registry
|
|
252
|
-
.allTasks()
|
|
253
|
-
.filter((task) => task.status === "running" && task.id.startsWith(prefix.trim()))
|
|
254
|
-
.slice(0, 20)
|
|
255
|
-
.map((task) => ({
|
|
256
|
-
value: task.id,
|
|
257
|
-
label: `${task.id} ${taskDisplayName(task)}`,
|
|
258
|
-
description: truncateChars(task.command, 70),
|
|
259
|
-
}));
|
|
260
|
-
return matches.length > 0 ? matches : null;
|
|
261
|
-
},
|
|
262
|
-
handler: async (args, ctx) => {
|
|
263
|
-
try {
|
|
264
|
-
const task = registry.resolveTask(args.trim());
|
|
265
|
-
await registry.stopTask(task, "user");
|
|
266
|
-
ctx.ui.notify(
|
|
267
|
-
`Killed ${taskDisplayName(task)} (${task.id}). Output: ${task.outputPath}`,
|
|
268
|
-
"info",
|
|
269
|
-
);
|
|
270
|
-
} catch (error) {
|
|
271
|
-
ctx.ui.notify(
|
|
272
|
-
`Background kill error: ${error instanceof Error ? error.message : String(error)}`,
|
|
273
|
-
"error",
|
|
274
|
-
);
|
|
275
|
-
}
|
|
276
|
-
},
|
|
277
|
-
});
|
|
278
|
-
|
|
279
150
|
// Shortcuts (same keys as reference; documented in our README)
|
|
280
151
|
pi.registerCommand("unipi:bg-settings", {
|
|
281
152
|
description: "Open background-tasks settings (master toggle, defaults)",
|
|
@@ -301,21 +172,8 @@ export function registerToolsAndCommands(options: RegisterSurfaceOptions): void
|
|
|
301
172
|
|
|
302
173
|
pi.registerMessageRenderer<BgTaskSnapshot>(
|
|
303
174
|
"background-task-notification",
|
|
304
|
-
(message: { details?: BgTaskSnapshot }, _options: unknown, theme: any) =>
|
|
305
|
-
|
|
306
|
-
const status = task?.status ?? "completed";
|
|
307
|
-
const color: string =
|
|
308
|
-
status === "completed" ? "success" : status === "failed" ? "error" : status === "killed" ? "warning" : "accent";
|
|
309
|
-
const id = task?.id ?? "background task";
|
|
310
|
-
const name = task ? taskDisplayName(task) : "Background task";
|
|
311
|
-
const output = task?.outputPath ? `\n${theme.fg("dim", `Output: ${task.outputPath}`)}` : "";
|
|
312
|
-
const error = task?.error ? `\n${theme.fg("error", task.error)}` : "";
|
|
313
|
-
return new Text(
|
|
314
|
-
`${theme.fg(color, `[bg ${status}]`)} ${theme.fg("accent", name)} ${theme.fg("dim", `(${id})`)}${output}${error}`,
|
|
315
|
-
0,
|
|
316
|
-
0,
|
|
317
|
-
);
|
|
318
|
-
},
|
|
175
|
+
(message: { details?: BgTaskSnapshot }, _options: unknown, theme: any) =>
|
|
176
|
+
renderCompletionCard(theme, message.details),
|
|
319
177
|
);
|
|
320
178
|
|
|
321
179
|
// ── Tools (reference names kept) ─────────────────────────────────────────
|
|
@@ -371,12 +229,7 @@ export function registerToolsAndCommands(options: RegisterSurfaceOptions): void
|
|
|
371
229
|
);
|
|
372
230
|
},
|
|
373
231
|
renderResult(result: { details: BgRunDetails }, _options: unknown, theme: any) {
|
|
374
|
-
|
|
375
|
-
return new Text(
|
|
376
|
-
`${theme.fg("success", "✓ started")} ${theme.fg("accent", taskDisplayName(task))} ${theme.fg("dim", `(${task.id})`)}\n${theme.fg("dim", `Output: ${task.outputPath}`)}`,
|
|
377
|
-
0,
|
|
378
|
-
0,
|
|
379
|
-
);
|
|
232
|
+
return renderLaunchCard(theme, result.details.task);
|
|
380
233
|
},
|
|
381
234
|
});
|
|
382
235
|
|
|
@@ -491,42 +344,4 @@ export function registerToolsAndCommands(options: RegisterSurfaceOptions): void
|
|
|
491
344
|
);
|
|
492
345
|
},
|
|
493
346
|
});
|
|
494
|
-
|
|
495
|
-
pi.registerTool<typeof BgPiAttestedParams, BgRunDetails>({
|
|
496
|
-
name: "bg_run_pi_attested",
|
|
497
|
-
label: "Attested Pi Run",
|
|
498
|
-
description:
|
|
499
|
-
"Opt-in evidence-oriented direct Pi spawn. Launches exactly one `pi --mode json` child, records raw events/stderr, hashes prompt/report/output, observes OAuth through ModelRegistry, and emits a strict attestation sidecar only after successful completion.",
|
|
500
|
-
promptSnippet: "Start an attested direct Pi agent task and return its task ID plus output path",
|
|
501
|
-
promptGuidelines: [
|
|
502
|
-
"Use only when the user explicitly asks for an attested Pi evidence-producing task; ordinary background work should use bg_run unchanged.",
|
|
503
|
-
"Provide provider/model as structured fields and a relative reportPath that the child Pi prompt will write before exit.",
|
|
504
|
-
"Do not provide channel, auth, route, or hash claims; the producer observes those facts itself and fails loudly if it cannot attest them.",
|
|
505
|
-
],
|
|
506
|
-
parameters: BgPiAttestedParams,
|
|
507
|
-
async execute(_toolCallId, params, _signal, _onUpdate, ctx) {
|
|
508
|
-
const task = await options.startAttestedPiTask(ctx, params);
|
|
509
|
-
return {
|
|
510
|
-
content: textContent(
|
|
511
|
-
`Started attested Pi task ${taskDisplayName(task)} (${task.id})\nStatus: ${task.status}\nPID: ${String(task.pid ?? "unknown")}\nOutput: ${task.outputPath}\nAttestation: ${task.attestationPath ?? "pending until completion"}`,
|
|
512
|
-
),
|
|
513
|
-
details: { task: registry.snapshot(task) },
|
|
514
|
-
};
|
|
515
|
-
},
|
|
516
|
-
renderCall(args: Static<typeof BgPiAttestedParams>, theme: any) {
|
|
517
|
-
return new Text(
|
|
518
|
-
`${theme.fg("toolTitle", theme.bold("bg_run_pi_attested "))}${theme.fg("muted", truncateChars(args.name, COMMAND_PREVIEW_CHARS))}`,
|
|
519
|
-
0,
|
|
520
|
-
0,
|
|
521
|
-
);
|
|
522
|
-
},
|
|
523
|
-
renderResult(result: { details: BgRunDetails }, _options: unknown, theme: any) {
|
|
524
|
-
const { task } = result.details;
|
|
525
|
-
return new Text(
|
|
526
|
-
`${theme.fg("success", "✓ started")} ${theme.fg("accent", taskDisplayName(task))} ${theme.fg("dim", `(${task.id})`)}\n${theme.fg("dim", `Output: ${task.outputPath}`)}\n${theme.fg("dim", `Attestation: ${task.attestationPath ?? "pending"}`)}`,
|
|
527
|
-
0,
|
|
528
|
-
0,
|
|
529
|
-
);
|
|
530
|
-
},
|
|
531
|
-
});
|
|
532
347
|
}
|
package/src/types.ts
CHANGED
|
@@ -12,7 +12,6 @@
|
|
|
12
12
|
import { statSync, type WriteStream } from "node:fs";
|
|
13
13
|
import { join } from "node:path";
|
|
14
14
|
import type { BackgroundTaskChildProcess } from "./child-process.js";
|
|
15
|
-
import type { FusionResultDetails, FusionUsage, FusionWorkflowId } from "./fusion/types.js";
|
|
16
15
|
|
|
17
16
|
export const TASK_STATUS_VALUES = ["running", "completed", "failed", "killed"] as const;
|
|
18
17
|
export const TERMINAL_TASK_STATUS_VALUES = ["completed", "failed", "killed"] as const;
|
|
@@ -69,20 +68,9 @@ export interface BgTaskSnapshot {
|
|
|
69
68
|
toolUsage?: TaskToolUsage | undefined;
|
|
70
69
|
model?: string | undefined;
|
|
71
70
|
telemetryUnavailableReason?: string | undefined;
|
|
72
|
-
attestationPath?: string | undefined;
|
|
73
71
|
delegate?: DelegateTaskFacts | undefined;
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
export interface AttestedPiTaskFiles {
|
|
78
|
-
eventsPath: string;
|
|
79
|
-
stderrPath: string;
|
|
80
|
-
wrapperPath: string;
|
|
81
|
-
attestationPath: string;
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
export interface AttestedPiTaskSnapshot extends BgTaskSnapshot {
|
|
85
|
-
attestedPi?: AttestedPiTaskFiles | undefined;
|
|
72
|
+
/** Last few non-empty output lines (bounded), for compact chat cards. */
|
|
73
|
+
outputTail?: string[] | undefined;
|
|
86
74
|
}
|
|
87
75
|
|
|
88
76
|
/** Delegate-specific task facts surfaced through snapshots and `bg_result`. */
|
|
@@ -114,25 +102,6 @@ export interface DelegateTaskOutcome {
|
|
|
114
102
|
export type DelegateBudgetRouteSource = import("./delegate/types.js").DelegateBudgetRouteSource;
|
|
115
103
|
export type DelegateExtensionMode = import("./delegate/types.js").DelegateExtensionMode;
|
|
116
104
|
|
|
117
|
-
/** Fusion-specific task facts surfaced through snapshots and `bg_result`. */
|
|
118
|
-
export interface FusionTaskFacts {
|
|
119
|
-
runId: string;
|
|
120
|
-
workflow: FusionWorkflowId;
|
|
121
|
-
artifactDir: string;
|
|
122
|
-
artifactDirAbs: string;
|
|
123
|
-
state: string;
|
|
124
|
-
outcome?: FusionTaskOutcome | undefined;
|
|
125
|
-
/** Durable once-only accounting claim made by the first successful bg_result retrieval. */
|
|
126
|
-
usageDelivered: boolean;
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
export interface FusionTaskOutcome {
|
|
130
|
-
status: "committed" | "failed" | "cancelled";
|
|
131
|
-
resultDetails?: FusionResultDetails | undefined;
|
|
132
|
-
usage?: FusionUsage | undefined;
|
|
133
|
-
error?: string | undefined;
|
|
134
|
-
}
|
|
135
|
-
|
|
136
105
|
export interface BgTask extends Omit<BgTaskSnapshot, "name"> {
|
|
137
106
|
name: string;
|
|
138
107
|
outputAbsPath: string;
|
|
@@ -160,14 +129,8 @@ export interface BgTask extends Omit<BgTaskSnapshot, "name"> {
|
|
|
160
129
|
/** Partial trailing stdout line held between chunks while reconstructing wrapped-agent control lines. */
|
|
161
130
|
agentStdoutBuffer?: string | undefined;
|
|
162
131
|
telemetryUnavailableReason?: string | undefined;
|
|
163
|
-
attestationPath?: string | undefined;
|
|
164
|
-
attestedPi?: AttestedPiTaskFiles | undefined;
|
|
165
132
|
delegate?: DelegateTaskFacts | undefined;
|
|
166
|
-
|
|
167
|
-
/** Cancellation hook for an in-process managed task such as Fusion. */
|
|
168
|
-
managedCancel?: (() => void) | undefined;
|
|
169
|
-
managedCancelRequested?: boolean | undefined;
|
|
170
|
-
managedStopWaitMs?: number | undefined;
|
|
133
|
+
outputTail?: string[] | undefined;
|
|
171
134
|
metadataWriteChain?: Promise<void> | undefined;
|
|
172
135
|
waiters: Array<() => void>;
|
|
173
136
|
}
|
|
@@ -264,23 +227,6 @@ export interface StartTaskOptions {
|
|
|
264
227
|
terminalPublicationGate?: Promise<void> | undefined;
|
|
265
228
|
}
|
|
266
229
|
|
|
267
|
-
/** Prepared managed launch handed to the registry after preflight has succeeded. */
|
|
268
|
-
export interface StartManagedTaskOptions {
|
|
269
|
-
id: string;
|
|
270
|
-
name: string;
|
|
271
|
-
command: string;
|
|
272
|
-
description?: string | undefined;
|
|
273
|
-
isAgent: boolean;
|
|
274
|
-
completion: Promise<void>;
|
|
275
|
-
cancel: () => void;
|
|
276
|
-
notifyOnCompletion: boolean;
|
|
277
|
-
triggerOnCompletion: boolean;
|
|
278
|
-
fusion: FusionTaskFacts;
|
|
279
|
-
stopWaitMs?: number | undefined;
|
|
280
|
-
/** Prevent terminal publication until the launch receipt handoff is observable. */
|
|
281
|
-
terminalPublicationGate?: Promise<void> | undefined;
|
|
282
|
-
}
|
|
283
|
-
|
|
284
230
|
export interface StartDelegateTaskOptions {
|
|
285
231
|
name: string;
|
|
286
232
|
argv: readonly string[];
|
|
@@ -293,17 +239,6 @@ export interface StartDelegateTaskOptions {
|
|
|
293
239
|
timeoutSeconds?: number | undefined;
|
|
294
240
|
}
|
|
295
241
|
|
|
296
|
-
export interface StartAttestedPiTaskOptions {
|
|
297
|
-
name: string;
|
|
298
|
-
provider: string;
|
|
299
|
-
model: string;
|
|
300
|
-
prompt: string;
|
|
301
|
-
reportPath: string;
|
|
302
|
-
extraPiArgs?: string[] | undefined;
|
|
303
|
-
thinking?: string | undefined;
|
|
304
|
-
timeoutSeconds?: number | undefined;
|
|
305
|
-
}
|
|
306
|
-
|
|
307
242
|
/** Default tool-output byte cap (mirrors pi's DEFAULT_MAX_BYTES). */
|
|
308
243
|
export const DEFAULT_MAX_BYTES = 30 * 1024;
|
|
309
244
|
|
|
@@ -830,12 +765,24 @@ export function snapshot(task: BgTask): BgTaskSnapshot {
|
|
|
830
765
|
toolUsage: task.toolUsage,
|
|
831
766
|
model: task.model,
|
|
832
767
|
telemetryUnavailableReason: task.telemetryUnavailableReason,
|
|
833
|
-
attestationPath: task.attestationPath,
|
|
834
768
|
delegate: task.delegate,
|
|
835
|
-
|
|
769
|
+
outputTail: task.outputTail === undefined ? undefined : [...task.outputTail],
|
|
836
770
|
};
|
|
837
771
|
}
|
|
838
772
|
|
|
773
|
+
export const OUTPUT_TAIL_LINES = 3;
|
|
774
|
+
const OUTPUT_TAIL_LINE_CHARS = 200;
|
|
775
|
+
|
|
776
|
+
/** Fold a raw output chunk into the task's bounded tail ring (non-empty lines only). */
|
|
777
|
+
export function appendOutputTail(task: { outputTail?: string[] | undefined }, chunk: string): void {
|
|
778
|
+
if (chunk.length === 0) return;
|
|
779
|
+
const lines = chunk.split(/\r?\n/u).map((line) => line.replace(/\x1b\[[0-9;]*[A-Za-z]/gu, "").trimEnd()).filter((line) => line.trim().length > 0);
|
|
780
|
+
if (lines.length === 0) return;
|
|
781
|
+
const tail = task.outputTail ?? [];
|
|
782
|
+
for (const line of lines) tail.push(line.length > OUTPUT_TAIL_LINE_CHARS ? `${line.slice(0, OUTPUT_TAIL_LINE_CHARS)}…` : line);
|
|
783
|
+
task.outputTail = tail.slice(-OUTPUT_TAIL_LINES);
|
|
784
|
+
}
|
|
785
|
+
|
|
839
786
|
export async function boundedRead(
|
|
840
787
|
filePath: string,
|
|
841
788
|
maxBytes: number,
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export { default } from '../src/anthropic-attribution.js';
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export { default } from '../src/fusion-child-extension.js';
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @pi-unipi/background-tasks — Anthropic attribution extension path
|
|
3
|
-
*
|
|
4
|
-
* Resolves this package's own attribution extension entry so isolated child Pi
|
|
5
|
-
* processes can load it explicitly. Mirrors the reference layout:
|
|
6
|
-
* extensions/anthropic-attribution.ts re-exports src/anthropic-attribution.ts.
|
|
7
|
-
*/
|
|
8
|
-
|
|
9
|
-
import { dirname, resolve } from "node:path";
|
|
10
|
-
import { fileURLToPath } from "node:url";
|
|
11
|
-
import { existsSync } from "node:fs";
|
|
12
|
-
|
|
13
|
-
export function resolveAnthropicAttributionExtensionPath(): string {
|
|
14
|
-
// src/anthropic-attribution-path.ts -> packages/background-tasks/extensions/
|
|
15
|
-
const here = dirname(fileURLToPath(import.meta.url));
|
|
16
|
-
const candidate = resolve(here, "..", "extensions", "anthropic-attribution.ts");
|
|
17
|
-
if (!existsSync(candidate)) {
|
|
18
|
-
throw new Error(`Anthropic attribution extension is missing: ${candidate}`);
|
|
19
|
-
}
|
|
20
|
-
return candidate;
|
|
21
|
-
}
|