@codeworksh/harness 0.0.1-dev.20260824182323 → 0.0.1-dev.20260825090614

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/effect.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  import { n as __exportAll } from "./rolldown-runtime-B4iAMlE-.mjs";
2
- import { c as harness_exports, r as session_exports, s as sandbox_exports, u as tool_exports } from "./session-CF1B0VEr.mjs";
2
+ import { c as harness_exports, h as run_exports, r as session_exports, s as sandbox_exports, u as tool_exports } from "./session-BpTL_HoS.mjs";
3
3
  //#region src/effect/tools.ts
4
4
  var tools_exports = /* @__PURE__ */ __exportAll({
5
5
  Tools: () => tools_exports,
@@ -7,6 +7,6 @@ var tools_exports = /* @__PURE__ */ __exportAll({
7
7
  });
8
8
  const bash = "bash";
9
9
  //#endregion
10
- export { harness_exports as Harness, sandbox_exports as Sandbox, session_exports as Session, tool_exports as Tool, tools_exports as Tools };
10
+ export { harness_exports as Harness, run_exports as Runner, sandbox_exports as Sandbox, session_exports as Session, tool_exports as Tool, tools_exports as Tools };
11
11
 
12
12
  //# sourceMappingURL=effect.mjs.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@codeworksh/harness",
3
- "version": "0.0.1-dev.20260824182323",
3
+ "version": "0.0.1-dev.20260825090614",
4
4
  "description": "AI agent harness — agent loop, tools, and code execution sandbox.",
5
5
  "keywords": [
6
6
  "agent",
@@ -51,7 +51,7 @@
51
51
  "node": ">=24.14.1"
52
52
  },
53
53
  "dependencies": {
54
- "@codeworksh/aikit": "0.7.1",
54
+ "@codeworksh/aikit": "0.7.2",
55
55
  "@daytona/sdk": "^0.187.0",
56
56
  "@effect/platform-node": "4.0.0-beta.107",
57
57
  "@effect/sql-sqlite-node": "4.0.0-beta.107",
@@ -14,6 +14,7 @@ import { ChildProcess, ChildProcessSpawner } from "effect/unstable/process";
14
14
  import { MemoryProvider, RealFSProvider, SqliteProvider, create } from "@platformatic/vfs";
15
15
  import { Bash } from "just-bash";
16
16
  import { createHash } from "crypto";
17
+ import * as AikitFailure from "@codeworksh/aikit/failure";
17
18
  import { randomBytes } from "node:crypto";
18
19
  //#region src/schema.ts
19
20
  const aikitValidators = /* @__PURE__ */ new WeakMap();
@@ -985,7 +986,6 @@ const layer$20 = Layer.effect(Service$13, Effect.gen(function* () {
985
986
  const sql = yield* SqlClient.SqlClient;
986
987
  const pubsub = {
987
988
  all: yield* PubSub.unbounded(),
988
- durable: /* @__PURE__ */ new Map(),
989
989
  typed: /* @__PURE__ */ new Map()
990
990
  };
991
991
  const projectors = /* @__PURE__ */ new Map();
@@ -993,7 +993,6 @@ const layer$20 = Layer.effect(Service$13, Effect.gen(function* () {
993
993
  yield* Effect.addFinalizer(() => Effect.gen(function* () {
994
994
  yield* PubSub.shutdown(pubsub.all);
995
995
  yield* Effect.forEach(pubsub.typed.values(), PubSub.shutdown, { discard: true });
996
- yield* Effect.forEach(pubsub.durable.values(), (wakes) => Effect.forEach(wakes, PubSub.shutdown, { discard: true }), { discard: true });
997
996
  }));
998
997
  const observe = (event, observer) => Effect.suspend(() => observer(event)).pipe(Effect.catchCauseIf((cause) => !Cause.hasInterrupts(cause), (cause) => Effect.logError("Event listener failed", {
999
998
  eventID: event.id,
@@ -1097,7 +1096,7 @@ const layer$20 = Layer.effect(Service$13, Effect.gen(function* () {
1097
1096
  message: `Expected string aggregate field ${durable.aggregate}`
1098
1097
  }));
1099
1098
  const encoded = yield* Schema.encodeUnknownEffect(definition.data)(event.data);
1100
- const committed = yield* sql.withTransaction(Effect.gen(function* () {
1099
+ return yield* sql.withTransaction(Effect.gen(function* () {
1101
1100
  const { seq } = yield* bumpSequence(aggregateId);
1102
1101
  const existing = yield* findEventById(event.id);
1103
1102
  if (Option.isSome(existing)) return yield* Effect.die(new InvalidDurableEventError({
@@ -1122,8 +1121,6 @@ const layer$20 = Layer.effect(Service$13, Effect.gen(function* () {
1122
1121
  });
1123
1122
  return payload;
1124
1123
  }));
1125
- yield* Effect.forEach(pubsub.durable.get(aggregateId) ?? [], (wake) => PubSub.publish(wake, void 0), { discard: true });
1126
- return committed;
1127
1124
  }, Effect.orDie, Effect.uninterruptible);
1128
1125
  const publishEvent = Effect.fn("Event.publishEvent")(function* (definition, event) {
1129
1126
  if (definition.durable) {
@@ -1175,19 +1172,32 @@ const layer$20 = Layer.effect(Service$13, Effect.gen(function* () {
1175
1172
  const subscribe = (definition) => Stream.unwrap(getOrCreate(definition).pipe(Effect.map((created) => Stream.fromPubSub(created)))).pipe(Stream.map((event) => event));
1176
1173
  const streamAll = () => Stream.fromPubSub(pubsub.all);
1177
1174
  const stream = (input) => {
1178
- const tail = streamAll().pipe(Stream.filter((event) => event.data.sessionId === input.sessionId));
1179
- if (input.after === void 0) return tail;
1180
- return Stream.paginate(input.after, Effect.fn("Event.stream.history")(function* (after) {
1181
- const page = yield* readAggregate({
1182
- aggregateId: input.sessionId,
1183
- after,
1184
- limit: 100,
1185
- manifest: Manifest
1186
- });
1187
- const last = page.events.at(-1);
1188
- const next = page.hasMore && last?.durable !== void 0 ? Option.some(last.durable.seq) : Option.none();
1189
- return [page.events, next];
1190
- })).pipe(Stream.map((event) => event), Stream.concat(tail));
1175
+ const forSession = (event) => event.data.sessionId === input.sessionId;
1176
+ const after = input.after;
1177
+ if (after === void 0) return streamAll().pipe(Stream.filter(forSession));
1178
+ return Stream.unwrap(Effect.gen(function* () {
1179
+ const subscription = yield* PubSub.subscribe(pubsub.all);
1180
+ const watermark = yield* Ref.make(after);
1181
+ const history = Stream.paginate(after, Effect.fn("Event.stream.history")(function* (after) {
1182
+ const page = yield* readAggregate({
1183
+ aggregateId: input.sessionId,
1184
+ after,
1185
+ limit: 100,
1186
+ manifest: Manifest
1187
+ });
1188
+ const last = page.events.at(-1);
1189
+ const next = page.hasMore && last?.durable !== void 0 ? Option.some(last.durable.seq) : Option.none();
1190
+ return [page.events, next];
1191
+ })).pipe(Stream.map((event) => event), Stream.tap((event) => {
1192
+ const seq = event.durable?.seq;
1193
+ return seq === void 0 ? Effect.void : Ref.update(watermark, (current) => Math.max(current, seq));
1194
+ }));
1195
+ const tail = Stream.fromSubscription(subscription).pipe(Stream.filter(forSession), Stream.filterEffect((event) => {
1196
+ const seq = event.durable?.seq;
1197
+ return seq === void 0 ? Effect.succeed(true) : Ref.get(watermark).pipe(Effect.map((replayed) => seq > replayed));
1198
+ }));
1199
+ return history.pipe(Stream.concat(tail));
1200
+ }));
1191
1201
  };
1192
1202
  const listen = (listener) => Effect.sync(() => {
1193
1203
  listeners.push(listener);
@@ -2565,7 +2575,7 @@ const sanitizeError = (cause, redact = makeRedactor()) => {
2565
2575
  ...code === void 0 ? {} : { code: redact(code) }
2566
2576
  };
2567
2577
  };
2568
- const providerError = (input) => {
2578
+ const providerError$1 = (input) => {
2569
2579
  const error = new SandboxProviderError({
2570
2580
  driver: input.driver,
2571
2581
  operation: input.operation,
@@ -2881,7 +2891,7 @@ const encodeMetadataJson = Schema.encodeEffect(MetadataJson);
2881
2891
  const encodePersistedErrorJson = Schema.encodeEffect(PersistedErrorJson);
2882
2892
  /** Schema-aware runtime check; `instanceof` does not survive schema decoding. */
2883
2893
  const isSandboxProviderError = Schema.is(SandboxProviderError);
2884
- const parseJson = (driver, operation, value) => decodeUnknownJson(value).pipe(Effect.mapError((cause) => providerError({
2894
+ const parseJson = (driver, operation, value) => decodeUnknownJson(value).pipe(Effect.mapError((cause) => providerError$1({
2885
2895
  driver,
2886
2896
  operation,
2887
2897
  cause
@@ -2973,18 +2983,18 @@ const make$16 = Effect.fn("Sandbox.Controller.make")(function* (options = {}) {
2973
2983
  const runtime = Effect.fn("Sandbox.Controller.runtime")(function* (row, operation) {
2974
2984
  const driverName = Name.make(row.driver);
2975
2985
  const driver = yield* registry.get(driverName);
2976
- if (driver.kind !== row.kind) return yield* providerError({
2986
+ if (driver.kind !== row.kind) return yield* providerError$1({
2977
2987
  driver: driverName,
2978
2988
  operation,
2979
2989
  cause: /* @__PURE__ */ new Error(`registered kind ${driver.kind} conflicts with persisted kind ${row.kind}`)
2980
2990
  });
2981
- if (Option.isNone(row.runtimeConfig)) return yield* providerError({
2991
+ if (Option.isNone(row.runtimeConfig)) return yield* providerError$1({
2982
2992
  driver: driverName,
2983
2993
  operation,
2984
2994
  cause: /* @__PURE__ */ new Error(`sandbox runtime config is missing: ${row.id}`)
2985
2995
  });
2986
2996
  const decoded = yield* parseJson(driverName, operation, row.runtimeConfig.value);
2987
- const runtimeConfig = yield* registry.decodeRuntimeConfig(driverName, decoded).pipe(Effect.mapError((cause) => providerError({
2997
+ const runtimeConfig = yield* registry.decodeRuntimeConfig(driverName, decoded).pipe(Effect.mapError((cause) => providerError$1({
2988
2998
  driver: driverName,
2989
2999
  operation,
2990
3000
  cause
@@ -3101,7 +3111,7 @@ const make$16 = Effect.fn("Sandbox.Controller.make")(function* (options = {}) {
3101
3111
  }).pipe(Effect.catch((error) => persistProviderFailure(id, "faulted", error)));
3102
3112
  return yield* Effect.gen(function* () {
3103
3113
  const encoded = yield* registry.encodeRuntimeConfig(driver.name, provisioned.runtimeConfig);
3104
- const runtimeConfig = yield* encodeUnknownJson$1(encoded).pipe(Effect.mapError((cause) => providerError({
3114
+ const runtimeConfig = yield* encodeUnknownJson$1(encoded).pipe(Effect.mapError((cause) => providerError$1({
3105
3115
  driver: driver.name,
3106
3116
  operation: "create",
3107
3117
  cause
@@ -3149,7 +3159,7 @@ const make$16 = Effect.fn("Sandbox.Controller.make")(function* (options = {}) {
3149
3159
  overrides: input.runtimeConfig
3150
3160
  });
3151
3161
  const encoded = yield* registry.encodeRuntimeConfig(driver.name, runtimeConfig);
3152
- const persisted = yield* encodeUnknownJson$1(encoded).pipe(Effect.mapError((cause) => providerError({
3162
+ const persisted = yield* encodeUnknownJson$1(encoded).pipe(Effect.mapError((cause) => providerError$1({
3153
3163
  driver: driver.name,
3154
3164
  operation: "register",
3155
3165
  cause
@@ -3741,7 +3751,7 @@ const make$13 = () => {
3741
3751
  const resources = /* @__PURE__ */ new Map();
3742
3752
  const find = (operation, input) => {
3743
3753
  const vfs = resources.get(input.id);
3744
- return vfs === void 0 ? Effect.fail(providerError({
3754
+ return vfs === void 0 ? Effect.fail(providerError$1({
3745
3755
  driver: name,
3746
3756
  operation,
3747
3757
  cause: /* @__PURE__ */ new Error(`memory namespace is unavailable in this process: ${input.id}`),
@@ -3760,7 +3770,7 @@ const make$13 = () => {
3760
3770
  },
3761
3771
  createConfigCodec: CreateConfig$3,
3762
3772
  runtimeConfigCodec: RuntimeConfig$3,
3763
- create: ({ instanceId, config }) => make$15({ cwd: config.initializeCwd ?? config.defaultCwd }).pipe(Effect.mapError((cause) => providerError({
3773
+ create: ({ instanceId, config }) => make$15({ cwd: config.initializeCwd ?? config.defaultCwd }).pipe(Effect.mapError((cause) => providerError$1({
3764
3774
  driver: name,
3765
3775
  operation: "create",
3766
3776
  cause
@@ -3772,7 +3782,7 @@ const make$13 = () => {
3772
3782
  runtimeConfig: { defaultCwd: config.defaultCwd }
3773
3783
  };
3774
3784
  })),
3775
- runtimeConfigFor: ({ providerResourceId }) => Effect.fail(providerError({
3785
+ runtimeConfigFor: ({ providerResourceId }) => Effect.fail(providerError$1({
3776
3786
  driver: name,
3777
3787
  operation: "runtimeConfigFor",
3778
3788
  cause: /* @__PURE__ */ new Error(`memory resources cannot be reattached: ${providerResourceId}`),
@@ -3792,7 +3802,7 @@ const make$13 = () => {
3792
3802
  providerStatus: "retained"
3793
3803
  }),
3794
3804
  destroy: (input) => Effect.suspend(() => {
3795
- return resources.delete(input.id) || Option.isSome(input.providerResourceId) ? Effect.void : Effect.fail(providerError({
3805
+ return resources.delete(input.id) || Option.isSome(input.providerResourceId) ? Effect.void : Effect.fail(providerError$1({
3796
3806
  driver: name,
3797
3807
  operation: "destroy",
3798
3808
  cause: /* @__PURE__ */ new Error(`memory namespace is unavailable: ${input.id}`),
@@ -3851,7 +3861,7 @@ const make$11 = () => {
3851
3861
  const runtimeLocation = (input) => input.runtimeConfig.location ?? Option.getOrUndefined(input.providerResourceId);
3852
3862
  const persistentTransport = (location) => {
3853
3863
  const backend = layer$12({ location });
3854
- return transportLayer(Layer.effectContext(Layer.build(backend).pipe(Effect.mapError((cause) => providerError({
3864
+ return transportLayer(Layer.effectContext(Layer.build(backend).pipe(Effect.mapError((cause) => providerError$1({
3855
3865
  driver: name,
3856
3866
  operation: "attach",
3857
3867
  cause
@@ -3859,7 +3869,7 @@ const make$11 = () => {
3859
3869
  };
3860
3870
  const memoryResource = (operation, id) => {
3861
3871
  const resource = memory.get(id);
3862
- return resource === void 0 ? Effect.fail(providerError({
3872
+ return resource === void 0 ? Effect.fail(providerError$1({
3863
3873
  driver: name,
3864
3874
  operation,
3865
3875
  cause: /* @__PURE__ */ new Error(`in-memory sqlite namespace is unavailable in this process: ${id}`),
@@ -3880,7 +3890,7 @@ const make$11 = () => {
3880
3890
  runtimeConfigCodec: RuntimeConfig$2,
3881
3891
  create: ({ instanceId, config }) => {
3882
3892
  const location = config.location === void 0 ? void 0 : posix.resolve(config.location);
3883
- return make$12(location, { cwd: config.initializeCwd ?? config.defaultCwd }).pipe(Effect.mapError((cause) => providerError({
3893
+ return make$12(location, { cwd: config.initializeCwd ?? config.defaultCwd }).pipe(Effect.mapError((cause) => providerError$1({
3884
3894
  driver: name,
3885
3895
  operation: "create",
3886
3896
  cause
@@ -3899,7 +3909,7 @@ const make$11 = () => {
3899
3909
  }));
3900
3910
  },
3901
3911
  runtimeConfigFor: ({ providerResourceId, overrides }) => {
3902
- if (!posix.isAbsolute(providerResourceId)) return Effect.fail(providerError({
3912
+ if (!posix.isAbsolute(providerResourceId)) return Effect.fail(providerError$1({
3903
3913
  driver: name,
3904
3914
  operation: "runtimeConfigFor",
3905
3915
  cause: /* @__PURE__ */ new Error(`sqldb resource path must be absolute: ${providerResourceId}`)
@@ -3914,7 +3924,7 @@ const make$11 = () => {
3914
3924
  attach: (input) => {
3915
3925
  if (input.runtimeConfig.inMemory) return Layer.unwrap(Effect.map(memoryResource("attach", input.id), (resource) => transport$2(resource.vfs)));
3916
3926
  const location = runtimeLocation(input);
3917
- return location === void 0 ? Layer.unwrap(Effect.fail(providerError({
3927
+ return location === void 0 ? Layer.unwrap(Effect.fail(providerError$1({
3918
3928
  driver: name,
3919
3929
  operation: "attach",
3920
3930
  cause: /* @__PURE__ */ new Error(`sqldb runtime location is missing: ${input.id}`)
@@ -3926,12 +3936,12 @@ const make$11 = () => {
3926
3936
  providerStatus: "online"
3927
3937
  });
3928
3938
  const location = runtimeLocation(input);
3929
- if (location === void 0) return Effect.fail(providerError({
3939
+ if (location === void 0) return Effect.fail(providerError$1({
3930
3940
  driver: name,
3931
3941
  operation: "inspect",
3932
3942
  cause: /* @__PURE__ */ new Error(`sqldb runtime location is missing: ${input.id}`)
3933
3943
  }));
3934
- return fileSystem.access(location).pipe(Effect.mapError((cause) => providerError({
3944
+ return fileSystem.access(location).pipe(Effect.mapError((cause) => providerError$1({
3935
3945
  driver: name,
3936
3946
  operation: "inspect",
3937
3947
  cause,
@@ -3963,11 +3973,11 @@ const make$11 = () => {
3963
3973
  return Effect.void;
3964
3974
  }
3965
3975
  const location = runtimeLocation(input);
3966
- return location === void 0 ? Effect.fail(providerError({
3976
+ return location === void 0 ? Effect.fail(providerError$1({
3967
3977
  driver: name,
3968
3978
  operation: "destroy",
3969
3979
  cause: /* @__PURE__ */ new Error(`sqldb runtime location is missing: ${input.id}`)
3970
- })) : fileSystem.remove(location, { force: true }).pipe(Effect.mapError((cause) => providerError({
3980
+ })) : fileSystem.remove(location, { force: true }).pipe(Effect.mapError((cause) => providerError$1({
3971
3981
  driver: name,
3972
3982
  operation: "destroy",
3973
3983
  cause
@@ -4185,7 +4195,7 @@ const make$9 = (client = {}) => {
4185
4195
  sdk = loaded;
4186
4196
  return run(loaded);
4187
4197
  }),
4188
- catch: (cause) => providerError({
4198
+ catch: (cause) => providerError$1({
4189
4199
  driver: name$1,
4190
4200
  operation,
4191
4201
  cause,
@@ -4465,7 +4475,7 @@ const make$8 = (client = {}) => {
4465
4475
  const redact = makeRedactor([client.token ?? ""]);
4466
4476
  const attempt = (operation, run) => Effect.tryPromise({
4467
4477
  try: run,
4468
- catch: (cause) => providerError({
4478
+ catch: (cause) => providerError$1({
4469
4479
  driver: name,
4470
4480
  operation,
4471
4481
  cause,
@@ -5043,29 +5053,125 @@ const layer$8 = (ref = {}) => Layer.effect(Service$5, Effect.gen(function* () {
5043
5053
  }));
5044
5054
  //#endregion
5045
5055
  //#region src/runner/run.ts
5056
+ var run_exports = /* @__PURE__ */ __exportAll({
5057
+ LLMStreamError: () => LLMStreamError,
5058
+ ModelCatalogError: () => ModelCatalogError,
5059
+ ModelNotFoundError: () => ModelNotFoundError,
5060
+ ProviderAuthenticationError: () => ProviderAuthenticationError,
5061
+ ProviderAuthorizationError: () => ProviderAuthorizationError,
5062
+ ProviderConfigurationError: () => ProviderConfigurationError,
5063
+ ProviderContentPolicyError: () => ProviderContentPolicyError,
5064
+ ProviderError: () => ProviderError,
5065
+ ProviderFailureReason: () => ProviderFailureReason,
5066
+ ProviderInvalidRequestError: () => ProviderInvalidRequestError,
5067
+ ProviderInvalidResponseError: () => ProviderInvalidResponseError,
5068
+ ProviderModelUnavailableError: () => ProviderModelUnavailableError,
5069
+ ProviderQuotaError: () => ProviderQuotaError,
5070
+ ProviderRateLimitError: () => ProviderRateLimitError,
5071
+ ProviderTimeoutError: () => ProviderTimeoutError,
5072
+ ProviderTransportError: () => ProviderTransportError,
5073
+ ProviderUnavailableError: () => ProviderUnavailableError,
5074
+ ProviderUnknownError: () => ProviderUnknownError,
5075
+ Runner: () => run_exports,
5076
+ SandboxDirectoryNotFoundError: () => SandboxDirectoryNotFoundError,
5077
+ Service: () => Service$4
5078
+ });
5046
5079
  var SandboxDirectoryNotFoundError = class extends Schema.TaggedError()("Runner.SandboxDirectoryNotFoundError", {
5047
5080
  sessionId: Schema.String,
5048
5081
  sandboxInstanceId: ID$2,
5049
5082
  directory: Schema.String
5083
+ }) {
5084
+ get message() {
5085
+ return `sandbox directory not found: ${this.directory}`;
5086
+ }
5087
+ };
5088
+ const ProviderFailureFields = {
5089
+ message: Schema.String,
5090
+ isRetryable: Schema.Boolean,
5091
+ status: optional(Schema.Finite),
5092
+ code: optional(Schema.String),
5093
+ requestId: optional(Schema.String),
5094
+ retryAfter: optional(Schema.Duration)
5095
+ };
5096
+ var ProviderAuthenticationError = class extends Schema.TaggedError()("Runner.ProviderAuthenticationError", {
5097
+ authentication: Schema.Literals([
5098
+ "missing",
5099
+ "invalid",
5100
+ "expired"
5101
+ ]),
5102
+ ...ProviderFailureFields
5050
5103
  }) {};
5104
+ var ProviderConfigurationError = class extends Schema.TaggedError()("Runner.ProviderConfigurationError", ProviderFailureFields) {};
5105
+ var ProviderAuthorizationError = class extends Schema.TaggedError()("Runner.ProviderAuthorizationError", ProviderFailureFields) {};
5106
+ var ProviderModelUnavailableError = class extends Schema.TaggedError()("Runner.ProviderModelUnavailableError", ProviderFailureFields) {};
5107
+ var ProviderRateLimitError = class extends Schema.TaggedError()("Runner.ProviderRateLimitError", ProviderFailureFields) {};
5108
+ var ProviderQuotaError = class extends Schema.TaggedError()("Runner.ProviderQuotaError", ProviderFailureFields) {};
5109
+ var ProviderInvalidRequestError = class extends Schema.TaggedError()("Runner.ProviderInvalidRequestError", ProviderFailureFields) {};
5110
+ var ProviderContentPolicyError = class extends Schema.TaggedError()("Runner.ProviderContentPolicyError", ProviderFailureFields) {};
5111
+ var ProviderTimeoutError = class extends Schema.TaggedError()("Runner.ProviderTimeoutError", ProviderFailureFields) {};
5112
+ var ProviderTransportError = class extends Schema.TaggedError()("Runner.ProviderTransportError", ProviderFailureFields) {};
5113
+ var ProviderUnavailableError = class extends Schema.TaggedError()("Runner.ProviderUnavailableError", ProviderFailureFields) {};
5114
+ var ProviderInvalidResponseError = class extends Schema.TaggedError()("Runner.ProviderInvalidResponseError", ProviderFailureFields) {};
5115
+ var ProviderUnknownError = class extends Schema.TaggedError()("Runner.ProviderUnknownError", ProviderFailureFields) {};
5116
+ const ProviderFailureReason = Schema.Union([
5117
+ ProviderAuthenticationError,
5118
+ ProviderConfigurationError,
5119
+ ProviderAuthorizationError,
5120
+ ProviderModelUnavailableError,
5121
+ ProviderRateLimitError,
5122
+ ProviderQuotaError,
5123
+ ProviderInvalidRequestError,
5124
+ ProviderContentPolicyError,
5125
+ ProviderTimeoutError,
5126
+ ProviderTransportError,
5127
+ ProviderUnavailableError,
5128
+ ProviderInvalidResponseError,
5129
+ ProviderUnknownError
5130
+ ]);
5131
+ /** Stable provider boundary for SDK and RPC consumers; inspect `reason._tag` for the category. */
5132
+ var ProviderError = class extends Schema.TaggedError()("Runner.ProviderError", {
5133
+ provider: Schema.String,
5134
+ model: Schema.String,
5135
+ reason: ProviderFailureReason
5136
+ }) {
5137
+ cause = this.reason;
5138
+ get message() {
5139
+ return `${this.provider}/${this.model}: ${this.reason.message}`;
5140
+ }
5141
+ get isRetryable() {
5142
+ return this.reason.isRetryable;
5143
+ }
5144
+ };
5145
+ var ModelCatalogError = class extends Schema.TaggedError()("Runner.ModelCatalogError", {
5146
+ path: Schema.String,
5147
+ reason: Schema.Literals([
5148
+ "missing",
5149
+ "unreadable",
5150
+ "empty",
5151
+ "invalid"
5152
+ ]),
5153
+ detail: Schema.String
5154
+ }) {
5155
+ get message() {
5156
+ return this.detail;
5157
+ }
5158
+ };
5051
5159
  var ModelNotFoundError = class extends Schema.TaggedError()("Runner.ModelNotFoundError", {
5052
5160
  provider: Schema.String,
5053
5161
  model: Schema.String
5054
- }) {};
5055
- var ProviderTurnError = class extends Schema.TaggedError()("Runner.ProviderTurnError", {
5056
- provider: Schema.String,
5057
- model: Schema.String,
5058
- cause: Schema.Defect()
5059
- }) {};
5162
+ }) {
5163
+ get message() {
5164
+ return `model "${this.model}" is not present for provider "${this.provider}" in the model catalog`;
5165
+ }
5166
+ };
5060
5167
  var LLMStreamError = class extends Schema.TaggedError()("Runner.LLMStreamError", {
5061
5168
  sessionId: Schema.String,
5062
5169
  reason: Schema.String
5063
- }) {};
5064
- var TurnError = class extends Schema.TaggedError()("Runner.TurnError", {
5065
- sessionId: Schema.String,
5066
- messageId: optional(ID$1),
5067
- cause: TurnAbortCause
5068
- }) {};
5170
+ }) {
5171
+ get message() {
5172
+ return `invalid provider event stream: ${this.reason}`;
5173
+ }
5174
+ };
5069
5175
  var Service$4 = class extends Context.Service()("@codeworksh/harness/runner/run/Service") {};
5070
5176
  //#endregion
5071
5177
  //#region src/runner/execution.ts
@@ -5477,7 +5583,7 @@ const layer$6 = Layer.effect(Service$3, Effect.gen(function* () {
5477
5583
  sessionId,
5478
5584
  force
5479
5585
  }).pipe(Effect.provideContext(Context.merge(locationContext, mountContext)));
5480
- }).pipe(Effect.scoped, Effect.tapCause((cause) => Cause.hasInterruptsOnly(cause) ? Effect.void : Effect.logError("failed to drain session", cause).pipe(Effect.annotateLogs({ sessionId }))));
5586
+ }).pipe(Effect.scoped, Effect.tapCause((cause) => Cause.hasDies(cause) ? Effect.logError("runner defect", cause).pipe(Effect.annotateLogs({ sessionId })) : Effect.void));
5481
5587
  }) });
5482
5588
  return Service$3.of({
5483
5589
  active: coordinator.active,
@@ -5645,15 +5751,72 @@ const runtimeOptions = (input, signal) => ({
5645
5751
  sessionId: input.sessionId,
5646
5752
  signal
5647
5753
  });
5754
+ const reasonFields = (failure) => ({
5755
+ message: failure.message,
5756
+ isRetryable: failure.retryable,
5757
+ ...failure.status === void 0 ? {} : { status: failure.status },
5758
+ ...failure.code === void 0 ? {} : { code: failure.code },
5759
+ ...failure.requestId === void 0 ? {} : { requestId: failure.requestId },
5760
+ ...failure.retryAfterMs === void 0 ? {} : { retryAfter: Duration.millis(failure.retryAfterMs) }
5761
+ });
5762
+ /** Lift Aikit's JSON-safe failure data into the Effect-native Runner error channel. */
5763
+ const providerError = (input, failure) => {
5764
+ const fields = reasonFields(failure);
5765
+ const reason = (() => {
5766
+ switch (failure._tag) {
5767
+ case "Authentication": return new ProviderAuthenticationError({
5768
+ authentication: failure.reason,
5769
+ ...fields
5770
+ });
5771
+ case "Configuration": return new ProviderConfigurationError(fields);
5772
+ case "Authorization": return new ProviderAuthorizationError(fields);
5773
+ case "ModelUnavailable": return new ProviderModelUnavailableError(fields);
5774
+ case "RateLimit": return new ProviderRateLimitError(fields);
5775
+ case "Quota": return new ProviderQuotaError(fields);
5776
+ case "InvalidRequest": return new ProviderInvalidRequestError(fields);
5777
+ case "ContentPolicy": return new ProviderContentPolicyError(fields);
5778
+ case "Timeout": return new ProviderTimeoutError(fields);
5779
+ case "Transport": return new ProviderTransportError(fields);
5780
+ case "Unavailable": return new ProviderUnavailableError(fields);
5781
+ case "InvalidResponse": return new ProviderInvalidResponseError(fields);
5782
+ case "Unknown": return new ProviderUnknownError(fields);
5783
+ }
5784
+ })();
5785
+ return new ProviderError({
5786
+ provider: input.provider,
5787
+ model: input.model,
5788
+ reason
5789
+ });
5790
+ };
5791
+ const providerErrorFromUnknown = (input, cause) => providerError(input, AikitFailure.normalize(cause));
5792
+ const modelCatalogFailure = (cause) => {
5793
+ if (typeof cause !== "object" || cause === null || !("name" in cause) || cause.name !== "ModelCatalogLoadError") return;
5794
+ if (!("data" in cause) || typeof cause.data !== "object" || cause.data === null) return void 0;
5795
+ const data = cause.data;
5796
+ if (!("path" in data) || typeof data.path !== "string" || !("message" in data) || typeof data.message !== "string" || !("reason" in data) || data.reason !== "missing" && data.reason !== "unreadable" && data.reason !== "empty" && data.reason !== "invalid") return;
5797
+ return {
5798
+ path: data.path,
5799
+ reason: data.reason,
5800
+ message: data.message
5801
+ };
5802
+ };
5803
+ /** Read structured terminal data while remaining compatible with older Aikit messages. */
5804
+ const messageFailure = (message) => {
5805
+ const candidate = message.failure;
5806
+ return AikitFailure.isFailure(candidate) ? candidate : AikitFailure.fromMessage(message.errorMessage ?? "The provider turn failed.");
5807
+ };
5648
5808
  /** Resolve the configured model and start aikit's provider stream. */
5649
5809
  const open = Effect.fn("LLM.open")(function* (input, signal) {
5650
5810
  const model = yield* Effect.tryPromise({
5651
5811
  try: () => llm(input.provider, input.model),
5652
- catch: (cause) => new ProviderTurnError({
5653
- provider: input.provider,
5654
- model: input.model,
5655
- cause
5656
- })
5812
+ catch: (cause) => {
5813
+ const catalog = modelCatalogFailure(cause);
5814
+ return catalog === void 0 ? providerErrorFromUnknown(input, cause) : new ModelCatalogError({
5815
+ path: catalog.path,
5816
+ reason: catalog.reason,
5817
+ detail: catalog.message
5818
+ });
5819
+ }
5657
5820
  });
5658
5821
  if (model === void 0) return yield* new ModelNotFoundError({
5659
5822
  provider: input.provider,
@@ -5661,11 +5824,7 @@ const open = Effect.fn("LLM.open")(function* (input, signal) {
5661
5824
  });
5662
5825
  return yield* Effect.try({
5663
5826
  try: () => stream(model, input.context, runtimeOptions(input, signal)),
5664
- catch: (cause) => new ProviderTurnError({
5665
- provider: input.provider,
5666
- model: input.model,
5667
- cause
5668
- })
5827
+ catch: (cause) => providerErrorFromUnknown(input, cause)
5669
5828
  });
5670
5829
  });
5671
5830
  /**
@@ -5680,11 +5839,7 @@ const make$4 = (openStream) => {
5680
5839
  const abort = Scope.close(signalScope, Exit.void);
5681
5840
  return yield* Effect.uninterruptibleMask((restore) => Effect.gen(function* () {
5682
5841
  const iterable = yield* restore(openStream(input, signal)).pipe(Effect.onInterrupt(() => abort));
5683
- const consumer = yield* Stream.fromAsyncIterable(iterable, (cause) => new ProviderTurnError({
5684
- provider: input.provider,
5685
- model: input.model,
5686
- cause
5687
- })).pipe(Stream.runForEach(input.publisher.publish), Effect.andThen(input.publisher.terminal), Effect.interruptible).pipe(Effect.forkScoped({ startImmediately: true }));
5842
+ const consumer = yield* Stream.fromAsyncIterable(iterable, (cause) => providerErrorFromUnknown(input, cause)).pipe(Stream.runForEach(input.publisher.publish), Effect.andThen(input.publisher.terminal), Effect.interruptible).pipe(Effect.forkScoped({ startImmediately: true }));
5688
5843
  const awaited = yield* restore(Fiber.await(consumer)).pipe(Effect.onInterrupt(() => abort), Effect.exit);
5689
5844
  if (Exit.isFailure(awaited)) {
5690
5845
  const drained = yield* Fiber.await(consumer);
@@ -6644,7 +6799,10 @@ const layer$4 = (options = {}) => {
6644
6799
  //#region src/runner/loop.ts
6645
6800
  const errorMessage = (cause) => {
6646
6801
  const squashed = Cause.squash(cause);
6647
- return squashed instanceof Error ? squashed.message : String(squashed);
6802
+ if (squashed instanceof Error && squashed.message.trim().length > 0) return squashed.message;
6803
+ if (typeof squashed === "string" && squashed.trim().length > 0) return squashed;
6804
+ if (typeof squashed === "object" && squashed !== null && "_tag" in squashed) return String(squashed._tag);
6805
+ return "the turn failed for an unknown reason";
6648
6806
  };
6649
6807
  const terminalResult = (text) => ({
6650
6808
  content: [{
@@ -6827,15 +6985,11 @@ const layer$3 = (options = {}) => Layer.effect(Service$4, Effect.gen(function* (
6827
6985
  publisher
6828
6986
  });
6829
6987
  if (terminal.outcome === "failed") {
6830
- const cause = terminal.reason === "aborted" ? { _tag: "interrupted" } : {
6831
- _tag: "error",
6832
- message: terminal.message.errorMessage ?? "provider turn failed"
6833
- };
6834
- return yield* new TurnError({
6835
- sessionId,
6836
- ...publisher.startedMessageId === void 0 ? {} : { messageId: publisher.startedMessageId },
6837
- cause
6838
- });
6988
+ if (terminal.reason === "aborted") return yield* Effect.interrupt;
6989
+ return yield* providerError({
6990
+ provider: snapshot.provider,
6991
+ model: snapshot.model
6992
+ }, messageFailure(terminal.message));
6839
6993
  }
6840
6994
  const interrupted = yield* settleTools(snapshot, terminal.message, terminal.reason, () => {
6841
6995
  committed = true;
@@ -6847,32 +7001,26 @@ const layer$3 = (options = {}) => Layer.effect(Service$4, Effect.gen(function* (
6847
7001
  };
6848
7002
  }).pipe(Effect.catchCause((cause) => {
6849
7003
  if (committed) return Effect.failCause(cause);
6850
- const failure = Cause.findErrorOption(cause);
6851
- if (Option.isSome(failure) && failure.value._tag === "Runner.TurnError") return Effect.fail(failure.value);
6852
7004
  const turnCause = Cause.hasInterruptsOnly(cause) ? { _tag: "interrupted" } : {
6853
7005
  _tag: "error",
6854
7006
  message: errorMessage(cause)
6855
7007
  };
6856
- return Effect.fail(new TurnError({
6857
- sessionId,
6858
- ...publisher?.startedMessageId === void 0 ? {} : { messageId: publisher.startedMessageId },
6859
- cause: turnCause
6860
- }));
7008
+ const record = Effect.gen(function* () {
7009
+ if (publisher?.startedMessageId !== void 0) {
7010
+ const stored = yield* sessions.entry(publisher.startedMessageId);
7011
+ if (Option.isSome(stored) && stored.value.entry.state === "draft") yield* publishFailure(stored.value, turnCause);
7012
+ }
7013
+ yield* events.publish(TurnAborted, {
7014
+ timestamp: yield* DateTime.now,
7015
+ sessionId,
7016
+ cause: turnCause
7017
+ });
7018
+ });
7019
+ return Effect.uninterruptible(record).pipe(Effect.andThen(Effect.failCause(cause)));
6861
7020
  }));
6862
7021
  });
6863
7022
  const runTurn = Effect.fn("Loop.runTurn")(function* (promotion, snapshot) {
6864
- return yield* runTurnAttempt(promotion, snapshot).pipe(Effect.catchTag("Runner.TurnError", (error) => Effect.gen(function* () {
6865
- if (error.messageId !== void 0) {
6866
- const stored = yield* sessions.entry(error.messageId);
6867
- if (Option.isSome(stored) && stored.value.entry.state === "draft") yield* publishFailure(stored.value, error.cause);
6868
- }
6869
- yield* events.publish(TurnAborted, {
6870
- timestamp: yield* DateTime.now,
6871
- sessionId: snapshot.sessionId,
6872
- cause: error.cause
6873
- });
6874
- return yield* error;
6875
- })));
7023
+ return yield* runTurnAttempt(promotion, snapshot);
6876
7024
  });
6877
7025
  const run$1 = Effect.fn("Loop.run")(function* (input) {
6878
7026
  yield* healDanglingDraft(input.sessionId);
@@ -7265,6 +7413,6 @@ const attach = Effect.fn("Session.attach")(function* (input) {
7265
7413
  return found.value;
7266
7414
  });
7267
7415
  //#endregion
7268
- export { create$2 as a, harness_exports as c, ID$4 as d, Drivers as i, layer as l, create$1 as n, register as o, session_exports as r, sandbox_exports as s, attach as t, tool_exports as u };
7416
+ export { LLMTextDelta as _, create$2 as a, harness_exports as c, LLMStreamError as d, ModelCatalogError as f, LLMEnded as g, run_exports as h, Drivers as i, layer as l, ProviderError as m, create$1 as n, register as o, ModelNotFoundError as p, session_exports as r, sandbox_exports as s, attach as t, tool_exports as u, TurnEnded as v, ID$4 as y };
7269
7417
 
7270
- //# sourceMappingURL=session-CF1B0VEr.mjs.map
7418
+ //# sourceMappingURL=session-BpTL_HoS.mjs.map