@codeworksh/harness 0.0.1-dev.20260922135939 → 0.0.1-dev.20260923035712

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
@@ -24,6 +24,8 @@ import path from "node:path";
24
24
  import { Script, constants } from "node:vm";
25
25
  import npa from "npm-package-arg";
26
26
  import * as AikitFailure from "@codeworksh/aikit/failure";
27
+ import { JsonGitHubCopilotAuthStorage, getGitHubCopilotApiKey } from "@codeworksh/aikit/oauth/github/copilot";
28
+ import { JsonOpenAICodexAuthStorage, getOpenAICodexApiKey } from "@codeworksh/aikit/oauth/openai/codex";
27
29
  import "@codeworksh/plugin/tool/error";
28
30
  import { parse, printParseErrorCode } from "jsonc-parser";
29
31
  //#region src/schema.ts
@@ -97,6 +99,7 @@ var global_exports = /* @__PURE__ */ __exportAll({
97
99
  Service: () => Service$17,
98
100
  app: () => app,
99
101
  appConfigDir: () => appConfigDir,
102
+ authFile: () => authFile,
100
103
  defaultLayer: () => defaultLayer$4,
101
104
  homeConfig: () => homeConfig,
102
105
  layer: () => layer$26,
@@ -119,6 +122,16 @@ function make$18(input = {}) {
119
122
  log: input.log ?? posix.join(home, "log")
120
123
  };
121
124
  }
125
+ /**
126
+ * Where a Codework home keeps its OAuth credentials, or undefined to let aikit
127
+ * resolve them (`CODEWORK_CREDENTIALS`, then the default home).
128
+ *
129
+ * Callers pass a home only when the user actually chose one, so an explicit
130
+ * `--home` pins the file and everything else defers to aikit. The harness and
131
+ * the RPC server both go through here: if they disagreed, a login stored by one
132
+ * would be invisible to the other.
133
+ */
134
+ const authFile = (home) => home === void 0 ? void 0 : posix.join(home, "aikit", "auth.json");
122
135
  const resolve$3 = Effect.fn("Global.resolve")(function* (input = {}) {
123
136
  const home = input.home === void 0 ? yield* homeConfig : expandHome(input.home);
124
137
  return make$18({
@@ -7400,14 +7413,50 @@ const resolve$1 = Effect.fn("LLM.resolve")(function* (input) {
7400
7413
  });
7401
7414
  return model;
7402
7415
  });
7416
+ /**
7417
+ * Fill in what an OAuth provider needs and the model catalog cannot carry: the
7418
+ * stored access token, and for Copilot the plan-specific inference host chosen
7419
+ * at login. Anything the request already pins is left alone, and a provider
7420
+ * with no stored login resolves to `{}` so aikit reports the missing key.
7421
+ */
7422
+ const oauthCredentials = async (protocol, options) => {
7423
+ const storage = options.authFile === void 0 ? {} : { path: options.authFile };
7424
+ if (protocol === "openai-codex") {
7425
+ const apiKey = await getOpenAICodexApiKey({ storage: new JsonOpenAICodexAuthStorage(storage) });
7426
+ return apiKey === void 0 ? {} : { apiKey };
7427
+ }
7428
+ if (protocol === "github-copilot") {
7429
+ const store = new JsonGitHubCopilotAuthStorage(storage);
7430
+ const stored = await store.get();
7431
+ const apiKey = await getGitHubCopilotApiKey({ storage: store });
7432
+ if (apiKey === void 0) return {};
7433
+ const apiEndpoint = apiKey === stored?.access ? stored.apiEndpoint : void 0;
7434
+ return {
7435
+ apiKey,
7436
+ ...apiEndpoint === void 0 ? {} : { baseURL: apiEndpoint }
7437
+ };
7438
+ }
7439
+ return {};
7440
+ };
7403
7441
  /** Start a provider stream using the model pinned by State. */
7404
- const open = Effect.fn("LLM.open")(function* (input, signal) {
7442
+ const openWith = (options = {}) => Effect.fn("LLM.open")(function* (input, signal) {
7405
7443
  const model = input.resolvedModel;
7444
+ const configured = runtimeOptions(input, model, signal);
7445
+ const resolved = configured.apiKey === void 0 ? yield* Effect.tryPromise({
7446
+ try: () => oauthCredentials(model.protocol, options),
7447
+ catch: (cause) => providerErrorFromUnknown(input, cause)
7448
+ }) : {};
7449
+ const request = {
7450
+ ...configured,
7451
+ ...resolved,
7452
+ ...configured.baseURL === void 0 ? {} : { baseURL: configured.baseURL }
7453
+ };
7406
7454
  return yield* Effect.try({
7407
- try: () => stream(model, input.context, runtimeOptions(input, model, signal)),
7455
+ try: () => stream(model, input.context, request),
7408
7456
  catch: (cause) => providerErrorFromUnknown(input, cause)
7409
7457
  });
7410
7458
  });
7459
+ const open = openWith();
7411
7460
  /**
7412
7461
  * Build a provider request from an opener. Tests use this with deterministic
7413
7462
  * aikit event streams; production uses `open` above.
@@ -8789,7 +8838,9 @@ const layer = (options = {}) => Layer.unwrap(Effect.gen(function* () {
8789
8838
  const configured = yield* loadAll(options.sandboxes ?? [], { hostCwd });
8790
8839
  const drivers = layer$18(driver_exports.SandboxDriver.withSource(make$11().driver, "core"), driver_exports.SandboxDriver.withSource(make$9().driver, "core"), ...configured);
8791
8840
  const sandboxes = layer$16({ hostCwd }).pipe(Layer.provideMerge(drivers), Layer.provideMerge(database));
8792
- const loop = options.llm === void 0 ? layer$3() : layer$3({ request: make$5(options.llm) });
8841
+ const authFile$1 = authFile(options.home === void 0 ? void 0 : paths.home);
8842
+ const open = options.llm ?? openWith(authFile$1 === void 0 ? {} : { authFile: authFile$1 });
8843
+ const loop = layer$3({ request: make$5(open) });
8793
8844
  return layer$9.pipe(Layer.provideMerge(layer$7.pipe(Layer.provide(loop))), Layer.provideMerge(layer$4({}, pool, references, followStore, rebuild)), Layer.provideMerge(layer$5(settingsOptions)), Layer.provideMerge(layer$6), Layer.provideMerge(sandboxes), Layer.provideMerge(layer$21), Layer.provideMerge(layer$1), Layer.provideMerge(layer$24), Layer.provideMerge(layer$8(definitions)), Layer.provideMerge(database), Layer.provideMerge(global));
8794
8845
  }));
8795
8846
  //#endregion