@zachwill/pi-orchestrate 0.8.0 → 0.9.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/extension/catalog.ts +70 -75
- package/extension/delivery.ts +49 -7
- package/extension/domain.ts +83 -58
- package/extension/host.ts +321 -31
- package/extension/index.ts +33 -26
- package/extension/presentation.ts +36 -83
- package/extension/runtime.ts +1702 -884
- package/extension/tools.ts +143 -243
- package/extension/tui.ts +50 -0
- package/extension/worker-session.ts +514 -188
- package/extension/worker-settlement.ts +105 -44
- package/package.json +1 -1
- package/extension/scheduler.ts +0 -85
|
@@ -1,41 +1,18 @@
|
|
|
1
1
|
import { Schema } from "effect";
|
|
2
|
-
import
|
|
2
|
+
import {
|
|
3
|
+
RunId,
|
|
4
|
+
WorkerAbortedOutcome,
|
|
5
|
+
WorkerCompletedOutcome,
|
|
6
|
+
WorkerFailedOutcome,
|
|
7
|
+
WorkerId,
|
|
8
|
+
WorkerReadyOutcome,
|
|
9
|
+
WorkerResponseOutcome,
|
|
10
|
+
WorkerUsage,
|
|
11
|
+
} from "./domain.js";
|
|
3
12
|
|
|
4
|
-
const NonnegativeFinite = Schema.Finite.check(Schema.isGreaterThanOrEqualTo(0));
|
|
5
13
|
const NonnegativeInteger = Schema.Int.check(Schema.isGreaterThanOrEqualTo(0));
|
|
6
14
|
const PositiveInteger = Schema.Int.check(Schema.isGreaterThan(0));
|
|
7
15
|
|
|
8
|
-
const WorkerUsage = Schema.Struct({
|
|
9
|
-
input: NonnegativeFinite,
|
|
10
|
-
output: NonnegativeFinite,
|
|
11
|
-
cacheRead: NonnegativeFinite,
|
|
12
|
-
cacheWrite: NonnegativeFinite,
|
|
13
|
-
cost: NonnegativeFinite,
|
|
14
|
-
contextTokens: NonnegativeFinite,
|
|
15
|
-
turns: NonnegativeInteger,
|
|
16
|
-
});
|
|
17
|
-
|
|
18
|
-
const WorkerOutcome = Schema.Union([
|
|
19
|
-
Schema.Struct({
|
|
20
|
-
status: Schema.Literal("completed"),
|
|
21
|
-
assistantText: Schema.String,
|
|
22
|
-
}),
|
|
23
|
-
Schema.Struct({
|
|
24
|
-
status: Schema.Literal("ready"),
|
|
25
|
-
assistantText: Schema.String,
|
|
26
|
-
}),
|
|
27
|
-
Schema.Struct({
|
|
28
|
-
status: Schema.Literal("failed"),
|
|
29
|
-
message: Schema.String,
|
|
30
|
-
assistantText: Schema.optionalKey(Schema.String),
|
|
31
|
-
}),
|
|
32
|
-
Schema.Struct({
|
|
33
|
-
status: Schema.Literal("aborted"),
|
|
34
|
-
message: Schema.optionalKey(Schema.String),
|
|
35
|
-
assistantText: Schema.optionalKey(Schema.String),
|
|
36
|
-
}),
|
|
37
|
-
]);
|
|
38
|
-
|
|
39
16
|
const FailureStage = Schema.Literals([
|
|
40
17
|
"startup",
|
|
41
18
|
"prompt",
|
|
@@ -48,15 +25,15 @@ export const WorkerSettlementDetails = Schema.Struct({
|
|
|
48
25
|
eventId: Schema.String,
|
|
49
26
|
sequence: PositiveInteger,
|
|
50
27
|
ownerSessionId: Schema.String,
|
|
51
|
-
runId:
|
|
52
|
-
workerId:
|
|
28
|
+
runId: RunId,
|
|
29
|
+
workerId: WorkerId,
|
|
53
30
|
generation: PositiveInteger,
|
|
54
31
|
mode: Schema.Literals(["async", "inline"]),
|
|
55
32
|
worker: Schema.String,
|
|
56
33
|
title: Schema.String,
|
|
57
34
|
lifecycle: Schema.Literals(["one-shot", "interactive"]),
|
|
58
35
|
status: Schema.Literals(["completed", "ready", "failed", "aborted"]),
|
|
59
|
-
outcome:
|
|
36
|
+
outcome: WorkerResponseOutcome,
|
|
60
37
|
usage: WorkerUsage,
|
|
61
38
|
startedAt: NonnegativeInteger,
|
|
62
39
|
settledAt: NonnegativeInteger,
|
|
@@ -107,14 +84,9 @@ export type SettlementFailureStage = NonNullable<
|
|
|
107
84
|
WorkerSettlementDetails["failureStage"]
|
|
108
85
|
>;
|
|
109
86
|
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
"runId" | "workerId"
|
|
114
|
-
> & {
|
|
115
|
-
readonly runId: RunId;
|
|
116
|
-
readonly workerId: WorkerId;
|
|
117
|
-
};
|
|
87
|
+
export type WorkerSettlement = Schema.Schema.Type<
|
|
88
|
+
typeof WorkerSettlementDetails
|
|
89
|
+
>;
|
|
118
90
|
|
|
119
91
|
const decodeCurrentWorkerSettlement = Schema.decodeUnknownResult(
|
|
120
92
|
WorkerSettlementDetails,
|
|
@@ -123,3 +95,92 @@ const decodeCurrentWorkerSettlement = Schema.decodeUnknownResult(
|
|
|
123
95
|
export function decodePersistedWorkerSettlementDetails(value: unknown) {
|
|
124
96
|
return decodeCurrentWorkerSettlement(value);
|
|
125
97
|
}
|
|
98
|
+
|
|
99
|
+
const InlineWorkerOutcome = Schema.Union([
|
|
100
|
+
WorkerCompletedOutcome.pipe(
|
|
101
|
+
Schema.encodeKeys({ assistantText: "assistant_text" }),
|
|
102
|
+
),
|
|
103
|
+
WorkerReadyOutcome.pipe(
|
|
104
|
+
Schema.encodeKeys({ assistantText: "assistant_text" }),
|
|
105
|
+
),
|
|
106
|
+
WorkerFailedOutcome.pipe(
|
|
107
|
+
Schema.encodeKeys({ assistantText: "assistant_text" }),
|
|
108
|
+
),
|
|
109
|
+
WorkerAbortedOutcome.pipe(
|
|
110
|
+
Schema.encodeKeys({ assistantText: "assistant_text" }),
|
|
111
|
+
),
|
|
112
|
+
]);
|
|
113
|
+
|
|
114
|
+
const InlineWorkerUsage = WorkerUsage.pipe(
|
|
115
|
+
Schema.encodeKeys({
|
|
116
|
+
cacheRead: "cache_read",
|
|
117
|
+
cacheWrite: "cache_write",
|
|
118
|
+
contextTokens: "context_tokens",
|
|
119
|
+
}),
|
|
120
|
+
);
|
|
121
|
+
|
|
122
|
+
/** Tool transport projection derived from the canonical settlement field schemas. */
|
|
123
|
+
export const InlineWorkerSettlementDetails = Schema.Struct({
|
|
124
|
+
workerId: WorkerSettlementDetails.fields.workerId,
|
|
125
|
+
worker: WorkerSettlementDetails.fields.worker,
|
|
126
|
+
title: WorkerSettlementDetails.fields.title,
|
|
127
|
+
status: WorkerSettlementDetails.fields.status,
|
|
128
|
+
outcome: InlineWorkerOutcome,
|
|
129
|
+
usage: InlineWorkerUsage,
|
|
130
|
+
startedAt: WorkerSettlementDetails.fields.startedAt,
|
|
131
|
+
settledAt: WorkerSettlementDetails.fields.settledAt,
|
|
132
|
+
sessionFile: WorkerSettlementDetails.fields.sessionFile,
|
|
133
|
+
}).pipe(
|
|
134
|
+
Schema.encodeKeys({
|
|
135
|
+
workerId: "worker_id",
|
|
136
|
+
startedAt: "started_at",
|
|
137
|
+
settledAt: "settled_at",
|
|
138
|
+
sessionFile: "session_file",
|
|
139
|
+
}),
|
|
140
|
+
).check(
|
|
141
|
+
Schema.makeFilter((settlement) => {
|
|
142
|
+
if (settlement.outcome.status !== settlement.status) {
|
|
143
|
+
return "outcome status must match settlement status";
|
|
144
|
+
}
|
|
145
|
+
if (settlement.settledAt < settlement.startedAt) {
|
|
146
|
+
return "settlement timestamp must not precede start timestamp";
|
|
147
|
+
}
|
|
148
|
+
}),
|
|
149
|
+
);
|
|
150
|
+
|
|
151
|
+
export interface InlineWorkerSettlementDetails
|
|
152
|
+
extends Schema.Schema.Type<typeof InlineWorkerSettlementDetails> {}
|
|
153
|
+
|
|
154
|
+
export const InlineWorkerToolDetails = Schema.Struct({
|
|
155
|
+
mode: Schema.Literal("inline"),
|
|
156
|
+
runId: Schema.optionalKey(WorkerSettlementDetails.fields.runId),
|
|
157
|
+
ownerSessionId: Schema.optionalKey(
|
|
158
|
+
WorkerSettlementDetails.fields.ownerSessionId,
|
|
159
|
+
),
|
|
160
|
+
result: InlineWorkerSettlementDetails,
|
|
161
|
+
}).pipe(
|
|
162
|
+
Schema.encodeKeys({
|
|
163
|
+
runId: "run_id",
|
|
164
|
+
ownerSessionId: "owner_session_id",
|
|
165
|
+
}),
|
|
166
|
+
);
|
|
167
|
+
|
|
168
|
+
export interface InlineWorkerToolDetails
|
|
169
|
+
extends Schema.Schema.Type<typeof InlineWorkerToolDetails> {}
|
|
170
|
+
|
|
171
|
+
const decodeInlineWorkerToolDetailsResult = Schema.decodeUnknownResult(
|
|
172
|
+
InlineWorkerToolDetails,
|
|
173
|
+
);
|
|
174
|
+
const encodeInlineWorkerToolDetailsSync = Schema.encodeSync(
|
|
175
|
+
InlineWorkerToolDetails,
|
|
176
|
+
);
|
|
177
|
+
|
|
178
|
+
export function decodeInlineWorkerToolDetails(value: unknown) {
|
|
179
|
+
return decodeInlineWorkerToolDetailsResult(value);
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
export function encodeInlineWorkerToolDetails(
|
|
183
|
+
value: InlineWorkerToolDetails,
|
|
184
|
+
) {
|
|
185
|
+
return encodeInlineWorkerToolDetailsSync(value);
|
|
186
|
+
}
|
package/package.json
CHANGED
package/extension/scheduler.ts
DELETED
|
@@ -1,85 +0,0 @@
|
|
|
1
|
-
import { Cause, Context, Effect, FiberMap, Layer, ManagedRuntime } from "effect";
|
|
2
|
-
|
|
3
|
-
export type WorkflowDefectHandler = (error: unknown) => void;
|
|
4
|
-
|
|
5
|
-
export interface WorkflowScheduler<Key> {
|
|
6
|
-
/** Starts a workflow immediately, interrupting and replacing the previous workflow at the key. */
|
|
7
|
-
start(
|
|
8
|
-
key: Key,
|
|
9
|
-
workflow: Effect.Effect<void, never>,
|
|
10
|
-
onDefect: WorkflowDefectHandler,
|
|
11
|
-
): void;
|
|
12
|
-
/** Interrupts the current workflow at the key and waits for its fiber to settle. */
|
|
13
|
-
remove(key: Key): Promise<void>;
|
|
14
|
-
/** Interrupts every retained workflow and closes the scheduler scope. */
|
|
15
|
-
close(): Promise<void>;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
interface WorkflowSupervisorService {
|
|
19
|
-
readonly start: (
|
|
20
|
-
key: unknown,
|
|
21
|
-
workflow: Effect.Effect<void, never>,
|
|
22
|
-
) => void;
|
|
23
|
-
readonly remove: (key: unknown) => Effect.Effect<void>;
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
class WorkflowSupervisor extends Context.Service<
|
|
27
|
-
WorkflowSupervisor,
|
|
28
|
-
WorkflowSupervisorService
|
|
29
|
-
>()("@zachwill/pi-orchestrate/WorkflowSupervisor") {}
|
|
30
|
-
|
|
31
|
-
const workflowSupervisorLayer = Layer.effect(
|
|
32
|
-
WorkflowSupervisor,
|
|
33
|
-
Effect.gen(function* () {
|
|
34
|
-
const fibers = yield* FiberMap.make<unknown, void, never>();
|
|
35
|
-
const run = yield* FiberMap.runtime(fibers)<never>();
|
|
36
|
-
return WorkflowSupervisor.of({
|
|
37
|
-
start(key, workflow) {
|
|
38
|
-
run(key, workflow);
|
|
39
|
-
},
|
|
40
|
-
remove: (key) => FiberMap.remove(fibers, key),
|
|
41
|
-
});
|
|
42
|
-
}),
|
|
43
|
-
);
|
|
44
|
-
|
|
45
|
-
class EffectWorkflowScheduler<Key> implements WorkflowScheduler<Key> {
|
|
46
|
-
private readonly managedRuntime = ManagedRuntime.make(workflowSupervisorLayer);
|
|
47
|
-
private readonly supervisor = this.managedRuntime.runSync(WorkflowSupervisor);
|
|
48
|
-
private closePromise: Promise<void> | undefined;
|
|
49
|
-
|
|
50
|
-
start(
|
|
51
|
-
key: Key,
|
|
52
|
-
workflow: Effect.Effect<void, never>,
|
|
53
|
-
onDefect: WorkflowDefectHandler,
|
|
54
|
-
): void {
|
|
55
|
-
const supervised = workflow.pipe(
|
|
56
|
-
Effect.catchCause((cause) => {
|
|
57
|
-
if (!Cause.hasInterruptsOnly(cause)) {
|
|
58
|
-
return Effect.sync(() => {
|
|
59
|
-
try {
|
|
60
|
-
onDefect(Cause.squash(cause));
|
|
61
|
-
} catch {
|
|
62
|
-
// Defect reporting must not become another unsupervised defect.
|
|
63
|
-
}
|
|
64
|
-
});
|
|
65
|
-
}
|
|
66
|
-
return Effect.void;
|
|
67
|
-
}),
|
|
68
|
-
);
|
|
69
|
-
|
|
70
|
-
this.supervisor.start(key, supervised);
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
remove(key: Key): Promise<void> {
|
|
74
|
-
return this.managedRuntime.runPromise(this.supervisor.remove(key));
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
close(): Promise<void> {
|
|
78
|
-
this.closePromise ??= this.managedRuntime.dispose();
|
|
79
|
-
return this.closePromise;
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
export function createWorkflowScheduler<Key>(): WorkflowScheduler<Key> {
|
|
84
|
-
return new EffectWorkflowScheduler<Key>();
|
|
85
|
-
}
|