@oisincoveney/pipeline 3.11.18 → 3.11.20
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/dist/argo-workflow.js +4 -1
- package/dist/moka-submit.d.ts +6 -6
- package/dist/run-state/opencode-accounts.js +59 -9
- package/dist/runner-command/run.js +1 -0
- package/dist/runner-event-schema.d.ts +6 -6
- package/dist/runtime/events/events.js +1 -1
- package/dist/runtime/json-validation/json-validation.js +1 -1
- package/dist/runtime/opencode-session-executor.js +11 -1
- package/package.json +1 -1
package/dist/argo-workflow.js
CHANGED
|
@@ -21,6 +21,9 @@ const RUNNER_RETRY_STRATEGY = {
|
|
|
21
21
|
const RUNNER_OPENCODE_ENV = [{
|
|
22
22
|
name: "CODEX_AUTH_PER_PROJECT_ACCOUNTS",
|
|
23
23
|
value: "0"
|
|
24
|
+
}, {
|
|
25
|
+
name: "PIPELINE_AGENT_TIMEOUT_MS",
|
|
26
|
+
value: "1200000"
|
|
24
27
|
}];
|
|
25
28
|
const DEFAULT_RUNNER_RESOURCES = {
|
|
26
29
|
limits: {
|
|
@@ -32,7 +35,7 @@ const DEFAULT_RUNNER_RESOURCES = {
|
|
|
32
35
|
memory: "5Gi"
|
|
33
36
|
}
|
|
34
37
|
};
|
|
35
|
-
const DEFAULT_RUNNER_DEADLINE_SECONDS =
|
|
38
|
+
const DEFAULT_RUNNER_DEADLINE_SECONDS = 5400;
|
|
36
39
|
const kubernetesNameSchema = z.string().min(1);
|
|
37
40
|
const labelValueSchema = z.string().min(1);
|
|
38
41
|
const stringMapSchema = z.record(z.string().min(1), z.string().min(1));
|
package/dist/moka-submit.d.ts
CHANGED
|
@@ -5,13 +5,13 @@ import { z } from "zod";
|
|
|
5
5
|
//#region src/moka-submit.d.ts
|
|
6
6
|
declare const mokaSubmitDirectHooksSchema: z.ZodRecord<z.ZodEnum<{
|
|
7
7
|
"workflow.start": "workflow.start";
|
|
8
|
+
"node.finish": "node.finish";
|
|
9
|
+
"node.start": "node.start";
|
|
8
10
|
"workflow.success": "workflow.success";
|
|
9
11
|
"workflow.failure": "workflow.failure";
|
|
10
12
|
"workflow.complete": "workflow.complete";
|
|
11
|
-
"node.start": "node.start";
|
|
12
13
|
"node.success": "node.success";
|
|
13
14
|
"node.error": "node.error";
|
|
14
|
-
"node.finish": "node.finish";
|
|
15
15
|
"gate.failure": "gate.failure";
|
|
16
16
|
}> & z.core.$partial, z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
17
17
|
failure: z.ZodDefault<z.ZodEnum<{
|
|
@@ -94,13 +94,13 @@ declare const mokaSubmitOptionsSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
|
94
94
|
}, z.core.$strict>>;
|
|
95
95
|
hooks: z.ZodOptional<z.ZodRecord<z.ZodEnum<{
|
|
96
96
|
"workflow.start": "workflow.start";
|
|
97
|
+
"node.finish": "node.finish";
|
|
98
|
+
"node.start": "node.start";
|
|
97
99
|
"workflow.success": "workflow.success";
|
|
98
100
|
"workflow.failure": "workflow.failure";
|
|
99
101
|
"workflow.complete": "workflow.complete";
|
|
100
|
-
"node.start": "node.start";
|
|
101
102
|
"node.success": "node.success";
|
|
102
103
|
"node.error": "node.error";
|
|
103
|
-
"node.finish": "node.finish";
|
|
104
104
|
"gate.failure": "gate.failure";
|
|
105
105
|
}> & z.core.$partial, z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
106
106
|
failure: z.ZodDefault<z.ZodEnum<{
|
|
@@ -207,13 +207,13 @@ declare const mokaSubmitOptionsSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
|
207
207
|
}, z.core.$strict>>;
|
|
208
208
|
hooks: z.ZodOptional<z.ZodRecord<z.ZodEnum<{
|
|
209
209
|
"workflow.start": "workflow.start";
|
|
210
|
+
"node.finish": "node.finish";
|
|
211
|
+
"node.start": "node.start";
|
|
210
212
|
"workflow.success": "workflow.success";
|
|
211
213
|
"workflow.failure": "workflow.failure";
|
|
212
214
|
"workflow.complete": "workflow.complete";
|
|
213
|
-
"node.start": "node.start";
|
|
214
215
|
"node.success": "node.success";
|
|
215
216
|
"node.error": "node.error";
|
|
216
|
-
"node.finish": "node.finish";
|
|
217
217
|
"gate.failure": "gate.failure";
|
|
218
218
|
}> & z.core.$partial, z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
219
219
|
failure: z.ZodDefault<z.ZodEnum<{
|
|
@@ -1,26 +1,30 @@
|
|
|
1
|
-
import {
|
|
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
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
7
|
const OPENCODE_AUTH_STAGING_DIR = "/etc/pipeline/opencode-auth";
|
|
8
|
+
const ACCOUNTS_FILE_NAME = "oc-codex-multi-auth-accounts.json";
|
|
9
|
+
const AUTH_FILE_NAME = "auth.json";
|
|
10
|
+
const HOST_OPENAI_PROVIDER = "openai";
|
|
7
11
|
const WRITABLE_OPENCODE_CREDENTIAL_FILES = [{
|
|
8
|
-
destFromHome: [".opencode",
|
|
12
|
+
destFromHome: [".opencode", ACCOUNTS_FILE_NAME],
|
|
9
13
|
stagedPath: join(OPENCODE_OPENAI_ACCOUNTS_STAGING_DIR, "accounts.json")
|
|
10
14
|
}, {
|
|
11
15
|
destFromHome: [
|
|
12
16
|
".local",
|
|
13
17
|
"share",
|
|
14
18
|
"opencode",
|
|
15
|
-
|
|
19
|
+
AUTH_FILE_NAME
|
|
16
20
|
],
|
|
17
|
-
stagedPath: join(OPENCODE_AUTH_STAGING_DIR,
|
|
21
|
+
stagedPath: join(OPENCODE_AUTH_STAGING_DIR, AUTH_FILE_NAME)
|
|
18
22
|
}];
|
|
19
23
|
/**
|
|
20
|
-
* Copy each staged opencode credential secret to its writable live path
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
*
|
|
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).
|
|
24
28
|
*/
|
|
25
29
|
function prepareOpencodeCredentials(options = {}) {
|
|
26
30
|
const home = homedir();
|
|
@@ -36,7 +40,53 @@ function prepareOpencodeCredentials(options = {}) {
|
|
|
36
40
|
chmodSync(destPath, 384);
|
|
37
41
|
copied.push(basename(destPath));
|
|
38
42
|
}
|
|
39
|
-
|
|
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;
|
|
40
90
|
}
|
|
41
91
|
//#endregion
|
|
42
92
|
export { OPENCODE_AUTH_STAGING_DIR, OPENCODE_OPENAI_ACCOUNTS_STAGING_DIR, prepareOpencodeCredentials };
|
|
@@ -107,6 +107,7 @@ function runRunnerCommandEffect(options, runtime) {
|
|
|
107
107
|
const credentialsPrep = yield* io.prepareOpencodeCredentials();
|
|
108
108
|
logger.info({
|
|
109
109
|
copied: credentialsPrep.copied,
|
|
110
|
+
hostOpenaiTokenSynced: credentialsPrep.hostOpenaiTokenSynced,
|
|
110
111
|
phase: "opencode.credentials.prepare",
|
|
111
112
|
status: "finish"
|
|
112
113
|
}, "opencode.credentials.prepare finish");
|
|
@@ -11,8 +11,8 @@ declare const runnerEventRecordSchema: z.ZodUnion<readonly [z.ZodObject<{
|
|
|
11
11
|
runId: z.ZodString;
|
|
12
12
|
sequence: z.ZodNumber;
|
|
13
13
|
type: z.ZodEnum<{
|
|
14
|
-
"workflow.start": "workflow.start";
|
|
15
14
|
"workflow.planned": "workflow.planned";
|
|
15
|
+
"workflow.start": "workflow.start";
|
|
16
16
|
}>;
|
|
17
17
|
workflowPlan: z.ZodObject<{
|
|
18
18
|
edges: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
@@ -58,10 +58,10 @@ declare const runnerEventRecordSchema: z.ZodUnion<readonly [z.ZodObject<{
|
|
|
58
58
|
}>;
|
|
59
59
|
}, z.core.$strip>;
|
|
60
60
|
type: z.ZodEnum<{
|
|
61
|
-
"node.start": "node.start";
|
|
62
|
-
"node.finish": "node.finish";
|
|
63
61
|
"agent.finish": "agent.finish";
|
|
64
62
|
"agent.start": "agent.start";
|
|
63
|
+
"node.finish": "node.finish";
|
|
64
|
+
"node.start": "node.start";
|
|
65
65
|
}>;
|
|
66
66
|
}, z.core.$strip>, z.ZodObject<{
|
|
67
67
|
at: z.ZodOptional<z.ZodString>;
|
|
@@ -189,8 +189,8 @@ declare const runnerEventBatchSchema: z.ZodObject<{
|
|
|
189
189
|
runId: z.ZodString;
|
|
190
190
|
sequence: z.ZodNumber;
|
|
191
191
|
type: z.ZodEnum<{
|
|
192
|
-
"workflow.start": "workflow.start";
|
|
193
192
|
"workflow.planned": "workflow.planned";
|
|
193
|
+
"workflow.start": "workflow.start";
|
|
194
194
|
}>;
|
|
195
195
|
workflowPlan: z.ZodObject<{
|
|
196
196
|
edges: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
@@ -236,10 +236,10 @@ declare const runnerEventBatchSchema: z.ZodObject<{
|
|
|
236
236
|
}>;
|
|
237
237
|
}, z.core.$strip>;
|
|
238
238
|
type: z.ZodEnum<{
|
|
239
|
-
"node.start": "node.start";
|
|
240
|
-
"node.finish": "node.finish";
|
|
241
239
|
"agent.finish": "agent.finish";
|
|
242
240
|
"agent.start": "agent.start";
|
|
241
|
+
"node.finish": "node.finish";
|
|
242
|
+
"node.start": "node.start";
|
|
243
243
|
}>;
|
|
244
244
|
}, z.core.$strip>, z.ZodObject<{
|
|
245
245
|
at: z.ZodOptional<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";
|
|
@@ -24,7 +24,17 @@ function executeOpencodeEffect(deps, plan, options) {
|
|
|
24
24
|
function executeOpencodeSession(deps, plan, options) {
|
|
25
25
|
return Effect.gen(function* () {
|
|
26
26
|
return successResult(plan, yield* driveSession(deps, plan, options));
|
|
27
|
-
}).pipe(Effect.catchAll((error) => Effect.succeed(failureResult(plan, error))));
|
|
27
|
+
}).pipe(withAgentTimeout(plan), Effect.catchAll((error) => Effect.succeed(failureResult(plan, error))));
|
|
28
|
+
}
|
|
29
|
+
function withAgentTimeout(plan) {
|
|
30
|
+
return (effect) => {
|
|
31
|
+
const timeoutMs = plan.timeoutMs;
|
|
32
|
+
if (!timeoutMs || timeoutMs <= 0) return effect;
|
|
33
|
+
return Effect.timeoutFail(effect, {
|
|
34
|
+
duration: Duration.millis(timeoutMs),
|
|
35
|
+
onTimeout: () => /* @__PURE__ */ new Error(`agent session timed out after ${timeoutMs}ms`)
|
|
36
|
+
});
|
|
37
|
+
};
|
|
28
38
|
}
|
|
29
39
|
function validateOpencodePlan(plan) {
|
|
30
40
|
if (plan.type === "opencode") return Effect.void;
|
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.
|
|
131
|
+
"version": "3.11.20",
|
|
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",
|