@jpowersdev/effect-pi 0.1.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.
Files changed (97) hide show
  1. package/CHANGELOG.md +15 -0
  2. package/CONTRIBUTING.md +40 -0
  3. package/LICENSE +21 -0
  4. package/README.md +91 -0
  5. package/dist/ClusterSessions.d.ts +2 -0
  6. package/dist/ClusterSessions.d.ts.map +1 -0
  7. package/dist/ClusterSessions.js +2 -0
  8. package/dist/ClusterSessions.js.map +1 -0
  9. package/dist/LocalSessions.d.ts +2 -0
  10. package/dist/LocalSessions.d.ts.map +1 -0
  11. package/dist/LocalSessions.js +2 -0
  12. package/dist/LocalSessions.js.map +1 -0
  13. package/dist/ModelRuntime.d.ts +2 -0
  14. package/dist/ModelRuntime.d.ts.map +1 -0
  15. package/dist/ModelRuntime.js +2 -0
  16. package/dist/ModelRuntime.js.map +1 -0
  17. package/dist/ResourceLoader.d.ts +2 -0
  18. package/dist/ResourceLoader.d.ts.map +1 -0
  19. package/dist/ResourceLoader.js +2 -0
  20. package/dist/ResourceLoader.js.map +1 -0
  21. package/dist/Session.d.ts +3 -0
  22. package/dist/Session.d.ts.map +1 -0
  23. package/dist/Session.js +3 -0
  24. package/dist/Session.js.map +1 -0
  25. package/dist/Sessions.d.ts +14 -0
  26. package/dist/Sessions.d.ts.map +1 -0
  27. package/dist/Sessions.js +5 -0
  28. package/dist/Sessions.js.map +1 -0
  29. package/dist/index.d.ts +7 -0
  30. package/dist/index.d.ts.map +1 -0
  31. package/dist/index.js +7 -0
  32. package/dist/index.js.map +1 -0
  33. package/dist/internal/ClusterSessions.d.ts +44 -0
  34. package/dist/internal/ClusterSessions.d.ts.map +1 -0
  35. package/dist/internal/ClusterSessions.js +72 -0
  36. package/dist/internal/ClusterSessions.js.map +1 -0
  37. package/dist/internal/LocalSessions.d.ts +19 -0
  38. package/dist/internal/LocalSessions.d.ts.map +1 -0
  39. package/dist/internal/LocalSessions.js +25 -0
  40. package/dist/internal/LocalSessions.js.map +1 -0
  41. package/dist/internal/ModelRuntime.d.ts +42 -0
  42. package/dist/internal/ModelRuntime.d.ts.map +1 -0
  43. package/dist/internal/ModelRuntime.js +66 -0
  44. package/dist/internal/ModelRuntime.js.map +1 -0
  45. package/dist/internal/Persistence.d.ts +12 -0
  46. package/dist/internal/Persistence.d.ts.map +1 -0
  47. package/dist/internal/Persistence.js +26 -0
  48. package/dist/internal/Persistence.js.map +1 -0
  49. package/dist/internal/Pi.d.ts +51 -0
  50. package/dist/internal/Pi.d.ts.map +1 -0
  51. package/dist/internal/Pi.js +258 -0
  52. package/dist/internal/Pi.js.map +1 -0
  53. package/dist/internal/Protocol.d.ts +41 -0
  54. package/dist/internal/Protocol.d.ts.map +1 -0
  55. package/dist/internal/Protocol.js +33 -0
  56. package/dist/internal/Protocol.js.map +1 -0
  57. package/dist/internal/ResourceLoader.d.ts +46 -0
  58. package/dist/internal/ResourceLoader.d.ts.map +1 -0
  59. package/dist/internal/ResourceLoader.js +77 -0
  60. package/dist/internal/ResourceLoader.js.map +1 -0
  61. package/dist/internal/Session.d.ts +82 -0
  62. package/dist/internal/Session.d.ts.map +1 -0
  63. package/dist/internal/Session.js +63 -0
  64. package/dist/internal/Session.js.map +1 -0
  65. package/dist-examples/cluster-session.d.ts +2 -0
  66. package/dist-examples/cluster-session.d.ts.map +1 -0
  67. package/dist-examples/cluster-session.js +77 -0
  68. package/dist-examples/cluster-session.js.map +1 -0
  69. package/dist-examples/local-session-pool.d.ts +2 -0
  70. package/dist-examples/local-session-pool.d.ts.map +1 -0
  71. package/dist-examples/local-session-pool.js +60 -0
  72. package/dist-examples/local-session-pool.js.map +1 -0
  73. package/dist-examples/single-session.d.ts +2 -0
  74. package/dist-examples/single-session.d.ts.map +1 -0
  75. package/dist-examples/single-session.js +49 -0
  76. package/dist-examples/single-session.js.map +1 -0
  77. package/docs/reference.md +248 -0
  78. package/examples/README.md +111 -0
  79. package/examples/cluster-session.ts +131 -0
  80. package/examples/local-session-pool.ts +107 -0
  81. package/examples/single-session.ts +85 -0
  82. package/package.json +62 -0
  83. package/src/ClusterSessions.ts +6 -0
  84. package/src/LocalSessions.ts +1 -0
  85. package/src/ModelRuntime.ts +10 -0
  86. package/src/ResourceLoader.ts +13 -0
  87. package/src/Session.ts +14 -0
  88. package/src/Sessions.ts +17 -0
  89. package/src/index.ts +6 -0
  90. package/src/internal/ClusterSessions.ts +126 -0
  91. package/src/internal/LocalSessions.ts +45 -0
  92. package/src/internal/ModelRuntime.ts +105 -0
  93. package/src/internal/Persistence.ts +40 -0
  94. package/src/internal/Pi.ts +346 -0
  95. package/src/internal/Protocol.ts +39 -0
  96. package/src/internal/ResourceLoader.ts +128 -0
  97. package/src/internal/Session.ts +109 -0
@@ -0,0 +1,77 @@
1
+ import * as Pi from "@earendil-works/pi-coding-agent";
2
+ import * as Config from "effect/Config";
3
+ import * as Context from "effect/Context";
4
+ import * as Effect from "effect/Effect";
5
+ import * as Layer from "effect/Layer";
6
+ import * as Schema from "effect/Schema";
7
+ export class Error extends Schema.TaggedError()("ResourceLoaderError", {
8
+ operation: Schema.Literals(["load", "release"]),
9
+ message: Schema.String
10
+ }) {
11
+ }
12
+ export class ResourceLoader extends Context.Service()("@jpowersdev/effect-pi/ResourceLoader") {
13
+ }
14
+ const scoped = (create) => ({
15
+ load: Effect.fn("ResourceLoader.load")(function* (cwd) {
16
+ // Register invalidation before reload: even failed/late extension loading must
17
+ // release its tracked event-bus subscriptions. Pi reload has no AbortSignal.
18
+ const loaded = yield* Effect.acquireRelease(Effect.try({
19
+ try: () => create(cwd),
20
+ catch: () => new Error({ operation: "load", message: "Unable to construct Pi resources" })
21
+ }), ({ resourceLoader }) => Effect.try({
22
+ try: () => resourceLoader.getExtensions().runtime.invalidate(),
23
+ catch: () => new Error({ operation: "release", message: "Unable to release Pi resources" })
24
+ }).pipe(Effect.orDie));
25
+ yield* Effect.tryPromise({
26
+ try: () => loaded.resourceLoader.reload(),
27
+ catch: () => new Error({ operation: "load", message: "Unable to load Pi resources" })
28
+ }).pipe(Effect.uninterruptible);
29
+ return loaded;
30
+ })
31
+ });
32
+ /** Opt into Pi resource discovery. Prefer layerEmpty for isolated applications. */
33
+ export const layer = (options = {}) => Layer.sync(ResourceLoader, () => scoped((cwd) => {
34
+ const { settings, ...loaderOptions } = options;
35
+ const agentDir = options.agentDir ?? Pi.getAgentDir();
36
+ const settingsManager = settings === undefined
37
+ ? Pi.SettingsManager.create(cwd, agentDir)
38
+ : Pi.SettingsManager.inMemory(settings);
39
+ return {
40
+ settingsManager,
41
+ resourceLoader: new Pi.DefaultResourceLoader({
42
+ ...loaderOptions,
43
+ cwd,
44
+ agentDir,
45
+ settingsManager
46
+ })
47
+ };
48
+ }));
49
+ /** Resolve discovery options using the active ConfigProvider at layer build time. */
50
+ export const layerConfig = (options) => Layer.unwrap(Effect.map(Config.unwrap(options), layer));
51
+ /** Resolve isolated resource options using the active ConfigProvider at layer build time. */
52
+ export const layerEmptyConfig = (options) => Layer.unwrap(Effect.map(Config.unwrap(options), layerEmpty));
53
+ /** No filesystem discovery, extensions, context files, or ambient settings. */
54
+ export const layerEmpty = (options = {}) => Layer.sync(ResourceLoader, () => scoped(() => {
55
+ const extensions = {
56
+ extensions: [],
57
+ errors: [],
58
+ runtime: Pi.createExtensionRuntime()
59
+ };
60
+ return {
61
+ settingsManager: Pi.SettingsManager.inMemory(options.settings),
62
+ resourceLoader: {
63
+ getExtensions: () => extensions,
64
+ getSkills: () => ({ skills: [], diagnostics: [] }),
65
+ getPrompts: () => ({ prompts: [], diagnostics: [] }),
66
+ getThemes: () => ({ themes: [], diagnostics: [] }),
67
+ getAgentsFiles: () => ({ agentsFiles: [] }),
68
+ getSystemPrompt: () => options.systemPrompt,
69
+ getSystemPromptSource: () => undefined,
70
+ getAppendSystemPrompt: () => [],
71
+ getAppendSystemPromptSources: () => [],
72
+ extendResources: () => { },
73
+ reload: async () => { }
74
+ }
75
+ };
76
+ }));
77
+ //# sourceMappingURL=ResourceLoader.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ResourceLoader.js","sourceRoot":"","sources":["../../src/internal/ResourceLoader.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,82 @@
1
+ import type * as Pi from "@earendil-works/pi-coding-agent";
2
+ import type * as Effect from "effect/Effect";
3
+ import * as Schema from "effect/Schema";
4
+ import type * as Stream from "effect/Stream";
5
+ /** A Pi session id accepted by Pi's SessionManager. */
6
+ export declare const Id: Schema.brand<Schema.String, "@jpowersdev/effect-pi/SessionId">;
7
+ export type Id = typeof Id.Type;
8
+ export declare const Status: Schema.Literals<readonly ["idle", "streaming"]>;
9
+ export type Status = typeof Status.Type;
10
+ declare const Snapshot_base: Schema.Class<Snapshot, Schema.Struct<{
11
+ readonly id: Schema.brand<Schema.String, "@jpowersdev/effect-pi/SessionId">;
12
+ readonly status: Schema.Literals<readonly ["idle", "streaming"]>;
13
+ readonly messageCount: Schema.Natural;
14
+ readonly lastAssistantText: Schema.String;
15
+ }>, {}>;
16
+ export declare class Snapshot extends Snapshot_base {
17
+ }
18
+ declare const PromptResult_base: Schema.Class<PromptResult, Schema.Struct<{
19
+ readonly snapshot: typeof Snapshot;
20
+ readonly text: Schema.String;
21
+ readonly stopReason: Schema.String;
22
+ readonly inputTokens: Schema.Natural;
23
+ readonly outputTokens: Schema.Natural;
24
+ readonly totalTokens: Schema.Natural;
25
+ readonly costUsd: Schema.Number;
26
+ }>, {}>;
27
+ /** Last new assistant response, with usage summed over entries appended by this invocation. */
28
+ export declare class PromptResult extends PromptResult_base {
29
+ }
30
+ /** Stable, serializable subset of Pi's live session events. */
31
+ export declare const Event: Schema.Union<readonly [Schema.TaggedStruct<"Status", {
32
+ readonly sequence: Schema.Natural;
33
+ readonly status: Schema.Literals<readonly ["idle", "streaming"]>;
34
+ }>, Schema.TaggedStruct<"TextDelta", {
35
+ readonly sequence: Schema.Natural;
36
+ readonly delta: Schema.String;
37
+ }>, Schema.TaggedStruct<"ToolStarted", {
38
+ readonly sequence: Schema.Natural;
39
+ readonly toolName: Schema.String;
40
+ }>, Schema.TaggedStruct<"ToolFinished", {
41
+ readonly sequence: Schema.Natural;
42
+ readonly toolName: Schema.String;
43
+ readonly isError: Schema.Boolean;
44
+ }>]>;
45
+ export type Event = typeof Event.Type;
46
+ export declare const Operation: Schema.Literals<readonly ["abort", "events", "jsonl", "load", "make", "prompt", "save", "snapshot"]>;
47
+ export type Operation = typeof Operation.Type;
48
+ declare const Error_base: Schema.Class<Error, Schema.TaggedStruct<"SessionError", {
49
+ readonly sessionId: Schema.brand<Schema.String, "@jpowersdev/effect-pi/SessionId">;
50
+ readonly operation: Schema.Literals<readonly ["abort", "events", "jsonl", "load", "make", "prompt", "save", "snapshot"]>;
51
+ readonly message: Schema.String;
52
+ }>, import("effect/Cause").YieldableError>;
53
+ export declare class Error extends Error_base {
54
+ }
55
+ /** One scoped Pi session, whether local or represented by a cluster client. */
56
+ export interface Session {
57
+ readonly id: Id;
58
+ readonly snapshot: Effect.Effect<Snapshot, Error>;
59
+ /** Nonempty text. Interruption waits for SDK settlement and a checkpoint. */
60
+ readonly prompt: (text: string) => Effect.Effect<PromptResult, Error>;
61
+ /** Interrupt the active prompt; queued prompts remain eligible to run. */
62
+ readonly abort: Effect.Effect<void, Error>;
63
+ /** Ephemeral, bounded stream. Sequence gaps indicate lost events; restoration resets sequence numbers. */
64
+ readonly events: Stream.Stream<Event, Error>;
65
+ /** Current serialization, not an acknowledgement that the backing store has been flushed. */
66
+ readonly jsonl: Effect.Effect<string, Error>;
67
+ }
68
+ export type PiOptions = Omit<Pi.CreateAgentSessionOptions, "cwd" | "sessionManager" | "modelRuntime" | "model" | "resourceLoader" | "settingsManager">;
69
+ /** Configuration shared by direct, local-pool, and cluster session construction. */
70
+ export interface Config {
71
+ /** Tool working directory, not a sandbox or filesystem access boundary. */
72
+ readonly cwd: string;
73
+ /** Defaults to "effect-pi/sessions/". Keep stable across all owners of a document. */
74
+ readonly keyPrefix?: string;
75
+ /** Per-session SDK options (such as tools). ModelRuntime owns model, auth, resources, and settings. */
76
+ readonly configure?: (sessionId: Id) => PiOptions;
77
+ }
78
+ export interface MakeOptions extends Config {
79
+ readonly id: Id;
80
+ }
81
+ export {};
82
+ //# sourceMappingURL=Session.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Session.d.ts","sourceRoot":"","sources":["../../src/internal/Session.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,EAAE,MAAM,iCAAiC,CAAA;AAC1D,OAAO,KAAK,KAAK,MAAM,MAAM,eAAe,CAAA;AAC5C,OAAO,KAAK,MAAM,MAAM,eAAe,CAAA;AACvC,OAAO,KAAK,KAAK,MAAM,MAAM,eAAe,CAAA;AAE5C,uDAAuD;AACvD,eAAO,MAAM,EAAE,gEAEwC,CAAA;AACvD,MAAM,MAAM,EAAE,GAAG,OAAO,EAAE,CAAC,IAAI,CAAA;AAE/B,eAAO,MAAM,MAAM,iDAAyC,CAAA;AAC5D,MAAM,MAAM,MAAM,GAAG,OAAO,MAAM,CAAC,IAAI,CAAA;;;;;;;AAEvC,qBAAa,QAAS,SAAQ,aAK5B;CAAG;;;;;;;;;;AAEL,+FAA+F;AAC/F,qBAAa,YAAa,SAAQ,iBAQhC;CAAG;AAoBL,+DAA+D;AAC/D,eAAO,MAAM,KAAK;;;;;;;;;;;;;IAKhB,CAAA;AACF,MAAM,MAAM,KAAK,GAAG,OAAO,KAAK,CAAC,IAAI,CAAA;AAErC,eAAO,MAAM,SAAS,sGASpB,CAAA;AACF,MAAM,MAAM,SAAS,GAAG,OAAO,SAAS,CAAC,IAAI,CAAA;;;;;;AAE7C,qBAAa,KAAM,SAAQ,UAIzB;CAAG;AAEL,+EAA+E;AAC/E,MAAM,WAAW,OAAO;IACtB,QAAQ,CAAC,EAAE,EAAE,EAAE,CAAA;IACf,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAA;IACjD,6EAA6E;IAC7E,QAAQ,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC,MAAM,CAAC,YAAY,EAAE,KAAK,CAAC,CAAA;IACrE,0EAA0E;IAC1E,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,CAAA;IAC1C,0GAA0G;IAC1G,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,KAAK,EAAE,KAAK,CAAC,CAAA;IAC5C,6FAA6F;IAC7F,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,CAAA;CAC7C;AAED,MAAM,MAAM,SAAS,GAAG,IAAI,CAC1B,EAAE,CAAC,yBAAyB,EAC5B,KAAK,GAAG,gBAAgB,GAAG,cAAc,GAAG,OAAO,GAAG,gBAAgB,GAAG,iBAAiB,CAC3F,CAAA;AAED,oFAAoF;AACpF,MAAM,WAAW,MAAM;IACrB,2EAA2E;IAC3E,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;IACpB,sFAAsF;IACtF,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAA;IAC3B,uGAAuG;IACvG,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC,SAAS,EAAE,EAAE,KAAK,SAAS,CAAA;CAClD;AAED,MAAM,WAAW,WAAY,SAAQ,MAAM;IACzC,QAAQ,CAAC,EAAE,EAAE,EAAE,CAAA;CAChB"}
@@ -0,0 +1,63 @@
1
+ import * as Schema from "effect/Schema";
2
+ /** A Pi session id accepted by Pi's SessionManager. */
3
+ export const Id = Schema.String.check(Schema.isPattern(/^[A-Za-z0-9](?:[A-Za-z0-9._-]*[A-Za-z0-9])?$/)).pipe(Schema.brand("@jpowersdev/effect-pi/SessionId"));
4
+ export const Status = Schema.Literals(["idle", "streaming"]);
5
+ export class Snapshot extends Schema.Class("@jpowersdev/effect-pi/SessionSnapshot")({
6
+ id: Id,
7
+ status: Status,
8
+ messageCount: Schema.Natural,
9
+ lastAssistantText: Schema.String
10
+ }) {
11
+ }
12
+ /** Last new assistant response, with usage summed over entries appended by this invocation. */
13
+ export class PromptResult extends Schema.Class("@jpowersdev/effect-pi/PromptResult")({
14
+ snapshot: Snapshot,
15
+ text: Schema.String,
16
+ stopReason: Schema.String,
17
+ inputTokens: Schema.Natural,
18
+ outputTokens: Schema.Natural,
19
+ totalTokens: Schema.Natural,
20
+ costUsd: Schema.Number.check(Schema.isGreaterThanOrEqualTo(0))
21
+ }) {
22
+ }
23
+ const StatusEvent = Schema.TaggedStruct("Status", {
24
+ sequence: Schema.Natural,
25
+ status: Status
26
+ });
27
+ const TextDeltaEvent = Schema.TaggedStruct("TextDelta", {
28
+ sequence: Schema.Natural,
29
+ delta: Schema.String
30
+ });
31
+ const ToolStartedEvent = Schema.TaggedStruct("ToolStarted", {
32
+ sequence: Schema.Natural,
33
+ toolName: Schema.String
34
+ });
35
+ const ToolFinishedEvent = Schema.TaggedStruct("ToolFinished", {
36
+ sequence: Schema.Natural,
37
+ toolName: Schema.String,
38
+ isError: Schema.Boolean
39
+ });
40
+ /** Stable, serializable subset of Pi's live session events. */
41
+ export const Event = Schema.Union([
42
+ StatusEvent,
43
+ TextDeltaEvent,
44
+ ToolStartedEvent,
45
+ ToolFinishedEvent
46
+ ]);
47
+ export const Operation = Schema.Literals([
48
+ "abort",
49
+ "events",
50
+ "jsonl",
51
+ "load",
52
+ "make",
53
+ "prompt",
54
+ "save",
55
+ "snapshot"
56
+ ]);
57
+ export class Error extends Schema.TaggedError()("SessionError", {
58
+ sessionId: Id,
59
+ operation: Operation,
60
+ message: Schema.String
61
+ }) {
62
+ }
63
+ //# sourceMappingURL=Session.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Session.js","sourceRoot":"","sources":["../../src/internal/Session.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,MAAM,MAAM,eAAe,CAAA;AAGvC,uDAAuD;AACvD,MAAM,CAAC,MAAM,EAAE,GAAG,MAAM,CAAC,MAAM,CAAC,KAAK,CACnC,MAAM,CAAC,SAAS,CAAC,8CAA8C,CAAC,CACjE,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,iCAAiC,CAAC,CAAC,CAAA;AAGvD,MAAM,CAAC,MAAM,MAAM,GAAG,MAAM,CAAC,QAAQ,CAAC,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC,CAAA;AAG5D,MAAM,OAAO,QAAS,SAAQ,MAAM,CAAC,KAAK,CAAW,uCAAuC,CAAC,CAAC;IAC5F,EAAE,EAAE,EAAE;IACN,MAAM,EAAE,MAAM;IACd,YAAY,EAAE,MAAM,CAAC,OAAO;IAC5B,iBAAiB,EAAE,MAAM,CAAC,MAAM;CACjC,CAAC;CAAG;AAEL,+FAA+F;AAC/F,MAAM,OAAO,YAAa,SAAQ,MAAM,CAAC,KAAK,CAAe,oCAAoC,CAAC,CAAC;IACjG,QAAQ,EAAE,QAAQ;IAClB,IAAI,EAAE,MAAM,CAAC,MAAM;IACnB,UAAU,EAAE,MAAM,CAAC,MAAM;IACzB,WAAW,EAAE,MAAM,CAAC,OAAO;IAC3B,YAAY,EAAE,MAAM,CAAC,OAAO;IAC5B,WAAW,EAAE,MAAM,CAAC,OAAO;IAC3B,OAAO,EAAE,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,sBAAsB,CAAC,CAAC,CAAC,CAAC;CAC/D,CAAC;CAAG;AAEL,MAAM,WAAW,GAAG,MAAM,CAAC,YAAY,CAAC,QAAQ,EAAE;IAChD,QAAQ,EAAE,MAAM,CAAC,OAAO;IACxB,MAAM,EAAE,MAAM;CACf,CAAC,CAAA;AACF,MAAM,cAAc,GAAG,MAAM,CAAC,YAAY,CAAC,WAAW,EAAE;IACtD,QAAQ,EAAE,MAAM,CAAC,OAAO;IACxB,KAAK,EAAE,MAAM,CAAC,MAAM;CACrB,CAAC,CAAA;AACF,MAAM,gBAAgB,GAAG,MAAM,CAAC,YAAY,CAAC,aAAa,EAAE;IAC1D,QAAQ,EAAE,MAAM,CAAC,OAAO;IACxB,QAAQ,EAAE,MAAM,CAAC,MAAM;CACxB,CAAC,CAAA;AACF,MAAM,iBAAiB,GAAG,MAAM,CAAC,YAAY,CAAC,cAAc,EAAE;IAC5D,QAAQ,EAAE,MAAM,CAAC,OAAO;IACxB,QAAQ,EAAE,MAAM,CAAC,MAAM;IACvB,OAAO,EAAE,MAAM,CAAC,OAAO;CACxB,CAAC,CAAA;AAEF,+DAA+D;AAC/D,MAAM,CAAC,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC;IAChC,WAAW;IACX,cAAc;IACd,gBAAgB;IAChB,iBAAiB;CAClB,CAAC,CAAA;AAGF,MAAM,CAAC,MAAM,SAAS,GAAG,MAAM,CAAC,QAAQ,CAAC;IACvC,OAAO;IACP,QAAQ;IACR,OAAO;IACP,MAAM;IACN,MAAM;IACN,QAAQ;IACR,MAAM;IACN,UAAU;CACX,CAAC,CAAA;AAGF,MAAM,OAAO,KAAM,SAAQ,MAAM,CAAC,WAAW,EAAS,CAAC,cAAc,EAAE;IACrE,SAAS,EAAE,EAAE;IACb,SAAS,EAAE,SAAS;IACpB,OAAO,EAAE,MAAM,CAAC,MAAM;CACvB,CAAC;CAAG"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=cluster-session.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cluster-session.d.ts","sourceRoot":"","sources":["../examples/cluster-session.ts"],"names":[],"mappings":""}
@@ -0,0 +1,77 @@
1
+ /** Start a runner and a separate cluster client in one process, then shut both down. */
2
+ import * as NodeClusterSocket from "@effect/platform-node/NodeClusterSocket";
3
+ import * as NodeRuntime from "@effect/platform-node/NodeRuntime";
4
+ import * as NodeServices from "@effect/platform-node/NodeServices";
5
+ import * as SqliteClient from "@effect/sql-sqlite-node/SqliteClient";
6
+ import * as Config from "effect/Config";
7
+ import * as Console from "effect/Console";
8
+ import * as Effect from "effect/Effect";
9
+ import * as Layer from "effect/Layer";
10
+ import * as Option from "effect/Option";
11
+ import * as Stream from "effect/Stream";
12
+ import * as Argument from "effect/unstable/cli/Argument";
13
+ import * as Command from "effect/unstable/cli/Command";
14
+ import * as Flag from "effect/unstable/cli/Flag";
15
+ import * as MessageStorage from "effect/unstable/cluster/MessageStorage";
16
+ import * as RunnerAddress from "effect/unstable/cluster/RunnerAddress";
17
+ import * as RunnerStorage from "effect/unstable/cluster/RunnerStorage";
18
+ import * as ShardingConfig from "effect/unstable/cluster/ShardingConfig";
19
+ import * as KeyValueStore from "effect/unstable/persistence/KeyValueStore";
20
+ import { ClusterSessions, ModelRuntime, ResourceLoader, Session, Sessions } from "@jpowersdev/effect-pi";
21
+ // Model and resource configuration belongs to the runner, not the cluster client.
22
+ const ResourcesLive = ResourceLoader.layerEmpty({
23
+ systemPrompt: "You are a helpful assistant. Use the read-only tools only when asked to inspect files.",
24
+ settings: { retry: { enabled: false } }
25
+ });
26
+ const ModelLive = ModelRuntime.layerConfig(Config.all({
27
+ provider: Config.NonEmptyString("EFFECT_PI_PROVIDER"),
28
+ modelId: Config.NonEmptyString("EFFECT_PI_MODEL"),
29
+ apiKey: Config.Redacted("EFFECT_PI_API_KEY")
30
+ }).pipe(Config.map(({ provider, modelId, apiKey }) => ({
31
+ model: { provider, id: modelId },
32
+ apiKeys: { [provider]: apiKey },
33
+ authPath: ".data/effect-pi/auth.json",
34
+ modelsPath: null,
35
+ refreshOnCreate: false
36
+ })))).pipe(Layer.provide(ResourcesLive));
37
+ const StoreLive = KeyValueStore.layerSql({ table: "pi_sessions" }).pipe(Layer.provide(SqliteClient.layer({ filename: ".data/effect-pi/sessions.sqlite" })));
38
+ // Both runtimes share in-memory discovery; only conversation documents use SQLite.
39
+ const DiscoveryLive = Layer.merge(RunnerStorage.layerMemory, MessageStorage.layerMemory).pipe(Layer.provide(ShardingConfig.layer()));
40
+ const RunnerSharding = NodeClusterSocket.layer({
41
+ storage: "byo",
42
+ serialization: "ndjson",
43
+ shardingConfig: {
44
+ runnerAddress: Option.some(RunnerAddress.make("127.0.0.1", 34431))
45
+ }
46
+ }).pipe(Layer.fresh, Layer.provide(DiscoveryLive));
47
+ // Fresh sharding runtimes make requests travel over the socket, not local dispatch.
48
+ const ClientSharding = NodeClusterSocket.layer({
49
+ clientOnly: true,
50
+ storage: "byo",
51
+ serialization: "ndjson",
52
+ shardingConfig: { runnerAddress: Option.none() }
53
+ }).pipe(Layer.fresh, Layer.provide(DiscoveryLive));
54
+ const RunnerLive = ClusterSessions.runnerLayer({
55
+ cwd: ".",
56
+ configure: () => ({ tools: ["read", "grep", "find", "ls"] })
57
+ }).pipe(Layer.provide([ModelLive, StoreLive, RunnerSharding]));
58
+ const ClientLive = ClusterSessions.clientLayer.pipe(Layer.provide(ClientSharding),
59
+ // Register the runner first and keep it alive until the client exits.
60
+ Layer.provide(RunnerLive));
61
+ const cli = Command.make("cluster-session", {
62
+ prompt: Argument.String("prompt").pipe(Argument.withDefault("Say hello in one short sentence.")),
63
+ snapshot: Flag.Boolean("snapshot").pipe(Flag.withDefault(false), Flag.withDescription("Print saved state without calling a model"))
64
+ }, ({ prompt, snapshot }) => Effect.gen(function* () {
65
+ const sessions = yield* Sessions;
66
+ const session = yield* sessions.open(Session.Id.make("cluster-session"));
67
+ if (snapshot) {
68
+ return yield* Console.log(yield* session.snapshot);
69
+ }
70
+ // Remote subscriptions are best-effort; use the prompt result to reconcile.
71
+ yield* session.events.pipe(Stream.runForEach((event) => Console.log(event)), Effect.catch((error) => Console.warn(error)), Effect.forkScoped({ startImmediately: true }));
72
+ const result = yield* session.prompt(prompt).pipe(Effect.timeout("2 minutes"));
73
+ yield* Console.log("Result:", result);
74
+ }).pipe(Effect.scoped)).pipe(Command.provide(ClientLive));
75
+ const program = Command.run(cli, { version: "0.1.0" }).pipe(Effect.provide(NodeServices.layer));
76
+ NodeRuntime.runMain(program);
77
+ //# sourceMappingURL=cluster-session.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cluster-session.js","sourceRoot":"","sources":["../examples/cluster-session.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=local-session-pool.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"local-session-pool.d.ts","sourceRoot":"","sources":["../examples/local-session-pool.ts"],"names":[],"mappings":""}
@@ -0,0 +1,60 @@
1
+ /** Share sessions by id and reopen them across separate request scopes. */
2
+ import * as NodeRuntime from "@effect/platform-node/NodeRuntime";
3
+ import * as NodeServices from "@effect/platform-node/NodeServices";
4
+ import * as SqliteClient from "@effect/sql-sqlite-node/SqliteClient";
5
+ import * as Config from "effect/Config";
6
+ import * as Console from "effect/Console";
7
+ import * as Effect from "effect/Effect";
8
+ import * as Layer from "effect/Layer";
9
+ import * as Stream from "effect/Stream";
10
+ import * as Argument from "effect/unstable/cli/Argument";
11
+ import * as Command from "effect/unstable/cli/Command";
12
+ import * as Flag from "effect/unstable/cli/Flag";
13
+ import * as KeyValueStore from "effect/unstable/persistence/KeyValueStore";
14
+ import { LocalSessions, ModelRuntime, ResourceLoader, Session, Sessions } from "@jpowersdev/effect-pi";
15
+ const ResourcesLive = ResourceLoader.layerEmpty({
16
+ systemPrompt: "You are a helpful assistant. Use the read-only tools only when asked to inspect files.",
17
+ settings: { retry: { enabled: false } }
18
+ });
19
+ const ModelLive = ModelRuntime.layerConfig(Config.all({
20
+ provider: Config.NonEmptyString("EFFECT_PI_PROVIDER"),
21
+ modelId: Config.NonEmptyString("EFFECT_PI_MODEL"),
22
+ apiKey: Config.Redacted("EFFECT_PI_API_KEY")
23
+ }).pipe(Config.map(({ provider, modelId, apiKey }) => ({
24
+ model: { provider, id: modelId },
25
+ apiKeys: { [provider]: apiKey },
26
+ authPath: ".data/effect-pi/auth.json",
27
+ modelsPath: null,
28
+ refreshOnCreate: false
29
+ })))).pipe(Layer.provide(ResourcesLive));
30
+ const StoreLive = KeyValueStore.layerSql({ table: "pi_sessions" }).pipe(Layer.provide(SqliteClient.layer({ filename: ".data/effect-pi/sessions.sqlite" })));
31
+ const SessionsLive = LocalSessions.layer({
32
+ cwd: ".",
33
+ idleTimeToLive: "1 minute",
34
+ configure: () => ({ tools: ["read", "grep", "find", "ls"] })
35
+ }).pipe(Layer.provide([ModelLive, StoreLive]));
36
+ const cli = Command.make("local-session-pool", {
37
+ prompt: Argument.String("prompt").pipe(Argument.withDefault("Say hello in one short sentence.")),
38
+ snapshot: Flag.Boolean("snapshot").pipe(Flag.withDefault(false), Flag.withDescription("Print saved state without calling a model"))
39
+ }, ({ prompt, snapshot }) => Effect.gen(function* () {
40
+ const sessions = yield* Sessions;
41
+ const id = Session.Id.make("pooled-session");
42
+ // A request holds a reference to the session for the duration of its scope.
43
+ yield* Effect.scoped(Effect.gen(function* () {
44
+ const session = yield* sessions.open(id);
45
+ if (snapshot) {
46
+ return yield* Console.log(yield* session.snapshot);
47
+ }
48
+ yield* session.events.pipe(Stream.runForEach((event) => Console.log(event)), Effect.catch((error) => Console.warn(error)), Effect.forkScoped({ startImmediately: true }));
49
+ const result = yield* session.prompt(prompt).pipe(Effect.timeout("2 minutes"));
50
+ yield* Console.log("Result:", result);
51
+ }));
52
+ // Reuse the same live session before the idle TTL; after eviction, restore from SQLite.
53
+ yield* Effect.scoped(Effect.gen(function* () {
54
+ const session = yield* sessions.open(id);
55
+ yield* Console.log("Reopened:", yield* session.snapshot);
56
+ }));
57
+ }).pipe(Effect.scoped)).pipe(Command.provide(SessionsLive));
58
+ const program = Command.run(cli, { version: "0.1.0" }).pipe(Effect.provide(NodeServices.layer));
59
+ NodeRuntime.runMain(program);
60
+ //# sourceMappingURL=local-session-pool.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"local-session-pool.js","sourceRoot":"","sources":["../examples/local-session-pool.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=single-session.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"single-session.d.ts","sourceRoot":"","sources":["../examples/single-session.ts"],"names":[],"mappings":""}
@@ -0,0 +1,49 @@
1
+ /** Create one session, send a prompt, and save its history in SQLite. */
2
+ import * as NodeRuntime from "@effect/platform-node/NodeRuntime";
3
+ import * as NodeServices from "@effect/platform-node/NodeServices";
4
+ import * as SqliteClient from "@effect/sql-sqlite-node/SqliteClient";
5
+ import * as Config from "effect/Config";
6
+ import * as Console from "effect/Console";
7
+ import * as Effect from "effect/Effect";
8
+ import * as Layer from "effect/Layer";
9
+ import * as Stream from "effect/Stream";
10
+ import * as Argument from "effect/unstable/cli/Argument";
11
+ import * as Command from "effect/unstable/cli/Command";
12
+ import * as Flag from "effect/unstable/cli/Flag";
13
+ import * as KeyValueStore from "effect/unstable/persistence/KeyValueStore";
14
+ import { ModelRuntime, ResourceLoader, Session } from "@jpowersdev/effect-pi";
15
+ const ResourcesLive = ResourceLoader.layerEmpty({
16
+ systemPrompt: "You are a helpful assistant. Use the read-only tools only when asked to inspect files.",
17
+ settings: { retry: { enabled: false } }
18
+ });
19
+ const ModelLive = ModelRuntime.layerConfig(Config.all({
20
+ provider: Config.NonEmptyString("EFFECT_PI_PROVIDER"),
21
+ modelId: Config.NonEmptyString("EFFECT_PI_MODEL"),
22
+ apiKey: Config.Redacted("EFFECT_PI_API_KEY")
23
+ }).pipe(Config.map(({ provider, modelId, apiKey }) => ({
24
+ model: { provider, id: modelId },
25
+ apiKeys: { [provider]: apiKey },
26
+ authPath: ".data/effect-pi/auth.json",
27
+ modelsPath: null,
28
+ refreshOnCreate: false
29
+ })))).pipe(Layer.provide(ResourcesLive));
30
+ const StoreLive = KeyValueStore.layerSql({ table: "pi_sessions" }).pipe(Layer.provide(SqliteClient.layer({ filename: ".data/effect-pi/sessions.sqlite" })));
31
+ const cli = Command.make("single-session", {
32
+ prompt: Argument.String("prompt").pipe(Argument.withDefault("Say hello in one short sentence.")),
33
+ snapshot: Flag.Boolean("snapshot").pipe(Flag.withDefault(false), Flag.withDescription("Print saved state without calling a model"))
34
+ }, ({ prompt, snapshot }) => Effect.gen(function* () {
35
+ const session = yield* Session.make({
36
+ id: Session.Id.make("single-session"),
37
+ cwd: ".",
38
+ configure: () => ({ tools: ["read", "grep", "find", "ls"] })
39
+ });
40
+ if (snapshot) {
41
+ return yield* Console.log(yield* session.snapshot);
42
+ }
43
+ yield* session.events.pipe(Stream.runForEach((event) => Console.log(event)), Effect.catch((error) => Console.warn(error)), Effect.forkScoped({ startImmediately: true }));
44
+ const result = yield* session.prompt(prompt).pipe(Effect.timeout("2 minutes"));
45
+ yield* Console.log("Result:", result);
46
+ }).pipe(Effect.scoped)).pipe(Command.provide(Layer.merge(ModelLive, StoreLive)));
47
+ const program = Command.run(cli, { version: "0.1.0" }).pipe(Effect.provide(NodeServices.layer));
48
+ NodeRuntime.runMain(program);
49
+ //# sourceMappingURL=single-session.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"single-session.js","sourceRoot":"","sources":["../examples/single-session.ts"],"names":[],"mappings":"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"}