@earendil-works/pi-coding-agent 0.85.0 → 0.85.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 +18 -0
- package/README.md +0 -2
- package/dist/bun/cli.d.ts +3 -1
- package/dist/bun/cli.d.ts.map +1 -1
- package/dist/bun/cli.js +3 -12
- package/dist/bun/cli.js.map +1 -1
- package/dist/bun/sandbox-env-setup.d.ts +2 -0
- package/dist/bun/sandbox-env-setup.d.ts.map +1 -0
- package/dist/bun/sandbox-env-setup.js +4 -0
- package/dist/bun/sandbox-env-setup.js.map +1 -0
- package/dist/bundle/chunks/{anthropic-messages-QAQLEQIY.js → anthropic-messages-VWZZOSJQ.js} +1 -1
- package/dist/bundle/chunks/{azure-openai-responses-Q7MJBRE6.js → azure-openai-responses-BJLAM6CD.js} +1 -1
- package/dist/bundle/chunks/{chunk-R7UUJ4C2.js → chunk-CLNPYIDP.js} +1 -1
- package/dist/bundle/chunks/chunk-JVUZSMYM.js +1547 -0
- package/dist/bundle/chunks/{chunk-2KVJKXS2.js → chunk-U6ZMQKGD.js} +1 -1
- package/dist/bundle/chunks/github-copilot.js +1 -1
- package/dist/bundle/chunks/{google-generative-ai-BSMTYDAM.js → google-generative-ai-Q2K7FBDI.js} +1 -1
- package/dist/bundle/chunks/{google-vertex-5C3HASOJ.js → google-vertex-7UJBF4S7.js} +1 -1
- package/dist/bundle/chunks/{node-EM5FIVUN.js → node-KG362ECQ.js} +1 -1
- package/dist/bundle/chunks/{openai-codex-responses-YJOO52RW.js → openai-codex-responses-R6VYZTVY.js} +1 -1
- package/dist/bundle/chunks/{openai-completions-QOT3QX7D.js → openai-completions-EKZT2IH2.js} +1 -1
- package/dist/bundle/chunks/openai-responses-TFDINO6W.js +2 -0
- package/dist/bundle/chunks/{pi-messages-EGZIFQGG.js → pi-messages-PML4SPVJ.js} +1 -1
- package/dist/bundle/cli.js +1 -1
- package/dist/bundle/index.js +1 -1
- package/dist/bundle/rpc-entry.js +1 -1
- package/dist/cli/args.d.ts.map +1 -1
- package/dist/cli/args.js +0 -2
- package/dist/cli/args.js.map +1 -1
- package/dist/cli/setup.d.ts +2 -0
- package/dist/cli/setup.d.ts.map +1 -0
- package/dist/cli/setup.js +12 -0
- package/dist/cli/setup.js.map +1 -0
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +3 -25
- package/dist/cli.js.map +1 -1
- package/dist/core/keybindings.d.ts +5 -0
- package/dist/core/keybindings.d.ts.map +1 -1
- package/dist/core/keybindings.js +4 -0
- package/dist/core/keybindings.js.map +1 -1
- package/dist/main.d.ts.map +1 -1
- package/dist/main.js +0 -122
- package/dist/main.js.map +1 -1
- package/dist/modes/interactive/components/model-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/model-selector.js +5 -5
- package/dist/modes/interactive/components/model-selector.js.map +1 -1
- package/dist/modes/interactive/components/scoped-models-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/scoped-models-selector.js +8 -8
- package/dist/modes/interactive/components/scoped-models-selector.js.map +1 -1
- package/dist/modes/interactive/components/thinking-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/thinking-selector.js +4 -4
- package/dist/modes/interactive/components/thinking-selector.js.map +1 -1
- package/docs/containerization.md +45 -0
- package/docs/development.md +19 -0
- package/docs/environment-variables.md +2 -2
- package/docs/keybindings.md +2 -1
- package/docs/models.md +1 -1
- package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
- package/examples/extensions/custom-provider-anthropic/package.json +1 -1
- package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
- package/examples/extensions/gondolin/package-lock.json +2 -2
- package/examples/extensions/gondolin/package.json +1 -1
- package/examples/extensions/sandbox/package-lock.json +2 -2
- package/examples/extensions/sandbox/package.json +1 -1
- package/examples/extensions/with-deps/package-lock.json +2 -2
- package/examples/extensions/with-deps/package.json +1 -1
- package/npm-shrinkwrap.json +20 -46
- package/package.json +13 -12
- package/dist/bundle/chunks/chunk-EQ6DR6XK.js +0 -5
- package/dist/bundle/chunks/chunk-LZKJTKCT.js +0 -2
- package/dist/bundle/chunks/chunk-WBE4J4AU.js +0 -9
- package/dist/bundle/chunks/chunk-WZB2R5YO.js +0 -1558
- package/dist/bundle/chunks/openai-responses-U7LNPQN4.js +0 -2
- package/dist/bundle/client.js +0 -2
- package/dist/bundle/coordinator.js +0 -3
- package/dist/cli/experimental/cli.d.ts +0 -10
- package/dist/cli/experimental/cli.d.ts.map +0 -1
- package/dist/cli/experimental/cli.js +0 -9
- package/dist/cli/experimental/cli.js.map +0 -1
- package/dist/cli/experimental/command-options.d.ts +0 -28
- package/dist/cli/experimental/command-options.d.ts.map +0 -1
- package/dist/cli/experimental/command-options.js +0 -84
- package/dist/cli/experimental/command-options.js.map +0 -1
- package/dist/cli/experimental/command.d.ts +0 -70
- package/dist/cli/experimental/command.d.ts.map +0 -1
- package/dist/cli/experimental/command.js +0 -144
- package/dist/cli/experimental/command.js.map +0 -1
- package/dist/cli/experimental/commands/client.d.ts +0 -19
- package/dist/cli/experimental/commands/client.d.ts.map +0 -1
- package/dist/cli/experimental/commands/client.js +0 -63
- package/dist/cli/experimental/commands/client.js.map +0 -1
- package/dist/cli/experimental/commands/server.d.ts +0 -17
- package/dist/cli/experimental/commands/server.d.ts.map +0 -1
- package/dist/cli/experimental/commands/server.js +0 -44
- package/dist/cli/experimental/commands/server.js.map +0 -1
- package/dist/client/index.d.ts +0 -2
- package/dist/client/index.d.ts.map +0 -1
- package/dist/client/index.js +0 -2
- package/dist/client/index.js.map +0 -1
- package/dist/experimental/client-runtime.d.ts +0 -43
- package/dist/experimental/client-runtime.d.ts.map +0 -1
- package/dist/experimental/client-runtime.js +0 -183
- package/dist/experimental/client-runtime.js.map +0 -1
- package/dist/experimental/client-tui-chat.d.ts +0 -14
- package/dist/experimental/client-tui-chat.d.ts.map +0 -1
- package/dist/experimental/client-tui-chat.js +0 -171
- package/dist/experimental/client-tui-chat.js.map +0 -1
- package/dist/experimental/client-tui.d.ts +0 -37
- package/dist/experimental/client-tui.d.ts.map +0 -1
- package/dist/experimental/client-tui.js +0 -702
- package/dist/experimental/client-tui.js.map +0 -1
- package/dist/experimental/client.d.ts +0 -25
- package/dist/experimental/client.d.ts.map +0 -1
- package/dist/experimental/client.js +0 -99
- package/dist/experimental/client.js.map +0 -1
- package/dist/experimental/coordinator-entry.d.ts +0 -3
- package/dist/experimental/coordinator-entry.d.ts.map +0 -1
- package/dist/experimental/coordinator-entry.js +0 -11
- package/dist/experimental/coordinator-entry.js.map +0 -1
- package/dist/experimental/coordinator.d.ts +0 -38
- package/dist/experimental/coordinator.d.ts.map +0 -1
- package/dist/experimental/coordinator.js +0 -570
- package/dist/experimental/coordinator.js.map +0 -1
- package/dist/experimental/mini/main.d.ts +0 -7
- package/dist/experimental/mini/main.d.ts.map +0 -1
- package/dist/experimental/mini/main.js +0 -21
- package/dist/experimental/mini/main.js.map +0 -1
- package/dist/experimental/mini/server/entry.d.ts +0 -3
- package/dist/experimental/mini/server/entry.d.ts.map +0 -1
- package/dist/experimental/mini/server/entry.js +0 -11
- package/dist/experimental/mini/server/entry.js.map +0 -1
- package/dist/experimental/mini/server/run.d.ts +0 -13
- package/dist/experimental/mini/server/run.d.ts.map +0 -1
- package/dist/experimental/mini/server/run.js +0 -150
- package/dist/experimental/mini/server/run.js.map +0 -1
- package/dist/experimental/mini/shared/protocol.d.ts +0 -127
- package/dist/experimental/mini/shared/protocol.d.ts.map +0 -1
- package/dist/experimental/mini/shared/protocol.js +0 -13
- package/dist/experimental/mini/shared/protocol.js.map +0 -1
- package/dist/experimental/mini/shared/rpc.d.ts +0 -49
- package/dist/experimental/mini/shared/rpc.d.ts.map +0 -1
- package/dist/experimental/mini/shared/rpc.js +0 -171
- package/dist/experimental/mini/shared/rpc.js.map +0 -1
- package/dist/experimental/mini/shared/transport.d.ts +0 -35
- package/dist/experimental/mini/shared/transport.d.ts.map +0 -1
- package/dist/experimental/mini/shared/transport.js +0 -94
- package/dist/experimental/mini/shared/transport.js.map +0 -1
- package/dist/experimental/mini/tui/run.d.ts +0 -9
- package/dist/experimental/mini/tui/run.d.ts.map +0 -1
- package/dist/experimental/mini/tui/run.js +0 -62
- package/dist/experimental/mini/tui/run.js.map +0 -1
- package/dist/experimental/mini/tui/session.d.ts +0 -26
- package/dist/experimental/mini/tui/session.d.ts.map +0 -1
- package/dist/experimental/mini/tui/session.js +0 -94
- package/dist/experimental/mini/tui/session.js.map +0 -1
- package/dist/experimental/mini/tui/view.d.ts +0 -10
- package/dist/experimental/mini/tui/view.d.ts.map +0 -1
- package/dist/experimental/mini/tui/view.js +0 -459
- package/dist/experimental/mini/tui/view.js.map +0 -1
- package/dist/experimental/mini/worker/entry.d.ts +0 -3
- package/dist/experimental/mini/worker/entry.d.ts.map +0 -1
- package/dist/experimental/mini/worker/entry.js +0 -10
- package/dist/experimental/mini/worker/entry.js.map +0 -1
- package/dist/experimental/mini/worker/lane-service.d.ts +0 -44
- package/dist/experimental/mini/worker/lane-service.d.ts.map +0 -1
- package/dist/experimental/mini/worker/lane-service.js +0 -97
- package/dist/experimental/mini/worker/lane-service.js.map +0 -1
- package/dist/experimental/mini/worker/models-service.d.ts +0 -19
- package/dist/experimental/mini/worker/models-service.d.ts.map +0 -1
- package/dist/experimental/mini/worker/models-service.js +0 -136
- package/dist/experimental/mini/worker/models-service.js.map +0 -1
- package/dist/experimental/mini/worker/run.d.ts +0 -14
- package/dist/experimental/mini/worker/run.d.ts.map +0 -1
- package/dist/experimental/mini/worker/run.js +0 -88
- package/dist/experimental/mini/worker/run.js.map +0 -1
- package/dist/experimental/plugin.d.ts +0 -4
- package/dist/experimental/plugin.d.ts.map +0 -1
- package/dist/experimental/plugin.js +0 -4
- package/dist/experimental/plugin.js.map +0 -1
- package/dist/experimental/plugins/bundled.d.ts +0 -7
- package/dist/experimental/plugins/bundled.d.ts.map +0 -1
- package/dist/experimental/plugins/bundled.js +0 -48
- package/dist/experimental/plugins/bundled.js.map +0 -1
- package/dist/experimental/plugins/package.d.ts +0 -18
- package/dist/experimental/plugins/package.d.ts.map +0 -1
- package/dist/experimental/plugins/package.js +0 -113
- package/dist/experimental/plugins/package.js.map +0 -1
- package/dist/experimental/process.d.ts +0 -20
- package/dist/experimental/process.d.ts.map +0 -1
- package/dist/experimental/process.js +0 -85
- package/dist/experimental/process.js.map +0 -1
- package/dist/experimental/radius-auth.d.ts +0 -17
- package/dist/experimental/radius-auth.d.ts.map +0 -1
- package/dist/experimental/radius-auth.js +0 -52
- package/dist/experimental/radius-auth.js.map +0 -1
- package/dist/experimental/radius-relay.d.ts +0 -90
- package/dist/experimental/radius-relay.d.ts.map +0 -1
- package/dist/experimental/radius-relay.js +0 -582
- package/dist/experimental/radius-relay.js.map +0 -1
- package/dist/experimental/server.d.ts +0 -75
- package/dist/experimental/server.d.ts.map +0 -1
- package/dist/experimental/server.js +0 -682
- package/dist/experimental/server.js.map +0 -1
- package/dist/experimental/services/agent-controller-provider.d.ts +0 -4
- package/dist/experimental/services/agent-controller-provider.d.ts.map +0 -1
- package/dist/experimental/services/agent-controller-provider.js +0 -84
- package/dist/experimental/services/agent-controller-provider.js.map +0 -1
- package/dist/experimental/services/agent-controller.d.ts +0 -57
- package/dist/experimental/services/agent-controller.d.ts.map +0 -1
- package/dist/experimental/services/agent-controller.js +0 -3
- package/dist/experimental/services/agent-controller.js.map +0 -1
- package/dist/experimental/services/connection.d.ts +0 -40
- package/dist/experimental/services/connection.d.ts.map +0 -1
- package/dist/experimental/services/connection.js +0 -300
- package/dist/experimental/services/connection.js.map +0 -1
- package/dist/experimental/services/models-provider.d.ts +0 -16
- package/dist/experimental/services/models-provider.d.ts.map +0 -1
- package/dist/experimental/services/models-provider.js +0 -116
- package/dist/experimental/services/models-provider.js.map +0 -1
- package/dist/experimental/services/models.d.ts +0 -36
- package/dist/experimental/services/models.d.ts.map +0 -1
- package/dist/experimental/services/models.js +0 -3
- package/dist/experimental/services/models.js.map +0 -1
- package/dist/experimental/services/plugins.d.ts +0 -16
- package/dist/experimental/services/plugins.d.ts.map +0 -1
- package/dist/experimental/services/plugins.js +0 -4
- package/dist/experimental/services/plugins.js.map +0 -1
- package/dist/experimental/services/presentation-ui.d.ts +0 -13
- package/dist/experimental/services/presentation-ui.d.ts.map +0 -1
- package/dist/experimental/services/presentation-ui.js +0 -3
- package/dist/experimental/services/presentation-ui.js.map +0 -1
- package/dist/experimental/services/server.d.ts +0 -19
- package/dist/experimental/services/server.d.ts.map +0 -1
- package/dist/experimental/services/server.js +0 -104
- package/dist/experimental/services/server.js.map +0 -1
- package/dist/experimental/services/sessions.d.ts +0 -28
- package/dist/experimental/services/sessions.d.ts.map +0 -1
- package/dist/experimental/services/sessions.js +0 -4
- package/dist/experimental/services/sessions.js.map +0 -1
- package/dist/experimental/services/slash-commands-provider.d.ts +0 -14
- package/dist/experimental/services/slash-commands-provider.d.ts.map +0 -1
- package/dist/experimental/services/slash-commands-provider.js +0 -200
- package/dist/experimental/services/slash-commands-provider.js.map +0 -1
- package/dist/experimental/services/slash-commands.d.ts +0 -24
- package/dist/experimental/services/slash-commands.d.ts.map +0 -1
- package/dist/experimental/services/slash-commands.js +0 -3
- package/dist/experimental/services/slash-commands.js.map +0 -1
- package/dist/experimental/services/transcript-provider.d.ts +0 -12
- package/dist/experimental/services/transcript-provider.d.ts.map +0 -1
- package/dist/experimental/services/transcript-provider.js +0 -109
- package/dist/experimental/services/transcript-provider.js.map +0 -1
- package/dist/experimental/services/transcript.d.ts +0 -13
- package/dist/experimental/services/transcript.d.ts.map +0 -1
- package/dist/experimental/services/transcript.js +0 -3
- package/dist/experimental/services/transcript.js.map +0 -1
- package/dist/experimental/services/worker.d.ts +0 -28
- package/dist/experimental/services/worker.d.ts.map +0 -1
- package/dist/experimental/services/worker.js +0 -107
- package/dist/experimental/services/worker.js.map +0 -1
- package/dist/experimental/session-worker-manager.d.ts +0 -24
- package/dist/experimental/session-worker-manager.d.ts.map +0 -1
- package/dist/experimental/session-worker-manager.js +0 -691
- package/dist/experimental/session-worker-manager.js.map +0 -1
- package/dist/experimental/session-worker.d.ts +0 -188
- package/dist/experimental/session-worker.d.ts.map +0 -1
- package/dist/experimental/session-worker.js +0 -785
- package/dist/experimental/session-worker.js.map +0 -1
- package/dist/experimental/source-resolver.d.ts +0 -2
- package/dist/experimental/source-resolver.d.ts.map +0 -1
- package/dist/experimental/source-resolver.js +0 -71
- package/dist/experimental/source-resolver.js.map +0 -1
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Worker-side implementation of the `Lane` service.
|
|
3
|
-
*
|
|
4
|
-
* The lane, harness, and model registry stay here. Each presentation gets its own `lane.watch()`,
|
|
5
|
-
* whose snapshot and event stream the harness already pairs with no gap and no duplicate, so nothing
|
|
6
|
-
* here re-implements that alignment: a subscription is just a watch handle plus an id.
|
|
7
|
-
*/
|
|
8
|
-
import type { AgentLane, Context, HarnessEvent } from "@earendil-works/pi-agent-core";
|
|
9
|
-
import type { Models } from "@earendil-works/pi-ai";
|
|
10
|
-
import type { CommandResult, LaneServiceApi, LaneSubscription, ModelRef, ModelsState } from "../shared/protocol.ts";
|
|
11
|
-
export interface LaneServiceOptions {
|
|
12
|
-
lane: AgentLane;
|
|
13
|
-
models: Models;
|
|
14
|
-
context: Context;
|
|
15
|
-
session: {
|
|
16
|
-
id: string;
|
|
17
|
-
cwd: string;
|
|
18
|
-
path: string;
|
|
19
|
-
};
|
|
20
|
-
/** Model catalog state belongs to the `Models` service; the snapshot carries a copy. */
|
|
21
|
-
modelsState: () => ModelsState;
|
|
22
|
-
publish: (subscriptionId: string, to: string, event: HarnessEvent) => void;
|
|
23
|
-
}
|
|
24
|
-
export declare class LaneService implements LaneServiceApi {
|
|
25
|
-
#private;
|
|
26
|
-
constructor(options: LaneServiceOptions);
|
|
27
|
-
/** Capture a snapshot. The harness buffers this subscription's events until `start`. */
|
|
28
|
-
watch(presentationId: string): Promise<LaneSubscription>;
|
|
29
|
-
/** Begin delivery, draining what buffered since the snapshot. */
|
|
30
|
-
start(subscriptionId: string): Promise<void>;
|
|
31
|
-
unwatch(subscriptionId: string): Promise<void>;
|
|
32
|
-
prompt(text: string): Promise<CommandResult>;
|
|
33
|
-
steer(text: string): Promise<CommandResult>;
|
|
34
|
-
followUp(text: string): Promise<CommandResult>;
|
|
35
|
-
compact(): Promise<CommandResult>;
|
|
36
|
-
abort(): Promise<CommandResult>;
|
|
37
|
-
/**
|
|
38
|
-
* The lane stores a durable identity, so the ref passes straight through. The registry lookup is
|
|
39
|
-
* only a courtesy: an identity this worker cannot serve fails at generation time otherwise.
|
|
40
|
-
*/
|
|
41
|
-
setModel(ref: ModelRef): Promise<CommandResult>;
|
|
42
|
-
close(): void;
|
|
43
|
-
}
|
|
44
|
-
//# sourceMappingURL=lane-service.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"lane-service.d.ts","sourceRoot":"","sources":["../../../../src/experimental/mini/worker/lane-service.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,KAAK,EAAE,SAAS,EAAE,OAAO,EAAE,YAAY,EAA6B,MAAM,+BAA+B,CAAC;AACjH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,uBAAuB,CAAC;AACpD,OAAO,KAAK,EACX,aAAa,EACb,cAAc,EACd,gBAAgB,EAChB,QAAQ,EACR,WAAW,EAEX,MAAM,uBAAuB,CAAC;AAE/B,MAAM,WAAW,kBAAkB;IAClC,IAAI,EAAE,SAAS,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;IACnD,wFAAwF;IACxF,WAAW,EAAE,MAAM,WAAW,CAAC;IAC/B,OAAO,EAAE,CAAC,cAAc,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,YAAY,KAAK,IAAI,CAAC;CAC3E;AAED,qBAAa,WAAY,YAAW,cAAc;;IAIjD,YAAY,OAAO,EAAE,kBAAkB,EAEtC;IAED,wFAAwF;IAClF,KAAK,CAAC,cAAc,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAmB7D;IAED,iEAAiE;IAC3D,KAAK,CAAC,cAAc,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAIjD;IAEK,OAAO,CAAC,cAAc,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAGnD;IAED,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC,CAE3C;IAED,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC,CAE1C;IAED,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC,CAE7C;IAED,OAAO,IAAI,OAAO,CAAC,aAAa,CAAC,CAEhC;IAED,KAAK,IAAI,OAAO,CAAC,aAAa,CAAC,CAE9B;IAED;;;OAGG;IACG,QAAQ,CAAC,GAAG,EAAE,QAAQ,GAAG,OAAO,CAAC,aAAa,CAAC,CAUpD;IAED,KAAK,IAAI,IAAI,CAGZ;CAUD","sourcesContent":["/**\n * Worker-side implementation of the `Lane` service.\n *\n * The lane, harness, and model registry stay here. Each presentation gets its own `lane.watch()`,\n * whose snapshot and event stream the harness already pairs with no gap and no duplicate, so nothing\n * here re-implements that alignment: a subscription is just a watch handle plus an id.\n */\n\nimport { randomUUID } from \"node:crypto\";\nimport type { AgentLane, Context, HarnessEvent, LaneSnapshot, WatchHandle } from \"@earendil-works/pi-agent-core\";\nimport type { Models } from \"@earendil-works/pi-ai\";\nimport type {\n\tCommandResult,\n\tLaneServiceApi,\n\tLaneSubscription,\n\tModelRef,\n\tModelsState,\n\tSessionSnapshot,\n} from \"../shared/protocol.ts\";\n\nexport interface LaneServiceOptions {\n\tlane: AgentLane;\n\tmodels: Models;\n\tcontext: Context;\n\tsession: { id: string; cwd: string; path: string };\n\t/** Model catalog state belongs to the `Models` service; the snapshot carries a copy. */\n\tmodelsState: () => ModelsState;\n\tpublish: (subscriptionId: string, to: string, event: HarnessEvent) => void;\n}\n\nexport class LaneService implements LaneServiceApi {\n\treadonly #options: LaneServiceOptions;\n\treadonly #watches = new Map<string, { handle: WatchHandle<LaneSnapshot>; to: string }>();\n\n\tconstructor(options: LaneServiceOptions) {\n\t\tthis.#options = options;\n\t}\n\n\t/** Capture a snapshot. The harness buffers this subscription's events until `start`. */\n\tasync watch(presentationId: string): Promise<LaneSubscription> {\n\t\tconst { lane, context, session } = this.#options;\n\t\tconst subscriptionId = randomUUID();\n\t\tconst handle = await lane.watch(context);\n\t\ttry {\n\t\t\tthis.#watches.set(subscriptionId, { handle, to: presentationId });\n\t\t\tconst snapshot: SessionSnapshot = {\n\t\t\t\tsessionId: session.id,\n\t\t\t\tcwd: session.cwd,\n\t\t\t\tsessionPath: session.path,\n\t\t\t\tlane: handle.snapshot,\n\t\t\t\tmodels: this.#options.modelsState(),\n\t\t\t};\n\t\t\treturn { subscriptionId, snapshot };\n\t\t} catch (error) {\n\t\t\t// A watcher that is never started buffers without bound.\n\t\t\thandle.unsubscribe();\n\t\t\tthrow error;\n\t\t}\n\t}\n\n\t/** Begin delivery, draining what buffered since the snapshot. */\n\tasync start(subscriptionId: string): Promise<void> {\n\t\tconst watch = this.#watches.get(subscriptionId);\n\t\tif (!watch) throw new Error(`Unknown subscription: ${subscriptionId}`);\n\t\twatch.handle.start((event) => this.#options.publish(subscriptionId, watch.to, event));\n\t}\n\n\tasync unwatch(subscriptionId: string): Promise<void> {\n\t\tthis.#watches.get(subscriptionId)?.handle.unsubscribe();\n\t\tthis.#watches.delete(subscriptionId);\n\t}\n\n\tprompt(text: string): Promise<CommandResult> {\n\t\treturn this.#command(() => this.#options.lane.prompt(text, undefined, this.#options.context));\n\t}\n\n\tsteer(text: string): Promise<CommandResult> {\n\t\treturn this.#command(() => this.#options.lane.steer(text, undefined, this.#options.context));\n\t}\n\n\tfollowUp(text: string): Promise<CommandResult> {\n\t\treturn this.#command(() => this.#options.lane.followUp(text, undefined, this.#options.context));\n\t}\n\n\tcompact(): Promise<CommandResult> {\n\t\treturn this.#command(() => this.#options.lane.compact(undefined, this.#options.context));\n\t}\n\n\tabort(): Promise<CommandResult> {\n\t\treturn this.#command(() => this.#options.lane.abort(this.#options.context));\n\t}\n\n\t/**\n\t * The lane stores a durable identity, so the ref passes straight through. The registry lookup is\n\t * only a courtesy: an identity this worker cannot serve fails at generation time otherwise.\n\t */\n\tasync setModel(ref: ModelRef): Promise<CommandResult> {\n\t\tif (!this.#options.models.getModel(ref.provider, ref.modelId)) {\n\t\t\treturn { ok: false, error: `Unknown model: ${ref.provider}/${ref.modelId}` };\n\t\t}\n\t\ttry {\n\t\t\tawait this.#options.lane.setModel(ref, this.#options.context);\n\t\t\treturn { ok: true };\n\t\t} catch (error) {\n\t\t\treturn { ok: false, error: message(error) };\n\t\t}\n\t}\n\n\tclose(): void {\n\t\tfor (const watch of this.#watches.values()) watch.handle.unsubscribe();\n\t\tthis.#watches.clear();\n\t}\n\n\tasync #command(run: () => Promise<{ ok: boolean; error?: { message: string } }>): Promise<CommandResult> {\n\t\ttry {\n\t\t\tconst result = await run();\n\t\t\treturn result.ok ? { ok: true } : { ok: false, error: result.error?.message ?? \"Command failed\" };\n\t\t} catch (error) {\n\t\t\treturn { ok: false, error: message(error) };\n\t\t}\n\t}\n}\n\nfunction message(error: unknown): string {\n\treturn error instanceof Error ? error.message : String(error);\n}\n"]}
|
|
@@ -1,97 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Worker-side implementation of the `Lane` service.
|
|
3
|
-
*
|
|
4
|
-
* The lane, harness, and model registry stay here. Each presentation gets its own `lane.watch()`,
|
|
5
|
-
* whose snapshot and event stream the harness already pairs with no gap and no duplicate, so nothing
|
|
6
|
-
* here re-implements that alignment: a subscription is just a watch handle plus an id.
|
|
7
|
-
*/
|
|
8
|
-
import { randomUUID } from "node:crypto";
|
|
9
|
-
export class LaneService {
|
|
10
|
-
#options;
|
|
11
|
-
#watches = new Map();
|
|
12
|
-
constructor(options) {
|
|
13
|
-
this.#options = options;
|
|
14
|
-
}
|
|
15
|
-
/** Capture a snapshot. The harness buffers this subscription's events until `start`. */
|
|
16
|
-
async watch(presentationId) {
|
|
17
|
-
const { lane, context, session } = this.#options;
|
|
18
|
-
const subscriptionId = randomUUID();
|
|
19
|
-
const handle = await lane.watch(context);
|
|
20
|
-
try {
|
|
21
|
-
this.#watches.set(subscriptionId, { handle, to: presentationId });
|
|
22
|
-
const snapshot = {
|
|
23
|
-
sessionId: session.id,
|
|
24
|
-
cwd: session.cwd,
|
|
25
|
-
sessionPath: session.path,
|
|
26
|
-
lane: handle.snapshot,
|
|
27
|
-
models: this.#options.modelsState(),
|
|
28
|
-
};
|
|
29
|
-
return { subscriptionId, snapshot };
|
|
30
|
-
}
|
|
31
|
-
catch (error) {
|
|
32
|
-
// A watcher that is never started buffers without bound.
|
|
33
|
-
handle.unsubscribe();
|
|
34
|
-
throw error;
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
/** Begin delivery, draining what buffered since the snapshot. */
|
|
38
|
-
async start(subscriptionId) {
|
|
39
|
-
const watch = this.#watches.get(subscriptionId);
|
|
40
|
-
if (!watch)
|
|
41
|
-
throw new Error(`Unknown subscription: ${subscriptionId}`);
|
|
42
|
-
watch.handle.start((event) => this.#options.publish(subscriptionId, watch.to, event));
|
|
43
|
-
}
|
|
44
|
-
async unwatch(subscriptionId) {
|
|
45
|
-
this.#watches.get(subscriptionId)?.handle.unsubscribe();
|
|
46
|
-
this.#watches.delete(subscriptionId);
|
|
47
|
-
}
|
|
48
|
-
prompt(text) {
|
|
49
|
-
return this.#command(() => this.#options.lane.prompt(text, undefined, this.#options.context));
|
|
50
|
-
}
|
|
51
|
-
steer(text) {
|
|
52
|
-
return this.#command(() => this.#options.lane.steer(text, undefined, this.#options.context));
|
|
53
|
-
}
|
|
54
|
-
followUp(text) {
|
|
55
|
-
return this.#command(() => this.#options.lane.followUp(text, undefined, this.#options.context));
|
|
56
|
-
}
|
|
57
|
-
compact() {
|
|
58
|
-
return this.#command(() => this.#options.lane.compact(undefined, this.#options.context));
|
|
59
|
-
}
|
|
60
|
-
abort() {
|
|
61
|
-
return this.#command(() => this.#options.lane.abort(this.#options.context));
|
|
62
|
-
}
|
|
63
|
-
/**
|
|
64
|
-
* The lane stores a durable identity, so the ref passes straight through. The registry lookup is
|
|
65
|
-
* only a courtesy: an identity this worker cannot serve fails at generation time otherwise.
|
|
66
|
-
*/
|
|
67
|
-
async setModel(ref) {
|
|
68
|
-
if (!this.#options.models.getModel(ref.provider, ref.modelId)) {
|
|
69
|
-
return { ok: false, error: `Unknown model: ${ref.provider}/${ref.modelId}` };
|
|
70
|
-
}
|
|
71
|
-
try {
|
|
72
|
-
await this.#options.lane.setModel(ref, this.#options.context);
|
|
73
|
-
return { ok: true };
|
|
74
|
-
}
|
|
75
|
-
catch (error) {
|
|
76
|
-
return { ok: false, error: message(error) };
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
close() {
|
|
80
|
-
for (const watch of this.#watches.values())
|
|
81
|
-
watch.handle.unsubscribe();
|
|
82
|
-
this.#watches.clear();
|
|
83
|
-
}
|
|
84
|
-
async #command(run) {
|
|
85
|
-
try {
|
|
86
|
-
const result = await run();
|
|
87
|
-
return result.ok ? { ok: true } : { ok: false, error: result.error?.message ?? "Command failed" };
|
|
88
|
-
}
|
|
89
|
-
catch (error) {
|
|
90
|
-
return { ok: false, error: message(error) };
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
function message(error) {
|
|
95
|
-
return error instanceof Error ? error.message : String(error);
|
|
96
|
-
}
|
|
97
|
-
//# sourceMappingURL=lane-service.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"lane-service.js","sourceRoot":"","sources":["../../../../src/experimental/mini/worker/lane-service.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Worker-side implementation of the `Lane` service.\n *\n * The lane, harness, and model registry stay here. Each presentation gets its own `lane.watch()`,\n * whose snapshot and event stream the harness already pairs with no gap and no duplicate, so nothing\n * here re-implements that alignment: a subscription is just a watch handle plus an id.\n */\n\nimport { randomUUID } from \"node:crypto\";\nimport type { AgentLane, Context, HarnessEvent, LaneSnapshot, WatchHandle } from \"@earendil-works/pi-agent-core\";\nimport type { Models } from \"@earendil-works/pi-ai\";\nimport type {\n\tCommandResult,\n\tLaneServiceApi,\n\tLaneSubscription,\n\tModelRef,\n\tModelsState,\n\tSessionSnapshot,\n} from \"../shared/protocol.ts\";\n\nexport interface LaneServiceOptions {\n\tlane: AgentLane;\n\tmodels: Models;\n\tcontext: Context;\n\tsession: { id: string; cwd: string; path: string };\n\t/** Model catalog state belongs to the `Models` service; the snapshot carries a copy. */\n\tmodelsState: () => ModelsState;\n\tpublish: (subscriptionId: string, to: string, event: HarnessEvent) => void;\n}\n\nexport class LaneService implements LaneServiceApi {\n\treadonly #options: LaneServiceOptions;\n\treadonly #watches = new Map<string, { handle: WatchHandle<LaneSnapshot>; to: string }>();\n\n\tconstructor(options: LaneServiceOptions) {\n\t\tthis.#options = options;\n\t}\n\n\t/** Capture a snapshot. The harness buffers this subscription's events until `start`. */\n\tasync watch(presentationId: string): Promise<LaneSubscription> {\n\t\tconst { lane, context, session } = this.#options;\n\t\tconst subscriptionId = randomUUID();\n\t\tconst handle = await lane.watch(context);\n\t\ttry {\n\t\t\tthis.#watches.set(subscriptionId, { handle, to: presentationId });\n\t\t\tconst snapshot: SessionSnapshot = {\n\t\t\t\tsessionId: session.id,\n\t\t\t\tcwd: session.cwd,\n\t\t\t\tsessionPath: session.path,\n\t\t\t\tlane: handle.snapshot,\n\t\t\t\tmodels: this.#options.modelsState(),\n\t\t\t};\n\t\t\treturn { subscriptionId, snapshot };\n\t\t} catch (error) {\n\t\t\t// A watcher that is never started buffers without bound.\n\t\t\thandle.unsubscribe();\n\t\t\tthrow error;\n\t\t}\n\t}\n\n\t/** Begin delivery, draining what buffered since the snapshot. */\n\tasync start(subscriptionId: string): Promise<void> {\n\t\tconst watch = this.#watches.get(subscriptionId);\n\t\tif (!watch) throw new Error(`Unknown subscription: ${subscriptionId}`);\n\t\twatch.handle.start((event) => this.#options.publish(subscriptionId, watch.to, event));\n\t}\n\n\tasync unwatch(subscriptionId: string): Promise<void> {\n\t\tthis.#watches.get(subscriptionId)?.handle.unsubscribe();\n\t\tthis.#watches.delete(subscriptionId);\n\t}\n\n\tprompt(text: string): Promise<CommandResult> {\n\t\treturn this.#command(() => this.#options.lane.prompt(text, undefined, this.#options.context));\n\t}\n\n\tsteer(text: string): Promise<CommandResult> {\n\t\treturn this.#command(() => this.#options.lane.steer(text, undefined, this.#options.context));\n\t}\n\n\tfollowUp(text: string): Promise<CommandResult> {\n\t\treturn this.#command(() => this.#options.lane.followUp(text, undefined, this.#options.context));\n\t}\n\n\tcompact(): Promise<CommandResult> {\n\t\treturn this.#command(() => this.#options.lane.compact(undefined, this.#options.context));\n\t}\n\n\tabort(): Promise<CommandResult> {\n\t\treturn this.#command(() => this.#options.lane.abort(this.#options.context));\n\t}\n\n\t/**\n\t * The lane stores a durable identity, so the ref passes straight through. The registry lookup is\n\t * only a courtesy: an identity this worker cannot serve fails at generation time otherwise.\n\t */\n\tasync setModel(ref: ModelRef): Promise<CommandResult> {\n\t\tif (!this.#options.models.getModel(ref.provider, ref.modelId)) {\n\t\t\treturn { ok: false, error: `Unknown model: ${ref.provider}/${ref.modelId}` };\n\t\t}\n\t\ttry {\n\t\t\tawait this.#options.lane.setModel(ref, this.#options.context);\n\t\t\treturn { ok: true };\n\t\t} catch (error) {\n\t\t\treturn { ok: false, error: message(error) };\n\t\t}\n\t}\n\n\tclose(): void {\n\t\tfor (const watch of this.#watches.values()) watch.handle.unsubscribe();\n\t\tthis.#watches.clear();\n\t}\n\n\tasync #command(run: () => Promise<{ ok: boolean; error?: { message: string } }>): Promise<CommandResult> {\n\t\ttry {\n\t\t\tconst result = await run();\n\t\t\treturn result.ok ? { ok: true } : { ok: false, error: result.error?.message ?? \"Command failed\" };\n\t\t} catch (error) {\n\t\t\treturn { ok: false, error: message(error) };\n\t\t}\n\t}\n}\n\nfunction message(error: unknown): string {\n\treturn error instanceof Error ? error.message : String(error);\n}\n"]}
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Worker-side implementation of the `Models` service.
|
|
3
|
-
*
|
|
4
|
-
* `ModelRuntime`, `Model`, and provider objects stay here. What leaves is a serializable catalog and
|
|
5
|
-
* account list, plus login prompts and notices as data.
|
|
6
|
-
*/
|
|
7
|
-
import type { ModelRuntime } from "../../../core/model-runtime.ts";
|
|
8
|
-
import type { CommandResult, ModelsEvent, ModelsServiceApi, ModelsState, ProviderAccount } from "../shared/protocol.ts";
|
|
9
|
-
export declare class ModelsService implements ModelsServiceApi {
|
|
10
|
-
#private;
|
|
11
|
-
constructor(runtime: ModelRuntime, publish: (event: ModelsEvent) => void);
|
|
12
|
-
get state(): ModelsState;
|
|
13
|
-
refresh(): Promise<CommandResult>;
|
|
14
|
-
/** Prompts and notices travel to the presentation as events; answers come back via `authReply`. */
|
|
15
|
-
login(providerId: string, authType: ProviderAccount["authType"]): Promise<CommandResult>;
|
|
16
|
-
authReply(requestId: string, answer: string | null): Promise<void>;
|
|
17
|
-
logout(providerId: string): Promise<CommandResult>;
|
|
18
|
-
}
|
|
19
|
-
//# sourceMappingURL=models-service.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"models-service.d.ts","sourceRoot":"","sources":["../../../../src/experimental/mini/worker/models-service.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,gCAAgC,CAAC;AAEnE,OAAO,KAAK,EAEX,aAAa,EACb,WAAW,EACX,gBAAgB,EAChB,WAAW,EACX,eAAe,EACf,MAAM,uBAAuB,CAAC;AAI/B,qBAAa,aAAc,YAAW,gBAAgB;;IAOrD,YAAY,OAAO,EAAE,YAAY,EAAE,OAAO,EAAE,CAAC,KAAK,EAAE,WAAW,KAAK,IAAI,EAIvE;IAED,IAAI,KAAK,IAAI,WAAW,CAEvB;IAEK,OAAO,IAAI,OAAO,CAAC,aAAa,CAAC,CAetC;IAED,mGAAmG;IAC7F,KAAK,CAAC,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,eAAe,CAAC,UAAU,CAAC,GAAG,OAAO,CAAC,aAAa,CAAC,CAe7F;IAEK,SAAS,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAIvE;IAsBK,MAAM,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC,CASvD;CAMD","sourcesContent":["/**\n * Worker-side implementation of the `Models` service.\n *\n * `ModelRuntime`, `Model`, and provider objects stay here. What leaves is a serializable catalog and\n * account list, plus login prompts and notices as data.\n */\n\nimport { randomUUID } from \"node:crypto\";\nimport type { ModelRuntime } from \"../../../core/model-runtime.ts\";\nimport { refreshModelCatalogs } from \"../../../modes/interactive/model-catalog-refresh.ts\";\nimport type {\n\tAuthPromptRequest,\n\tCommandResult,\n\tModelsEvent,\n\tModelsServiceApi,\n\tModelsState,\n\tProviderAccount,\n} from \"../shared/protocol.ts\";\n\nconst CATALOG_REFRESH_TIMEOUT_MS = 15_000;\n\nexport class ModelsService implements ModelsServiceApi {\n\treadonly #runtime: ModelRuntime;\n\treadonly #publish: (event: ModelsEvent) => void;\n\t/** Prompts issued to the presentation, awaiting `authReply`. */\n\treadonly #pendingAuth = new Map<string, (answer: string | null) => void>();\n\t#state: ModelsState;\n\n\tconstructor(runtime: ModelRuntime, publish: (event: ModelsEvent) => void) {\n\t\tthis.#runtime = runtime;\n\t\tthis.#publish = publish;\n\t\tthis.#state = readState(runtime, false);\n\t}\n\n\tget state(): ModelsState {\n\t\treturn this.#state;\n\t}\n\n\tasync refresh(): Promise<CommandResult> {\n\t\tthis.#update(true);\n\t\tconst controller = new AbortController();\n\t\tconst timeout = setTimeout(() => controller.abort(), CATALOG_REFRESH_TIMEOUT_MS);\n\t\ttry {\n\t\t\tconst result = await refreshModelCatalogs(this.#runtime, controller.signal);\n\t\t\treturn result.errors.size === 0\n\t\t\t\t? { ok: true }\n\t\t\t\t: { ok: false, error: `Some catalogs could not be refreshed: ${[...result.errors.keys()].join(\", \")}` };\n\t\t} catch (error) {\n\t\t\treturn { ok: false, error: message(error) };\n\t\t} finally {\n\t\t\tclearTimeout(timeout);\n\t\t\tthis.#update(false);\n\t\t}\n\t}\n\n\t/** Prompts and notices travel to the presentation as events; answers come back via `authReply`. */\n\tasync login(providerId: string, authType: ProviderAccount[\"authType\"]): Promise<CommandResult> {\n\t\ttry {\n\t\t\tawait this.#runtime.login(providerId, authType, {\n\t\t\t\tprompt: (prompt) => {\n\t\t\t\t\tconst { signal, ...request } = prompt;\n\t\t\t\t\treturn this.#ask(request, signal);\n\t\t\t\t},\n\t\t\t\tnotify: (notice) => this.#publish({ type: \"notice\", notice }),\n\t\t\t});\n\t\t\treturn { ok: true };\n\t\t} catch (error) {\n\t\t\treturn { ok: false, error: message(error) };\n\t\t} finally {\n\t\t\tthis.#update(false);\n\t\t}\n\t}\n\n\tasync authReply(requestId: string, answer: string | null): Promise<void> {\n\t\tconst waiter = this.#pendingAuth.get(requestId);\n\t\tthis.#pendingAuth.delete(requestId);\n\t\twaiter?.(answer);\n\t}\n\n\t/** Ask the presentation one question, honouring a provider-supplied deadline. */\n\t#ask(request: AuthPromptRequest, signal: AbortSignal | undefined): Promise<string> {\n\t\tif (signal?.aborted) return Promise.reject(new Error(\"Login cancelled\"));\n\t\treturn new Promise<string>((resolve, reject) => {\n\t\t\tconst requestId = randomUUID();\n\t\t\tconst settle = (answer: string | null): void => {\n\t\t\t\tsignal?.removeEventListener(\"abort\", onAbort);\n\t\t\t\tif (answer === null) reject(new Error(\"Login cancelled\"));\n\t\t\t\telse resolve(answer);\n\t\t\t};\n\t\t\tconst onAbort = (): void => {\n\t\t\t\tthis.#pendingAuth.delete(requestId);\n\t\t\t\treject(new Error(\"Login cancelled\"));\n\t\t\t};\n\t\t\tthis.#pendingAuth.set(requestId, settle);\n\t\t\tsignal?.addEventListener(\"abort\", onAbort, { once: true });\n\t\t\tthis.#publish({ type: \"prompt\", requestId, request });\n\t\t});\n\t}\n\n\tasync logout(providerId: string): Promise<CommandResult> {\n\t\ttry {\n\t\t\tawait this.#runtime.logout(providerId);\n\t\t\treturn { ok: true };\n\t\t} catch (error) {\n\t\t\treturn { ok: false, error: message(error) };\n\t\t} finally {\n\t\t\tthis.#update(false);\n\t\t}\n\t}\n\n\t#update(refreshing: boolean): void {\n\t\tthis.#state = readState(this.#runtime, refreshing);\n\t\tthis.#publish({ type: \"state\", state: this.#state });\n\t}\n}\n\nfunction readState(runtime: ModelRuntime, refreshing: boolean): ModelsState {\n\tconst models = runtime\n\t\t.getAvailableSnapshot()\n\t\t.map((model) => ({ provider: model.provider, modelId: model.id, name: model.name }));\n\tconst accounts: ProviderAccount[] = [];\n\tfor (const provider of runtime.getProviders()) {\n\t\tconst status = runtime.getProviderAuthStatus(provider.id);\n\t\tconst shared = {\n\t\t\tid: provider.id,\n\t\t\tname: provider.name,\n\t\t\tconfigured: status.configured,\n\t\t\t...((status.label ?? status.source === undefined) ? {} : { source: status.label ?? status.source }),\n\t\t};\n\t\tif (provider.auth.oauth) {\n\t\t\taccounts.push({ ...shared, authType: \"oauth\", interactive: true, methodName: provider.auth.oauth.name });\n\t\t}\n\t\tif (provider.auth.apiKey) {\n\t\t\taccounts.push({\n\t\t\t\t...shared,\n\t\t\t\tauthType: \"api_key\",\n\t\t\t\tinteractive: provider.auth.apiKey.login !== undefined,\n\t\t\t\tmethodName: provider.auth.apiKey.name,\n\t\t\t});\n\t\t}\n\t}\n\taccounts.sort((left, right) => left.name.localeCompare(right.name));\n\treturn { models, accounts, refreshing };\n}\n\nfunction message(error: unknown): string {\n\treturn error instanceof Error ? error.message : String(error);\n}\n"]}
|
|
@@ -1,136 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Worker-side implementation of the `Models` service.
|
|
3
|
-
*
|
|
4
|
-
* `ModelRuntime`, `Model`, and provider objects stay here. What leaves is a serializable catalog and
|
|
5
|
-
* account list, plus login prompts and notices as data.
|
|
6
|
-
*/
|
|
7
|
-
import { randomUUID } from "node:crypto";
|
|
8
|
-
import { refreshModelCatalogs } from "../../../modes/interactive/model-catalog-refresh.js";
|
|
9
|
-
const CATALOG_REFRESH_TIMEOUT_MS = 15_000;
|
|
10
|
-
export class ModelsService {
|
|
11
|
-
#runtime;
|
|
12
|
-
#publish;
|
|
13
|
-
/** Prompts issued to the presentation, awaiting `authReply`. */
|
|
14
|
-
#pendingAuth = new Map();
|
|
15
|
-
#state;
|
|
16
|
-
constructor(runtime, publish) {
|
|
17
|
-
this.#runtime = runtime;
|
|
18
|
-
this.#publish = publish;
|
|
19
|
-
this.#state = readState(runtime, false);
|
|
20
|
-
}
|
|
21
|
-
get state() {
|
|
22
|
-
return this.#state;
|
|
23
|
-
}
|
|
24
|
-
async refresh() {
|
|
25
|
-
this.#update(true);
|
|
26
|
-
const controller = new AbortController();
|
|
27
|
-
const timeout = setTimeout(() => controller.abort(), CATALOG_REFRESH_TIMEOUT_MS);
|
|
28
|
-
try {
|
|
29
|
-
const result = await refreshModelCatalogs(this.#runtime, controller.signal);
|
|
30
|
-
return result.errors.size === 0
|
|
31
|
-
? { ok: true }
|
|
32
|
-
: { ok: false, error: `Some catalogs could not be refreshed: ${[...result.errors.keys()].join(", ")}` };
|
|
33
|
-
}
|
|
34
|
-
catch (error) {
|
|
35
|
-
return { ok: false, error: message(error) };
|
|
36
|
-
}
|
|
37
|
-
finally {
|
|
38
|
-
clearTimeout(timeout);
|
|
39
|
-
this.#update(false);
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
/** Prompts and notices travel to the presentation as events; answers come back via `authReply`. */
|
|
43
|
-
async login(providerId, authType) {
|
|
44
|
-
try {
|
|
45
|
-
await this.#runtime.login(providerId, authType, {
|
|
46
|
-
prompt: (prompt) => {
|
|
47
|
-
const { signal, ...request } = prompt;
|
|
48
|
-
return this.#ask(request, signal);
|
|
49
|
-
},
|
|
50
|
-
notify: (notice) => this.#publish({ type: "notice", notice }),
|
|
51
|
-
});
|
|
52
|
-
return { ok: true };
|
|
53
|
-
}
|
|
54
|
-
catch (error) {
|
|
55
|
-
return { ok: false, error: message(error) };
|
|
56
|
-
}
|
|
57
|
-
finally {
|
|
58
|
-
this.#update(false);
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
async authReply(requestId, answer) {
|
|
62
|
-
const waiter = this.#pendingAuth.get(requestId);
|
|
63
|
-
this.#pendingAuth.delete(requestId);
|
|
64
|
-
waiter?.(answer);
|
|
65
|
-
}
|
|
66
|
-
/** Ask the presentation one question, honouring a provider-supplied deadline. */
|
|
67
|
-
#ask(request, signal) {
|
|
68
|
-
if (signal?.aborted)
|
|
69
|
-
return Promise.reject(new Error("Login cancelled"));
|
|
70
|
-
return new Promise((resolve, reject) => {
|
|
71
|
-
const requestId = randomUUID();
|
|
72
|
-
const settle = (answer) => {
|
|
73
|
-
signal?.removeEventListener("abort", onAbort);
|
|
74
|
-
if (answer === null)
|
|
75
|
-
reject(new Error("Login cancelled"));
|
|
76
|
-
else
|
|
77
|
-
resolve(answer);
|
|
78
|
-
};
|
|
79
|
-
const onAbort = () => {
|
|
80
|
-
this.#pendingAuth.delete(requestId);
|
|
81
|
-
reject(new Error("Login cancelled"));
|
|
82
|
-
};
|
|
83
|
-
this.#pendingAuth.set(requestId, settle);
|
|
84
|
-
signal?.addEventListener("abort", onAbort, { once: true });
|
|
85
|
-
this.#publish({ type: "prompt", requestId, request });
|
|
86
|
-
});
|
|
87
|
-
}
|
|
88
|
-
async logout(providerId) {
|
|
89
|
-
try {
|
|
90
|
-
await this.#runtime.logout(providerId);
|
|
91
|
-
return { ok: true };
|
|
92
|
-
}
|
|
93
|
-
catch (error) {
|
|
94
|
-
return { ok: false, error: message(error) };
|
|
95
|
-
}
|
|
96
|
-
finally {
|
|
97
|
-
this.#update(false);
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
#update(refreshing) {
|
|
101
|
-
this.#state = readState(this.#runtime, refreshing);
|
|
102
|
-
this.#publish({ type: "state", state: this.#state });
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
function readState(runtime, refreshing) {
|
|
106
|
-
const models = runtime
|
|
107
|
-
.getAvailableSnapshot()
|
|
108
|
-
.map((model) => ({ provider: model.provider, modelId: model.id, name: model.name }));
|
|
109
|
-
const accounts = [];
|
|
110
|
-
for (const provider of runtime.getProviders()) {
|
|
111
|
-
const status = runtime.getProviderAuthStatus(provider.id);
|
|
112
|
-
const shared = {
|
|
113
|
-
id: provider.id,
|
|
114
|
-
name: provider.name,
|
|
115
|
-
configured: status.configured,
|
|
116
|
-
...((status.label ?? status.source === undefined) ? {} : { source: status.label ?? status.source }),
|
|
117
|
-
};
|
|
118
|
-
if (provider.auth.oauth) {
|
|
119
|
-
accounts.push({ ...shared, authType: "oauth", interactive: true, methodName: provider.auth.oauth.name });
|
|
120
|
-
}
|
|
121
|
-
if (provider.auth.apiKey) {
|
|
122
|
-
accounts.push({
|
|
123
|
-
...shared,
|
|
124
|
-
authType: "api_key",
|
|
125
|
-
interactive: provider.auth.apiKey.login !== undefined,
|
|
126
|
-
methodName: provider.auth.apiKey.name,
|
|
127
|
-
});
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
accounts.sort((left, right) => left.name.localeCompare(right.name));
|
|
131
|
-
return { models, accounts, refreshing };
|
|
132
|
-
}
|
|
133
|
-
function message(error) {
|
|
134
|
-
return error instanceof Error ? error.message : String(error);
|
|
135
|
-
}
|
|
136
|
-
//# sourceMappingURL=models-service.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"models-service.js","sourceRoot":"","sources":["../../../../src/experimental/mini/worker/models-service.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Worker-side implementation of the `Models` service.\n *\n * `ModelRuntime`, `Model`, and provider objects stay here. What leaves is a serializable catalog and\n * account list, plus login prompts and notices as data.\n */\n\nimport { randomUUID } from \"node:crypto\";\nimport type { ModelRuntime } from \"../../../core/model-runtime.ts\";\nimport { refreshModelCatalogs } from \"../../../modes/interactive/model-catalog-refresh.ts\";\nimport type {\n\tAuthPromptRequest,\n\tCommandResult,\n\tModelsEvent,\n\tModelsServiceApi,\n\tModelsState,\n\tProviderAccount,\n} from \"../shared/protocol.ts\";\n\nconst CATALOG_REFRESH_TIMEOUT_MS = 15_000;\n\nexport class ModelsService implements ModelsServiceApi {\n\treadonly #runtime: ModelRuntime;\n\treadonly #publish: (event: ModelsEvent) => void;\n\t/** Prompts issued to the presentation, awaiting `authReply`. */\n\treadonly #pendingAuth = new Map<string, (answer: string | null) => void>();\n\t#state: ModelsState;\n\n\tconstructor(runtime: ModelRuntime, publish: (event: ModelsEvent) => void) {\n\t\tthis.#runtime = runtime;\n\t\tthis.#publish = publish;\n\t\tthis.#state = readState(runtime, false);\n\t}\n\n\tget state(): ModelsState {\n\t\treturn this.#state;\n\t}\n\n\tasync refresh(): Promise<CommandResult> {\n\t\tthis.#update(true);\n\t\tconst controller = new AbortController();\n\t\tconst timeout = setTimeout(() => controller.abort(), CATALOG_REFRESH_TIMEOUT_MS);\n\t\ttry {\n\t\t\tconst result = await refreshModelCatalogs(this.#runtime, controller.signal);\n\t\t\treturn result.errors.size === 0\n\t\t\t\t? { ok: true }\n\t\t\t\t: { ok: false, error: `Some catalogs could not be refreshed: ${[...result.errors.keys()].join(\", \")}` };\n\t\t} catch (error) {\n\t\t\treturn { ok: false, error: message(error) };\n\t\t} finally {\n\t\t\tclearTimeout(timeout);\n\t\t\tthis.#update(false);\n\t\t}\n\t}\n\n\t/** Prompts and notices travel to the presentation as events; answers come back via `authReply`. */\n\tasync login(providerId: string, authType: ProviderAccount[\"authType\"]): Promise<CommandResult> {\n\t\ttry {\n\t\t\tawait this.#runtime.login(providerId, authType, {\n\t\t\t\tprompt: (prompt) => {\n\t\t\t\t\tconst { signal, ...request } = prompt;\n\t\t\t\t\treturn this.#ask(request, signal);\n\t\t\t\t},\n\t\t\t\tnotify: (notice) => this.#publish({ type: \"notice\", notice }),\n\t\t\t});\n\t\t\treturn { ok: true };\n\t\t} catch (error) {\n\t\t\treturn { ok: false, error: message(error) };\n\t\t} finally {\n\t\t\tthis.#update(false);\n\t\t}\n\t}\n\n\tasync authReply(requestId: string, answer: string | null): Promise<void> {\n\t\tconst waiter = this.#pendingAuth.get(requestId);\n\t\tthis.#pendingAuth.delete(requestId);\n\t\twaiter?.(answer);\n\t}\n\n\t/** Ask the presentation one question, honouring a provider-supplied deadline. */\n\t#ask(request: AuthPromptRequest, signal: AbortSignal | undefined): Promise<string> {\n\t\tif (signal?.aborted) return Promise.reject(new Error(\"Login cancelled\"));\n\t\treturn new Promise<string>((resolve, reject) => {\n\t\t\tconst requestId = randomUUID();\n\t\t\tconst settle = (answer: string | null): void => {\n\t\t\t\tsignal?.removeEventListener(\"abort\", onAbort);\n\t\t\t\tif (answer === null) reject(new Error(\"Login cancelled\"));\n\t\t\t\telse resolve(answer);\n\t\t\t};\n\t\t\tconst onAbort = (): void => {\n\t\t\t\tthis.#pendingAuth.delete(requestId);\n\t\t\t\treject(new Error(\"Login cancelled\"));\n\t\t\t};\n\t\t\tthis.#pendingAuth.set(requestId, settle);\n\t\t\tsignal?.addEventListener(\"abort\", onAbort, { once: true });\n\t\t\tthis.#publish({ type: \"prompt\", requestId, request });\n\t\t});\n\t}\n\n\tasync logout(providerId: string): Promise<CommandResult> {\n\t\ttry {\n\t\t\tawait this.#runtime.logout(providerId);\n\t\t\treturn { ok: true };\n\t\t} catch (error) {\n\t\t\treturn { ok: false, error: message(error) };\n\t\t} finally {\n\t\t\tthis.#update(false);\n\t\t}\n\t}\n\n\t#update(refreshing: boolean): void {\n\t\tthis.#state = readState(this.#runtime, refreshing);\n\t\tthis.#publish({ type: \"state\", state: this.#state });\n\t}\n}\n\nfunction readState(runtime: ModelRuntime, refreshing: boolean): ModelsState {\n\tconst models = runtime\n\t\t.getAvailableSnapshot()\n\t\t.map((model) => ({ provider: model.provider, modelId: model.id, name: model.name }));\n\tconst accounts: ProviderAccount[] = [];\n\tfor (const provider of runtime.getProviders()) {\n\t\tconst status = runtime.getProviderAuthStatus(provider.id);\n\t\tconst shared = {\n\t\t\tid: provider.id,\n\t\t\tname: provider.name,\n\t\t\tconfigured: status.configured,\n\t\t\t...((status.label ?? status.source === undefined) ? {} : { source: status.label ?? status.source }),\n\t\t};\n\t\tif (provider.auth.oauth) {\n\t\t\taccounts.push({ ...shared, authType: \"oauth\", interactive: true, methodName: provider.auth.oauth.name });\n\t\t}\n\t\tif (provider.auth.apiKey) {\n\t\t\taccounts.push({\n\t\t\t\t...shared,\n\t\t\t\tauthType: \"api_key\",\n\t\t\t\tinteractive: provider.auth.apiKey.login !== undefined,\n\t\t\t\tmethodName: provider.auth.apiKey.name,\n\t\t\t});\n\t\t}\n\t}\n\taccounts.sort((left, right) => left.name.localeCompare(right.name));\n\treturn { models, accounts, refreshing };\n}\n\nfunction message(error: unknown): string {\n\treturn error instanceof Error ? error.message : String(error);\n}\n"]}
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Session worker: one process per session.
|
|
3
|
-
*
|
|
4
|
-
* It owns every live object — storage, harness, lane, model runtime — and publishes them only as the
|
|
5
|
-
* `Lane` and `Models` services. It speaks JSON over its stdio pipes to the server that spawned it,
|
|
6
|
-
* and can call server services (`Sessions`) over the same peer.
|
|
7
|
-
*/
|
|
8
|
-
/** Run one session worker until its stdio closes. `sessionId` undefined creates a new session. */
|
|
9
|
-
export declare function runSessionWorker(options: {
|
|
10
|
-
sessionsRoot: string;
|
|
11
|
-
sessionId?: string;
|
|
12
|
-
cwd: string;
|
|
13
|
-
}): Promise<void>;
|
|
14
|
-
//# sourceMappingURL=run.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"run.d.ts","sourceRoot":"","sources":["../../../../src/experimental/mini/worker/run.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AA4CH,kGAAkG;AAClG,wBAAsB,gBAAgB,CAAC,OAAO,EAAE;IAC/C,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,GAAG,EAAE,MAAM,CAAC;CACZ,GAAG,OAAO,CAAC,IAAI,CAAC,CAyDhB","sourcesContent":["/**\n * Session worker: one process per session.\n *\n * It owns every live object — storage, harness, lane, model runtime — and publishes them only as the\n * `Lane` and `Models` services. It speaks JSON over its stdio pipes to the server that spawned it,\n * and can call server services (`Sessions`) over the same peer.\n */\n\nimport {\n\tAgentHarness,\n\tBACKGROUND_CONTEXT,\n\ttype Context,\n\tcreateBashTool,\n\tcreateEditTool,\n\tcreateReadTool,\n\tcreateWriteTool,\n\ttype JsonlSessionMetadata,\n\tJsonlSessionRepo,\n\ttype Session,\n} from \"@earendil-works/pi-agent-core\";\nimport { NodeExecutionEnv } from \"@earendil-works/pi-agent-core/node\";\nimport { findInitialModel } from \"../../../core/model-resolver.ts\";\nimport { ModelRuntime } from \"../../../core/model-runtime.ts\";\nimport { Lane, Models, Worker } from \"../shared/protocol.ts\";\nimport { createPeer } from \"../shared/rpc.ts\";\nimport { parentConnection } from \"../shared/transport.ts\";\nimport { LaneService } from \"./lane-service.ts\";\nimport { ModelsService } from \"./models-service.ts\";\n\nfunction systemPrompt(cwd: string): string {\n\treturn [\n\t\t\"You are a coding agent working in a terminal.\",\n\t\t`Working directory: ${cwd}`,\n\t\t\"Use the read, write, edit, and bash tools to inspect and change files.\",\n\t\t\"Keep answers short and technical.\",\n\t].join(\"\\n\");\n}\n\nasync function openSession(\n\trepo: JsonlSessionRepo,\n\tsessionId: string | undefined,\n\tcwd: string,\n\tcontext: Context,\n): Promise<Session<JsonlSessionMetadata>> {\n\tif (sessionId === undefined) return repo.create({ cwd }, context);\n\tconst metadata = (await repo.list(undefined, context)).find((candidate) => candidate.id === sessionId);\n\tif (!metadata) throw new Error(`Unknown session: ${sessionId}`);\n\treturn repo.open(metadata, context);\n}\n\n/** Run one session worker until its stdio closes. `sessionId` undefined creates a new session. */\nexport async function runSessionWorker(options: {\n\tsessionsRoot: string;\n\tsessionId?: string;\n\tcwd: string;\n}): Promise<void> {\n\tconst context = BACKGROUND_CONTEXT;\n\tconst { cwd } = options;\n\tconst modelRuntime = await ModelRuntime.create();\n\tconst { model, thinkingLevel } = await findInitialModel({ scopedModels: [], isContinuing: false, modelRuntime });\n\tif (!model) throw new Error(\"No model available. Configure credentials with `pi` first.\");\n\n\tconst executionEnv = new NodeExecutionEnv({ cwd });\n\tconst repo = new JsonlSessionRepo({ fileSystem: executionEnv, sessionsRoot: options.sessionsRoot });\n\tconst session = await openSession(repo, options.sessionId, cwd, context);\n\tconst { harness, open } = await AgentHarness.create(\n\t\t{\n\t\t\tsession,\n\t\t\tmodels: modelRuntime,\n\t\t\tmodel,\n\t\t\tthinkingLevel,\n\t\t\ttools: [createReadTool(), createWriteTool(), createEditTool(), createBashTool()],\n\t\t\ttoolContext: { env: executionEnv },\n\t\t\tsystemPrompt: systemPrompt(cwd),\n\t\t},\n\t\tcontext,\n\t);\n\tconst lane = await harness.lane(\"main\", context);\n\tconst connection = parentConnection();\n\tconst peer = createPeer(connection);\n\n\tconst models = new ModelsService(modelRuntime, (event) => peer.emit(Models, event));\n\tconst laneService = new LaneService({\n\t\tlane,\n\t\tmodels: modelRuntime,\n\t\tcontext,\n\t\tsession: { id: session.metadata.id, cwd, path: session.metadata.path },\n\t\tmodelsState: () => models.state,\n\t\tpublish: (subscriptionId, to, event) => peer.emitTo(Lane, { subscriptionId, event }, to),\n\t});\n\tpeer.provide(Lane, laneService);\n\tpeer.provide(Models, models);\n\tpeer.provide(Worker, { describe: async () => ({ sessionId: session.metadata.id }) });\n\n\t// Creation restores durable operation state without starting effects. Once services are reachable,\n\t// install a new process-local drive for every operation left open by the previous worker.\n\tconst recoveries = open.map(async (operation) => {\n\t\ttry {\n\t\t\tconst restoredLane = operation.lane === lane.name ? lane : await harness.lane(operation.lane, context);\n\t\t\tconst result = await restoredLane.resume(context);\n\t\t\tif (!result.ok) throw result.error;\n\t\t} catch (error) {\n\t\t\tconsole.error(`Failed to resume ${operation.lane}/${operation.operationId}:`, error);\n\t\t}\n\t});\n\n\tawait new Promise<void>((resolve) => connection.onClose(resolve));\n\tlaneService.close();\n\tawait harness.close(context).catch(() => {});\n\tawait Promise.all(recoveries);\n\tawait repo.close(context).catch(() => {});\n\tawait executionEnv.cleanup(context).catch(() => {});\n}\n"]}
|
|
@@ -1,88 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Session worker: one process per session.
|
|
3
|
-
*
|
|
4
|
-
* It owns every live object — storage, harness, lane, model runtime — and publishes them only as the
|
|
5
|
-
* `Lane` and `Models` services. It speaks JSON over its stdio pipes to the server that spawned it,
|
|
6
|
-
* and can call server services (`Sessions`) over the same peer.
|
|
7
|
-
*/
|
|
8
|
-
import { AgentHarness, BACKGROUND_CONTEXT, createBashTool, createEditTool, createReadTool, createWriteTool, JsonlSessionRepo, } from "@earendil-works/pi-agent-core";
|
|
9
|
-
import { NodeExecutionEnv } from "@earendil-works/pi-agent-core/node";
|
|
10
|
-
import { findInitialModel } from "../../../core/model-resolver.js";
|
|
11
|
-
import { ModelRuntime } from "../../../core/model-runtime.js";
|
|
12
|
-
import { Lane, Models, Worker } from "../shared/protocol.js";
|
|
13
|
-
import { createPeer } from "../shared/rpc.js";
|
|
14
|
-
import { parentConnection } from "../shared/transport.js";
|
|
15
|
-
import { LaneService } from "./lane-service.js";
|
|
16
|
-
import { ModelsService } from "./models-service.js";
|
|
17
|
-
function systemPrompt(cwd) {
|
|
18
|
-
return [
|
|
19
|
-
"You are a coding agent working in a terminal.",
|
|
20
|
-
`Working directory: ${cwd}`,
|
|
21
|
-
"Use the read, write, edit, and bash tools to inspect and change files.",
|
|
22
|
-
"Keep answers short and technical.",
|
|
23
|
-
].join("\n");
|
|
24
|
-
}
|
|
25
|
-
async function openSession(repo, sessionId, cwd, context) {
|
|
26
|
-
if (sessionId === undefined)
|
|
27
|
-
return repo.create({ cwd }, context);
|
|
28
|
-
const metadata = (await repo.list(undefined, context)).find((candidate) => candidate.id === sessionId);
|
|
29
|
-
if (!metadata)
|
|
30
|
-
throw new Error(`Unknown session: ${sessionId}`);
|
|
31
|
-
return repo.open(metadata, context);
|
|
32
|
-
}
|
|
33
|
-
/** Run one session worker until its stdio closes. `sessionId` undefined creates a new session. */
|
|
34
|
-
export async function runSessionWorker(options) {
|
|
35
|
-
const context = BACKGROUND_CONTEXT;
|
|
36
|
-
const { cwd } = options;
|
|
37
|
-
const modelRuntime = await ModelRuntime.create();
|
|
38
|
-
const { model, thinkingLevel } = await findInitialModel({ scopedModels: [], isContinuing: false, modelRuntime });
|
|
39
|
-
if (!model)
|
|
40
|
-
throw new Error("No model available. Configure credentials with `pi` first.");
|
|
41
|
-
const executionEnv = new NodeExecutionEnv({ cwd });
|
|
42
|
-
const repo = new JsonlSessionRepo({ fileSystem: executionEnv, sessionsRoot: options.sessionsRoot });
|
|
43
|
-
const session = await openSession(repo, options.sessionId, cwd, context);
|
|
44
|
-
const { harness, open } = await AgentHarness.create({
|
|
45
|
-
session,
|
|
46
|
-
models: modelRuntime,
|
|
47
|
-
model,
|
|
48
|
-
thinkingLevel,
|
|
49
|
-
tools: [createReadTool(), createWriteTool(), createEditTool(), createBashTool()],
|
|
50
|
-
toolContext: { env: executionEnv },
|
|
51
|
-
systemPrompt: systemPrompt(cwd),
|
|
52
|
-
}, context);
|
|
53
|
-
const lane = await harness.lane("main", context);
|
|
54
|
-
const connection = parentConnection();
|
|
55
|
-
const peer = createPeer(connection);
|
|
56
|
-
const models = new ModelsService(modelRuntime, (event) => peer.emit(Models, event));
|
|
57
|
-
const laneService = new LaneService({
|
|
58
|
-
lane,
|
|
59
|
-
models: modelRuntime,
|
|
60
|
-
context,
|
|
61
|
-
session: { id: session.metadata.id, cwd, path: session.metadata.path },
|
|
62
|
-
modelsState: () => models.state,
|
|
63
|
-
publish: (subscriptionId, to, event) => peer.emitTo(Lane, { subscriptionId, event }, to),
|
|
64
|
-
});
|
|
65
|
-
peer.provide(Lane, laneService);
|
|
66
|
-
peer.provide(Models, models);
|
|
67
|
-
peer.provide(Worker, { describe: async () => ({ sessionId: session.metadata.id }) });
|
|
68
|
-
// Creation restores durable operation state without starting effects. Once services are reachable,
|
|
69
|
-
// install a new process-local drive for every operation left open by the previous worker.
|
|
70
|
-
const recoveries = open.map(async (operation) => {
|
|
71
|
-
try {
|
|
72
|
-
const restoredLane = operation.lane === lane.name ? lane : await harness.lane(operation.lane, context);
|
|
73
|
-
const result = await restoredLane.resume(context);
|
|
74
|
-
if (!result.ok)
|
|
75
|
-
throw result.error;
|
|
76
|
-
}
|
|
77
|
-
catch (error) {
|
|
78
|
-
console.error(`Failed to resume ${operation.lane}/${operation.operationId}:`, error);
|
|
79
|
-
}
|
|
80
|
-
});
|
|
81
|
-
await new Promise((resolve) => connection.onClose(resolve));
|
|
82
|
-
laneService.close();
|
|
83
|
-
await harness.close(context).catch(() => { });
|
|
84
|
-
await Promise.all(recoveries);
|
|
85
|
-
await repo.close(context).catch(() => { });
|
|
86
|
-
await executionEnv.cleanup(context).catch(() => { });
|
|
87
|
-
}
|
|
88
|
-
//# sourceMappingURL=run.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"run.js","sourceRoot":"","sources":["../../../../src/experimental/mini/worker/run.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Session worker: one process per session.\n *\n * It owns every live object — storage, harness, lane, model runtime — and publishes them only as the\n * `Lane` and `Models` services. It speaks JSON over its stdio pipes to the server that spawned it,\n * and can call server services (`Sessions`) over the same peer.\n */\n\nimport {\n\tAgentHarness,\n\tBACKGROUND_CONTEXT,\n\ttype Context,\n\tcreateBashTool,\n\tcreateEditTool,\n\tcreateReadTool,\n\tcreateWriteTool,\n\ttype JsonlSessionMetadata,\n\tJsonlSessionRepo,\n\ttype Session,\n} from \"@earendil-works/pi-agent-core\";\nimport { NodeExecutionEnv } from \"@earendil-works/pi-agent-core/node\";\nimport { findInitialModel } from \"../../../core/model-resolver.ts\";\nimport { ModelRuntime } from \"../../../core/model-runtime.ts\";\nimport { Lane, Models, Worker } from \"../shared/protocol.ts\";\nimport { createPeer } from \"../shared/rpc.ts\";\nimport { parentConnection } from \"../shared/transport.ts\";\nimport { LaneService } from \"./lane-service.ts\";\nimport { ModelsService } from \"./models-service.ts\";\n\nfunction systemPrompt(cwd: string): string {\n\treturn [\n\t\t\"You are a coding agent working in a terminal.\",\n\t\t`Working directory: ${cwd}`,\n\t\t\"Use the read, write, edit, and bash tools to inspect and change files.\",\n\t\t\"Keep answers short and technical.\",\n\t].join(\"\\n\");\n}\n\nasync function openSession(\n\trepo: JsonlSessionRepo,\n\tsessionId: string | undefined,\n\tcwd: string,\n\tcontext: Context,\n): Promise<Session<JsonlSessionMetadata>> {\n\tif (sessionId === undefined) return repo.create({ cwd }, context);\n\tconst metadata = (await repo.list(undefined, context)).find((candidate) => candidate.id === sessionId);\n\tif (!metadata) throw new Error(`Unknown session: ${sessionId}`);\n\treturn repo.open(metadata, context);\n}\n\n/** Run one session worker until its stdio closes. `sessionId` undefined creates a new session. */\nexport async function runSessionWorker(options: {\n\tsessionsRoot: string;\n\tsessionId?: string;\n\tcwd: string;\n}): Promise<void> {\n\tconst context = BACKGROUND_CONTEXT;\n\tconst { cwd } = options;\n\tconst modelRuntime = await ModelRuntime.create();\n\tconst { model, thinkingLevel } = await findInitialModel({ scopedModels: [], isContinuing: false, modelRuntime });\n\tif (!model) throw new Error(\"No model available. Configure credentials with `pi` first.\");\n\n\tconst executionEnv = new NodeExecutionEnv({ cwd });\n\tconst repo = new JsonlSessionRepo({ fileSystem: executionEnv, sessionsRoot: options.sessionsRoot });\n\tconst session = await openSession(repo, options.sessionId, cwd, context);\n\tconst { harness, open } = await AgentHarness.create(\n\t\t{\n\t\t\tsession,\n\t\t\tmodels: modelRuntime,\n\t\t\tmodel,\n\t\t\tthinkingLevel,\n\t\t\ttools: [createReadTool(), createWriteTool(), createEditTool(), createBashTool()],\n\t\t\ttoolContext: { env: executionEnv },\n\t\t\tsystemPrompt: systemPrompt(cwd),\n\t\t},\n\t\tcontext,\n\t);\n\tconst lane = await harness.lane(\"main\", context);\n\tconst connection = parentConnection();\n\tconst peer = createPeer(connection);\n\n\tconst models = new ModelsService(modelRuntime, (event) => peer.emit(Models, event));\n\tconst laneService = new LaneService({\n\t\tlane,\n\t\tmodels: modelRuntime,\n\t\tcontext,\n\t\tsession: { id: session.metadata.id, cwd, path: session.metadata.path },\n\t\tmodelsState: () => models.state,\n\t\tpublish: (subscriptionId, to, event) => peer.emitTo(Lane, { subscriptionId, event }, to),\n\t});\n\tpeer.provide(Lane, laneService);\n\tpeer.provide(Models, models);\n\tpeer.provide(Worker, { describe: async () => ({ sessionId: session.metadata.id }) });\n\n\t// Creation restores durable operation state without starting effects. Once services are reachable,\n\t// install a new process-local drive for every operation left open by the previous worker.\n\tconst recoveries = open.map(async (operation) => {\n\t\ttry {\n\t\t\tconst restoredLane = operation.lane === lane.name ? lane : await harness.lane(operation.lane, context);\n\t\t\tconst result = await restoredLane.resume(context);\n\t\t\tif (!result.ok) throw result.error;\n\t\t} catch (error) {\n\t\t\tconsole.error(`Failed to resume ${operation.lane}/${operation.operationId}:`, error);\n\t\t}\n\t});\n\n\tawait new Promise<void>((resolve) => connection.onClose(resolve));\n\tlaneService.close();\n\tawait harness.close(context).catch(() => {});\n\tawait Promise.all(recoveries);\n\tawait repo.close(context).catch(() => {});\n\tawait executionEnv.cleanup(context).catch(() => {});\n}\n"]}
|
|
@@ -1,4 +0,0 @@
|
|
|
1
|
-
export { type AgentCompactionRequest, AgentController, type AgentNavigationRequest, type AgentOperationError, type AgentOperationResponse, type AgentPromptRequest, type AgentQueueResponse, } from "./services/agent-controller.ts";
|
|
2
|
-
export { type PresentationSelectItem, PresentationUI } from "./services/presentation-ui.ts";
|
|
3
|
-
export { type SlashCommandCompletion, type SlashCommandContribution, type SlashCommandRunResult, SlashCommands, } from "./services/slash-commands.ts";
|
|
4
|
-
//# sourceMappingURL=plugin.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../../src/experimental/plugin.ts"],"names":[],"mappings":"AAAA,OAAO,EACN,KAAK,sBAAsB,EAC3B,eAAe,EACf,KAAK,sBAAsB,EAC3B,KAAK,mBAAmB,EACxB,KAAK,sBAAsB,EAC3B,KAAK,kBAAkB,EACvB,KAAK,kBAAkB,GACvB,MAAM,gCAAgC,CAAC;AACxC,OAAO,EAAE,KAAK,sBAAsB,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAC;AAC5F,OAAO,EACN,KAAK,sBAAsB,EAC3B,KAAK,wBAAwB,EAC7B,KAAK,qBAAqB,EAC1B,aAAa,GACb,MAAM,8BAA8B,CAAC","sourcesContent":["export {\n\ttype AgentCompactionRequest,\n\tAgentController,\n\ttype AgentNavigationRequest,\n\ttype AgentOperationError,\n\ttype AgentOperationResponse,\n\ttype AgentPromptRequest,\n\ttype AgentQueueResponse,\n} from \"./services/agent-controller.ts\";\nexport { type PresentationSelectItem, PresentationUI } from \"./services/presentation-ui.ts\";\nexport {\n\ttype SlashCommandCompletion,\n\ttype SlashCommandContribution,\n\ttype SlashCommandRunResult,\n\tSlashCommands,\n} from \"./services/slash-commands.ts\";\n"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"plugin.js","sourceRoot":"","sources":["../../src/experimental/plugin.ts"],"names":[],"mappings":"AAAA,OAAO,EAEN,eAAe,GAMf,MAAM,gCAAgC,CAAC;AACxC,OAAO,EAA+B,cAAc,EAAE,MAAM,+BAA+B,CAAC;AAC5F,OAAO,EAIN,aAAa,GACb,MAAM,8BAA8B,CAAC","sourcesContent":["export {\n\ttype AgentCompactionRequest,\n\tAgentController,\n\ttype AgentNavigationRequest,\n\ttype AgentOperationError,\n\ttype AgentOperationResponse,\n\ttype AgentPromptRequest,\n\ttype AgentQueueResponse,\n} from \"./services/agent-controller.ts\";\nexport { type PresentationSelectItem, PresentationUI } from \"./services/presentation-ui.ts\";\nexport {\n\ttype SlashCommandCompletion,\n\ttype SlashCommandContribution,\n\ttype SlashCommandRunResult,\n\tSlashCommands,\n} from \"./services/slash-commands.ts\";\n"]}
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
import { type FacetLoader, type JsonValue } from "@earendil-works/chord";
|
|
2
|
-
import { type FacetBundleArtifact } from "@earendil-works/chord/node";
|
|
3
|
-
export declare function createSessionPluginFacetLoader(manifestPaths: readonly string[]): FacetLoader | undefined;
|
|
4
|
-
export declare function createPresentationFacetData(artifacts: readonly FacetBundleArtifact[]): JsonValue;
|
|
5
|
-
/** Create local loaders only from artifacts selected and sent by the connected server. */
|
|
6
|
-
export declare function createPresentationFacetLoaders(data: JsonValue): readonly FacetLoader[];
|
|
7
|
-
//# sourceMappingURL=bundled.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"bundled.d.ts","sourceRoot":"","sources":["../../../src/experimental/plugins/bundled.ts"],"names":[],"mappings":"AAAA,OAAO,EAAuB,KAAK,WAAW,EAAE,KAAK,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAC9F,OAAO,EAGN,KAAK,mBAAmB,EAExB,MAAM,4BAA4B,CAAC;AAKpC,wBAAgB,8BAA8B,CAAC,aAAa,EAAE,SAAS,MAAM,EAAE,GAAG,WAAW,GAAG,SAAS,CAGxG;AAiBD,wBAAgB,2BAA2B,CAAC,SAAS,EAAE,SAAS,mBAAmB,EAAE,GAAG,SAAS,CAIhG;AAED,0FAA0F;AAC1F,wBAAgB,8BAA8B,CAAC,IAAI,EAAE,SAAS,GAAG,SAAS,WAAW,EAAE,CAUtF","sourcesContent":["import { combineFacetLoaders, type FacetLoader, type JsonValue } from \"@earendil-works/chord\";\nimport {\n\tcreateFacetBundleArtifactLoader,\n\tcreateFacetBundleLoader,\n\ttype FacetBundleArtifact,\n\treadFacetBundleManifest,\n} from \"@earendil-works/chord/node\";\n\nconst PRESENTATION_FACET_BUNDLES_KEY = \"presentationFacetBundles\";\nconst PI_PLUGIN_API = \"@earendil-works/pi-coding-agent/experimental/plugin\";\n\nexport function createSessionPluginFacetLoader(manifestPaths: readonly string[]): FacetLoader | undefined {\n\tif (manifestPaths.length === 0) return undefined;\n\treturn combineFacetLoaders(manifestPaths.map(createOptionalSessionFacetLoader));\n}\n\nfunction createOptionalSessionFacetLoader(manifestPath: string): FacetLoader {\n\tconst loader = createFacetBundleLoader({\n\t\tmanifestPath,\n\t\tentry: \"session\",\n\t\tresolveExternal: resolvePluginExternal,\n\t});\n\treturn {\n\t\tasync load() {\n\t\t\tconst manifest = await readFacetBundleManifest(manifestPath);\n\t\t\tif (manifest.entries.session !== undefined) return loader.load();\n\t\t\treturn { facets: Object.freeze([]), async dispose() {} };\n\t\t},\n\t};\n}\n\nexport function createPresentationFacetData(artifacts: readonly FacetBundleArtifact[]): JsonValue {\n\treturn {\n\t\t[PRESENTATION_FACET_BUNDLES_KEY]: artifacts.map((artifact) => artifact as unknown as JsonValue),\n\t};\n}\n\n/** Create local loaders only from artifacts selected and sent by the connected server. */\nexport function createPresentationFacetLoaders(data: JsonValue): readonly FacetLoader[] {\n\tif (data === null || Array.isArray(data) || typeof data !== \"object\") {\n\t\tthrow new Error(\"Invalid presentation plugin data\");\n\t}\n\tconst artifacts = data[PRESENTATION_FACET_BUNDLES_KEY];\n\tif (artifacts === undefined) return [];\n\tif (!Array.isArray(artifacts)) throw new Error(\"Invalid presentation plugin bundle list\");\n\treturn artifacts.map((artifact) =>\n\t\tcreateFacetBundleArtifactLoader({ artifact, resolveExternal: resolvePluginExternal }),\n\t);\n}\n\nfunction resolvePluginExternal(specifier: string): string | undefined {\n\tif (specifier !== PI_PLUGIN_API) return undefined;\n\tconst extension = import.meta.url.endsWith(\".ts\") ? \"ts\" : \"js\";\n\treturn new URL(`../plugin.${extension}`, import.meta.url).href;\n}\n"]}
|
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
import { combineFacetLoaders } from "@earendil-works/chord";
|
|
2
|
-
import { createFacetBundleArtifactLoader, createFacetBundleLoader, readFacetBundleManifest, } from "@earendil-works/chord/node";
|
|
3
|
-
const PRESENTATION_FACET_BUNDLES_KEY = "presentationFacetBundles";
|
|
4
|
-
const PI_PLUGIN_API = "@earendil-works/pi-coding-agent/experimental/plugin";
|
|
5
|
-
export function createSessionPluginFacetLoader(manifestPaths) {
|
|
6
|
-
if (manifestPaths.length === 0)
|
|
7
|
-
return undefined;
|
|
8
|
-
return combineFacetLoaders(manifestPaths.map(createOptionalSessionFacetLoader));
|
|
9
|
-
}
|
|
10
|
-
function createOptionalSessionFacetLoader(manifestPath) {
|
|
11
|
-
const loader = createFacetBundleLoader({
|
|
12
|
-
manifestPath,
|
|
13
|
-
entry: "session",
|
|
14
|
-
resolveExternal: resolvePluginExternal,
|
|
15
|
-
});
|
|
16
|
-
return {
|
|
17
|
-
async load() {
|
|
18
|
-
const manifest = await readFacetBundleManifest(manifestPath);
|
|
19
|
-
if (manifest.entries.session !== undefined)
|
|
20
|
-
return loader.load();
|
|
21
|
-
return { facets: Object.freeze([]), async dispose() { } };
|
|
22
|
-
},
|
|
23
|
-
};
|
|
24
|
-
}
|
|
25
|
-
export function createPresentationFacetData(artifacts) {
|
|
26
|
-
return {
|
|
27
|
-
[PRESENTATION_FACET_BUNDLES_KEY]: artifacts.map((artifact) => artifact),
|
|
28
|
-
};
|
|
29
|
-
}
|
|
30
|
-
/** Create local loaders only from artifacts selected and sent by the connected server. */
|
|
31
|
-
export function createPresentationFacetLoaders(data) {
|
|
32
|
-
if (data === null || Array.isArray(data) || typeof data !== "object") {
|
|
33
|
-
throw new Error("Invalid presentation plugin data");
|
|
34
|
-
}
|
|
35
|
-
const artifacts = data[PRESENTATION_FACET_BUNDLES_KEY];
|
|
36
|
-
if (artifacts === undefined)
|
|
37
|
-
return [];
|
|
38
|
-
if (!Array.isArray(artifacts))
|
|
39
|
-
throw new Error("Invalid presentation plugin bundle list");
|
|
40
|
-
return artifacts.map((artifact) => createFacetBundleArtifactLoader({ artifact, resolveExternal: resolvePluginExternal }));
|
|
41
|
-
}
|
|
42
|
-
function resolvePluginExternal(specifier) {
|
|
43
|
-
if (specifier !== PI_PLUGIN_API)
|
|
44
|
-
return undefined;
|
|
45
|
-
const extension = import.meta.url.endsWith(".ts") ? "ts" : "js";
|
|
46
|
-
return new URL(`../plugin.${extension}`, import.meta.url).href;
|
|
47
|
-
}
|
|
48
|
-
//# sourceMappingURL=bundled.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"bundled.js","sourceRoot":"","sources":["../../../src/experimental/plugins/bundled.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAoC,MAAM,uBAAuB,CAAC;AAC9F,OAAO,EACN,+BAA+B,EAC/B,uBAAuB,EAEvB,uBAAuB,GACvB,MAAM,4BAA4B,CAAC;AAEpC,MAAM,8BAA8B,GAAG,0BAA0B,CAAC;AAClE,MAAM,aAAa,GAAG,qDAAqD,CAAC;AAE5E,MAAM,UAAU,8BAA8B,CAAC,aAAgC,EAA2B;IACzG,IAAI,aAAa,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,SAAS,CAAC;IACjD,OAAO,mBAAmB,CAAC,aAAa,CAAC,GAAG,CAAC,gCAAgC,CAAC,CAAC,CAAC;AAAA,CAChF;AAED,SAAS,gCAAgC,CAAC,YAAoB,EAAe;IAC5E,MAAM,MAAM,GAAG,uBAAuB,CAAC;QACtC,YAAY;QACZ,KAAK,EAAE,SAAS;QAChB,eAAe,EAAE,qBAAqB;KACtC,CAAC,CAAC;IACH,OAAO;QACN,KAAK,CAAC,IAAI,GAAG;YACZ,MAAM,QAAQ,GAAG,MAAM,uBAAuB,CAAC,YAAY,CAAC,CAAC;YAC7D,IAAI,QAAQ,CAAC,OAAO,CAAC,OAAO,KAAK,SAAS;gBAAE,OAAO,MAAM,CAAC,IAAI,EAAE,CAAC;YACjE,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,KAAK,CAAC,OAAO,GAAG,EAAC,CAAC,EAAE,CAAC;QAAA,CACzD;KACD,CAAC;AAAA,CACF;AAED,MAAM,UAAU,2BAA2B,CAAC,SAAyC,EAAa;IACjG,OAAO;QACN,CAAC,8BAA8B,CAAC,EAAE,SAAS,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,QAAgC,CAAC;KAC/F,CAAC;AAAA,CACF;AAED,0FAA0F;AAC1F,MAAM,UAAU,8BAA8B,CAAC,IAAe,EAA0B;IACvF,IAAI,IAAI,KAAK,IAAI,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,OAAO,IAAI,KAAK,QAAQ,EAAE,CAAC;QACtE,MAAM,IAAI,KAAK,CAAC,kCAAkC,CAAC,CAAC;IACrD,CAAC;IACD,MAAM,SAAS,GAAG,IAAI,CAAC,8BAA8B,CAAC,CAAC;IACvD,IAAI,SAAS,KAAK,SAAS;QAAE,OAAO,EAAE,CAAC;IACvC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,SAAS,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,yCAAyC,CAAC,CAAC;IAC1F,OAAO,SAAS,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,EAAE,CACjC,+BAA+B,CAAC,EAAE,QAAQ,EAAE,eAAe,EAAE,qBAAqB,EAAE,CAAC,CACrF,CAAC;AAAA,CACF;AAED,SAAS,qBAAqB,CAAC,SAAiB,EAAsB;IACrE,IAAI,SAAS,KAAK,aAAa;QAAE,OAAO,SAAS,CAAC;IAClD,MAAM,SAAS,GAAG,OAAO,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC;IAChE,OAAO,IAAI,GAAG,CAAC,aAAa,SAAS,EAAE,EAAE,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC;AAAA,CAC/D","sourcesContent":["import { combineFacetLoaders, type FacetLoader, type JsonValue } from \"@earendil-works/chord\";\nimport {\n\tcreateFacetBundleArtifactLoader,\n\tcreateFacetBundleLoader,\n\ttype FacetBundleArtifact,\n\treadFacetBundleManifest,\n} from \"@earendil-works/chord/node\";\n\nconst PRESENTATION_FACET_BUNDLES_KEY = \"presentationFacetBundles\";\nconst PI_PLUGIN_API = \"@earendil-works/pi-coding-agent/experimental/plugin\";\n\nexport function createSessionPluginFacetLoader(manifestPaths: readonly string[]): FacetLoader | undefined {\n\tif (manifestPaths.length === 0) return undefined;\n\treturn combineFacetLoaders(manifestPaths.map(createOptionalSessionFacetLoader));\n}\n\nfunction createOptionalSessionFacetLoader(manifestPath: string): FacetLoader {\n\tconst loader = createFacetBundleLoader({\n\t\tmanifestPath,\n\t\tentry: \"session\",\n\t\tresolveExternal: resolvePluginExternal,\n\t});\n\treturn {\n\t\tasync load() {\n\t\t\tconst manifest = await readFacetBundleManifest(manifestPath);\n\t\t\tif (manifest.entries.session !== undefined) return loader.load();\n\t\t\treturn { facets: Object.freeze([]), async dispose() {} };\n\t\t},\n\t};\n}\n\nexport function createPresentationFacetData(artifacts: readonly FacetBundleArtifact[]): JsonValue {\n\treturn {\n\t\t[PRESENTATION_FACET_BUNDLES_KEY]: artifacts.map((artifact) => artifact as unknown as JsonValue),\n\t};\n}\n\n/** Create local loaders only from artifacts selected and sent by the connected server. */\nexport function createPresentationFacetLoaders(data: JsonValue): readonly FacetLoader[] {\n\tif (data === null || Array.isArray(data) || typeof data !== \"object\") {\n\t\tthrow new Error(\"Invalid presentation plugin data\");\n\t}\n\tconst artifacts = data[PRESENTATION_FACET_BUNDLES_KEY];\n\tif (artifacts === undefined) return [];\n\tif (!Array.isArray(artifacts)) throw new Error(\"Invalid presentation plugin bundle list\");\n\treturn artifacts.map((artifact) =>\n\t\tcreateFacetBundleArtifactLoader({ artifact, resolveExternal: resolvePluginExternal }),\n\t);\n}\n\nfunction resolvePluginExternal(specifier: string): string | undefined {\n\tif (specifier !== PI_PLUGIN_API) return undefined;\n\tconst extension = import.meta.url.endsWith(\".ts\") ? \"ts\" : \"js\";\n\treturn new URL(`../plugin.${extension}`, import.meta.url).href;\n}\n"]}
|