@oisincoveney/pipeline 3.11.17 → 3.11.19

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.
@@ -1,5 +1,5 @@
1
1
  import { compileArgoExecutionGraph } from "./argo-graph.js";
2
- import { OPENCODE_OPENAI_ACCOUNTS_STAGING_DIR } from "./run-state/opencode-accounts.js";
2
+ import { OPENCODE_AUTH_STAGING_DIR, OPENCODE_OPENAI_ACCOUNTS_STAGING_DIR } from "./run-state/opencode-accounts.js";
3
3
  import { DEFAULT_RUNNER_TASK_DESCRIPTOR_PATH } from "./runner-command/task-descriptor.js";
4
4
  import { stringify } from "yaml";
5
5
  import { z } from "zod";
@@ -303,10 +303,9 @@ function runnerWorkflowStorage(options, tasks) {
303
303
  }
304
304
  });
305
305
  volumeMounts.push({
306
- mountPath: "/root/.local/share/opencode/auth.json",
306
+ mountPath: OPENCODE_AUTH_STAGING_DIR,
307
307
  name: "opencode-auth",
308
- readOnly: true,
309
- subPath: "auth.json"
308
+ readOnly: true
310
309
  });
311
310
  }
312
311
  if (options.opencodeOpenaiAccountsSecret) {
@@ -509,8 +509,8 @@ declare const configSchema: z.ZodObject<{
509
509
  schedules: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodObject<{
510
510
  description: z.ZodOptional<z.ZodString>;
511
511
  baseline: z.ZodEnum<{
512
- quick: "quick";
513
512
  execute: "execute";
513
+ quick: "quick";
514
514
  }>;
515
515
  max_parallel_nodes: z.ZodOptional<z.ZodNumber>;
516
516
  node_catalog: z.ZodOptional<z.ZodString>;
@@ -161,8 +161,8 @@ declare const mokaSubmitOptionsSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
161
161
  }, z.core.$strict>>;
162
162
  serviceAccountName: z.ZodOptional<z.ZodString>;
163
163
  mode: z.ZodEnum<{
164
- full: "full";
165
164
  quick: "quick";
165
+ full: "full";
166
166
  }>;
167
167
  schedulePath: z.ZodOptional<z.ZodString>;
168
168
  scheduleYaml: z.ZodOptional<z.ZodString>;
@@ -1,24 +1,92 @@
1
- import { chmodSync, copyFileSync, existsSync, mkdirSync } from "node:fs";
1
+ import { isRecord } from "../safe-json.js";
2
+ import { chmodSync, copyFileSync, existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
2
3
  import { homedir } from "node:os";
3
- import { dirname, join } from "node:path";
4
+ import { basename, dirname, join } from "node:path";
4
5
  //#region src/run-state/opencode-accounts.ts
5
6
  const OPENCODE_OPENAI_ACCOUNTS_STAGING_DIR = "/etc/pipeline/opencode-openai-accounts";
6
- const STAGED_ACCOUNTS_FILE = join(OPENCODE_OPENAI_ACCOUNTS_STAGING_DIR, "accounts.json");
7
+ const OPENCODE_AUTH_STAGING_DIR = "/etc/pipeline/opencode-auth";
7
8
  const ACCOUNTS_FILE_NAME = "oc-codex-multi-auth-accounts.json";
9
+ const AUTH_FILE_NAME = "auth.json";
10
+ const HOST_OPENAI_PROVIDER = "openai";
11
+ const WRITABLE_OPENCODE_CREDENTIAL_FILES = [{
12
+ destFromHome: [".opencode", ACCOUNTS_FILE_NAME],
13
+ stagedPath: join(OPENCODE_OPENAI_ACCOUNTS_STAGING_DIR, "accounts.json")
14
+ }, {
15
+ destFromHome: [
16
+ ".local",
17
+ "share",
18
+ "opencode",
19
+ AUTH_FILE_NAME
20
+ ],
21
+ stagedPath: join(OPENCODE_AUTH_STAGING_DIR, AUTH_FILE_NAME)
22
+ }];
8
23
  /**
9
- * Copy the staged codex-multi-auth accounts secret to the writable plugin path
10
- * so the plugin can persist rotated tokens. A no-op (copied: false) when no
11
- * staged secret is mounted local dev, tests, and configs without the accounts
12
- * secret keep whatever account store already exists.
24
+ * Copy each staged opencode credential secret to its writable live path, then
25
+ * sync the account pool's active openai token into auth.json's openai entry.
26
+ * Only files whose staged source exists are copied (local dev / tests / configs
27
+ * without a given secret keep whatever store is already present).
13
28
  */
14
- function prepareOpencodeAccounts(options = {}) {
15
- const stagedPath = options.stagedPath ?? STAGED_ACCOUNTS_FILE;
16
- if (!existsSync(stagedPath)) return { copied: false };
17
- const destPath = options.destPath ?? join(homedir(), ".opencode", ACCOUNTS_FILE_NAME);
18
- mkdirSync(dirname(destPath), { recursive: true });
19
- copyFileSync(stagedPath, destPath);
20
- chmodSync(destPath, 384);
21
- return { copied: true };
29
+ function prepareOpencodeCredentials(options = {}) {
30
+ const home = homedir();
31
+ const files = options.files ?? WRITABLE_OPENCODE_CREDENTIAL_FILES.map((file) => ({
32
+ destPath: join(home, ...file.destFromHome),
33
+ stagedPath: file.stagedPath
34
+ }));
35
+ const copied = [];
36
+ for (const { stagedPath, destPath } of files) {
37
+ if (!existsSync(stagedPath)) continue;
38
+ mkdirSync(dirname(destPath), { recursive: true });
39
+ copyFileSync(stagedPath, destPath);
40
+ chmodSync(destPath, 384);
41
+ copied.push(basename(destPath));
42
+ }
43
+ const accountsPath = files.find((file) => basename(file.destPath) === ACCOUNTS_FILE_NAME)?.destPath;
44
+ const authPath = files.find((file) => basename(file.destPath) === AUTH_FILE_NAME)?.destPath;
45
+ return {
46
+ copied,
47
+ hostOpenaiTokenSynced: accountsPath !== void 0 && authPath !== void 0 && syncHostOpenaiToken(accountsPath, authPath)
48
+ };
49
+ }
50
+ function activeAccountOAuth(accountsRaw) {
51
+ if (!isRecord(accountsRaw)) return;
52
+ const accounts = accountsRaw.accounts;
53
+ if (!Array.isArray(accounts)) return;
54
+ const account = accounts[activeAccountIndex(accountsRaw)] ?? accounts[0];
55
+ return isRecord(account) ? oauthFromAccount(account) : void 0;
56
+ }
57
+ function nonEmptyString(value) {
58
+ return typeof value === "string" && value.length > 0;
59
+ }
60
+ function oauthFromAccount(account) {
61
+ const { accessToken, refreshToken, expiresAt } = account;
62
+ if (nonEmptyString(accessToken) && nonEmptyString(refreshToken) && typeof expiresAt === "number") return {
63
+ access: accessToken,
64
+ expires: expiresAt,
65
+ refresh: refreshToken
66
+ };
67
+ }
68
+ function activeAccountIndex(accountsRaw) {
69
+ const byFamily = accountsRaw.activeIndexByFamily;
70
+ if (isRecord(byFamily) && typeof byFamily.codex === "number") return byFamily.codex;
71
+ return typeof accountsRaw.activeIndex === "number" ? accountsRaw.activeIndex : 0;
72
+ }
73
+ function syncHostOpenaiToken(accountsPath, authPath) {
74
+ if (!(existsSync(accountsPath) && existsSync(authPath))) return false;
75
+ const token = activeAccountOAuth(JSON.parse(readFileSync(accountsPath, "utf8")));
76
+ if (!token) return false;
77
+ const auth = JSON.parse(readFileSync(authPath, "utf8"));
78
+ if (!isRecord(auth)) return false;
79
+ const next = {
80
+ ...auth,
81
+ [HOST_OPENAI_PROVIDER]: {
82
+ access: token.access,
83
+ expires: token.expires,
84
+ refresh: token.refresh,
85
+ type: "oauth"
86
+ }
87
+ };
88
+ writeFileSync(authPath, `${JSON.stringify(next, null, 2)}\n`, { mode: 384 });
89
+ return true;
22
90
  }
23
91
  //#endregion
24
- export { OPENCODE_OPENAI_ACCOUNTS_STAGING_DIR, prepareOpencodeAccounts };
92
+ export { OPENCODE_AUTH_STAGING_DIR, OPENCODE_OPENAI_ACCOUNTS_STAGING_DIR, prepareOpencodeCredentials };
@@ -101,15 +101,16 @@ function runRunnerCommandEffect(options, runtime) {
101
101
  status: "finish"
102
102
  }, "git.workspace.prepare finish");
103
103
  logger.info({
104
- phase: "opencode.accounts.prepare",
104
+ phase: "opencode.credentials.prepare",
105
105
  status: "start"
106
- }, "opencode.accounts.prepare start");
107
- const accountsPrep = yield* io.prepareOpencodeAccounts();
106
+ }, "opencode.credentials.prepare start");
107
+ const credentialsPrep = yield* io.prepareOpencodeCredentials();
108
108
  logger.info({
109
- copied: accountsPrep.copied,
110
- phase: "opencode.accounts.prepare",
109
+ copied: credentialsPrep.copied,
110
+ hostOpenaiTokenSynced: credentialsPrep.hostOpenaiTokenSynced,
111
+ phase: "opencode.credentials.prepare",
111
112
  status: "finish"
112
- }, "opencode.accounts.prepare finish");
113
+ }, "opencode.credentials.prepare finish");
113
114
  logger.info({
114
115
  phase: "config.load",
115
116
  status: "start"
@@ -43,8 +43,8 @@ declare const runnerDeliverySchema: z.ZodObject<{
43
43
  declare const mokaSubmissionSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
44
44
  kind: z.ZodLiteral<"graph">;
45
45
  mode: z.ZodEnum<{
46
- full: "full";
47
46
  quick: "quick";
47
+ full: "full";
48
48
  }>;
49
49
  }, z.core.$strict>, z.ZodObject<{
50
50
  argv: z.ZodArray<z.ZodString>;
@@ -104,8 +104,8 @@ declare const runnerCommandPayloadSchema: z.ZodObject<{
104
104
  submission: z.ZodDefault<z.ZodDiscriminatedUnion<[z.ZodObject<{
105
105
  kind: z.ZodLiteral<"graph">;
106
106
  mode: z.ZodEnum<{
107
- full: "full";
108
107
  quick: "quick";
108
+ full: "full";
109
109
  }>;
110
110
  }, z.core.$strict>, z.ZodObject<{
111
111
  argv: z.ZodArray<z.ZodString>;
@@ -1,5 +1,5 @@
1
- import { flattenNodes } from "../../planning/graph.js";
2
1
  import { isRecord } from "../../safe-json.js";
2
+ import { flattenNodes } from "../../planning/graph.js";
3
3
  import { runtimeActorId } from "../actor-ids.js";
4
4
  import { parseRuntimeOutput, validateJsonSchemaSource } from "../json-validation/json-validation.js";
5
5
  import "../json-validation/index.js";
@@ -1,5 +1,5 @@
1
- import { standardOutputSchemaJson, standardOutputSchemaNameFromPath } from "../../standard-output-schemas.js";
2
1
  import { isRecord, parseJson, parseJsonRecord } from "../../safe-json.js";
2
+ import { standardOutputSchemaJson, standardOutputSchemaNameFromPath } from "../../standard-output-schemas.js";
3
3
  import { FileSystemService, FileSystemServiceLive, runFileSystemSync } from "../services/file-system-service.js";
4
4
  import { Effect } from "effect";
5
5
  import { join } from "node:path";
@@ -1,4 +1,4 @@
1
- import { prepareOpencodeAccounts } from "../../run-state/opencode-accounts.js";
1
+ import { prepareOpencodeCredentials } from "../../run-state/opencode-accounts.js";
2
2
  import { commitAndPushNodeRef, mergeDependencyRefs, prepareRunnerGitWorkspace, promoteFinalRef } from "../../run-state/git-refs.js";
3
3
  import { runScheduledWorkflowTask } from "../../pipeline-runtime.js";
4
4
  import { resolveRunnerEventSinkAuthToken } from "../../runner-command-contract.js";
@@ -46,8 +46,8 @@ const RunnerCommandIoServiceLive = Layer.succeed(RunnerCommandIoService, {
46
46
  try: () => mergeDependencyRefs(options),
47
47
  catch: (error) => error
48
48
  }),
49
- prepareOpencodeAccounts: () => Effect.try({
50
- try: () => prepareOpencodeAccounts(),
49
+ prepareOpencodeCredentials: () => Effect.try({
50
+ try: () => prepareOpencodeCredentials(),
51
51
  catch: (error) => error
52
52
  }),
53
53
  prepareRunnerGitWorkspace: (payload, options) => Effect.tryPromise({
package/package.json CHANGED
@@ -128,7 +128,7 @@
128
128
  "prepack": "bun run build:cli"
129
129
  },
130
130
  "type": "module",
131
- "version": "3.11.17",
131
+ "version": "3.11.19",
132
132
  "description": "Config-driven multi-agent pipeline runner for repository work",
133
133
  "main": "./dist/index.js",
134
134
  "types": "./dist/index.d.ts",