@usine/executor 0.0.0 → 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 (63) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +57 -1
  3. package/dist/child-command.d.ts +18 -0
  4. package/dist/child-command.d.ts.map +1 -0
  5. package/dist/child-command.js +47 -0
  6. package/dist/child-command.js.map +1 -0
  7. package/dist/exe-dev/channel.d.ts +8 -0
  8. package/dist/exe-dev/channel.d.ts.map +1 -0
  9. package/dist/exe-dev/channel.js +45 -0
  10. package/dist/exe-dev/channel.js.map +1 -0
  11. package/dist/exe-dev/commands.d.ts +22 -0
  12. package/dist/exe-dev/commands.d.ts.map +1 -0
  13. package/dist/exe-dev/commands.js +67 -0
  14. package/dist/exe-dev/commands.js.map +1 -0
  15. package/dist/exe-dev/grants.d.ts +9 -0
  16. package/dist/exe-dev/grants.d.ts.map +1 -0
  17. package/dist/exe-dev/grants.js +88 -0
  18. package/dist/exe-dev/grants.js.map +1 -0
  19. package/dist/exe-dev/index.d.ts +8 -0
  20. package/dist/exe-dev/index.d.ts.map +1 -0
  21. package/dist/exe-dev/index.js +239 -0
  22. package/dist/exe-dev/index.js.map +1 -0
  23. package/dist/exe-dev/model.d.ts +58 -0
  24. package/dist/exe-dev/model.d.ts.map +1 -0
  25. package/dist/exe-dev/model.js +33 -0
  26. package/dist/exe-dev/model.js.map +1 -0
  27. package/dist/exe-dev/preflight.d.ts +9 -0
  28. package/dist/exe-dev/preflight.d.ts.map +1 -0
  29. package/dist/exe-dev/preflight.js +82 -0
  30. package/dist/exe-dev/preflight.js.map +1 -0
  31. package/dist/exe-dev/shell.d.ts +12 -0
  32. package/dist/exe-dev/shell.d.ts.map +1 -0
  33. package/dist/exe-dev/shell.js +31 -0
  34. package/dist/exe-dev/shell.js.map +1 -0
  35. package/dist/exe-dev/sweep.d.ts +12 -0
  36. package/dist/exe-dev/sweep.d.ts.map +1 -0
  37. package/dist/exe-dev/sweep.js +119 -0
  38. package/dist/exe-dev/sweep.js.map +1 -0
  39. package/dist/index.d.ts +82 -0
  40. package/dist/index.d.ts.map +1 -0
  41. package/dist/index.js +82 -0
  42. package/dist/index.js.map +1 -0
  43. package/dist/invalid-frame.d.ts +17 -0
  44. package/dist/invalid-frame.d.ts.map +1 -0
  45. package/dist/invalid-frame.js +110 -0
  46. package/dist/invalid-frame.js.map +1 -0
  47. package/dist/keyed-lock.d.ts +11 -0
  48. package/dist/keyed-lock.d.ts.map +1 -0
  49. package/dist/keyed-lock.js +21 -0
  50. package/dist/keyed-lock.js.map +1 -0
  51. package/dist/local/index.d.ts +15 -0
  52. package/dist/local/index.d.ts.map +1 -0
  53. package/dist/local/index.js +302 -0
  54. package/dist/local/index.js.map +1 -0
  55. package/dist/provision.d.ts +33 -0
  56. package/dist/provision.d.ts.map +1 -0
  57. package/dist/provision.js +76 -0
  58. package/dist/provision.js.map +1 -0
  59. package/dist/run-host-session.d.ts +22 -0
  60. package/dist/run-host-session.d.ts.map +1 -0
  61. package/dist/run-host-session.js +228 -0
  62. package/dist/run-host-session.js.map +1 -0
  63. package/package.json +51 -4
@@ -0,0 +1,119 @@
1
+ import { Attempt, Worker } from "@usine/core";
2
+ import { Effect, Ref, Schema } from "effect";
3
+ import { ExecutorOperationError } from "../index.js";
4
+ import { keyedLockFor } from "../keyed-lock.js";
5
+ const SWEEP_CONCURRENCY = 4;
6
+ const directChildSchema = (parent) => {
7
+ const prefix = `${parent}/`;
8
+ return Schema.String.check(Schema.makeFilter((value) => {
9
+ const segment = value.slice(prefix.length);
10
+ return (value.startsWith(prefix) &&
11
+ segment.length > 0 &&
12
+ segment !== "." &&
13
+ segment !== ".." &&
14
+ !segment.includes("/"));
15
+ }, { message: `Expected a direct child of ${parent}` }));
16
+ };
17
+ const directChildren = (parent, output) => Schema.decodeUnknownEffect(Schema.Array(directChildSchema(parent)))(output.split("\0").filter((value) => value.length > 0)).pipe(Effect.mapError((cause) => new ExecutorOperationError({
18
+ operation: "prepare",
19
+ message: `Worker returned an invalid path while sweeping ${parent}`,
20
+ cause,
21
+ })));
22
+ /**
23
+ * Reclaims crash leftovers once, before this process starts work on a VM.
24
+ * Every removal is isolated: one immovable leftover must never block the
25
+ * sweep's siblings or, worse, every future prepare on the Worker — so the
26
+ * sweep is marked done even when parts of it failed, and each failure is
27
+ * logged instead of propagated.
28
+ */
29
+ export const abandonedWorktreeSweepFor = Effect.fn("ExeDevExecutor.abandonedWorktreeSweepFor")(function* (commands) {
30
+ const locks = yield* keyedLockFor();
31
+ const swept = yield* Ref.make(new Set());
32
+ const sweep = Effect.fn("ExeDevExecutor.sweepAbandonedWorktrees")(function* (attemptId, worker, vm, root) {
33
+ yield* Effect.annotateCurrentSpan({ attemptId, worker, host: vm.sshDest });
34
+ yield* locks.withLock(worker)(Effect.gen(function* () {
35
+ if ((yield* Ref.get(swept)).has(worker)) {
36
+ yield* Effect.logDebug("exe.dev abandoned-worktree sweep was already complete", {
37
+ attemptId,
38
+ worker,
39
+ host: vm.sshDest,
40
+ });
41
+ return;
42
+ }
43
+ // One shot per Worker per process: a partial sweep must not retry
44
+ // forever in front of every prepare, so mark it done up front and
45
+ // rely on the next process start to reclaim what failed today.
46
+ yield* Ref.update(swept, (current) => new Set(current).add(worker));
47
+ const attemptsRoot = `${root}/attempts`;
48
+ const reposRoot = `${root}/repos`;
49
+ yield* Effect.logInfo("Sweeping abandoned exe.dev Attempt worktrees", {
50
+ attemptId,
51
+ worker,
52
+ host: vm.sshDest,
53
+ });
54
+ yield* commands.remote("prepare", vm.sshDest, "mkdir", ["-p", attemptsRoot, reposRoot]);
55
+ const attempts = yield* commands
56
+ .remote("prepare", vm.sshDest, "find", [
57
+ attemptsRoot,
58
+ "-mindepth",
59
+ "1",
60
+ "-maxdepth",
61
+ "1",
62
+ "-print0",
63
+ ])
64
+ .pipe(Effect.flatMap((output) => directChildren(attemptsRoot, output)));
65
+ const failures = yield* Ref.make(0);
66
+ yield* Effect.forEach(attempts, (worktree) => Effect.logInfo("Sweeping abandoned exe.dev Attempt worktree", {
67
+ attemptId,
68
+ worker,
69
+ host: vm.sshDest,
70
+ worktree,
71
+ }).pipe(Effect.andThen(commands.remote("prepare", vm.sshDest, "rm", ["-rf", worktree])), Effect.tapError((error) => Effect.logWarning("Could not remove an abandoned exe.dev worktree", {
72
+ attemptId,
73
+ worker,
74
+ host: vm.sshDest,
75
+ worktree,
76
+ message: error.message,
77
+ }).pipe(Effect.andThen(Ref.update(failures, (count) => count + 1)))), Effect.ignore), { concurrency: SWEEP_CONCURRENCY, discard: true });
78
+ const caches = yield* commands
79
+ .remote("prepare", vm.sshDest, "find", [
80
+ reposRoot,
81
+ "-mindepth",
82
+ "1",
83
+ "-maxdepth",
84
+ "1",
85
+ "-type",
86
+ "d",
87
+ "-name",
88
+ "*.git",
89
+ "-print0",
90
+ ])
91
+ .pipe(Effect.flatMap((output) => directChildren(reposRoot, output)));
92
+ yield* Effect.forEach(caches, (cache) => commands
93
+ .remote("prepare", vm.sshDest, "git", ["--git-dir", cache, "worktree", "prune"])
94
+ .pipe(Effect.tapError((error) => Effect.logWarning("Could not prune an exe.dev cache during the sweep", {
95
+ attemptId,
96
+ worker,
97
+ host: vm.sshDest,
98
+ cache,
99
+ message: error.message,
100
+ })), Effect.ignore), { concurrency: SWEEP_CONCURRENCY, discard: true });
101
+ const failed = yield* Ref.get(failures);
102
+ yield* Effect.logInfo("exe.dev abandoned-worktree sweep completed", {
103
+ attemptId,
104
+ worker,
105
+ host: vm.sshDest,
106
+ removed: attempts.length - failed,
107
+ failed,
108
+ caches: caches.length,
109
+ });
110
+ }).pipe(Effect.tapError((error) => Effect.logWarning("exe.dev abandoned-worktree sweep failed; continuing", {
111
+ attemptId,
112
+ worker,
113
+ host: vm.sshDest,
114
+ message: error.message,
115
+ })), Effect.ignore));
116
+ });
117
+ return sweep;
118
+ });
119
+ //# sourceMappingURL=sweep.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sweep.js","sourceRoot":"","sources":["../../src/exe-dev/sweep.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,82 @@
1
+ /** @usine/executor — platform-free worker execution contract. */
2
+ import { Agent, Attempt, AttemptChannel, AttemptFailure, Repository, StepResult, Worker } from "@usine/core";
3
+ import { Context, Effect, Redacted, Schema } from "effect";
4
+ export declare const ExecutorOperation: Schema.Literals<readonly ["preflight", "prepare", "launch", "cancel", "cleanup"]>;
5
+ export type ExecutorOperation = typeof ExecutorOperation.Type;
6
+ export declare const WorkerCapability: Schema.Literals<readonly ["machine", "toolchain", "run-host", "harness-login", "credentials"]>;
7
+ export type WorkerCapability = typeof WorkerCapability.Type;
8
+ declare const ExecutorOperationError_base: Schema.Class<ExecutorOperationError, Schema.TaggedStruct<"ExecutorOperationError", {
9
+ readonly operation: Schema.Literals<readonly ["preflight", "prepare", "launch", "cancel", "cleanup"]>;
10
+ readonly message: Schema.NonEmptyString;
11
+ readonly cause: Schema.Defect;
12
+ }>, import("effect/Cause").YieldableError>;
13
+ export declare class ExecutorOperationError extends ExecutorOperationError_base {
14
+ }
15
+ declare const CredentialUnavailableError_base: Schema.Class<CredentialUnavailableError, Schema.TaggedStruct<"CredentialUnavailableError", {
16
+ readonly repository: Schema.brand<Schema.String, "RepoName">;
17
+ readonly message: Schema.NonEmptyString;
18
+ readonly cause: Schema.Defect;
19
+ }>, import("effect/Cause").YieldableError>;
20
+ export declare class CredentialUnavailableError extends CredentialUnavailableError_base {
21
+ }
22
+ declare const WorkerCapabilityError_base: Schema.Class<WorkerCapabilityError, Schema.TaggedStruct<"WorkerCapabilityError", {
23
+ readonly worker: Schema.brand<Schema.String, "WorkerName">;
24
+ readonly capability: Schema.Literals<readonly ["machine", "toolchain", "run-host", "harness-login", "credentials"]>;
25
+ readonly message: Schema.NonEmptyString;
26
+ readonly cause: Schema.Defect;
27
+ }>, import("effect/Cause").YieldableError>;
28
+ /** A verify-only preflight found a Worker capability missing or incompatible. */
29
+ export declare class WorkerCapabilityError extends WorkerCapabilityError_base {
30
+ }
31
+ export declare const ExecutorError: Schema.Union<readonly [typeof ExecutorOperationError, typeof CredentialUnavailableError, typeof WorkerCapabilityError]>;
32
+ export type ExecutorError = typeof ExecutorError.Type;
33
+ /** Every preflight refusal is logged: a missing capability must be explainable from logs alone. */
34
+ export declare const logPreflightFailure: <A, R>(effect: Effect.Effect<A, ExecutorError, R>) => Effect.Effect<A, ExecutorError, R>;
35
+ /** Process command for a one-shot run host or a preflight capability probe. */
36
+ export interface RunHostCommand {
37
+ readonly command: string;
38
+ readonly args: ReadonlyArray<string>;
39
+ }
40
+ declare const CheckoutRequest_base: Schema.Class<CheckoutRequest, Schema.Struct<{
41
+ readonly attemptId: Schema.brand<Schema.NonEmptyString, "AttemptId">;
42
+ readonly worker: Schema.brand<Schema.String, "WorkerName">;
43
+ readonly repository: Schema.brand<Schema.String, "RepoName">;
44
+ readonly revision: Schema.brand<Schema.String, "RepositoryRevision">;
45
+ readonly payload: Schema.Codec<Schema.Json, Schema.Json, never, never>;
46
+ readonly task: Schema.brand<Schema.String, "AttemptTask">;
47
+ readonly agent: typeof Agent.Agent;
48
+ readonly parentModel: Schema.Option<Schema.brand<Schema.String, "ModelId">>;
49
+ }>, {}>;
50
+ /** Secret-free request used to create one fresh Attempt workspace. */
51
+ export declare class CheckoutRequest extends CheckoutRequest_base {
52
+ }
53
+ /** Value object (branded path): one Attempt's disposable checkout directory. */
54
+ export declare const WorktreePath: Schema.brand<Schema.NonEmptyString, "WorktreePath">;
55
+ export type WorktreePath = typeof WorktreePath.Type;
56
+ declare const PreparedAttempt_base: Schema.Class<PreparedAttempt, Schema.Struct<{
57
+ readonly worker: Schema.brand<Schema.String, "WorkerName">;
58
+ readonly spec: typeof AttemptChannel.RunSpec;
59
+ readonly worktree: Schema.brand<Schema.NonEmptyString, "WorktreePath">;
60
+ }>, {}>;
61
+ /** Prepared workspace descriptor. Credentials remain private to the adapter. */
62
+ export declare class PreparedAttempt extends PreparedAttempt_base {
63
+ }
64
+ declare const CredentialProvider_base: Context.ServiceClass<CredentialProvider, "@usine/executor/CredentialProvider", {
65
+ readonly issue: (repository: Repository.Name, attemptId: Attempt.AttemptId) => Effect.Effect<Redacted.Redacted<string>, CredentialUnavailableError>;
66
+ }>;
67
+ /** Mints exactly one repository-scoped credential for each prepared Attempt. */
68
+ export declare class CredentialProvider extends CredentialProvider_base {
69
+ }
70
+ declare const Executor_base: Context.ServiceClass<Executor, "@usine/executor/Executor", {
71
+ readonly kind: Worker.Kind;
72
+ readonly preflight: (worker: Worker.Name) => Effect.Effect<void, ExecutorError>;
73
+ readonly prepare: (request: CheckoutRequest) => Effect.Effect<PreparedAttempt, ExecutorError>;
74
+ readonly launch: (prepared: PreparedAttempt, io: AttemptChannel.Sink) => Effect.Effect<StepResult.StepResult, AttemptFailure.AttemptFailure>;
75
+ readonly cancel: (attemptId: Attempt.AttemptId) => Effect.Effect<void, ExecutorError>;
76
+ readonly cleanup: (prepared: PreparedAttempt) => Effect.Effect<void, ExecutorError>;
77
+ }>;
78
+ /** The five-operation worker contract from ADR 0006. Preflight verifies only — it never installs. */
79
+ export declare class Executor extends Executor_base {
80
+ }
81
+ export {};
82
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,iEAAiE;AAEjE,OAAO,EACL,KAAK,EACL,OAAO,EACP,cAAc,EACd,cAAc,EACd,UAAU,EACV,UAAU,EACV,MAAM,EACP,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAE3D,eAAO,MAAM,iBAAiB,mFAM5B,CAAC;AACH,MAAM,MAAM,iBAAiB,GAAG,OAAO,iBAAiB,CAAC,IAAI,CAAC;AAE9D,eAAO,MAAM,gBAAgB,gGAM3B,CAAC;AACH,MAAM,MAAM,gBAAgB,GAAG,OAAO,gBAAgB,CAAC,IAAI,CAAC;;;;;;AAE5D,qBAAa,sBAAuB,SAAQ,2BAM1C;CAAG;;;;;;AAEL,qBAAa,0BAA2B,SAAQ,+BAM9C;CAAG;;;;;;;AAEL,iFAAiF;AACjF,qBAAa,qBAAsB,SAAQ,0BAOzC;CAAG;AAEL,eAAO,MAAM,aAAa,yHAIxB,CAAC;AACH,MAAM,MAAM,aAAa,GAAG,OAAO,aAAa,CAAC,IAAI,CAAC;AAEtD,mGAAmG;AACnG,eAAO,MAAM,mBAAmB,GAAI,CAAC,EAAE,CAAC,UAC9B,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,aAAa,EAAE,CAAC,CAAC,KACzC,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,aAAa,EAAE,CAAC,CAajC,CAAC;AAEJ,+EAA+E;AAC/E,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,IAAI,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;CACtC;;;;;;;;;;;AAED,sEAAsE;AACtE,qBAAa,eAAgB,SAAQ,oBAWnC;CAAG;AAEL,gFAAgF;AAChF,eAAO,MAAM,YAAY,qDAA2D,CAAC;AACrF,MAAM,MAAM,YAAY,GAAG,OAAO,YAAY,CAAC,IAAI,CAAC;;;;;;AAEpD,gFAAgF;AAChF,qBAAa,eAAgB,SAAQ,oBAMnC;CAAG;;oBAMe,CACd,UAAU,EAAE,UAAU,CAAC,IAAI,EAC3B,SAAS,EAAE,OAAO,CAAC,SAAS,KACzB,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,0BAA0B,CAAC;;AAP7E,gFAAgF;AAChF,qBAAa,kBAAmB,SAAQ,uBAQC;CAAG;;mBAMzB,MAAM,CAAC,IAAI;wBACN,CAAC,MAAM,EAAE,MAAM,CAAC,IAAI,KAAK,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,aAAa,CAAC;sBAC7D,CAAC,OAAO,EAAE,eAAe,KAAK,MAAM,CAAC,MAAM,CAAC,eAAe,EAAE,aAAa,CAAC;qBAC5E,CACf,QAAQ,EAAE,eAAe,EACzB,EAAE,EAAE,cAAc,CAAC,IAAI,KACpB,MAAM,CAAC,MAAM,CAAC,UAAU,CAAC,UAAU,EAAE,cAAc,CAAC,cAAc,CAAC;qBACvD,CAAC,SAAS,EAAE,OAAO,CAAC,SAAS,KAAK,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,aAAa,CAAC;sBACnE,CAAC,QAAQ,EAAE,eAAe,KAAK,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,aAAa,CAAC;;AAZvF,qGAAqG;AACrG,qBAAa,QAAS,SAAQ,aAaC;CAAG"}
package/dist/index.js ADDED
@@ -0,0 +1,82 @@
1
+ /** @usine/executor — platform-free worker execution contract. */
2
+ import { Agent, Attempt, AttemptChannel, AttemptFailure, Repository, StepResult, Worker, } from "@usine/core";
3
+ import { Context, Effect, Redacted, Schema } from "effect";
4
+ export const ExecutorOperation = Schema.Literals([
5
+ "preflight",
6
+ "prepare",
7
+ "launch",
8
+ "cancel",
9
+ "cleanup",
10
+ ]);
11
+ export const WorkerCapability = Schema.Literals([
12
+ "machine",
13
+ "toolchain",
14
+ "run-host",
15
+ "harness-login",
16
+ "credentials",
17
+ ]);
18
+ export class ExecutorOperationError extends Schema.TaggedError("@usine/executor/ExecutorOperationError")("ExecutorOperationError", {
19
+ operation: ExecutorOperation,
20
+ message: Schema.NonEmptyString,
21
+ cause: Schema.Defect(),
22
+ }) {
23
+ }
24
+ export class CredentialUnavailableError extends Schema.TaggedError("@usine/executor/CredentialUnavailableError")("CredentialUnavailableError", {
25
+ repository: Repository.Name,
26
+ message: Schema.NonEmptyString,
27
+ cause: Schema.Defect(),
28
+ }) {
29
+ }
30
+ /** A verify-only preflight found a Worker capability missing or incompatible. */
31
+ export class WorkerCapabilityError extends Schema.TaggedError("@usine/executor/WorkerCapabilityError")("WorkerCapabilityError", {
32
+ worker: Worker.Name,
33
+ capability: WorkerCapability,
34
+ message: Schema.NonEmptyString,
35
+ cause: Schema.Defect(),
36
+ }) {
37
+ }
38
+ export const ExecutorError = Schema.Union([
39
+ ExecutorOperationError,
40
+ CredentialUnavailableError,
41
+ WorkerCapabilityError,
42
+ ]);
43
+ /** Every preflight refusal is logged: a missing capability must be explainable from logs alone. */
44
+ export const logPreflightFailure = (effect) => Effect.tapError(effect, (error) => error instanceof WorkerCapabilityError
45
+ ? Effect.logError("Worker preflight failed", {
46
+ error: error._tag,
47
+ message: error.message,
48
+ worker: error.worker,
49
+ capability: error.capability,
50
+ })
51
+ : Effect.logError("Worker preflight failed", {
52
+ error: error._tag,
53
+ message: error.message,
54
+ }));
55
+ /** Secret-free request used to create one fresh Attempt workspace. */
56
+ export class CheckoutRequest extends Schema.Class("@usine/executor/CheckoutRequest")({
57
+ attemptId: Attempt.AttemptId,
58
+ worker: Worker.Name,
59
+ repository: Repository.Name,
60
+ revision: Repository.Revision,
61
+ payload: Schema.Json,
62
+ task: AttemptChannel.Task,
63
+ agent: Agent.Agent,
64
+ parentModel: Schema.Option(Agent.ModelId),
65
+ }) {
66
+ }
67
+ /** Value object (branded path): one Attempt's disposable checkout directory. */
68
+ export const WorktreePath = Schema.NonEmptyString.pipe(Schema.brand("WorktreePath"));
69
+ /** Prepared workspace descriptor. Credentials remain private to the adapter. */
70
+ export class PreparedAttempt extends Schema.Class("@usine/executor/PreparedAttempt")({
71
+ worker: Worker.Name,
72
+ spec: AttemptChannel.RunSpec,
73
+ worktree: WorktreePath,
74
+ }) {
75
+ }
76
+ /** Mints exactly one repository-scoped credential for each prepared Attempt. */
77
+ export class CredentialProvider extends Context.Service()("@usine/executor/CredentialProvider") {
78
+ }
79
+ /** The five-operation worker contract from ADR 0006. Preflight verifies only — it never installs. */
80
+ export class Executor extends Context.Service()("@usine/executor/Executor") {
81
+ }
82
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ type FrameSource = "effect-log" | "json" | "non-json";
2
+ export interface InvalidFrameDiagnostic {
3
+ readonly byteLength: number;
4
+ readonly eventTag: string | undefined;
5
+ readonly issues: ReadonlyArray<{
6
+ readonly message: string;
7
+ readonly path: string;
8
+ }>;
9
+ readonly payloadTag: string | undefined;
10
+ readonly source: FrameSource;
11
+ readonly version: number | undefined;
12
+ }
13
+ /** Redacted frame diagnostics: shape and schema metadata only, never frame content. */
14
+ export declare const invalidFrameDiagnostic: (line: string, cause: unknown) => InvalidFrameDiagnostic;
15
+ export declare const invalidFrameMessage: (diagnostic: InvalidFrameDiagnostic) => string;
16
+ export {};
17
+ //# sourceMappingURL=invalid-frame.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"invalid-frame.d.ts","sourceRoot":"","sources":["../src/invalid-frame.ts"],"names":[],"mappings":"AAiEA,KAAK,WAAW,GAAG,YAAY,GAAG,MAAM,GAAG,UAAU,CAAC;AAEtD,MAAM,WAAW,sBAAsB;IACrC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,SAAS,CAAC;IACtC,QAAQ,CAAC,MAAM,EAAE,aAAa,CAAC;QAC7B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;QACzB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;KACvB,CAAC,CAAC;IACH,QAAQ,CAAC,UAAU,EAAE,MAAM,GAAG,SAAS,CAAC;IACxC,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAC;IAC7B,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,SAAS,CAAC;CACtC;AAeD,uFAAuF;AACvF,eAAO,MAAM,sBAAsB,SAAU,MAAM,SAAS,OAAO,KAAG,sBAgCrE,CAAC;AAEF,eAAO,MAAM,mBAAmB,eAAgB,sBAAsB,KAAG,MAUxE,CAAC"}
@@ -0,0 +1,110 @@
1
+ import { Option, Schema, SchemaIssue } from "effect";
2
+ const encoder = new TextEncoder();
3
+ const SAFE_TAG_VALUES = [
4
+ "Started",
5
+ "SessionEvent",
6
+ "Final",
7
+ "Failed",
8
+ "Interrupted",
9
+ "SessionStarted",
10
+ "TextOutput",
11
+ "ToolStarted",
12
+ "ToolFinished",
13
+ "PoolRateLimitsUpdated",
14
+ "SessionFinished",
15
+ ];
16
+ const SafeFrameTag = Schema.Literals(SAFE_TAG_VALUES);
17
+ const FramePreview = Schema.Struct({
18
+ version: Schema.optionalKey(Schema.Int),
19
+ payload: Schema.optionalKey(Schema.Struct({
20
+ _tag: Schema.optionalKey(Schema.String),
21
+ event: Schema.optionalKey(Schema.Struct({ _tag: Schema.optionalKey(Schema.String) })),
22
+ })),
23
+ });
24
+ const decodeJsonOption = Schema.decodeUnknownOption(Schema.fromJsonString(Schema.Json));
25
+ const decodeFramePreviewOption = Schema.decodeUnknownOption(FramePreview);
26
+ const decodeSafeFrameTagOption = Schema.decodeUnknownOption(SafeFrameTag);
27
+ const SAFE_PATH_SEGMENTS = new Set([
28
+ "version",
29
+ "attemptId",
30
+ "sequence",
31
+ "sentAt",
32
+ "payload",
33
+ "_tag",
34
+ "event",
35
+ "session",
36
+ "id",
37
+ "parentId",
38
+ "agent",
39
+ "brain",
40
+ "harness",
41
+ "model",
42
+ "effort",
43
+ "callId",
44
+ "tool",
45
+ "input",
46
+ "output",
47
+ "isError",
48
+ "text",
49
+ "pool",
50
+ "rateLimits",
51
+ "limitId",
52
+ "limitName",
53
+ "primary",
54
+ "secondary",
55
+ "usedPercent",
56
+ "windowDurationMinutes",
57
+ "resetsAt",
58
+ "parentModel",
59
+ "result",
60
+ "failure",
61
+ ]);
62
+ const formatSchemaIssues = SchemaIssue.makeFormatterStandardSchemaV1();
63
+ const safeIssuePath = (path) => path
64
+ .map((segment) => {
65
+ const value = String(segment);
66
+ return SAFE_PATH_SEGMENTS.has(value) ? value : "<unexpected>";
67
+ })
68
+ .join(".");
69
+ /** Redacted frame diagnostics: shape and schema metadata only, never frame content. */
70
+ export const invalidFrameDiagnostic = (line, cause) => {
71
+ const byteLength = encoder.encode(line).byteLength;
72
+ const parsed = decodeJsonOption(line);
73
+ if (Option.isNone(parsed)) {
74
+ return {
75
+ byteLength,
76
+ eventTag: undefined,
77
+ issues: [],
78
+ payloadTag: undefined,
79
+ source: /^\[\d{2}:\d{2}:\d{2}[.\]]/u.test(line) ? "effect-log" : "non-json",
80
+ version: undefined,
81
+ };
82
+ }
83
+ const preview = decodeFramePreviewOption(parsed.value);
84
+ const issues = Schema.isSchemaError(cause)
85
+ ? formatSchemaIssues(cause.issue).issues.map((issue) => ({
86
+ message: issue.message.slice(0, 200),
87
+ path: safeIssuePath(issue.path ?? []),
88
+ }))
89
+ : [];
90
+ return {
91
+ byteLength,
92
+ eventTag: Option.flatMap(preview, ({ payload }) => decodeSafeFrameTagOption(payload?.event?._tag)).pipe(Option.getOrUndefined),
93
+ issues,
94
+ payloadTag: Option.flatMap(preview, ({ payload }) => decodeSafeFrameTagOption(payload?._tag)).pipe(Option.getOrUndefined),
95
+ source: "json",
96
+ version: Option.map(preview, ({ version }) => version).pipe(Option.getOrUndefined),
97
+ };
98
+ };
99
+ export const invalidFrameMessage = (diagnostic) => {
100
+ if (diagnostic.source !== "json") {
101
+ return diagnostic.source === "effect-log"
102
+ ? "The run host wrote a log line to its protocol output"
103
+ : "The run host emitted malformed JSON";
104
+ }
105
+ const first = diagnostic.issues[0];
106
+ return first === undefined
107
+ ? "The run host emitted a schema-invalid frame"
108
+ : `The run host emitted a schema-invalid frame at ${first.path || "<root>"}: ${first.message}`;
109
+ };
110
+ //# sourceMappingURL=invalid-frame.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"invalid-frame.js","sourceRoot":"","sources":["../src/invalid-frame.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ import { Effect } from "effect";
2
+ export interface KeyedLock<in K> {
3
+ readonly withLock: (key: K) => <A, E, R>(effect: Effect.Effect<A, E, R>) => Effect.Effect<A, E, R>;
4
+ }
5
+ /**
6
+ * One mutex per key. `PartitionedSemaphore` is not this: its `permits` option
7
+ * is a single shared pool and the partition key only orders waiters, so
8
+ * `make({ permits: 1 })` serializes every key behind one global permit.
9
+ */
10
+ export declare const keyedLockFor: <K>() => Effect.Effect<KeyedLock<K>>;
11
+ //# sourceMappingURL=keyed-lock.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"keyed-lock.d.ts","sourceRoot":"","sources":["../src/keyed-lock.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAkB,MAAM,QAAQ,CAAC;AAEhD,MAAM,WAAW,SAAS,CAAC,EAAE,CAAC,CAAC;IAC7B,QAAQ,CAAC,QAAQ,EAAE,CACjB,GAAG,EAAE,CAAC,KACH,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,KAAK,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;CAC1E;AAED;;;;GAIG;AACH,eAAO,MAAM,YAAY,GAAI,CAAC,OAAK,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,CAcxD,CAAC"}
@@ -0,0 +1,21 @@
1
+ import { Effect, Ref, Semaphore } from "effect";
2
+ /**
3
+ * One mutex per key. `PartitionedSemaphore` is not this: its `permits` option
4
+ * is a single shared pool and the partition key only orders waiters, so
5
+ * `make({ permits: 1 })` serializes every key behind one global permit.
6
+ */
7
+ export const keyedLockFor = () => Effect.map(Ref.make(new Map()), (locks) => ({
8
+ withLock: (key) => {
9
+ const semaphore = Ref.modify(locks, (current) => {
10
+ const existing = current.get(key);
11
+ if (existing !== undefined)
12
+ return [existing, current];
13
+ const created = Semaphore.makeUnsafe(1);
14
+ const next = new Map(current);
15
+ next.set(key, created);
16
+ return [created, next];
17
+ });
18
+ return (effect) => Effect.flatMap(semaphore, (lock) => Semaphore.withPermit(lock, effect));
19
+ },
20
+ }));
21
+ //# sourceMappingURL=keyed-lock.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"keyed-lock.js","sourceRoot":"","sources":["../src/keyed-lock.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAC;AAQhD;;;;GAIG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG,GAAmC,EAAE,CAC/D,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,GAAG,EAA0B,CAAC,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;IAClE,QAAQ,EAAE,CAAC,GAAM,EAAE,EAAE;QACnB,MAAM,SAAS,GAAG,GAAG,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC,OAAO,EAAE,EAAE;YAC9C,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;YAClC,IAAI,QAAQ,KAAK,SAAS;gBAAE,OAAO,CAAC,QAAQ,EAAE,OAAO,CAAU,CAAC;YAChE,MAAM,OAAO,GAAG,SAAS,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;YACxC,MAAM,IAAI,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,CAAC;YAC9B,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;YACvB,OAAO,CAAC,OAAO,EAAE,IAAI,CAAU,CAAC;QAClC,CAAC,CAAC,CAAC;QACH,OAAO,CAAU,MAA8B,EAA0B,EAAE,CACzE,MAAM,CAAC,OAAO,CAAC,SAAS,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,SAAS,CAAC,UAAU,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC;IAC5E,CAAC;CACF,CAAC,CAAC,CAAC"}
@@ -0,0 +1,15 @@
1
+ import { Instance, Repository } from "@usine/core";
2
+ import { Effect, FileSystem, Layer, Path } from "effect";
3
+ import { ChildProcessSpawner } from "effect/unstable/process";
4
+ import { CredentialProvider, Executor, type RunHostCommand } from "../index.ts";
5
+ export type { RunHostCommand } from "../index.ts";
6
+ export interface LocalExecutorOptions {
7
+ readonly instanceDirectory: Instance.Directory;
8
+ /** How to launch the one-shot run host; the composition root resolves it. */
9
+ readonly runHost: RunHostCommand;
10
+ readonly repositoryUrl?: (repository: Repository.Name) => string;
11
+ readonly interruptGrace?: Parameters<typeof Effect.timeoutOption>[1];
12
+ }
13
+ /** Node-only local executor; the package root remains platform-free. */
14
+ export declare const layer: (options: LocalExecutorOptions) => Layer.Layer<Executor, never, CredentialProvider | FileSystem.FileSystem | Path.Path | ChildProcessSpawner.ChildProcessSpawner>;
15
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/local/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAA2C,QAAQ,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAC5F,OAAO,EACL,MAAM,EACN,UAAU,EACV,KAAK,EACL,IAAI,EAOL,MAAM,QAAQ,CAAC;AAChB,OAAO,EAAgB,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AAE5E,OAAO,EAEL,kBAAkB,EAClB,QAAQ,EAKR,KAAK,cAAc,EAGpB,MAAM,aAAa,CAAC;AAKrB,YAAY,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAElD,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,iBAAiB,EAAE,QAAQ,CAAC,SAAS,CAAC;IAC/C,6EAA6E;IAC7E,QAAQ,CAAC,OAAO,EAAE,cAAc,CAAC;IACjC,QAAQ,CAAC,aAAa,CAAC,EAAE,CAAC,UAAU,EAAE,UAAU,CAAC,IAAI,KAAK,MAAM,CAAC;IACjE,QAAQ,CAAC,cAAc,CAAC,EAAE,UAAU,CAAC,OAAO,MAAM,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC;CACtE;AAqYD,wEAAwE;AACxE,eAAO,MAAM,KAAK,YACP,oBAAoB,KAC5B,KAAK,CAAC,KAAK,CACZ,QAAQ,EACR,KAAK,EACL,kBAAkB,GAAG,UAAU,CAAC,UAAU,GAAG,IAAI,CAAC,IAAI,GAAG,mBAAmB,CAAC,mBAAmB,CAC3C,CAAC"}