@pi-unipi/background-tasks 2.6.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.
- package/README.md +87 -0
- package/extensions/anthropic-attribution.ts +1 -0
- package/extensions/delegate-child.ts +1 -0
- package/extensions/fusion-child.ts +1 -0
- package/package.json +40 -0
- package/src/__tests__/anthropic-attribution.test.ts +195 -0
- package/src/__tests__/config.test.ts +137 -0
- package/src/__tests__/core.test.ts +493 -0
- package/src/__tests__/delegate-artifacts.test.ts +528 -0
- package/src/__tests__/delegate-budget.test.ts +456 -0
- package/src/__tests__/delegate-launch.test.ts +676 -0
- package/src/__tests__/delegate-result-package.test.ts +350 -0
- package/src/__tests__/delegate-seed.test.ts +392 -0
- package/src/__tests__/durable-fs.test.ts +559 -0
- package/src/__tests__/extension-api.test.ts +579 -0
- package/src/__tests__/fusion-artifacts.test.ts +1039 -0
- package/src/__tests__/fusion-budget.test.ts +1356 -0
- package/src/__tests__/fusion-claude-cache.test.ts +320 -0
- package/src/__tests__/fusion-config.test.ts +335 -0
- package/src/__tests__/fusion-context-prompts.test.ts +670 -0
- package/src/__tests__/fusion-evaluation.test.ts +315 -0
- package/src/__tests__/fusion-extraction-equivalence.test.ts +58 -0
- package/src/__tests__/fusion-golden-bytes.test.ts +35 -0
- package/src/__tests__/fusion-high-cardinality.test.ts +192 -0
- package/src/__tests__/fusion-model-selector.test.ts +205 -0
- package/src/__tests__/fusion-orchestrator.test.ts +1194 -0
- package/src/__tests__/fusion-rpc.test.ts +369 -0
- package/src/__tests__/fusion-sdk.test.ts +1226 -0
- package/src/__tests__/fusion-v5-core.test.ts +219 -0
- package/src/__tests__/fusion-validate-orchestrator.test.ts +240 -0
- package/src/__tests__/fusion-web-fetch.test.ts +485 -0
- package/src/__tests__/fusion-workflows.test.ts +59 -0
- package/src/__tests__/helpers/delegate-deterministic-seed.ts +109 -0
- package/src/__tests__/helpers/delegate-seed-subprocess.ts +10 -0
- package/src/__tests__/helpers/fusion-canonical-subprocess.ts +21 -0
- package/src/__tests__/helpers/fusion-canonical.ts +140 -0
- package/src/__tests__/helpers/fusion-fake-pi.ts +279 -0
- package/src/__tests__/helpers/fusion-golden-corpus.ts +500 -0
- package/src/__tests__/helpers/fusion-high-cardinality.ts +140 -0
- package/src/__tests__/helpers/normalize.ts +22 -0
- package/src/__tests__/helpers/pi-hook-contract-evidence.json +18 -0
- package/src/__tests__/pi-launch.test.ts +202 -0
- package/src/__tests__/registry.test.ts +1580 -0
- package/src/__tests__/scripted-provider/delegate-ambient-provider.test.ts +130 -0
- package/src/__tests__/scripted-provider/delegate-child-guard.test.ts +631 -0
- package/src/__tests__/scripted-provider/delegate-guard-provider.ts +403 -0
- package/src/__tests__/scripted-provider/follow-up.test.ts +448 -0
- package/src/__tests__/scripted-provider/fusion-output-recovery.test.ts +132 -0
- package/src/__tests__/scripted-provider/fusion-reason.test.ts +310 -0
- package/src/__tests__/scripted-provider/fusion-runtime-guard.test.ts +163 -0
- package/src/__tests__/scripted-provider/hook-contract-provider.ts +179 -0
- package/src/__tests__/scripted-provider/hook-probe-a.ts +3 -0
- package/src/__tests__/scripted-provider/hook-probe-b.ts +3 -0
- package/src/__tests__/scripted-provider/hook-probe-extension.ts +126 -0
- package/src/__tests__/scripted-provider/output-recovery-provider.ts +153 -0
- package/src/__tests__/scripted-provider/pi-hook-contract-evidence.json +18 -0
- package/src/__tests__/scripted-provider/pi-hook-contract.test.ts +477 -0
- package/src/__tests__/scripted-provider/runtime-guard-probe.ts +28 -0
- package/src/__tests__/scripted-provider/runtime-guard-provider.ts +49 -0
- package/src/__tests__/scripted-provider/scripted-provider-extension.ts +408 -0
- package/src/__tests__/task-manager.test.ts +479 -0
- package/src/__tests__/windows-taskkill.test.ts +161 -0
- package/src/anthropic-attribution-path.ts +21 -0
- package/src/anthropic-attribution.ts +1983 -0
- package/src/attested-pi-run.ts +612 -0
- package/src/child-process.ts +55 -0
- package/src/common.ts +8 -0
- package/src/config.ts +292 -0
- package/src/context-parent-snapshot.ts +142 -0
- package/src/context-token-budget.ts +903 -0
- package/src/context-visible-conversation-v2.ts +551 -0
- package/src/delegate/artifacts.ts +487 -0
- package/src/delegate/budget.ts +415 -0
- package/src/delegate/hook-contract-evidence.json +18 -0
- package/src/delegate/hook-contract.ts +154 -0
- package/src/delegate/launch.ts +497 -0
- package/src/delegate/result-package.ts +459 -0
- package/src/delegate/runner.ts +449 -0
- package/src/delegate/seed.ts +423 -0
- package/src/delegate/types.ts +323 -0
- package/src/delegate-child-extension.ts +978 -0
- package/src/delegate-extension.ts +806 -0
- package/src/durable-fs.ts +386 -0
- package/src/extension-api.ts +548 -0
- package/src/fixtures/delegate-context-incident.json +17 -0
- package/src/fixtures/fusion-golden-bytes.json +310 -0
- package/src/fixtures/fusion-validate-golden-bytes.json +282 -0
- package/src/fusion/artifacts.ts +967 -0
- package/src/fusion/budget.ts +1162 -0
- package/src/fusion/child-protocol.ts +305 -0
- package/src/fusion/claude-cache.ts +207 -0
- package/src/fusion/clean-context.ts +91 -0
- package/src/fusion/config.ts +449 -0
- package/src/fusion/context.ts +265 -0
- package/src/fusion/evaluation.ts +800 -0
- package/src/fusion/orchestrator.ts +1288 -0
- package/src/fusion/output-contract.ts +34 -0
- package/src/fusion/pi-child.ts +2373 -0
- package/src/fusion/prompts.ts +345 -0
- package/src/fusion/result-package.ts +959 -0
- package/src/fusion/source-policy.ts +257 -0
- package/src/fusion/types.ts +1139 -0
- package/src/fusion/web-fetch.ts +1060 -0
- package/src/fusion/workflows.ts +184 -0
- package/src/fusion-child-extension.ts +1052 -0
- package/src/fusion-extension.ts +1293 -0
- package/src/index.ts +295 -0
- package/src/pi-launch.ts +225 -0
- package/src/registry.ts +2424 -0
- package/src/settings-overlay.ts +208 -0
- package/src/task-manager.ts +774 -0
- package/src/tools.ts +530 -0
- package/src/turndown.d.ts +15 -0
- package/src/types.ts +963 -0
- package/src/ui/fusion-model-selector.ts +322 -0
- package/src/windows-taskkill.ts +250 -0
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @pi-unipi/background-tasks — Settings overlay TUI
|
|
3
|
+
*
|
|
4
|
+
* Interactive editor for background-tasks config, mounted in our panel style
|
|
5
|
+
* (mcp/settings-overlay precedent): box-drawn overlay, arrow/vim navigation,
|
|
6
|
+
* space to cycle values, saved atomically to the global config file.
|
|
7
|
+
*
|
|
8
|
+
* The master `enabled` toggle lives here: turning it off disables the whole
|
|
9
|
+
* module on the next Pi start (Pi 0.80 cannot unregister tools at runtime).
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import { Key, matchesKey, truncateToWidth, type TUI, visibleWidth } from "@earendil-works/pi-tui";
|
|
13
|
+
import type { Theme, KeybindingsManager } from "@earendil-works/pi-coding-agent";
|
|
14
|
+
import {
|
|
15
|
+
loadBackgroundTasksConfig,
|
|
16
|
+
saveGlobalBackgroundTasksConfig,
|
|
17
|
+
type BackgroundTasksConfig,
|
|
18
|
+
} from "./config.js";
|
|
19
|
+
import { normalizeWidth, WidthKeyedCache } from "@pi-unipi/core";
|
|
20
|
+
|
|
21
|
+
/** One editable row in the overlay. */
|
|
22
|
+
interface SettingRow {
|
|
23
|
+
key: string;
|
|
24
|
+
label: string;
|
|
25
|
+
/** Render the current value for display. */
|
|
26
|
+
display: (config: BackgroundTasksConfig) => string;
|
|
27
|
+
/** Cycle to the next value (booleans toggle; enums step). */
|
|
28
|
+
cycle: (config: BackgroundTasksConfig) => void;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const ROWS: SettingRow[] = [
|
|
32
|
+
{
|
|
33
|
+
key: "enabled",
|
|
34
|
+
label: "Enabled (master toggle)",
|
|
35
|
+
display: (c) => (c.enabled ? "on" : "off"),
|
|
36
|
+
cycle: (c) => {
|
|
37
|
+
c.enabled = !c.enabled;
|
|
38
|
+
},
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
key: "notifyOnCompletion",
|
|
42
|
+
label: "Notify on completion",
|
|
43
|
+
display: (c) => (c.notifyOnCompletion ? "on" : "off"),
|
|
44
|
+
cycle: (c) => {
|
|
45
|
+
c.notifyOnCompletion = !c.notifyOnCompletion;
|
|
46
|
+
},
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
key: "triggerOnCompletion",
|
|
50
|
+
label: "Wake follow-up turn",
|
|
51
|
+
display: (c) => (c.triggerOnCompletion ? "on" : "off"),
|
|
52
|
+
cycle: (c) => {
|
|
53
|
+
c.triggerOnCompletion = !c.triggerOnCompletion;
|
|
54
|
+
},
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
key: "delegate.extensionMode",
|
|
58
|
+
label: "Delegate mode",
|
|
59
|
+
display: (c) => c.delegate.extensionMode,
|
|
60
|
+
cycle: (c) => {
|
|
61
|
+
c.delegate.extensionMode = c.delegate.extensionMode === "isolated" ? "ambient" : "isolated";
|
|
62
|
+
},
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
key: "delegate.autoDeliver",
|
|
66
|
+
label: "Delegate auto-deliver",
|
|
67
|
+
display: (c) => c.delegate.autoDeliver,
|
|
68
|
+
cycle: (c) => {
|
|
69
|
+
const order = ["never", "when_small", "always"] as const;
|
|
70
|
+
const index = order.indexOf(c.delegate.autoDeliver);
|
|
71
|
+
c.delegate.autoDeliver = order[(index + 1) % order.length];
|
|
72
|
+
},
|
|
73
|
+
},
|
|
74
|
+
];
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Render the background-tasks settings overlay.
|
|
78
|
+
*/
|
|
79
|
+
export function renderBackgroundTasksSettingsOverlay(params?: {
|
|
80
|
+
cwd?: string;
|
|
81
|
+
onComplete?: () => void;
|
|
82
|
+
}) {
|
|
83
|
+
return (
|
|
84
|
+
tui: TUI,
|
|
85
|
+
theme: Theme,
|
|
86
|
+
_kb: KeybindingsManager,
|
|
87
|
+
done: (result: { action?: string } | null) => void,
|
|
88
|
+
) => {
|
|
89
|
+
const cwd = params?.cwd ?? process.cwd();
|
|
90
|
+
const loaded = loadBackgroundTasksConfig(cwd);
|
|
91
|
+
// Edit a working copy; save is explicit and atomic.
|
|
92
|
+
let config: BackgroundTasksConfig = structuredClone(loaded.config);
|
|
93
|
+
let selectedIndex = 0;
|
|
94
|
+
let dirty = false;
|
|
95
|
+
|
|
96
|
+
// Width-keyed so a terminal resize can never serve stale, over-wide lines.
|
|
97
|
+
const lineCache = new WidthKeyedCache();
|
|
98
|
+
|
|
99
|
+
function refresh() {
|
|
100
|
+
lineCache.clear();
|
|
101
|
+
tui.requestRender();
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
function handleInput(data: string) {
|
|
105
|
+
if (matchesKey(data, Key.escape) || data === "q") {
|
|
106
|
+
done(null);
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
if (matchesKey(data, Key.up) || data === "k") {
|
|
111
|
+
if (selectedIndex > 0) {
|
|
112
|
+
selectedIndex--;
|
|
113
|
+
refresh();
|
|
114
|
+
}
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
if (matchesKey(data, Key.down) || data === "j") {
|
|
119
|
+
if (selectedIndex < ROWS.length - 1) {
|
|
120
|
+
selectedIndex++;
|
|
121
|
+
refresh();
|
|
122
|
+
}
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
// Space/enter: cycle the selected value.
|
|
127
|
+
if (data === " " || data === "\r") {
|
|
128
|
+
ROWS[selectedIndex]?.cycle(config);
|
|
129
|
+
dirty = true;
|
|
130
|
+
refresh();
|
|
131
|
+
return;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
// s: save
|
|
135
|
+
if (data === "s") {
|
|
136
|
+
try {
|
|
137
|
+
saveGlobalBackgroundTasksConfig(config);
|
|
138
|
+
dirty = false;
|
|
139
|
+
} catch {
|
|
140
|
+
// Save failures are non-fatal; keep the overlay open.
|
|
141
|
+
}
|
|
142
|
+
refresh();
|
|
143
|
+
return;
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
function padVisible(content: string, targetWidth: number): string {
|
|
148
|
+
const vw = visibleWidth(content);
|
|
149
|
+
const pad = Math.max(0, targetWidth - vw);
|
|
150
|
+
return content + " ".repeat(pad);
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
function render(rawWidth: number): string[] {
|
|
154
|
+
const width = normalizeWidth(rawWidth);
|
|
155
|
+
const cached = lineCache.get(width);
|
|
156
|
+
if (cached) return cached;
|
|
157
|
+
|
|
158
|
+
const lines: string[] = [];
|
|
159
|
+
const innerWidth = normalizeWidth(width) - 2;
|
|
160
|
+
|
|
161
|
+
const header = " Background Tasks Settings ";
|
|
162
|
+
const stateLabel = dirty ? theme.fg("warning", "● unsaved") : theme.fg("success", "● saved");
|
|
163
|
+
const headerPad = Math.max(0, innerWidth - visibleWidth(header) - 12);
|
|
164
|
+
lines.push(theme.fg("accent", `╭${"─".repeat(innerWidth)}╮`));
|
|
165
|
+
lines.push(
|
|
166
|
+
theme.fg("accent", "│") +
|
|
167
|
+
theme.bold(header) +
|
|
168
|
+
theme.fg("accent", " ".repeat(headerPad)) +
|
|
169
|
+
stateLabel +
|
|
170
|
+
theme.fg("accent", "│"),
|
|
171
|
+
);
|
|
172
|
+
lines.push(theme.fg("accent", `├${"─".repeat(innerWidth)}┤`));
|
|
173
|
+
|
|
174
|
+
for (let i = 0; i < ROWS.length; i++) {
|
|
175
|
+
const row = ROWS[i];
|
|
176
|
+
const selected = i === selectedIndex;
|
|
177
|
+
const prefix = selected ? theme.fg("accent", "▸ ") : " ";
|
|
178
|
+
const label = selected ? theme.bold(row.label) : theme.fg("text", row.label);
|
|
179
|
+
const rawValue = row.display(config);
|
|
180
|
+
const value =
|
|
181
|
+
rawValue === "off" || rawValue === "never"
|
|
182
|
+
? theme.fg("error", rawValue)
|
|
183
|
+
: rawValue === "on"
|
|
184
|
+
? theme.fg("success", rawValue)
|
|
185
|
+
: theme.fg("accent", rawValue);
|
|
186
|
+
const line = ` ${prefix}${label} ${theme.fg("muted", "─")} ${value}`;
|
|
187
|
+
lines.push(
|
|
188
|
+
theme.fg("accent", "│") +
|
|
189
|
+
padVisible(truncateToWidth(line, innerWidth), innerWidth) +
|
|
190
|
+
theme.fg("accent", "│"),
|
|
191
|
+
);
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
lines.push(theme.fg("accent", `├${"─".repeat(innerWidth)}┤`));
|
|
195
|
+
const binds = " ↑↓ select Space cycle s save q/Esc close";
|
|
196
|
+
lines.push(
|
|
197
|
+
theme.fg("accent", "│") +
|
|
198
|
+
padVisible(theme.fg("muted", truncateToWidth(binds, innerWidth)), innerWidth) +
|
|
199
|
+
theme.fg("accent", "│"),
|
|
200
|
+
);
|
|
201
|
+
lines.push(theme.fg("accent", "╰" + "─".repeat(innerWidth) + "╯"));
|
|
202
|
+
|
|
203
|
+
return lineCache.set(width, lines);
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
return { render, invalidate: refresh, handleInput };
|
|
207
|
+
};
|
|
208
|
+
}
|