@marcoscale98/pi-extensible-workflows 5.14.1-fork.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/CHANGELOG.md +536 -0
- package/README.md +64 -0
- package/dist/src/agent-execution.d.ts +338 -0
- package/dist/src/agent-execution.js +1633 -0
- package/dist/src/background-widget.d.ts +74 -0
- package/dist/src/background-widget.js +1340 -0
- package/dist/src/budget.d.ts +38 -0
- package/dist/src/budget.js +188 -0
- package/dist/src/changelog.d.ts +6 -0
- package/dist/src/changelog.js +112 -0
- package/dist/src/decoders.d.ts +96 -0
- package/dist/src/decoders.js +629 -0
- package/dist/src/execution.d.ts +19 -0
- package/dist/src/execution.js +749 -0
- package/dist/src/herdr.d.ts +53 -0
- package/dist/src/herdr.js +270 -0
- package/dist/src/host-delivery.d.ts +95 -0
- package/dist/src/host-delivery.js +376 -0
- package/dist/src/host-navigator.d.ts +83 -0
- package/dist/src/host-navigator.js +1087 -0
- package/dist/src/host-phases.d.ts +89 -0
- package/dist/src/host-phases.js +320 -0
- package/dist/src/host-recovery.d.ts +141 -0
- package/dist/src/host-recovery.js +356 -0
- package/dist/src/host-runtime.d.ts +78 -0
- package/dist/src/host-runtime.js +378 -0
- package/dist/src/host-view.d.ts +116 -0
- package/dist/src/host-view.js +868 -0
- package/dist/src/host.d.ts +40 -0
- package/dist/src/host.js +1641 -0
- package/dist/src/index.d.ts +29 -0
- package/dist/src/index.js +13725 -0
- package/dist/src/index.js.map +6 -0
- package/dist/src/io.d.ts +14 -0
- package/dist/src/io.js +82 -0
- package/dist/src/package-identity.d.ts +4 -0
- package/dist/src/package-identity.js +6 -0
- package/dist/src/paths.d.ts +14 -0
- package/dist/src/paths.js +51 -0
- package/dist/src/persistence.d.ts +5 -0
- package/dist/src/persistence.js +5 -0
- package/dist/src/pi-runtime-adapter.d.ts +27 -0
- package/dist/src/pi-runtime-adapter.js +243 -0
- package/dist/src/pi-runtime-runner.d.ts +42 -0
- package/dist/src/pi-runtime-runner.js +505 -0
- package/dist/src/registry.d.ts +48 -0
- package/dist/src/registry.js +379 -0
- package/dist/src/retention.d.ts +17 -0
- package/dist/src/retention.js +195 -0
- package/dist/src/runtime/agent-runner.d.ts +143 -0
- package/dist/src/runtime/agent-runner.js +12 -0
- package/dist/src/runtime/index.d.ts +2 -0
- package/dist/src/runtime/index.js +2 -0
- package/dist/src/runtime/namespace.d.ts +14 -0
- package/dist/src/runtime/namespace.js +1 -0
- package/dist/src/runtime/workflow-result.d.ts +2 -0
- package/dist/src/runtime/workflow-result.js +6 -0
- package/dist/src/session-handoff.d.ts +2 -0
- package/dist/src/session-handoff.js +82 -0
- package/dist/src/session-lease.d.ts +12 -0
- package/dist/src/session-lease.js +180 -0
- package/dist/src/store.d.ts +95 -0
- package/dist/src/store.js +951 -0
- package/dist/src/subagent-manager-handle.d.ts +4 -0
- package/dist/src/subagent-manager-handle.js +6 -0
- package/dist/src/tool-timing.d.ts +12 -0
- package/dist/src/tool-timing.js +33 -0
- package/dist/src/trajectory-contracts.d.ts +8 -0
- package/dist/src/trajectory-contracts.js +9 -0
- package/dist/src/trajectory-host-handle.d.ts +12 -0
- package/dist/src/trajectory-host-handle.js +6 -0
- package/dist/src/trajectory.d.ts +128 -0
- package/dist/src/trajectory.js +594 -0
- package/dist/src/types.d.ts +960 -0
- package/dist/src/types.js +60 -0
- package/dist/src/utils.d.ts +57 -0
- package/dist/src/utils.js +225 -0
- package/dist/src/validation.d.ts +29 -0
- package/dist/src/validation.js +1100 -0
- package/dist/src/workflow-artifacts.d.ts +14 -0
- package/dist/src/workflow-artifacts.js +40 -0
- package/dist/starter/index.d.ts +1 -0
- package/dist/starter/index.js +103 -0
- package/dist/starter/index.js.map +6 -0
- package/dist/starter/review-loop.d.ts +72 -0
- package/dist/starter/review-loop.js +43 -0
- package/dist/starter/roles/developer.md +6 -0
- package/dist/starter/roles/oracle.md +18 -0
- package/dist/starter/roles/researcher.md +20 -0
- package/dist/starter/roles/reviewer.md +19 -0
- package/dist/starter/roles/scout.md +18 -0
- package/dist/subagents/index.d.ts +8 -0
- package/dist/subagents/index.js +8021 -0
- package/dist/subagents/index.js.map +6 -0
- package/dist/subagents/src/contracts.d.ts +173 -0
- package/dist/subagents/src/contracts.js +68 -0
- package/dist/subagents/src/decode.d.ts +15 -0
- package/dist/subagents/src/decode.js +182 -0
- package/dist/subagents/src/index.d.ts +12 -0
- package/dist/subagents/src/index.js +180 -0
- package/dist/subagents/src/manager.d.ts +3 -0
- package/dist/subagents/src/manager.js +1636 -0
- package/dist/subagents/src/navigator.d.ts +5 -0
- package/dist/subagents/src/navigator.js +627 -0
- package/dist/subagents/src/view.d.ts +70 -0
- package/dist/subagents/src/view.js +387 -0
- package/dist/subagents/src/worktree.d.ts +34 -0
- package/dist/subagents/src/worktree.js +68 -0
- package/dist/trajectory/assets/favicon.png +0 -0
- package/dist/trajectory/assets/index.html +772 -0
- package/dist/trajectory/assets/marked.min.js +6 -0
- package/dist/trajectory/assets/morphdom.min.js +1 -0
- package/dist/trajectory/index.d.ts +5 -0
- package/dist/trajectory/index.js +3459 -0
- package/dist/trajectory/index.js.map +6 -0
- package/dist/trajectory/src/assets/favicon.png +0 -0
- package/dist/trajectory/src/assets/index.html +772 -0
- package/dist/trajectory/src/assets/marked.min.js +6 -0
- package/dist/trajectory/src/assets/morphdom.min.js +1 -0
- package/dist/trajectory/src/export.d.ts +25 -0
- package/dist/trajectory/src/export.js +80 -0
- package/dist/trajectory/src/index.d.ts +26 -0
- package/dist/trajectory/src/index.js +732 -0
- package/dist/trajectory/src/server.d.ts +7 -0
- package/dist/trajectory/src/server.js +2534 -0
- package/dist/trajectory/src/server.js.map +6 -0
- package/examples/advanced-patterns/auto-model-router.mjs +78 -0
- package/examples/workflow-extension-template/README.md +37 -0
- package/examples/workflow-extension-template/extension.test.mjs +59 -0
- package/examples/workflow-extension-template/index.js +51 -0
- package/examples/workflow-extension-template/roles/reviewer.md +4 -0
- package/package.json +105 -0
- package/skills/pi-extensible-workflows/SKILL.md +160 -0
- package/src/agent-execution.ts +1533 -0
- package/src/background-widget.ts +1496 -0
- package/src/budget.ts +109 -0
- package/src/changelog.ts +114 -0
- package/src/decoders.ts +567 -0
- package/src/execution.ts +652 -0
- package/src/herdr.ts +240 -0
- package/src/host-delivery.ts +346 -0
- package/src/host-navigator.ts +871 -0
- package/src/host-phases.ts +264 -0
- package/src/host-recovery.ts +333 -0
- package/src/host-runtime.ts +373 -0
- package/src/host-view.ts +828 -0
- package/src/host.ts +1502 -0
- package/src/index.ts +29 -0
- package/src/io.ts +73 -0
- package/src/package-identity.ts +7 -0
- package/src/paths.ts +49 -0
- package/src/persistence.ts +11 -0
- package/src/pi-runtime-adapter.ts +247 -0
- package/src/pi-runtime-runner.ts +436 -0
- package/src/registry.ts +321 -0
- package/src/retention.ts +178 -0
- package/src/runtime/agent-runner.ts +158 -0
- package/src/runtime/index.ts +2 -0
- package/src/runtime/namespace.ts +16 -0
- package/src/runtime/workflow-result.ts +8 -0
- package/src/session-handoff.ts +78 -0
- package/src/session-lease.ts +125 -0
- package/src/store.ts +832 -0
- package/src/subagent-manager-handle.ts +8 -0
- package/src/tool-timing.ts +47 -0
- package/src/trajectory-contracts.ts +13 -0
- package/src/trajectory-host-handle.ts +16 -0
- package/src/trajectory.ts +543 -0
- package/src/types.ts +374 -0
- package/src/utils.ts +192 -0
- package/src/validation.ts +910 -0
- package/src/workflow-artifacts.ts +35 -0
- package/starter/index.ts +35 -0
- package/starter/prompts/council.md +16 -0
- package/starter/prompts/deep-research.md +16 -0
- package/starter/prompts/oracle.md +14 -0
- package/starter/prompts/parallel-review.md +22 -0
- package/starter/prompts/parallel-scout.md +16 -0
- package/starter/prompts/review-loop.md +14 -0
- package/starter/prompts/review.md +14 -0
- package/starter/prompts/scout.md +14 -0
- package/starter/review-loop.ts +73 -0
- package/starter/roles/developer.md +6 -0
- package/starter/roles/oracle.md +18 -0
- package/starter/roles/researcher.md +20 -0
- package/starter/roles/reviewer.md +19 -0
- package/starter/roles/scout.md +18 -0
- package/subagents/README.md +145 -0
- package/subagents/index.ts +8 -0
- package/subagents/src/contracts.ts +176 -0
- package/subagents/src/decode.ts +158 -0
- package/subagents/src/index.ts +194 -0
- package/subagents/src/manager.ts +1560 -0
- package/subagents/src/navigator.ts +488 -0
- package/subagents/src/view.ts +376 -0
- package/subagents/src/worktree.ts +99 -0
- package/trajectory/index.ts +5 -0
- package/trajectory/src/assets/favicon.png +0 -0
- package/trajectory/src/assets/index.html +772 -0
- package/trajectory/src/assets/marked.min.js +6 -0
- package/trajectory/src/assets/morphdom.min.js +1 -0
- package/trajectory/src/export.ts +85 -0
- package/trajectory/src/index.ts +604 -0
- package/trajectory/src/server.ts +447 -0
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
export type RuntimeJsonValue = null | boolean | number | string | RuntimeJsonValue[] | {
|
|
2
|
+
[key: string]: RuntimeJsonValue;
|
|
3
|
+
};
|
|
4
|
+
export type RuntimeJsonSchema = {
|
|
5
|
+
[key: string]: RuntimeJsonValue;
|
|
6
|
+
};
|
|
7
|
+
export interface RuntimeModel {
|
|
8
|
+
readonly provider: string;
|
|
9
|
+
readonly model: string;
|
|
10
|
+
readonly thinking?: "off" | "minimal" | "low" | "medium" | "high" | "xhigh" | "max";
|
|
11
|
+
}
|
|
12
|
+
export interface RuntimeToolCall {
|
|
13
|
+
readonly id: string;
|
|
14
|
+
readonly input: RuntimeJsonValue;
|
|
15
|
+
readonly signal: AbortSignal;
|
|
16
|
+
}
|
|
17
|
+
export interface RuntimeToolResult {
|
|
18
|
+
readonly value: RuntimeJsonValue;
|
|
19
|
+
readonly isError?: boolean;
|
|
20
|
+
}
|
|
21
|
+
export interface RuntimeTool {
|
|
22
|
+
readonly name: string;
|
|
23
|
+
readonly description: string;
|
|
24
|
+
readonly parameters: RuntimeJsonSchema;
|
|
25
|
+
execute(call: RuntimeToolCall): Promise<RuntimeToolResult>;
|
|
26
|
+
}
|
|
27
|
+
export type RuntimeUsageAvailability = "complete" | "partial" | "unavailable";
|
|
28
|
+
export interface RuntimeUsage {
|
|
29
|
+
readonly availability: RuntimeUsageAvailability;
|
|
30
|
+
readonly input?: number;
|
|
31
|
+
readonly output?: number;
|
|
32
|
+
readonly cacheRead?: number;
|
|
33
|
+
readonly cacheWrite?: number;
|
|
34
|
+
readonly costUsd?: number;
|
|
35
|
+
}
|
|
36
|
+
export type RuntimeAgentProviderRecovery = "retry" | "abort" | {
|
|
37
|
+
readonly model: string;
|
|
38
|
+
};
|
|
39
|
+
export interface RuntimeAgentProviderFailure {
|
|
40
|
+
readonly provider: string;
|
|
41
|
+
readonly model: string;
|
|
42
|
+
readonly error: string;
|
|
43
|
+
}
|
|
44
|
+
export declare class RuntimeAgentProviderError extends Error {
|
|
45
|
+
readonly failure: RuntimeAgentProviderFailure;
|
|
46
|
+
readonly recovery: RuntimeAgentProviderRecovery | undefined;
|
|
47
|
+
readonly handled: boolean;
|
|
48
|
+
constructor(failure: RuntimeAgentProviderFailure, recovery: RuntimeAgentProviderRecovery | undefined, handled: boolean);
|
|
49
|
+
}
|
|
50
|
+
export interface RuntimeAgentIdentity {
|
|
51
|
+
readonly id: string;
|
|
52
|
+
readonly structuralPath: readonly string[];
|
|
53
|
+
readonly parentId?: string;
|
|
54
|
+
}
|
|
55
|
+
export interface RuntimeRunIdentity {
|
|
56
|
+
readonly id: string;
|
|
57
|
+
readonly namespaceId: string;
|
|
58
|
+
readonly workflowName: string;
|
|
59
|
+
}
|
|
60
|
+
export interface RuntimeAgentState {
|
|
61
|
+
readonly model: RuntimeModel;
|
|
62
|
+
readonly thinking?: RuntimeModel["thinking"];
|
|
63
|
+
readonly tools: readonly string[];
|
|
64
|
+
readonly systemPrompt?: string;
|
|
65
|
+
}
|
|
66
|
+
export interface RuntimeToolCallProgress {
|
|
67
|
+
readonly id: string;
|
|
68
|
+
readonly name: string;
|
|
69
|
+
readonly state: "running" | "completed" | "failed";
|
|
70
|
+
}
|
|
71
|
+
export type RuntimeHandoffState = "local-running" | "takeover-pending" | "remote-running" | "returning-local" | "completed";
|
|
72
|
+
export interface RuntimeAgentHandoff {
|
|
73
|
+
readonly state: RuntimeHandoffState;
|
|
74
|
+
readonly transferred: boolean;
|
|
75
|
+
observe(event: {
|
|
76
|
+
readonly type: string;
|
|
77
|
+
}): void;
|
|
78
|
+
request(launch: () => Promise<void>): Promise<void>;
|
|
79
|
+
waitForTakeover(): Promise<void>;
|
|
80
|
+
takeover(): void;
|
|
81
|
+
waitForResume(): Promise<void>;
|
|
82
|
+
release(reason?: string): void;
|
|
83
|
+
}
|
|
84
|
+
export interface RuntimeAgentRunControl {
|
|
85
|
+
readonly handoff?: RuntimeAgentHandoff;
|
|
86
|
+
steer(message: string): Promise<void>;
|
|
87
|
+
}
|
|
88
|
+
export interface RuntimeAgentProgress {
|
|
89
|
+
readonly usage: RuntimeUsage;
|
|
90
|
+
readonly toolCalls: readonly RuntimeToolCallProgress[];
|
|
91
|
+
readonly state?: RuntimeAgentState;
|
|
92
|
+
readonly activity?: {
|
|
93
|
+
readonly kind: "reasoning" | "tool" | "text";
|
|
94
|
+
readonly text: string;
|
|
95
|
+
};
|
|
96
|
+
readonly lastEventAt?: number;
|
|
97
|
+
readonly persist: boolean;
|
|
98
|
+
}
|
|
99
|
+
export interface RuntimeAgentTurnPolicy {
|
|
100
|
+
beforeTurn(): void;
|
|
101
|
+
afterTurn(usage: RuntimeUsage, final: boolean, requestInstruction?: boolean): string | undefined;
|
|
102
|
+
}
|
|
103
|
+
export interface RuntimeAgentRunRequest {
|
|
104
|
+
readonly task: string;
|
|
105
|
+
readonly cwd: string;
|
|
106
|
+
readonly model: RuntimeModel;
|
|
107
|
+
readonly enabledTools: readonly string[];
|
|
108
|
+
/** Tools owned by the runtime runner; host-specific adapters may map them at session creation. */
|
|
109
|
+
readonly customTools: readonly RuntimeTool[];
|
|
110
|
+
/** Explicit result schema; omitted agents use the default string workflow_result schema. */
|
|
111
|
+
readonly resultSchema?: RuntimeJsonSchema;
|
|
112
|
+
readonly run: RuntimeRunIdentity;
|
|
113
|
+
readonly agent: RuntimeAgentIdentity;
|
|
114
|
+
readonly signal: AbortSignal;
|
|
115
|
+
readonly timeoutMs?: number | null;
|
|
116
|
+
readonly onProgress?: (progress: RuntimeAgentProgress) => void | Promise<void>;
|
|
117
|
+
readonly handoff?: RuntimeAgentHandoff;
|
|
118
|
+
readonly onControl?: (control: RuntimeAgentRunControl) => void | Promise<void>;
|
|
119
|
+
readonly turnPolicy?: RuntimeAgentTurnPolicy;
|
|
120
|
+
readonly onProviderError?: (failure: RuntimeAgentProviderFailure) => Promise<RuntimeAgentProviderRecovery>;
|
|
121
|
+
readonly onProviderLimit?: () => Promise<void>;
|
|
122
|
+
}
|
|
123
|
+
export interface RuntimeAgentReference {
|
|
124
|
+
readonly transport: string;
|
|
125
|
+
readonly locator?: RuntimeJsonValue;
|
|
126
|
+
}
|
|
127
|
+
export interface RuntimeAgentRunResult {
|
|
128
|
+
/** The accepted workflow_result string for unstructured agents, or schema value when resultSchema was requested. */
|
|
129
|
+
readonly value: RuntimeJsonValue;
|
|
130
|
+
readonly usage: RuntimeUsage;
|
|
131
|
+
readonly reference?: RuntimeAgentReference;
|
|
132
|
+
}
|
|
133
|
+
export interface RuntimeAgentRunner {
|
|
134
|
+
readonly id: string;
|
|
135
|
+
readonly capabilities: {
|
|
136
|
+
readonly customTools: boolean;
|
|
137
|
+
readonly structuredResults: boolean;
|
|
138
|
+
readonly steering: boolean;
|
|
139
|
+
readonly handoff: boolean;
|
|
140
|
+
readonly usage: RuntimeUsageAvailability;
|
|
141
|
+
};
|
|
142
|
+
run(request: Readonly<RuntimeAgentRunRequest>): Promise<RuntimeAgentRunResult>;
|
|
143
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export class RuntimeAgentProviderError extends Error {
|
|
2
|
+
failure;
|
|
3
|
+
recovery;
|
|
4
|
+
handled;
|
|
5
|
+
constructor(failure, recovery, handled) {
|
|
6
|
+
super(failure.error);
|
|
7
|
+
this.failure = failure;
|
|
8
|
+
this.recovery = recovery;
|
|
9
|
+
this.handled = handled;
|
|
10
|
+
this.name = "RuntimeAgentProviderError";
|
|
11
|
+
}
|
|
12
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export interface WorkflowNamespace {
|
|
2
|
+
readonly id: string;
|
|
3
|
+
readonly projectKey: string;
|
|
4
|
+
readonly cwd: string;
|
|
5
|
+
readonly storageRoot?: string;
|
|
6
|
+
}
|
|
7
|
+
export interface WorkflowLease {
|
|
8
|
+
readonly active: boolean;
|
|
9
|
+
release(): Promise<void>;
|
|
10
|
+
}
|
|
11
|
+
export interface WorkflowLeaseProvider {
|
|
12
|
+
acquire(namespace: Readonly<WorkflowNamespace>): Promise<WorkflowLease>;
|
|
13
|
+
isHeld(namespace: Readonly<WorkflowNamespace>): Promise<boolean>;
|
|
14
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { isTurnActivityStart, isTurnBoundaryEnd } from "./pi-runtime-adapter.js";
|
|
2
|
+
export function createLiveSessionHandoff() {
|
|
3
|
+
let state = "local-running";
|
|
4
|
+
let turnActive = false;
|
|
5
|
+
let boundary;
|
|
6
|
+
let resolveBoundary;
|
|
7
|
+
let takeover;
|
|
8
|
+
let resolveTakeover;
|
|
9
|
+
let takenOver = false;
|
|
10
|
+
let resume;
|
|
11
|
+
let resolveResume;
|
|
12
|
+
let request;
|
|
13
|
+
const waitForBoundary = () => {
|
|
14
|
+
if (!turnActive)
|
|
15
|
+
return Promise.resolve();
|
|
16
|
+
boundary ??= new Promise((resolve) => { resolveBoundary = resolve; });
|
|
17
|
+
return boundary;
|
|
18
|
+
};
|
|
19
|
+
const finishBoundary = () => {
|
|
20
|
+
turnActive = false;
|
|
21
|
+
resolveBoundary?.();
|
|
22
|
+
boundary = undefined;
|
|
23
|
+
resolveBoundary = undefined;
|
|
24
|
+
};
|
|
25
|
+
const finishTakeover = () => {
|
|
26
|
+
takenOver = true;
|
|
27
|
+
state = "herdr-running";
|
|
28
|
+
resolveTakeover?.();
|
|
29
|
+
resolveTakeover = undefined;
|
|
30
|
+
};
|
|
31
|
+
const isReleased = () => state === "completed";
|
|
32
|
+
return {
|
|
33
|
+
get state() { return state; },
|
|
34
|
+
get transferred() { return takenOver; },
|
|
35
|
+
observe(event) {
|
|
36
|
+
if (isTurnActivityStart(event.type))
|
|
37
|
+
turnActive = true;
|
|
38
|
+
if (isTurnBoundaryEnd(event.type))
|
|
39
|
+
finishBoundary();
|
|
40
|
+
},
|
|
41
|
+
async request(launch) {
|
|
42
|
+
if (request)
|
|
43
|
+
return request;
|
|
44
|
+
if (isReleased())
|
|
45
|
+
return;
|
|
46
|
+
state = "handoff-pending";
|
|
47
|
+
takeover = new Promise((resolve) => { resolveTakeover = resolve; });
|
|
48
|
+
resume = new Promise((resolve) => { resolveResume = resolve; });
|
|
49
|
+
request = (async () => {
|
|
50
|
+
await waitForBoundary();
|
|
51
|
+
if (isReleased())
|
|
52
|
+
return;
|
|
53
|
+
state = "herdr-running";
|
|
54
|
+
try {
|
|
55
|
+
await launch();
|
|
56
|
+
}
|
|
57
|
+
finally {
|
|
58
|
+
if (!takenOver) {
|
|
59
|
+
state = "returning-local";
|
|
60
|
+
resolveTakeover?.();
|
|
61
|
+
resolveTakeover = undefined;
|
|
62
|
+
}
|
|
63
|
+
resolveResume?.();
|
|
64
|
+
state = "completed";
|
|
65
|
+
}
|
|
66
|
+
})();
|
|
67
|
+
return request;
|
|
68
|
+
},
|
|
69
|
+
waitForTakeover() { return takeover ?? Promise.resolve(); },
|
|
70
|
+
takeover() { if (state === "herdr-running" && !takenOver)
|
|
71
|
+
finishTakeover(); },
|
|
72
|
+
waitForResume() { return resume ?? Promise.resolve(); },
|
|
73
|
+
release() {
|
|
74
|
+
state = "completed";
|
|
75
|
+
finishBoundary();
|
|
76
|
+
resolveTakeover?.();
|
|
77
|
+
resolveTakeover = undefined;
|
|
78
|
+
resolveResume?.();
|
|
79
|
+
resolveResume = undefined;
|
|
80
|
+
},
|
|
81
|
+
};
|
|
82
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export declare function processAlive(pid: number, startedAt?: number): Promise<boolean>;
|
|
2
|
+
export declare function hasLiveSessionLease(cwd: string, sessionId: string, home?: string): Promise<boolean>;
|
|
3
|
+
export declare class SessionLease {
|
|
4
|
+
#private;
|
|
5
|
+
readonly path: string;
|
|
6
|
+
readonly token: string;
|
|
7
|
+
constructor(path: string, token: string);
|
|
8
|
+
get active(): boolean;
|
|
9
|
+
release(): Promise<void>;
|
|
10
|
+
}
|
|
11
|
+
export declare function acquireSessionLease(cwd: string, sessionId: string, home?: string): Promise<SessionLease>;
|
|
12
|
+
export declare function listRunIds(cwd: string, sessionId: string, home?: string, cleanTemps?: boolean): Promise<string[]>;
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
import { randomUUID } from "node:crypto";
|
|
2
|
+
import { link, mkdir, open, readFile, readdir, rename, rm, stat } from "node:fs/promises";
|
|
3
|
+
import { homedir } from "node:os";
|
|
4
|
+
import { join } from "node:path";
|
|
5
|
+
import { WorkflowError } from "./types.js";
|
|
6
|
+
import { isNodeError } from "./utils.js";
|
|
7
|
+
import { decodeSessionOwner } from "./decoders.js";
|
|
8
|
+
import { json } from "./io.js";
|
|
9
|
+
import { runsDirectory } from "./paths.js";
|
|
10
|
+
const SESSION_OWNER_FILE = "owner.json";
|
|
11
|
+
const SESSION_OWNER_WRITE_GRACE_MS = 30_000;
|
|
12
|
+
const RUN_CREATE_TEMP = /^\.([a-zA-Z0-9._-]+)\.(\d+)\.[0-9a-f-]+\.tmp$/;
|
|
13
|
+
export async function processAlive(pid, startedAt) {
|
|
14
|
+
try {
|
|
15
|
+
process.kill(pid, 0);
|
|
16
|
+
}
|
|
17
|
+
catch (error) {
|
|
18
|
+
return !isNodeError(error, "ESRCH");
|
|
19
|
+
}
|
|
20
|
+
if (startedAt !== undefined && process.platform === "linux") {
|
|
21
|
+
try {
|
|
22
|
+
if ((await stat(`/proc/${String(pid)}`)).ctimeMs > startedAt)
|
|
23
|
+
return false;
|
|
24
|
+
}
|
|
25
|
+
catch (error) {
|
|
26
|
+
if (isNodeError(error, "ENOENT"))
|
|
27
|
+
return false;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
return true;
|
|
31
|
+
}
|
|
32
|
+
export async function hasLiveSessionLease(cwd, sessionId, home = homedir()) {
|
|
33
|
+
const path = join(runsDirectory(cwd, sessionId, home), SESSION_OWNER_FILE);
|
|
34
|
+
let owner;
|
|
35
|
+
try {
|
|
36
|
+
owner = await json(path);
|
|
37
|
+
}
|
|
38
|
+
catch (error) {
|
|
39
|
+
if (isNodeError(error, "ENOENT"))
|
|
40
|
+
return false;
|
|
41
|
+
throw error;
|
|
42
|
+
}
|
|
43
|
+
const candidate = decodeSessionOwner(owner);
|
|
44
|
+
if (!candidate)
|
|
45
|
+
throw new WorkflowError("RUN_OWNED", `Pi session ${sessionId} has an invalid ownership lease`);
|
|
46
|
+
return processAlive(candidate.pid, candidate.startedAt);
|
|
47
|
+
}
|
|
48
|
+
function sameOwner(left, right) {
|
|
49
|
+
if (left === undefined || right === undefined)
|
|
50
|
+
return false;
|
|
51
|
+
return left.pid === right.pid && left.token === right.token;
|
|
52
|
+
}
|
|
53
|
+
async function restoreLease(path, stale) {
|
|
54
|
+
try {
|
|
55
|
+
await link(stale, path);
|
|
56
|
+
}
|
|
57
|
+
catch (error) {
|
|
58
|
+
if (!isNodeError(error, "EEXIST") && !isNodeError(error, "ENOENT"))
|
|
59
|
+
throw error;
|
|
60
|
+
}
|
|
61
|
+
await rm(stale, { force: true });
|
|
62
|
+
}
|
|
63
|
+
async function cleanupRunTemps(directory, entries) {
|
|
64
|
+
await Promise.all(entries.map(async (entry) => {
|
|
65
|
+
const match = entry.isDirectory() ? RUN_CREATE_TEMP.exec(entry.name) : undefined;
|
|
66
|
+
const pid = match?.[2] ? Number(match[2]) : undefined;
|
|
67
|
+
if (pid && !await processAlive(pid))
|
|
68
|
+
await rm(join(directory, entry.name), { recursive: true, force: true });
|
|
69
|
+
}));
|
|
70
|
+
}
|
|
71
|
+
export class SessionLease {
|
|
72
|
+
path;
|
|
73
|
+
token;
|
|
74
|
+
#released = false;
|
|
75
|
+
constructor(path, token) {
|
|
76
|
+
this.path = path;
|
|
77
|
+
this.token = token;
|
|
78
|
+
}
|
|
79
|
+
get active() { return !this.#released; }
|
|
80
|
+
async release() {
|
|
81
|
+
if (this.#released)
|
|
82
|
+
return;
|
|
83
|
+
this.#released = true;
|
|
84
|
+
try {
|
|
85
|
+
const owner = decodeSessionOwner(await json(this.path));
|
|
86
|
+
if (owner?.token === this.token)
|
|
87
|
+
await rm(this.path, { force: true });
|
|
88
|
+
}
|
|
89
|
+
catch (error) {
|
|
90
|
+
if (!isNodeError(error, "ENOENT"))
|
|
91
|
+
throw error;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
export async function acquireSessionLease(cwd, sessionId, home = homedir()) {
|
|
96
|
+
const directory = runsDirectory(cwd, sessionId, home);
|
|
97
|
+
await mkdir(directory, { recursive: true, mode: 0o700 });
|
|
98
|
+
const path = join(directory, SESSION_OWNER_FILE);
|
|
99
|
+
for (;;) {
|
|
100
|
+
const token = randomUUID();
|
|
101
|
+
const owner = { pid: process.pid, token, startedAt: process.platform === "linux" ? (await stat(`/proc/${String(process.pid)}`)).ctimeMs : Date.now() };
|
|
102
|
+
try {
|
|
103
|
+
const handle = await open(path, "wx", 0o600);
|
|
104
|
+
try {
|
|
105
|
+
await handle.writeFile(`${JSON.stringify(owner)}\n`, "utf8");
|
|
106
|
+
}
|
|
107
|
+
finally {
|
|
108
|
+
await handle.close();
|
|
109
|
+
}
|
|
110
|
+
return new SessionLease(path, token);
|
|
111
|
+
}
|
|
112
|
+
catch (error) {
|
|
113
|
+
if (!isNodeError(error, "EEXIST"))
|
|
114
|
+
throw error;
|
|
115
|
+
let existingOwner;
|
|
116
|
+
let existingText = "";
|
|
117
|
+
try {
|
|
118
|
+
existingText = await readFile(path, "utf8");
|
|
119
|
+
existingOwner = decodeSessionOwner(JSON.parse(existingText));
|
|
120
|
+
if (existingOwner && await processAlive(existingOwner.pid, existingOwner.startedAt))
|
|
121
|
+
throw new WorkflowError("RUN_OWNED", `Pi session ${sessionId} is already owned by process ${String(existingOwner.pid)}`);
|
|
122
|
+
}
|
|
123
|
+
catch (readError) {
|
|
124
|
+
if (readError instanceof WorkflowError)
|
|
125
|
+
throw readError;
|
|
126
|
+
if (isNodeError(readError, "ENOENT"))
|
|
127
|
+
continue;
|
|
128
|
+
existingOwner = undefined;
|
|
129
|
+
}
|
|
130
|
+
if (existingOwner === undefined) {
|
|
131
|
+
const age = await stat(path).then((value) => Date.now() - value.mtimeMs).catch(() => 0);
|
|
132
|
+
if (age < SESSION_OWNER_WRITE_GRACE_MS)
|
|
133
|
+
throw new WorkflowError("RUN_OWNED", `Pi session ${sessionId} has an active ownership lease`);
|
|
134
|
+
}
|
|
135
|
+
const stale = `${path}.${randomUUID()}.stale`;
|
|
136
|
+
try {
|
|
137
|
+
await rename(path, stale);
|
|
138
|
+
const movedText = await readFile(stale, "utf8");
|
|
139
|
+
let movedOwner;
|
|
140
|
+
try {
|
|
141
|
+
movedOwner = decodeSessionOwner(JSON.parse(movedText));
|
|
142
|
+
}
|
|
143
|
+
catch {
|
|
144
|
+
movedOwner = undefined;
|
|
145
|
+
}
|
|
146
|
+
if (movedOwner === undefined) {
|
|
147
|
+
if (movedText === existingText)
|
|
148
|
+
await rm(stale, { force: true });
|
|
149
|
+
else
|
|
150
|
+
await restoreLease(path, stale);
|
|
151
|
+
continue;
|
|
152
|
+
}
|
|
153
|
+
if (!sameOwner(existingOwner, movedOwner)) {
|
|
154
|
+
await restoreLease(path, stale);
|
|
155
|
+
continue;
|
|
156
|
+
}
|
|
157
|
+
await rm(stale, { force: true });
|
|
158
|
+
}
|
|
159
|
+
catch (reclaimError) {
|
|
160
|
+
if (isNodeError(reclaimError, "ENOENT"))
|
|
161
|
+
continue;
|
|
162
|
+
throw reclaimError;
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
export async function listRunIds(cwd, sessionId, home = homedir(), cleanTemps = true) {
|
|
168
|
+
const directory = runsDirectory(cwd, sessionId, home);
|
|
169
|
+
try {
|
|
170
|
+
const entries = await readdir(directory, { withFileTypes: true });
|
|
171
|
+
if (cleanTemps)
|
|
172
|
+
await cleanupRunTemps(directory, entries);
|
|
173
|
+
return entries.filter((entry) => entry.isDirectory() && !entry.name.startsWith(".")).map(({ name }) => name);
|
|
174
|
+
}
|
|
175
|
+
catch (error) {
|
|
176
|
+
if (isNodeError(error, "ENOENT"))
|
|
177
|
+
return [];
|
|
178
|
+
throw error;
|
|
179
|
+
}
|
|
180
|
+
}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import { type JsonValue, type LaunchSnapshot, type WorkflowRunEvent } from "./types.js";
|
|
2
|
+
import { type AwaitingCheckpoint, type BorrowedWorktreeBinding, type CompletedOperation, type EffectiveSystemPrompt, type PendingWorkflowDecision, type PersistedOwnershipNode, type PersistedRun, type RunSummary, type WorktreeReference } from "./decoders.js";
|
|
3
|
+
export declare class RunStore {
|
|
4
|
+
#private;
|
|
5
|
+
readonly cwd: string;
|
|
6
|
+
readonly sessionId: string;
|
|
7
|
+
readonly runId: string;
|
|
8
|
+
readonly home: string;
|
|
9
|
+
readonly directory: string;
|
|
10
|
+
private journalLane;
|
|
11
|
+
private stateLane;
|
|
12
|
+
private summaryLane;
|
|
13
|
+
private worktreeLane;
|
|
14
|
+
private borrowedWorktreeLane;
|
|
15
|
+
private snapshotLane;
|
|
16
|
+
private launchSnapshotLane;
|
|
17
|
+
private systemPromptLane;
|
|
18
|
+
constructor(cwd: string, sessionId: string, runId: string, home?: string);
|
|
19
|
+
create(run: PersistedRun, snapshot: Readonly<LaunchSnapshot>): Promise<void>;
|
|
20
|
+
private refreshSummary;
|
|
21
|
+
private refreshSummaryBestEffort;
|
|
22
|
+
isComplete(): Promise<boolean>;
|
|
23
|
+
load(): Promise<{
|
|
24
|
+
run: PersistedRun;
|
|
25
|
+
snapshot: Readonly<LaunchSnapshot>;
|
|
26
|
+
}>;
|
|
27
|
+
loadStatus(): Promise<PersistedRun>;
|
|
28
|
+
loadSummary(): Promise<RunSummary>;
|
|
29
|
+
saveState(run: PersistedRun): Promise<void>;
|
|
30
|
+
updateState(update: (run: PersistedRun) => PersistedRun | Promise<PersistedRun>): Promise<PersistedRun>;
|
|
31
|
+
saveSnapshot(snapshot: Readonly<LaunchSnapshot>): Promise<void>;
|
|
32
|
+
appendEvent(event: WorkflowRunEvent): Promise<void>;
|
|
33
|
+
saveOwnership(nodes: readonly PersistedOwnershipNode[]): Promise<void>;
|
|
34
|
+
loadOwnership(): Promise<readonly PersistedOwnershipNode[]>;
|
|
35
|
+
systemPromptPath(): string;
|
|
36
|
+
private readSystemPromptArtifact;
|
|
37
|
+
private appendSystemPromptV2;
|
|
38
|
+
private migrateSystemPrompts;
|
|
39
|
+
private prepareSystemPromptStorage;
|
|
40
|
+
private readSystemPromptsV2;
|
|
41
|
+
recordSystemPrompt(entry: Omit<EffectiveSystemPrompt, "sha256">): Promise<void>;
|
|
42
|
+
systemPrompts(): Promise<readonly EffectiveSystemPrompt[]>;
|
|
43
|
+
private updateJournal;
|
|
44
|
+
complete(path: string, value: JsonValue): Promise<void>;
|
|
45
|
+
replay(path: string): Promise<CompletedOperation | undefined>;
|
|
46
|
+
replayableOperations(): Promise<readonly CompletedOperation[]>;
|
|
47
|
+
/** Every journaled agent operation of the retry lineage, mapped to its session file when one was recorded. */
|
|
48
|
+
agentSessionFiles(): Promise<ReadonlyMap<string, string | undefined>>;
|
|
49
|
+
private agentSessionFilesFrom;
|
|
50
|
+
/** Source lineage first, own journal last (it overrides); `path` narrows to one operation without cloning the rest. */
|
|
51
|
+
private replayableOperationsFrom;
|
|
52
|
+
awaitCheckpoint(checkpoint: AwaitingCheckpoint): Promise<boolean | undefined>;
|
|
53
|
+
awaitingCheckpoints(): Promise<readonly AwaitingCheckpoint[]>;
|
|
54
|
+
requestWorkflowDecision(request: PendingWorkflowDecision): Promise<void>;
|
|
55
|
+
pendingWorkflowDecisions(): Promise<readonly PendingWorkflowDecision[]>;
|
|
56
|
+
answerWorkflowDecision(proposalId: string, approved: boolean): Promise<PendingWorkflowDecision | undefined>;
|
|
57
|
+
answerCheckpoint(name: string, approved: boolean): Promise<AwaitingCheckpoint | undefined>;
|
|
58
|
+
private expectedWorktree;
|
|
59
|
+
private markerPath;
|
|
60
|
+
private namedWorktreeOwner;
|
|
61
|
+
private worktreeName;
|
|
62
|
+
private runWorktreePostCreateCommand;
|
|
63
|
+
private structuralWorktree;
|
|
64
|
+
private borrowedWorktreeRecords;
|
|
65
|
+
borrowedWorktrees(): Promise<readonly BorrowedWorktreeBinding[]>;
|
|
66
|
+
private borrowedWorktree;
|
|
67
|
+
private sourceRun;
|
|
68
|
+
validateParentRun(parentRunId: string): Promise<void>;
|
|
69
|
+
validateRetrySource(): Promise<void>;
|
|
70
|
+
private ownedWorktree;
|
|
71
|
+
private resolveBorrowedWorktree;
|
|
72
|
+
private findNamedWorktree;
|
|
73
|
+
resolveNamedWorktree(name: string, seen?: Set<string>): Promise<{
|
|
74
|
+
reference: WorktreeReference;
|
|
75
|
+
sourceRunId: string;
|
|
76
|
+
owner: string;
|
|
77
|
+
}>;
|
|
78
|
+
validateDeletionWorktrees(): Promise<void>;
|
|
79
|
+
validateBorrowedWorktrees(): Promise<void>;
|
|
80
|
+
validateNamedWorktrees(): Promise<void>;
|
|
81
|
+
ownsWorktree(owner: string): Promise<boolean>;
|
|
82
|
+
private cleanupMarker;
|
|
83
|
+
private cleanupOrphanWorktrees;
|
|
84
|
+
validateWorktree(owner: string, cwd?: string): Promise<WorktreeReference>;
|
|
85
|
+
worktree(owner: string): Promise<WorktreeReference>;
|
|
86
|
+
private resolveNamedWorktreeFromParent;
|
|
87
|
+
private bindBorrowedWorktree;
|
|
88
|
+
snapshotWorktree(owner: string): Promise<string>;
|
|
89
|
+
worktrees(): Promise<readonly WorktreeReference[]>;
|
|
90
|
+
validNamedWorktrees(): Promise<readonly string[]>;
|
|
91
|
+
changedWorktrees(): Promise<readonly WorktreeReference[]>;
|
|
92
|
+
saveResult(value: JsonValue): Promise<string>;
|
|
93
|
+
resultBytes(): Promise<number>;
|
|
94
|
+
delete(confirmed: boolean): Promise<void>;
|
|
95
|
+
}
|