@usine/durable 0.0.0-stage → 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 (83) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +81 -2
  3. package/dist/attempt/documents.d.ts +86 -0
  4. package/dist/attempt/documents.d.ts.map +1 -0
  5. package/dist/attempt/documents.js +30 -0
  6. package/dist/attempt/documents.js.map +1 -0
  7. package/dist/attempt/events.d.ts +22 -0
  8. package/dist/attempt/events.d.ts.map +1 -0
  9. package/dist/attempt/events.js +110 -0
  10. package/dist/attempt/events.js.map +1 -0
  11. package/dist/attempt/extension.d.ts +48 -0
  12. package/dist/attempt/extension.d.ts.map +1 -0
  13. package/dist/attempt/extension.js +34 -0
  14. package/dist/attempt/extension.js.map +1 -0
  15. package/dist/attempt/hubs.d.ts +117 -0
  16. package/dist/attempt/hubs.d.ts.map +1 -0
  17. package/dist/attempt/hubs.js +137 -0
  18. package/dist/attempt/hubs.js.map +1 -0
  19. package/dist/attempt/outcome.d.ts +22 -0
  20. package/dist/attempt/outcome.d.ts.map +1 -0
  21. package/dist/attempt/outcome.js +84 -0
  22. package/dist/attempt/outcome.js.map +1 -0
  23. package/dist/attempt/parent.d.ts +27 -0
  24. package/dist/attempt/parent.d.ts.map +1 -0
  25. package/dist/attempt/parent.js +109 -0
  26. package/dist/attempt/parent.js.map +1 -0
  27. package/dist/attempt/relay.d.ts +41 -0
  28. package/dist/attempt/relay.d.ts.map +1 -0
  29. package/dist/attempt/relay.js +457 -0
  30. package/dist/attempt/relay.js.map +1 -0
  31. package/dist/attempt/repair.d.ts +8 -0
  32. package/dist/attempt/repair.d.ts.map +1 -0
  33. package/dist/attempt/repair.js +130 -0
  34. package/dist/attempt/repair.js.map +1 -0
  35. package/dist/attempt/request.d.ts +18 -0
  36. package/dist/attempt/request.d.ts.map +1 -0
  37. package/dist/attempt/request.js +24 -0
  38. package/dist/attempt/request.js.map +1 -0
  39. package/dist/attempt/runtime.d.ts +10 -0
  40. package/dist/attempt/runtime.d.ts.map +1 -0
  41. package/dist/attempt/runtime.js +422 -0
  42. package/dist/attempt/runtime.js.map +1 -0
  43. package/dist/attempt/services.d.ts +15 -0
  44. package/dist/attempt/services.d.ts.map +1 -0
  45. package/dist/attempt/services.js +2 -0
  46. package/dist/attempt/services.js.map +1 -0
  47. package/dist/attempt/subagent.d.ts +17 -0
  48. package/dist/attempt/subagent.d.ts.map +1 -0
  49. package/dist/attempt/subagent.js +203 -0
  50. package/dist/attempt/subagent.js.map +1 -0
  51. package/dist/attempt/task.d.ts +61 -0
  52. package/dist/attempt/task.d.ts.map +1 -0
  53. package/dist/attempt/task.js +302 -0
  54. package/dist/attempt/task.js.map +1 -0
  55. package/dist/attempt/watch.d.ts +8 -0
  56. package/dist/attempt/watch.d.ts.map +1 -0
  57. package/dist/attempt/watch.js +25 -0
  58. package/dist/attempt/watch.js.map +1 -0
  59. package/dist/attempt-runtime.d.ts +123 -0
  60. package/dist/attempt-runtime.d.ts.map +1 -0
  61. package/dist/attempt-runtime.js +73 -0
  62. package/dist/attempt-runtime.js.map +1 -0
  63. package/dist/backup.d.ts +26 -0
  64. package/dist/backup.d.ts.map +1 -0
  65. package/dist/backup.js +100 -0
  66. package/dist/backup.js.map +1 -0
  67. package/dist/harness.d.ts +87 -0
  68. package/dist/harness.d.ts.map +1 -0
  69. package/dist/harness.js +271 -0
  70. package/dist/harness.js.map +1 -0
  71. package/dist/live.d.ts +15 -0
  72. package/dist/live.d.ts.map +1 -0
  73. package/dist/live.js +51 -0
  74. package/dist/live.js.map +1 -0
  75. package/dist/storage-path.d.ts +4 -0
  76. package/dist/storage-path.d.ts.map +1 -0
  77. package/dist/storage-path.js +2 -0
  78. package/dist/storage-path.js.map +1 -0
  79. package/dist/testing.d.ts +111 -0
  80. package/dist/testing.d.ts.map +1 -0
  81. package/dist/testing.js +303 -0
  82. package/dist/testing.js.map +1 -0
  83. package/package.json +72 -3
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Resolves with the first committed document value that `accept` matches, starting with the current
3
+ * value. Rejects if the context is aborted or the watch ends, and stops the watch in every case.
4
+ */
5
+ export const firstAccepted = (watch, accept, context) => new Promise((resolve, reject) => {
6
+ const signal = context.abortSignal;
7
+ const settle = (finish) => {
8
+ signal?.removeEventListener("abort", onAbort);
9
+ void watch.stop();
10
+ finish();
11
+ };
12
+ const onAbort = () => settle(() => reject(signal?.reason));
13
+ const initial = watch.value;
14
+ if (initial !== null && accept(initial))
15
+ return settle(() => resolve(initial));
16
+ if (signal?.aborted === true)
17
+ return onAbort();
18
+ signal?.addEventListener("abort", onAbort, { once: true });
19
+ watch.start(async (value) => {
20
+ if (value !== null && accept(value))
21
+ settle(() => resolve(value));
22
+ });
23
+ void watch.closed.then((end) => settle(() => reject(new Error(`The document watch ended: ${end.reason}`))));
24
+ });
25
+ //# sourceMappingURL=watch.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"watch.js","sourceRoot":"","sources":["../../src/attempt/watch.ts"],"names":[],"mappings":"AAGA;;;GAGG;AACH,MAAM,CAAC,MAAM,aAAa,GAAG,CAC3B,KAAuB,EACvB,MAAuC,EACvC,OAAqB,EACC,EAAE,CACxB,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;IAC9B,MAAM,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC;IACnC,MAAM,MAAM,GAAG,CAAC,MAAkB,EAAE,EAAE;QACpC,MAAM,EAAE,mBAAmB,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QAC9C,KAAK,KAAK,CAAC,IAAI,EAAE,CAAC;QAClB,MAAM,EAAE,CAAC;IACX,CAAC,CAAC;IACF,MAAM,OAAO,GAAG,GAAG,EAAE,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IAC3D,MAAM,OAAO,GAAG,KAAK,CAAC,KAAK,CAAC;IAC5B,IAAI,OAAO,KAAK,IAAI,IAAI,MAAM,CAAC,OAAO,CAAC;QAAE,OAAO,MAAM,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC;IAC/E,IAAI,MAAM,EAAE,OAAO,KAAK,IAAI;QAAE,OAAO,OAAO,EAAE,CAAC;IAC/C,MAAM,EAAE,gBAAgB,CAAC,OAAO,EAAE,OAAO,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;IAC3D,KAAK,CAAC,KAAK,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE;QAC1B,IAAI,KAAK,KAAK,IAAI,IAAI,MAAM,CAAC,KAAK,CAAC;YAAE,MAAM,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC;IACpE,CAAC,CAAC,CAAC;IACH,KAAK,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE,CAC7B,MAAM,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,6BAA6B,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,CAC3E,CAAC;AACJ,CAAC,CAAC,CAAC"}
@@ -0,0 +1,123 @@
1
+ import * as AttemptChannel from "@usine/core/attempt/channel";
2
+ import { AttemptId } from "@usine/core/attempt";
3
+ import { AgentFailure, AttemptFailure } from "@usine/core/attempt/failure";
4
+ import { StepResult, type StepResultFact } from "@usine/core/step/result";
5
+ import { Context, type Duration, Effect, type Option, Result, Schema } from "effect";
6
+ declare const StoredRequest_base: Schema.Class<StoredRequest, Schema.Struct<{
7
+ readonly spec: typeof AttemptChannel.RunSpec;
8
+ readonly worker: Schema.brand<Schema.String, "WorkerName">;
9
+ /** The absolute path of the Attempt's worktree on the Worker's machine. */
10
+ readonly cwd: Schema.NonEmptyString;
11
+ }>, {}>;
12
+ /** The persisted part of an Attempt's request, without `host` and `environment`. */
13
+ export declare class StoredRequest extends StoredRequest_base {
14
+ }
15
+ declare const AttemptRequest_base: Schema.Class<AttemptRequest, Schema.Struct<{
16
+ readonly spec: typeof AttemptChannel.RunSpec;
17
+ readonly worker: Schema.brand<Schema.String, "WorkerName">;
18
+ /** The absolute path of the Attempt's worktree on the Worker's machine. */
19
+ readonly cwd: Schema.NonEmptyString;
20
+ readonly host: Schema.Union<readonly [typeof import("@usine/agents/child-host").LocalProcess, typeof import("@usine/agents/child-host").RemoteShell]>;
21
+ /**
22
+ * The environment variables passed to the children: the Worker's allowlisted variables plus the
23
+ * Attempt's credential configuration (ADR 0011).
24
+ */
25
+ readonly environment: Schema.$Record<Schema.String, Schema.String>;
26
+ /**
27
+ * Returns the credential kind that the Worker's Gateway injects (ADR 0027), or `None` if the
28
+ * Worker has no Gateway or the harness uses its own login.
29
+ */
30
+ readonly gatewayCredential: Schema.declare<Effect.Effect<Option.Option<"api-key" | "subscription">, never, never>, unknown>;
31
+ }>, {}>;
32
+ export declare class AttemptRequest extends AttemptRequest_base {
33
+ }
34
+ declare const AttemptReport_base: Schema.Class<AttemptReport, Schema.Struct<{
35
+ readonly message: Schema.NonEmptyString;
36
+ /**
37
+ * Whether the parent's last turn replied to an operator message or steer and delegated nothing
38
+ * after it. Decodes as `false` for older reports.
39
+ */
40
+ readonly answeredOperator: Schema.withConstructorDefault<Schema.withDecodingDefaultKey<Schema.Boolean, never>>;
41
+ }>, {}>;
42
+ /** The parent's final report, without the harvested commits, pull requests, and comments. */
43
+ export declare class AttemptReport extends AttemptReport_base {
44
+ }
45
+ /**
46
+ * Returns the Attempt's StepResult. Fails with `AgentFailure` if `answeredOperator` is true and
47
+ * `facts` is empty (ADR 0018).
48
+ */
49
+ export declare const harvestedResult: (report: AttemptReport, facts: ReadonlyArray<StepResultFact>) => Result.Result<StepResult, AgentFailure>;
50
+ declare const ParentReported_base: Schema.Class<ParentReported, Schema.TaggedStruct<"ParentReported", {
51
+ readonly report: typeof AttemptReport;
52
+ }>, {}>;
53
+ /** A successful parent report with no stored harvested result. */
54
+ export declare class ParentReported extends ParentReported_base {
55
+ }
56
+ declare const ResultRecorded_base: Schema.Class<ResultRecorded, Schema.TaggedStruct<"ResultRecorded", {
57
+ readonly result: typeof StepResult;
58
+ }>, {}>;
59
+ /** A harvested result stored with `recordResult`. */
60
+ export declare class ResultRecorded extends ResultRecorded_base {
61
+ }
62
+ declare const ParentFailed_base: Schema.Class<ParentFailed, Schema.TaggedStruct<"ParentFailed", {
63
+ /** The failure that `execute` returned. */
64
+ readonly failure: Schema.Union<readonly [typeof import("@usine/core/attempt/failure").InfraFailure, typeof import("@usine/core/attempt/failure").DefectFailure, typeof AgentFailure, typeof import("@usine/core/attempt/failure").BlockedFailure, typeof import("@usine/core/attempt/failure").QuestionFailure, typeof import("@usine/core/attempt/failure").RunawayFailure, typeof import("@usine/core/attempt/failure").ChildSessionBudgetFailure]>;
65
+ }>, {}>;
66
+ export declare class ParentFailed extends ParentFailed_base {
67
+ }
68
+ /** The stored state of an Attempt whose terminal envelope was relayed. */
69
+ export declare const FinishedAttempt: Schema.Union<readonly [typeof ParentReported, typeof ResultRecorded, typeof ParentFailed]>;
70
+ export type FinishedAttempt = typeof FinishedAttempt.Type;
71
+ declare const AttemptRuntime_base: Context.ServiceClass<AttemptRuntime, "@usine/durable/AttemptRuntime", {
72
+ /**
73
+ * Creates or reattaches the parent task, appends its activity to `io`, and returns its report.
74
+ */
75
+ readonly execute: (request: AttemptRequest, io: AttemptChannel.Sink) => Effect.Effect<AttemptReport, AttemptFailure>;
76
+ /**
77
+ * Whether the Attempt is open in durable storage: true until `execute` relays the terminal
78
+ * envelope, and false for a canceled task.
79
+ */
80
+ readonly isLive: (attemptId: AttemptId) => Effect.Effect<boolean, AttemptFailure>;
81
+ /**
82
+ * Returns the parent task's final state after `execute` relays the terminal envelope. Returns
83
+ * `None` while the task runs, after `cancel`, or if the Attempt has no task.
84
+ */
85
+ readonly finished: (attemptId: AttemptId) => Effect.Effect<Option.Option<FinishedAttempt>, AttemptFailure>;
86
+ /** Stores the harvested result, which `finished` then returns as `ResultRecorded`. */
87
+ readonly recordResult: (attemptId: AttemptId, result: StepResult) => Effect.Effect<void, AttemptFailure>;
88
+ /**
89
+ * Stores the runaway guard's unsupervised time so a reattached guard resumes from it (#178).
90
+ * Ignores a value shorter than the stored one.
91
+ */
92
+ readonly recordUnsupervised: (attemptId: AttemptId, unsupervised: Duration.Duration) => Effect.Effect<void, AttemptFailure>;
93
+ /** Returns the time stored by `recordUnsupervised`, or `None` if none was stored. */
94
+ readonly unsupervised: (attemptId: AttemptId) => Effect.Effect<Option.Option<Duration.Duration>, AttemptFailure>;
95
+ /** Returns the request the task was created with, or `None` if the Attempt has no task. */
96
+ readonly request: (attemptId: AttemptId) => Effect.Effect<Option.Option<StoredRequest>, AttemptFailure>;
97
+ /**
98
+ * Applies an operator intervention to the live parent or a child and records it in the
99
+ * Attempt's sink, so the sink's `append` must not wait on this call. Fails if no `execute` call
100
+ * in this process is relaying the Attempt.
101
+ */
102
+ readonly intervene: (attemptId: AttemptId, intervention: AttemptChannel.Intervention) => Effect.Effect<void, AttemptFailure>;
103
+ /**
104
+ * Completes when an `execute` call in this process is relaying the Attempt. Never fails or
105
+ * times out, so callers must bound it.
106
+ */
107
+ readonly attached: (attemptId: AttemptId) => Effect.Effect<void>;
108
+ /** Aborts the children, then the parent conversation, and ends the pending `execute` call. */
109
+ readonly cancel: (attemptId: AttemptId) => Effect.Effect<void, AttemptFailure>;
110
+ /**
111
+ * Appends a Worker notice to the transcript. If the parent hasn't started, keeps only the
112
+ * latest notice (and a preceding `WorkerUnresponsive`) until `Started`.
113
+ */
114
+ readonly notify: (attemptId: AttemptId, notice: AttemptChannel.WorkerNotice) => Effect.Effect<void>;
115
+ }>;
116
+ /**
117
+ * Runs each Attempt's Pi parent as a durable task in the orchestrator process. `execute` is
118
+ * idempotent per Attempt ID.
119
+ */
120
+ export declare class AttemptRuntime extends AttemptRuntime_base {
121
+ }
122
+ export {};
123
+ //# sourceMappingURL=attempt-runtime.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"attempt-runtime.d.ts","sourceRoot":"","sources":["../src/attempt-runtime.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,73 @@
1
+ import { ChildHost } from "@usine/agents/child-host";
2
+ import * as AttemptChannel from "@usine/core/attempt/channel";
3
+ import { AttemptId } from "@usine/core/attempt";
4
+ import { AgentFailure, AttemptFailure } from "@usine/core/attempt/failure";
5
+ import { StepResult } from "@usine/core/step/result";
6
+ import { GatewayCredentialKind, WorkerName } from "@usine/core/worker";
7
+ import { Context, Effect, Result, Schema } from "effect";
8
+ /** The persisted part of an Attempt's request, without `host` and `environment`. */
9
+ export class StoredRequest extends Schema.Class("@usine/durable/StoredRequest")({
10
+ spec: AttemptChannel.RunSpec,
11
+ worker: WorkerName,
12
+ /** The absolute path of the Attempt's worktree on the Worker's machine. */
13
+ cwd: Schema.NonEmptyString,
14
+ }) {
15
+ }
16
+ export class AttemptRequest extends Schema.Class("@usine/durable/AttemptRequest")({
17
+ ...StoredRequest.fields,
18
+ host: ChildHost,
19
+ /**
20
+ * The environment variables passed to the children: the Worker's allowlisted variables plus the
21
+ * Attempt's credential configuration (ADR 0011).
22
+ */
23
+ environment: Schema.Record(Schema.String, Schema.String),
24
+ /**
25
+ * Returns the credential kind that the Worker's Gateway injects (ADR 0027), or `None` if the
26
+ * Worker has no Gateway or the harness uses its own login.
27
+ */
28
+ gatewayCredential: Schema.declare((u) => Effect.isEffect(u), { expected: "an Effect that reads the gateway's credential kind" }),
29
+ }) {
30
+ }
31
+ /** The parent's final report, without the harvested commits, pull requests, and comments. */
32
+ export class AttemptReport extends Schema.Class("@usine/durable/AttemptReport")({
33
+ message: Schema.NonEmptyString,
34
+ /**
35
+ * Whether the parent's last turn replied to an operator message or steer and delegated nothing
36
+ * after it. Decodes as `false` for older reports.
37
+ */
38
+ answeredOperator: Schema.Boolean.pipe(Schema.withDecodingDefaultKey(Effect.succeed(false)), Schema.withConstructorDefault(Effect.succeed(false))),
39
+ }) {
40
+ }
41
+ /**
42
+ * Returns the Attempt's StepResult. Fails with `AgentFailure` if `answeredOperator` is true and
43
+ * `facts` is empty (ADR 0018).
44
+ */
45
+ export const harvestedResult = (report, facts) => report.answeredOperator && facts.length === 0
46
+ ? Result.fail(new AgentFailure({
47
+ message: `The parent ended with an answer to the operator, and the attempt produced no commit, pull request, or comment. Answer: ${report.message}`,
48
+ }))
49
+ : Result.succeed(new StepResult({ message: report.message, facts }));
50
+ /** A successful parent report with no stored harvested result. */
51
+ export class ParentReported extends Schema.TaggedClass("@usine/durable/ParentReported")("ParentReported", {
52
+ report: AttemptReport,
53
+ }) {
54
+ }
55
+ /** A harvested result stored with `recordResult`. */
56
+ export class ResultRecorded extends Schema.TaggedClass("@usine/durable/ResultRecorded")("ResultRecorded", {
57
+ result: StepResult,
58
+ }) {
59
+ }
60
+ export class ParentFailed extends Schema.TaggedClass("@usine/durable/ParentFailed")("ParentFailed", {
61
+ /** The failure that `execute` returned. */
62
+ failure: AttemptFailure,
63
+ }) {
64
+ }
65
+ /** The stored state of an Attempt whose terminal envelope was relayed. */
66
+ export const FinishedAttempt = Schema.Union([ParentReported, ResultRecorded, ParentFailed]);
67
+ /**
68
+ * Runs each Attempt's Pi parent as a durable task in the orchestrator process. `execute` is
69
+ * idempotent per Attempt ID.
70
+ */
71
+ export class AttemptRuntime extends Context.Service()("@usine/durable/AttemptRuntime") {
72
+ }
73
+ //# sourceMappingURL=attempt-runtime.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"attempt-runtime.js","sourceRoot":"","sources":["../src/attempt-runtime.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,26 @@
1
+ import { Effect, Schema } from "effect";
2
+ declare const DurableStorageBackupError_base: Schema.Class<DurableStorageBackupError, Schema.TaggedStruct<"DurableStorageBackupError", {
3
+ /**
4
+ * The failed step: `open` (the storage file), `stage` (the temporary copy), `copy` (SQLite's
5
+ * backup), or `publish` (the hard link to `destination`, which fails if the file exists).
6
+ */
7
+ readonly operation: Schema.Literals<readonly ["open", "stage", "copy", "publish"]>;
8
+ /** The path of `.usine/durable.sqlite` in the instance directory. */
9
+ readonly source: Schema.String;
10
+ readonly destination: Schema.String;
11
+ /** A short operator-facing description of the failure. */
12
+ readonly reason: Schema.String;
13
+ readonly cause: Schema.Defect;
14
+ }>, import("effect/Cause").YieldableError>;
15
+ /**
16
+ * A failed durable storage backup, with both paths because a copy error can come from either file.
17
+ */
18
+ export declare class DurableStorageBackupError extends DurableStorageBackupError_base {
19
+ }
20
+ /**
21
+ * Copies `.usine/durable.sqlite`, including its WAL, to `destination` without overwriting an
22
+ * existing file. Returns `false` if the instance has no durable storage.
23
+ */
24
+ export declare const backup: (instanceDirectory: string & import("effect/Brand").Brand<"InstanceDirectory">, destination: string) => Effect.Effect<boolean, DurableStorageBackupError, never>;
25
+ export {};
26
+ //# sourceMappingURL=backup.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"backup.d.ts","sourceRoot":"","sources":["../src/backup.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,MAAM,EAAgD,MAAM,EAAE,MAAM,QAAQ,CAAC;;IASpF;;;OAGG;;IAEH,qEAAqE;;;IAGrE,0DAA0D;;;;AAd5D;;GAEG;AACH,qBAAa,yBAA0B,SAAQ,8BAc7C;CAAG;AAgBL;;;GAGG;AACH,eAAO,MAAM,MAAM,kKA6ElB,CAAC"}
package/dist/backup.js ADDED
@@ -0,0 +1,100 @@
1
+ import { backup as backupDatabase, DatabaseSync } from "node:sqlite";
2
+ import { NodeServices } from "@effect/platform-node";
3
+ import { Effect, FileSystem, Option, Path, Schema } from "effect";
4
+ import { durableStoragePath } from "./storage-path.js";
5
+ /**
6
+ * A failed durable storage backup, with both paths because a copy error can come from either file.
7
+ */
8
+ export class DurableStorageBackupError extends Schema.TaggedError("@usine/durable/DurableStorageBackupError")("DurableStorageBackupError", {
9
+ /**
10
+ * The failed step: `open` (the storage file), `stage` (the temporary copy), `copy` (SQLite's
11
+ * backup), or `publish` (the hard link to `destination`, which fails if the file exists).
12
+ */
13
+ operation: Schema.Literals(["open", "stage", "copy", "publish"]),
14
+ /** The path of `.usine/durable.sqlite` in the instance directory. */
15
+ source: Schema.String,
16
+ destination: Schema.String,
17
+ /** A short operator-facing description of the failure. */
18
+ reason: Schema.String,
19
+ cause: Schema.Defect(),
20
+ }) {
21
+ }
22
+ const errnoCode = Schema.decodeUnknownOption(Schema.Struct({ code: Schema.NonEmptyString }));
23
+ const platformReason = (cause) => {
24
+ if (cause.reason.description !== undefined)
25
+ return cause.reason.description;
26
+ if (cause.reason._tag !== "Unknown")
27
+ return cause.reason._tag;
28
+ return Option.match(errnoCode(cause.reason.cause), {
29
+ onNone: () => cause.reason._tag,
30
+ onSome: ({ code }) => code,
31
+ });
32
+ };
33
+ const sqliteReason = (cause) => cause instanceof Error && cause.message.length > 0 ? cause.message : String(cause);
34
+ /**
35
+ * Copies `.usine/durable.sqlite`, including its WAL, to `destination` without overwriting an
36
+ * existing file. Returns `false` if the instance has no durable storage.
37
+ */
38
+ export const backup = Effect.fn("DurableStorage.backup")(function* (instanceDirectory, destination) {
39
+ const fileSystem = yield* FileSystem.FileSystem;
40
+ const path = yield* Path.Path;
41
+ const source = durableStoragePath(path, instanceDirectory);
42
+ yield* Effect.annotateCurrentSpan({ instanceDirectory, source, destination });
43
+ const failed = (operation, reasonOf) => (cause) => new DurableStorageBackupError({
44
+ operation,
45
+ source,
46
+ destination,
47
+ reason: reasonOf(cause),
48
+ cause,
49
+ });
50
+ if (!(yield* fileSystem.exists(source).pipe(Effect.mapError(failed("open", platformReason))))) {
51
+ yield* Effect.logInfo("The instance has no durable storage to back up", { source });
52
+ return false;
53
+ }
54
+ const info = yield* fileSystem
55
+ .stat(source)
56
+ .pipe(Effect.mapError(failed("open", platformReason)));
57
+ if (info.type !== "File") {
58
+ return yield* new DurableStorageBackupError({
59
+ operation: "open",
60
+ source,
61
+ destination,
62
+ reason: `Expected a regular SQLite file, found ${info.type}`,
63
+ cause: new Error(info.type),
64
+ });
65
+ }
66
+ yield* Effect.logInfo("Durable storage backup started", { source, destination });
67
+ const totalPages = yield* Effect.scoped(Effect.gen(function* () {
68
+ const temporary = yield* fileSystem
69
+ .makeTempDirectoryScoped({
70
+ directory: path.dirname(destination),
71
+ prefix: ".usine-backup-",
72
+ })
73
+ .pipe(Effect.mapError(failed("stage", platformReason)));
74
+ const staged = path.join(temporary, "durable.sqlite");
75
+ yield* fileSystem
76
+ .writeFile(staged, new Uint8Array(), { mode: 0o600 })
77
+ .pipe(Effect.mapError(failed("stage", platformReason)));
78
+ // The backup cannot be canceled; it completes before the connection is closed and the
79
+ // staged file removed.
80
+ const pages = yield* Effect.acquireUseRelease(Effect.try({
81
+ try: () => new DatabaseSync(source, { readOnly: true, timeout: 5_000 }),
82
+ catch: failed("open", sqliteReason),
83
+ }), (database) => Effect.tryPromise({
84
+ try: () => backupDatabase(database, staged),
85
+ catch: failed("copy", sqliteReason),
86
+ }), (database) => Effect.sync(() => database.close())).pipe(Effect.uninterruptible);
87
+ yield* fileSystem
88
+ .link(staged, destination)
89
+ .pipe(Effect.mapError(failed("publish", platformReason)));
90
+ return pages;
91
+ }));
92
+ yield* Effect.logInfo("Durable storage backup completed", { source, destination, totalPages });
93
+ return true;
94
+ }, Effect.tapError((error) => Effect.logWarning("Durable storage backup failed", {
95
+ operation: error.operation,
96
+ source: error.source,
97
+ destination: error.destination,
98
+ reason: error.reason,
99
+ })), Effect.provide(NodeServices.layer));
100
+ //# sourceMappingURL=backup.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"backup.js","sourceRoot":"","sources":["../src/backup.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,87 @@
1
+ import type { Context as ChordContext } from "@earendil-works/chord";
2
+ import type { Models } from "@earendil-works/pi-ai";
3
+ import { type CommitPublication, type Extension, Harness, type ModelRef, type Storage } from "@earendil-works/pi-durable";
4
+ import { Context, Effect, Layer, Option, Schema, Scope } from "effect";
5
+ declare const DurableHarnessError_base: Schema.Class<DurableHarnessError, Schema.TaggedStruct<"DurableHarnessError", {
6
+ /**
7
+ * A description of the failed operation, such as `open`, `resume`, or the `operation` passed to
8
+ * `use`.
9
+ */
10
+ readonly operation: Schema.NonEmptyString;
11
+ /** The error message, or the stop reason if the harness has stopped. */
12
+ readonly message: Schema.NonEmptyString;
13
+ readonly cause: Schema.Defect;
14
+ }>, import("effect/Cause").YieldableError>;
15
+ /** A failed pi-durable call. */
16
+ export declare class DurableHarnessError extends DurableHarnessError_base {
17
+ }
18
+ /** Callbacks for harness events, kept across reopens. */
19
+ export interface HarnessListener {
20
+ /**
21
+ * Runs synchronously after every adopted commit, so it must not block, throw, or call the
22
+ * harness.
23
+ */
24
+ readonly onCommit: (publication: CommitPublication) => void;
25
+ /** Runs after a poisoned or stuck Session is replaced by a reopened harness. */
26
+ readonly onReopen: () => void;
27
+ /** Runs once the harness stops permanently. */
28
+ readonly onStop: () => void;
29
+ }
30
+ /**
31
+ * A storage repair that runs on a newly opened harness before its tasks resume. It must log its own
32
+ * failures and never fail.
33
+ */
34
+ export type BeforeResume = (harness: Harness) => Effect.Effect<void>;
35
+ export interface DurableHarnessOptions {
36
+ /** Opens the storage. Runs again on each reopen. */
37
+ readonly openStorage: Effect.Effect<Storage, DurableHarnessError>;
38
+ /** The pi-ai model access for generation and parent model resolution. */
39
+ readonly models: Models;
40
+ /**
41
+ * The parent model for Attempts that name none. If `None`, the first model with a configured
42
+ * credential is used.
43
+ */
44
+ readonly defaultModel: Option.Option<ModelRef>;
45
+ }
46
+ declare const DurableHarness_base: Context.ServiceClass<DurableHarness, "@usine/durable/DurableHarness", {
47
+ readonly models: Models;
48
+ readonly defaultModel: Option.Option<ModelRef>;
49
+ /**
50
+ * Installs or replaces an extension. Conversations that select it use the new code from their
51
+ * next phase.
52
+ */
53
+ readonly install: (extension: Extension) => Effect.Effect<void>;
54
+ /**
55
+ * Runs `beforeResume`, then starts the task scheduler, and repeats both on each reopen. Call it
56
+ * after installing all extensions.
57
+ */
58
+ readonly resume: (beforeResume: BeforeResume) => Effect.Effect<void, DurableHarnessError>;
59
+ /**
60
+ * Runs a call against the open harness and retries it once if the Session was poisoned or
61
+ * replaced, so the call must be safe to repeat. Fails with the stop reason after the harness
62
+ * stops.
63
+ */
64
+ readonly use: <A>(operation: string, run: (harness: Harness, context: ChordContext) => Promise<A>) => Effect.Effect<A, DurableHarnessError>;
65
+ /** Registers `listener` until the scope closes. */
66
+ readonly subscribe: (listener: HarnessListener) => Effect.Effect<void, never, Scope.Scope>;
67
+ }>;
68
+ /**
69
+ * The pi-durable Harness over one storage. Reopens the storage and resumes the tasks after a
70
+ * poisoned Session or a stuck step, and stops if the reopened harness gets stuck within
71
+ * `STUCK_AGAIN_MILLIS`.
72
+ */
73
+ export declare class DurableHarness extends DurableHarness_base {
74
+ }
75
+ /**
76
+ * The number of reports of one failure, with no adopted commit between them, after which a step
77
+ * counts as stuck.
78
+ */
79
+ export declare const StuckStepReports: Context.Reference<number>;
80
+ export declare const durableError: (operation: string, cause: unknown) => DurableHarnessError;
81
+ /**
82
+ * Opens the harness for the layer's lifetime. Closes it on release without writing any task
83
+ * outcome.
84
+ */
85
+ export declare const layer: (options: DurableHarnessOptions) => Layer.Layer<DurableHarness, DurableHarnessError>;
86
+ export {};
87
+ //# sourceMappingURL=harness.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"harness.d.ts","sourceRoot":"","sources":["../src/harness.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,IAAI,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAErE,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,uBAAuB,CAAC;AACpD,OAAO,EACL,KAAK,iBAAiB,EAEtB,KAAK,SAAS,EACd,OAAO,EACP,KAAK,QAAQ,EACb,KAAK,OAAO,EAEb,MAAM,4BAA4B,CAAC;AACpC,OAAO,EAAE,OAAO,EAAY,MAAM,EAAE,KAAK,EAAE,MAAM,EAAoB,MAAM,EAAE,KAAK,EAAE,MAAM,QAAQ,CAAC;;IAMjG;;;OAGG;;IAEH,wEAAwE;;;;AAT1E,gCAAgC;AAChC,qBAAa,mBAAoB,SAAQ,wBAWvC;CAAG;AAEL,yDAAyD;AACzD,MAAM,WAAW,eAAe;IAC9B;;;OAGG;IACH,QAAQ,CAAC,QAAQ,EAAE,CAAC,WAAW,EAAE,iBAAiB,KAAK,IAAI,CAAC;IAC5D,gFAAgF;IAChF,QAAQ,CAAC,QAAQ,EAAE,MAAM,IAAI,CAAC;IAC9B,+CAA+C;IAC/C,QAAQ,CAAC,MAAM,EAAE,MAAM,IAAI,CAAC;CAC7B;AAED;;;GAGG;AACH,MAAM,MAAM,YAAY,GAAG,CAAC,OAAO,EAAE,OAAO,KAAK,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;AAErE,MAAM,WAAW,qBAAqB;IACpC,oDAAoD;IACpD,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,mBAAmB,CAAC,CAAC;IAClE,yEAAyE;IACzE,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB;;;OAGG;IACH,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;CAChD;;qBAUoB,MAAM;2BACA,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC;IAC9C;;;OAGG;sBACe,CAAC,SAAS,EAAE,SAAS,KAAK,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC;IAC/D;;;OAGG;qBACc,CAAC,YAAY,EAAE,YAAY,KAAK,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,mBAAmB,CAAC;IACzF;;;;OAIG;kBACW,CAAC,CAAC,EACd,SAAS,EAAE,MAAM,EACjB,GAAG,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,YAAY,KAAK,OAAO,CAAC,CAAC,CAAC,KACzD,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,mBAAmB,CAAC;IAC1C,mDAAmD;wBAC/B,CAAC,QAAQ,EAAE,eAAe,KAAK,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,CAAC;;AA9B9F;;;;GAIG;AACH,qBAAa,cAAe,SAAQ,mBA2BA;CAAG;AAcvC;;;GAGG;AACH,eAAO,MAAM,gBAAgB,2BAE3B,CAAC;AAWH,eAAO,MAAM,YAAY,cAAe,MAAM,SAAS,OAAO,wBACY,CAAC;AA6S3E;;;GAGG;AACH,eAAO,MAAM,KAAK,YACP,qBAAqB,KAC7B,KAAK,CAAC,KAAK,CAAC,cAAc,EAAE,mBAAmB,CAAgD,CAAC"}