@oisincoveney/pipeline 2.0.1 → 2.1.1

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.
@@ -64,7 +64,7 @@ ecosystem_code:
64
64
  package: oc-codex-multi-auth
65
65
  plugin:
66
66
  kind: npm
67
- package: oc-codex-multi-auth
67
+ package: oc-codex-multi-auth@6.3.2
68
68
  role: ChatGPT Plus/Pro OAuth with multi-account rotation, health checks, and Codex/GPT-5 routing for OpenCode
69
69
  default_stack: true
70
70
  source: https://github.com/ndycode/oc-codex-multi-auth
@@ -83,6 +83,56 @@ ecosystem_code:
83
83
  role: OpenCode policy enforcement through tool execution hooks
84
84
  default_stack: true
85
85
  source: https://cupcake.eqtylab.io/getting-started/usage/opencode/
86
+ provider_models:
87
+ # Reasoning-effort variant selectors for ChatGPT OAuth Codex routing.
88
+ # Each id must match the oc-codex-multi-auth MODEL_MAP exactly; the plugin
89
+ # normalizes the selector back to the base API model (gpt-5.5) and the
90
+ # reasoning effort is carried by the generated options.reasoningEffort.
91
+ - id: gpt-5.5-none
92
+ provider: openai
93
+ role: zero-reasoning GPT-5.5 selector for mechanical low-stakes work
94
+ options:
95
+ reasoningEffort: none
96
+ reasoningSummary: auto
97
+ textVerbosity: medium
98
+ include: [reasoning.encrypted_content]
99
+ store: false
100
+ - id: gpt-5.5-low
101
+ provider: openai
102
+ role: low-reasoning GPT-5.5 selector for cheap inspection and bookkeeping roles
103
+ options:
104
+ reasoningEffort: low
105
+ reasoningSummary: auto
106
+ textVerbosity: medium
107
+ include: [reasoning.encrypted_content]
108
+ store: false
109
+ - id: gpt-5.5-medium
110
+ provider: openai
111
+ role: default-reasoning GPT-5.5 selector for research and coverage roles
112
+ options:
113
+ reasoningEffort: medium
114
+ reasoningSummary: auto
115
+ textVerbosity: medium
116
+ include: [reasoning.encrypted_content]
117
+ store: false
118
+ - id: gpt-5.5-high
119
+ provider: openai
120
+ role: high-reasoning GPT-5.5 selector for implementation roles
121
+ options:
122
+ reasoningEffort: high
123
+ reasoningSummary: detailed
124
+ textVerbosity: medium
125
+ include: [reasoning.encrypted_content]
126
+ store: false
127
+ - id: gpt-5.5-xhigh
128
+ provider: openai
129
+ role: maximum-reasoning GPT-5.5 selector for schedule planning
130
+ options:
131
+ reasoningEffort: xhigh
132
+ reasoningSummary: detailed
133
+ textVerbosity: medium
134
+ include: [reasoning.encrypted_content]
135
+ store: false
86
136
  mcp_backends:
87
137
  - id: pipeline-gateway
88
138
  locality: project-remote
@@ -1,6 +1,7 @@
1
1
  import { compileArgoExecutionGraph } from "./argo-graph.js";
2
2
  import { buildRunnerTaskDescriptor } from "./runner-command/task-descriptor.js";
3
3
  import { buildRunnerArgoWorkflowManifest, runnerArgoWorkflowManifestSchema } from "./argo-workflow.js";
4
+ import { normalizeRunnerRepositoryForSubmit } from "./git-remote-url.js";
4
5
  import { parseRunnerCommandPayload, runnerCommandPayloadSchema } from "./runner-command-contract.js";
5
6
  import { compileScheduleArtifact, parseScheduleArtifact } from "./schedule/planner.js";
6
7
  import "./schedule-planner.js";
@@ -52,7 +53,10 @@ const commandScheduleOptionsSchema = z.object({
52
53
  async function submitRunnerArgoWorkflow(rawOptions, dependencies = {}) {
53
54
  const { config, ...schemaOptions } = rawOptions;
54
55
  const options = submitRunnerArgoWorkflowOptionsSchema.parse(schemaOptions);
55
- const payload = runnerCommandPayloadSchema.parse(parseRunnerCommandPayload(options.payloadJson));
56
+ const { payload, payloadJson } = normalizeRunnerPayloadForSubmit({
57
+ payload: runnerCommandPayloadSchema.parse(parseRunnerCommandPayload(options.payloadJson)),
58
+ payloadJson: options.payloadJson
59
+ });
56
60
  const compiled = compileScheduleArtifact(config, parseScheduleArtifact(options.scheduleYaml, "schedule.yaml"));
57
61
  const payloadConfigMapName = `pipeline-payload-${randomBytes(6).toString("hex")}`;
58
62
  const scheduleArtifactConfigMapName = `pipeline-schedule-${randomBytes(6).toString("hex")}`;
@@ -94,7 +98,7 @@ async function submitRunnerArgoWorkflow(rawOptions, dependencies = {}) {
94
98
  await coreApi.createNamespacedConfigMap({
95
99
  body: configMapSchema.parse({
96
100
  apiVersion: "v1",
97
- data: { "payload.json": options.payloadJson },
101
+ data: { "payload.json": payloadJson },
98
102
  kind: "ConfigMap",
99
103
  metadata: {
100
104
  labels,
@@ -168,6 +172,18 @@ function buildCommandScheduleYaml(rawOptions) {
168
172
  }] } }
169
173
  });
170
174
  }
175
+ function normalizeRunnerPayloadForSubmit(input) {
176
+ const repository = normalizeRunnerRepositoryForSubmit(input.payload.repository);
177
+ if (repository === input.payload.repository) return input;
178
+ const payload = runnerCommandPayloadSchema.parse({
179
+ ...input.payload,
180
+ repository
181
+ });
182
+ return {
183
+ payload,
184
+ payloadJson: JSON.stringify(payload)
185
+ };
186
+ }
171
187
  function apiClients(options, dependencies) {
172
188
  if (dependencies.coreApi && dependencies.workflowApi) return {
173
189
  coreApi: dependencies.coreApi,
@@ -4,7 +4,7 @@ import { dirname, join } from "node:path";
4
4
  import { homedir } from "node:os";
5
5
  import { parse } from "jsonc-parser";
6
6
  //#region src/codex-auth-sync.ts
7
- const CODEX_MULTI_AUTH_PLUGIN = "oc-codex-multi-auth";
7
+ const CODEX_MULTI_AUTH_PLUGIN = "oc-codex-multi-auth@6.3.2";
8
8
  const GLOBAL_CODEX_AUTH_CONFIG_PATH = join(homedir(), ".opencode/openai-codex-auth-config.json");
9
9
  function syncLocalCodexAuth(options) {
10
10
  const items = [syncGlobalPluginConfig(options.globalConfigPath ?? GLOBAL_CODEX_AUTH_CONFIG_PATH, options), ...discoverGitRepositories(options.root).map((repo) => syncProjectOpenCodeConfig(repo, options))];
@@ -55,6 +55,31 @@ declare const openCodeEcosystemManifestSchema: z.ZodObject<{
55
55
  source: z.ZodOptional<z.ZodString>;
56
56
  used_by: z.ZodArray<z.ZodString>;
57
57
  }, z.core.$strict>>;
58
+ provider_models: z.ZodArray<z.ZodObject<{
59
+ id: z.ZodString;
60
+ options: z.ZodObject<{
61
+ include: z.ZodArray<z.ZodString>;
62
+ reasoningEffort: z.ZodEnum<{
63
+ none: "none";
64
+ low: "low";
65
+ medium: "medium";
66
+ high: "high";
67
+ xhigh: "xhigh";
68
+ }>;
69
+ reasoningSummary: z.ZodEnum<{
70
+ auto: "auto";
71
+ detailed: "detailed";
72
+ }>;
73
+ store: z.ZodLiteral<false>;
74
+ textVerbosity: z.ZodEnum<{
75
+ low: "low";
76
+ medium: "medium";
77
+ high: "high";
78
+ }>;
79
+ }, z.core.$strict>;
80
+ provider: z.ZodString;
81
+ role: z.ZodString;
82
+ }, z.core.$strict>>;
58
83
  runtime: z.ZodObject<{
59
84
  compatibility_runners: z.ZodArray<z.ZodString>;
60
85
  default_runner: z.ZodLiteral<"opencode">;
@@ -125,6 +150,18 @@ declare const DEFAULT_OPENCODE_ECOSYSTEM_MANIFEST: {
125
150
  path?: string | undefined;
126
151
  source?: string | undefined;
127
152
  }[];
153
+ provider_models: {
154
+ id: string;
155
+ options: {
156
+ include: string[];
157
+ reasoningEffort: "none" | "low" | "medium" | "high" | "xhigh";
158
+ reasoningSummary: "auto" | "detailed";
159
+ store: false;
160
+ textVerbosity: "low" | "medium" | "high";
161
+ };
162
+ provider: string;
163
+ role: string;
164
+ }[];
128
165
  runtime: {
129
166
  compatibility_runners: string[];
130
167
  default_runner: "opencode";
@@ -141,6 +141,7 @@ profiles:
141
141
  repair: { enabled: true, max_attempts: 1 }
142
142
  moka-inspector:
143
143
  runner: opencode
144
+ model: openai/gpt-5.5-low
144
145
  description: Inspect the repository without modifying files.
145
146
  instructions: { inline: "Inspect the repository without modifying files." }
146
147
  skills: [research]
@@ -150,6 +151,7 @@ profiles:
150
151
  network: { mode: inherit }
151
152
  moka-schedule-planner:
152
153
  runner: opencode
154
+ model: openai/gpt-5.5-xhigh
153
155
  description: Refine a baseline schedule into a specialized approved-plan artifact.
154
156
  instructions: { inline: "Generate exactly one workflow named root as an explicit schedule graph. Return YAML only." }
155
157
  timeout_ms: 300000
@@ -230,6 +232,7 @@ profiles:
230
232
  repair: { enabled: true, max_attempts: 1 }
231
233
  moka-learner:
232
234
  runner: opencode
235
+ model: openai/gpt-5.5-low
233
236
  description: Store durable lessons from the completed run.
234
237
  instructions: { inline: "Store durable lessons from the completed run when useful." }
235
238
  skills: [migrate]
@@ -289,54 +292,54 @@ scheduler:
289
292
  backlog-intake:
290
293
  category: intake
291
294
  profile: moka-researcher
292
- models: [openai/gpt-5.5-fast]
295
+ models: [openai/gpt-5.5-medium]
293
296
  red-tests:
294
297
  category: red
295
298
  profile: moka-test-writer
296
- models: [openai/gpt-5.5, kimi-for-coding/kimi-k2-thinking]
299
+ models: [openai/gpt-5.5-high, kimi-for-coding/kimi-k2-thinking]
297
300
  green-implementation:
298
301
  category: green
299
302
  profile: moka-code-writer
300
- models: [openai/gpt-5.5, kimi-for-coding/k2p6, opencode-go/qwen3.7-max]
303
+ models: [openai/gpt-5.5-high, kimi-for-coding/k2p6, opencode-go/qwen3.7-max]
301
304
  verification:
302
305
  category: verification
303
306
  profile: moka-verifier
304
- models: [openai/gpt-5.5]
307
+ models: [openai/gpt-5.5-medium]
305
308
  execute:
306
309
  required_categories: [intake, research, red, green, mechanical, acceptance, verification, learn]
307
310
  nodes:
308
311
  backlog-intake:
309
312
  category: intake
310
313
  profile: moka-researcher
311
- models: [openai/gpt-5.5-fast]
314
+ models: [openai/gpt-5.5-medium]
312
315
  research:
313
316
  category: research
314
317
  profile: moka-researcher
315
- models: [openai/gpt-5.5-fast, kimi-for-coding/k2p6]
318
+ models: [openai/gpt-5.5-medium, kimi-for-coding/k2p6]
316
319
  red-tests:
317
320
  category: red
318
321
  profile: moka-test-writer
319
- models: [openai/gpt-5.5, kimi-for-coding/kimi-k2-thinking]
322
+ models: [openai/gpt-5.5-high, kimi-for-coding/kimi-k2-thinking]
320
323
  green-backend:
321
324
  category: green
322
325
  profile: moka-code-writer
323
- models: [openai/gpt-5.5, kimi-for-coding/k2p6, opencode-go/qwen3.7-max]
326
+ models: [openai/gpt-5.5-high, kimi-for-coding/k2p6, opencode-go/qwen3.7-max]
324
327
  green-frontend:
325
328
  category: green
326
329
  profile: moka-code-writer
327
- models: [openai/gpt-5.5, kimi-for-coding/k2p6, opencode-go/qwen3.7-max]
330
+ models: [openai/gpt-5.5-high, kimi-for-coding/k2p6, opencode-go/qwen3.7-max]
328
331
  acceptance-review:
329
332
  category: acceptance
330
333
  profile: moka-acceptance-reviewer
331
- models: [openai/gpt-5.5]
334
+ models: [openai/gpt-5.5-medium]
332
335
  verification:
333
336
  category: verification
334
337
  profile: moka-verifier
335
- models: [openai/gpt-5.5]
338
+ models: [openai/gpt-5.5-medium]
336
339
  learn:
337
340
  category: learn
338
341
  profile: moka-learner
339
- models: [openai/gpt-5.5-fast]
342
+ models: [openai/gpt-5.5-low]
340
343
  schedules:
341
344
  quick-schedule:
342
345
  baseline: quick
@@ -385,6 +388,29 @@ const ecosystemCodeSchema = z.object({
385
388
  role: z.string().min(1),
386
389
  source: z.string().url()
387
390
  }).strict();
391
+ const ecosystemProviderModelOptionsSchema = z.object({
392
+ include: ecosystemStringArraySchema,
393
+ reasoningEffort: z.enum([
394
+ "none",
395
+ "low",
396
+ "medium",
397
+ "high",
398
+ "xhigh"
399
+ ]),
400
+ reasoningSummary: z.enum(["auto", "detailed"]),
401
+ store: z.literal(false),
402
+ textVerbosity: z.enum([
403
+ "low",
404
+ "medium",
405
+ "high"
406
+ ])
407
+ }).strict();
408
+ const ecosystemProviderModelSchema = z.object({
409
+ id: z.string().min(1),
410
+ options: ecosystemProviderModelOptionsSchema,
411
+ provider: z.string().min(1),
412
+ role: z.string().min(1)
413
+ }).strict();
388
414
  const ecosystemMcpBackendSchema = z.object({
389
415
  credentials: ecosystemStringArraySchema,
390
416
  id: z.string().min(1),
@@ -421,6 +447,7 @@ const openCodeEcosystemManifestSchema = z.object({
421
447
  mcp_backends: z.array(ecosystemMcpBackendSchema).min(1),
422
448
  official_dependencies: z.array(ecosystemDependencySchema).min(1),
423
449
  prompts: z.array(ecosystemProfileResourceSchema).min(1),
450
+ provider_models: z.array(ecosystemProviderModelSchema).min(1),
424
451
  runtime: ecosystemRuntimeSchema,
425
452
  skills: z.array(ecosystemProfileResourceSchema).min(1),
426
453
  sources: z.array(ecosystemSourceSchema).min(1),
@@ -310,7 +310,6 @@ declare const configSchema: z.ZodObject<{
310
310
  skills: z.ZodOptional<z.ZodArray<z.ZodString>>;
311
311
  timeout_ms: z.ZodOptional<z.ZodNumber>;
312
312
  tools: z.ZodOptional<z.ZodArray<z.ZodEnum<{
313
- task: "task";
314
313
  read: "read";
315
314
  list: "list";
316
315
  grep: "grep";
@@ -318,6 +317,7 @@ declare const configSchema: z.ZodObject<{
318
317
  bash: "bash";
319
318
  edit: "edit";
320
319
  write: "write";
320
+ task: "task";
321
321
  }>>>;
322
322
  }, z.core.$strict>>>;
323
323
  runner_command: z.ZodDefault<z.ZodObject<{
@@ -369,7 +369,6 @@ declare const configSchema: z.ZodObject<{
369
369
  rules: z.ZodOptional<z.ZodBoolean>;
370
370
  skills: z.ZodOptional<z.ZodBoolean>;
371
371
  tools: z.ZodOptional<z.ZodArray<z.ZodEnum<{
372
- task: "task";
373
372
  read: "read";
374
373
  list: "list";
375
374
  grep: "grep";
@@ -377,6 +376,7 @@ declare const configSchema: z.ZodObject<{
377
376
  bash: "bash";
378
377
  edit: "edit";
379
378
  write: "write";
379
+ task: "task";
380
380
  }>>>;
381
381
  }, z.core.$strict>;
382
382
  command: z.ZodOptional<z.ZodString>;
@@ -0,0 +1,30 @@
1
+ import parseGitUrl from "git-url-parse";
2
+ //#region src/git-remote-url.ts
3
+ const GITHUB_SOURCE = "github.com";
4
+ function normalizeRunnerRepositoryForSubmit(repository) {
5
+ const url = normalizeRepositoryUrlForSubmit(repository.url);
6
+ if (url === repository.url) return repository;
7
+ return {
8
+ ...repository,
9
+ url
10
+ };
11
+ }
12
+ function normalizeRepositoryUrlForSubmit(remoteUrl) {
13
+ const parsed = parseGitUrl(remoteUrl);
14
+ if (!isSshRemote(parsed)) return remoteUrl;
15
+ if (parsed.source !== GITHUB_SOURCE) throw new Error(`SSH git remote ${remoteUrl} is not supported for moka submit; use an HTTPS GitHub remote`);
16
+ return `https://${GITHUB_SOURCE}/${gitHubRepositoryPath(parsed, remoteUrl)}`;
17
+ }
18
+ function gitHubRepositoryPath(parsed, remoteUrl) {
19
+ return `${requiredGitHubPathSegment(parsed.owner, remoteUrl)}/${requiredGitHubPathSegment(parsed.name, remoteUrl)}.git`;
20
+ }
21
+ function requiredGitHubPathSegment(value, remoteUrl) {
22
+ const segment = value.trim();
23
+ if (segment.length > 0) return segment;
24
+ throw new Error(`GitHub SSH git remote ${remoteUrl} must include an owner and repository name`);
25
+ }
26
+ function isSshRemote(parsed) {
27
+ return parsed.protocols.includes("ssh");
28
+ }
29
+ //#endregion
30
+ export { normalizeRunnerRepositoryForSubmit };
@@ -271,9 +271,18 @@ function renderOpenCodeProjectConfig(config) {
271
271
  return formatOpenCodeProjectJson({
272
272
  ...config.mcp_gateway ? JSON.parse(renderOpenCodeGatewayConfig(config)) : { $schema: "https://opencode.ai/config.json" },
273
273
  lsp: true,
274
- ...opencodePluginConfig()
274
+ ...opencodePluginConfig(),
275
+ ...opencodeProviderConfig()
275
276
  });
276
277
  }
278
+ function opencodeProviderConfig() {
279
+ const provider = {};
280
+ for (const model of DEFAULT_OPENCODE_ECOSYSTEM_MANIFEST.provider_models) {
281
+ provider[model.provider] ??= { models: {} };
282
+ provider[model.provider].models[model.id] = { options: model.options };
283
+ }
284
+ return Object.keys(provider).length > 0 ? { provider } : {};
285
+ }
277
286
  function opencodePluginConfig() {
278
287
  const plugins = DEFAULT_OPENCODE_ECOSYSTEM_MANIFEST.ecosystem_code.flatMap((item) => npmPluginPackage(item)).sort((a, b) => a.localeCompare(b));
279
288
  return plugins.length > 0 ? { plugin: plugins } : {};
@@ -1,3 +1,4 @@
1
+ import { normalizeRunnerRepositoryForSubmit } from "./git-remote-url.js";
1
2
  import { buildRunnerCommandPayload, runnerDeliverySchema, runnerHookPolicySchema, runnerRepositoryContextSchema, runnerRunIdentitySchema, runnerTaskSchema } from "./runner-command-contract.js";
2
3
  import { compileScheduleArtifact, generateScheduleArtifact, parseScheduleArtifact } from "./schedule/planner.js";
3
4
  import "./schedule-planner.js";
@@ -353,7 +354,7 @@ function explicitSubmissionContext(options) {
353
354
  if (!(options.repository && options.run)) return null;
354
355
  assertRepositoryCredentialConfiguration(options);
355
356
  return {
356
- repository: options.repository,
357
+ repository: normalizeRunnerRepositoryForSubmit(options.repository),
357
358
  run: options.run
358
359
  };
359
360
  }
@@ -362,11 +363,11 @@ function resolveRequiredGit(options, dependencies) {
362
363
  return resolveGit(options.worktreePath, dependencies);
363
364
  }
364
365
  function repositoryContext(options, git) {
365
- return options.repository ?? {
366
+ return normalizeRunnerRepositoryForSubmit(options.repository ?? {
366
367
  baseBranch: git.baseBranch,
367
368
  sha: git.sha,
368
369
  url: git.url
369
- };
370
+ });
370
371
  }
371
372
  function assertRepositoryCredentialConfiguration(options) {
372
373
  if (!options.gitCredentialsSecretName) throw new Error("gitCredentialsSecretName is required for runner git clone, fetch, and push operations");
@@ -32,7 +32,15 @@ function parseOpenCodeProjectConfig(currentText) {
32
32
  };
33
33
  }
34
34
  function applyOpenCodeProjection(currentText, parsed, projection) {
35
- return applyPluginProjection(applyMcpProjection(setIfMissing(setIfMissing(currentText, parsed, ["$schema"], projection.$schema), parsed, ["lsp"], projection.lsp), parsed, projection), parsed, projection);
35
+ return applyProviderProjection(applyPluginProjection(applyMcpProjection(setIfMissing(setIfMissing(currentText, parsed, ["$schema"], projection.$schema), parsed, ["lsp"], projection.lsp), parsed, projection), parsed, projection), parsed, projection);
36
+ }
37
+ function applyProviderProjection(content, parsed, projection) {
38
+ return Object.entries(projection.provider ?? {}).reduce((providerContent, [providerId, provider]) => Object.entries(provider.models ?? {}).reduce((modelContent, [modelId, model]) => setIfMissing(modelContent, parsed, [
39
+ "provider",
40
+ providerId,
41
+ "models",
42
+ modelId
43
+ ], model), providerContent), content);
36
44
  }
37
45
  function applyMcpProjection(content, parsed, projection) {
38
46
  return Object.entries(projection.mcp ?? {}).reduce((nextContent, [name, server]) => setIfMissing(nextContent, parsed, ["mcp", name], server), content);
@@ -54,8 +62,14 @@ function hasPath(value, path) {
54
62
  return true;
55
63
  }
56
64
  function mergePluginEntries(existing, projected) {
57
- const merged = Array.isArray(existing) ? [...existing] : [];
58
- const seen = new Set(merged.map(pluginKey));
65
+ const projectedByKey = new Map(projected.map((plugin) => [pluginKey(plugin), plugin]));
66
+ const merged = [];
67
+ const seen = /* @__PURE__ */ new Set();
68
+ for (const plugin of Array.isArray(existing) ? existing : []) {
69
+ const key = pluginKey(plugin);
70
+ merged.push(projectedByKey.get(key) ?? plugin);
71
+ seen.add(key);
72
+ }
59
73
  for (const plugin of projected) {
60
74
  const key = pluginKey(plugin);
61
75
  if (seen.has(key)) continue;
@@ -65,8 +79,12 @@ function mergePluginEntries(existing, projected) {
65
79
  return merged;
66
80
  }
67
81
  function pluginKey(value) {
68
- if (Array.isArray(value)) return typeof value[0] === "string" ? value[0] : JSON.stringify(value);
69
- return typeof value === "string" ? value : JSON.stringify(value);
82
+ if (Array.isArray(value)) return typeof value[0] === "string" ? pluginName(value[0]) : JSON.stringify(value);
83
+ return typeof value === "string" ? pluginName(value) : JSON.stringify(value);
84
+ }
85
+ function pluginName(specifier) {
86
+ const versionSeparator = specifier.indexOf("@", 1);
87
+ return versionSeparator === -1 ? specifier : specifier.slice(0, versionSeparator);
70
88
  }
71
89
  function applyJsonEdit(content, path, value) {
72
90
  return applyEdits(content, modify(content, path, value, { formattingOptions: JSON_FORMAT_OPTIONS }));
package/package.json CHANGED
@@ -115,7 +115,7 @@
115
115
  "prepack": "bun run build:cli"
116
116
  },
117
117
  "type": "module",
118
- "version": "2.0.1",
118
+ "version": "2.1.1",
119
119
  "description": "Config-driven multi-agent pipeline runner for repository work",
120
120
  "main": "./dist/index.js",
121
121
  "types": "./dist/index.d.ts",