@oisincoveney/pipeline 2.0.1 → 2.1.0
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/.agents/skills/claude-code-opencode-execute/SKILL.md +116 -0
- package/defaults/opencode-ecosystem.yaml +51 -1
- package/dist/cli/program.js +10 -2
- package/dist/codex-auth-sync.js +1 -1
- package/dist/config/defaults.d.ts +37 -0
- package/dist/config/defaults.js +42 -12
- package/dist/config/schemas.d.ts +3 -3
- package/dist/hooks.d.ts +1 -1
- package/dist/install-commands/claude-code.js +24 -0
- package/dist/install-commands/opencode.js +14 -2
- package/dist/install-commands/shared.js +9 -3
- package/dist/install-commands.js +14 -7
- package/dist/moka-submit.d.ts +1 -1
- package/dist/opencode-project-config.js +23 -5
- package/dist/runner-command-contract.d.ts +2 -2
- package/package.json +1 -1
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: claude-code-opencode-execute
|
|
3
|
+
description: Use in Claude Code when executing Moka work locally through OpenCode; loads execute first, then spawns Claude Task agents that run opencode run with the correct MoKa agent prompts.
|
|
4
|
+
allowed-tools: Bash(opencode run *) Bash(pwd) Bash(git status *) Task
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Claude Code OpenCode Execute
|
|
8
|
+
|
|
9
|
+
Use this skill when Claude Code is the interactive host, but the work should be executed by local OpenCode MoKa agents through `opencode run` subprocesses.
|
|
10
|
+
|
|
11
|
+
This skill is a host adapter. It does not replace [[execute]]. Load and follow [[execute]] first; use this skill only for the Claude Code dispatch mechanics.
|
|
12
|
+
|
|
13
|
+
## Contract
|
|
14
|
+
|
|
15
|
+
1. Load [[execute]] and let it classify the request, required companion skills, acceptance criteria, and verification path.
|
|
16
|
+
2. Keep the execution doctrine from [[execute]]: vertical slices, test-first for behavior, root-cause fixes, fidelity checks, critique, and verification.
|
|
17
|
+
3. Use Claude Code `Task` subagents as wrappers around local OpenCode subprocesses when work can be delegated.
|
|
18
|
+
4. Each delegated Task agent should run exactly one MoKa-flavored OpenCode command and return the command, exit status, parsed evidence, touched files, and blockers.
|
|
19
|
+
5. Batch independent nodes in parallel, wait at barriers, synthesize outputs, then decide the next batch.
|
|
20
|
+
|
|
21
|
+
## OpenCode command shape
|
|
22
|
+
|
|
23
|
+
Task agents should run OpenCode with this shape from the repository root:
|
|
24
|
+
|
|
25
|
+
```sh
|
|
26
|
+
opencode run --agent "<MoKa Agent Name>" --format json --dir "$PWD" '<node prompt>'
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
Use `--format json` so the parent can inspect structured event output. If the output contains multiple assistant text candidates, prefer the latest candidate that satisfies the requested JSON or evidence contract.
|
|
30
|
+
|
|
31
|
+
Do not use `moka submit` for this local Claude Code adapter unless the user explicitly asks to submit an Argo Workflow. `moka submit` is the durable pipeline path; this skill is for interactive local orchestration through Claude Task agents and `opencode run`.
|
|
32
|
+
|
|
33
|
+
## Agent Selection
|
|
34
|
+
|
|
35
|
+
Select the MoKa agent by the slice's role:
|
|
36
|
+
|
|
37
|
+
| Role | OpenCode agent |
|
|
38
|
+
| --- | --- |
|
|
39
|
+
| Intake, repository research, requirements clarification | `MoKa Researcher` |
|
|
40
|
+
| Read-only code inspection | `MoKa Inspector` |
|
|
41
|
+
| Schedule graph generation or schedule review | `MoKa Schedule Planner` |
|
|
42
|
+
| Focused failing tests | `MoKa Test Writer` |
|
|
43
|
+
| Production implementation | `MoKa Code Writer` |
|
|
44
|
+
| Acceptance criteria audit | `MoKa Acceptance Reviewer` |
|
|
45
|
+
| Final quality review | `MoKa Thermo Nuclear Reviewer` |
|
|
46
|
+
| Verification evidence and command checks | `MoKa Verifier` |
|
|
47
|
+
| Durable lessons after a completed run | `MoKa Learner` |
|
|
48
|
+
|
|
49
|
+
Do not delegate normal child work to `MoKa Orchestrator`; the Claude Code parent is the local orchestrator for this adapter.
|
|
50
|
+
|
|
51
|
+
## Prompt Contract
|
|
52
|
+
|
|
53
|
+
Every `opencode run` prompt must include:
|
|
54
|
+
|
|
55
|
+
- The original user task.
|
|
56
|
+
- The current execution contract from [[execute]].
|
|
57
|
+
- The node id and role.
|
|
58
|
+
- The selected MoKa agent name and why it was selected.
|
|
59
|
+
- The exact files or modules in scope, or a read-only discovery scope.
|
|
60
|
+
- Dependency outputs from earlier nodes.
|
|
61
|
+
- The acceptance criteria this node owns.
|
|
62
|
+
- The output shape expected by the parent.
|
|
63
|
+
|
|
64
|
+
Use this template for delegated prompts:
|
|
65
|
+
|
|
66
|
+
```text
|
|
67
|
+
You are running as <MoKa Agent Name> for a Claude Code local Moka execution.
|
|
68
|
+
|
|
69
|
+
Original task:
|
|
70
|
+
<user task>
|
|
71
|
+
|
|
72
|
+
Execution contract:
|
|
73
|
+
<contract produced by execute>
|
|
74
|
+
|
|
75
|
+
Node:
|
|
76
|
+
- id: <node id>
|
|
77
|
+
- role: <role>
|
|
78
|
+
- selected agent: <MoKa Agent Name>
|
|
79
|
+
- scope: <files/modules/commands>
|
|
80
|
+
|
|
81
|
+
Dependency outputs:
|
|
82
|
+
<summaries or "none">
|
|
83
|
+
|
|
84
|
+
Acceptance criteria owned by this node:
|
|
85
|
+
<criteria>
|
|
86
|
+
|
|
87
|
+
Instructions:
|
|
88
|
+
- Follow the skills and grants configured for this MoKa agent.
|
|
89
|
+
- Stay inside this node's scope.
|
|
90
|
+
- Do not claim completion without fresh evidence.
|
|
91
|
+
- Return only the requested output shape.
|
|
92
|
+
|
|
93
|
+
Output shape:
|
|
94
|
+
<JSON or concise evidence contract>
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
## Batching Rules
|
|
98
|
+
|
|
99
|
+
- Run read-only discovery agents in parallel when their scopes do not require a shared conclusion first.
|
|
100
|
+
- Run test-writing before production implementation for behavior changes.
|
|
101
|
+
- Run multiple `MoKa Code Writer` agents in the same batch only when [[execute]] has produced independent vertical slices with disjoint files or clearly isolated worktrees.
|
|
102
|
+
- Never let two write-capable agents edit the same file in the same batch.
|
|
103
|
+
- Run acceptance review, final quality review, and verifier after implementation outputs have been integrated.
|
|
104
|
+
- If any delegated command fails, stop the batch, read the output, classify the blocker, and return to [[execute]] routing instead of retrying blindly.
|
|
105
|
+
|
|
106
|
+
## Parent Responsibilities
|
|
107
|
+
|
|
108
|
+
The Claude Code parent must:
|
|
109
|
+
|
|
110
|
+
- Inspect outputs before launching the next batch.
|
|
111
|
+
- Integrate or reconcile changes itself when multiple agents wrote code.
|
|
112
|
+
- Run the verification required by [[execute]] in the real repository context.
|
|
113
|
+
- Inspect the final diff for accidental edits, secrets, generated churn, and unrelated changes.
|
|
114
|
+
- Report partial verification honestly if the real command path cannot be exercised.
|
|
115
|
+
|
|
116
|
+
This skill is complete only when [[execute]] would allow the parent to claim completion.
|
|
@@ -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
|
package/dist/cli/program.js
CHANGED
|
@@ -150,7 +150,7 @@ function createCliProgram() {
|
|
|
150
150
|
const config = loadPipelineConfig(process.env.PIPELINE_TARGET_PATH ?? process.cwd(), { allowMissingLintFileReferences: true });
|
|
151
151
|
console.log(renderGatewayConfig(config));
|
|
152
152
|
});
|
|
153
|
-
gatewayCommand.command("configure-host").description("Rewrite host MCP config to the singleton pipeline gateway").addOption(new Option("--host <host>", "host config to update").choices(["all", "opencode"]).default("all").argParser(
|
|
153
|
+
gatewayCommand.command("configure-host").description("Rewrite host MCP config to the singleton pipeline gateway").addOption(new Option("--host <host>", "host config to update").choices(["all", "opencode"]).default("all").argParser(parseGatewayHost)).addOption(new Option("--scope <scope>", "config scope to update").choices(["project", "global"]).default("project").argParser(parseGatewayHostScope)).action((flags) => {
|
|
154
154
|
const cwd = process.env.PIPELINE_TARGET_PATH ?? process.cwd();
|
|
155
155
|
const result = configureGatewayHosts(loadPipelineConfig(cwd, { allowMissingLintFileReferences: true }), {
|
|
156
156
|
cwd,
|
|
@@ -182,7 +182,11 @@ function createCliProgram() {
|
|
|
182
182
|
const result = await initPipelineProject({ cwd: process.env.PIPELINE_TARGET_PATH ?? process.cwd() });
|
|
183
183
|
console.log(formatPipelineInitResult(result));
|
|
184
184
|
});
|
|
185
|
-
program.command("install-commands").description("Install generated slash-command adapters into this repository").addOption(new Option("--host <host>", "host command set to install").choices([
|
|
185
|
+
program.command("install-commands").description("Install generated slash-command adapters into this repository").addOption(new Option("--host <host>", "host command set to install").choices([
|
|
186
|
+
"all",
|
|
187
|
+
"opencode",
|
|
188
|
+
"claude-code"
|
|
189
|
+
]).default("all").argParser(parseCommandHost)).option("--dry-run", "show planned changes without writing files").option("--check", "fail if generated command files are missing or stale").option("--force", "overwrite manually edited command files").action(async (flags) => {
|
|
186
190
|
const result = await installCommands({
|
|
187
191
|
...flags,
|
|
188
192
|
cwd: process.env.PIPELINE_TARGET_PATH ?? process.cwd()
|
|
@@ -232,6 +236,10 @@ function parseGatewayHostScope(value) {
|
|
|
232
236
|
if (value === "project" || value === "global") return value;
|
|
233
237
|
throw new Error("scope must be project or global");
|
|
234
238
|
}
|
|
239
|
+
function parseGatewayHost(value) {
|
|
240
|
+
if (value === "all" || value === "opencode") return value;
|
|
241
|
+
throw new Error(`Unsupported gateway host "${value}"`);
|
|
242
|
+
}
|
|
235
243
|
async function runCli(argv) {
|
|
236
244
|
await createCliProgram().parseAsync(argv, { from: "node" });
|
|
237
245
|
}
|
package/dist/codex-auth-sync.js
CHANGED
|
@@ -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";
|
package/dist/config/defaults.js
CHANGED
|
@@ -73,6 +73,9 @@ skills:
|
|
|
73
73
|
quick:
|
|
74
74
|
path: .agents/skills/quick/SKILL.md
|
|
75
75
|
source_root: package
|
|
76
|
+
claude-code-opencode-execute:
|
|
77
|
+
path: .agents/skills/claude-code-opencode-execute/SKILL.md
|
|
78
|
+
source_root: package
|
|
76
79
|
critique:
|
|
77
80
|
path: .agents/skills/critique/SKILL.md
|
|
78
81
|
source_root: package
|
|
@@ -141,6 +144,7 @@ profiles:
|
|
|
141
144
|
repair: { enabled: true, max_attempts: 1 }
|
|
142
145
|
moka-inspector:
|
|
143
146
|
runner: opencode
|
|
147
|
+
model: openai/gpt-5.5-low
|
|
144
148
|
description: Inspect the repository without modifying files.
|
|
145
149
|
instructions: { inline: "Inspect the repository without modifying files." }
|
|
146
150
|
skills: [research]
|
|
@@ -150,6 +154,7 @@ profiles:
|
|
|
150
154
|
network: { mode: inherit }
|
|
151
155
|
moka-schedule-planner:
|
|
152
156
|
runner: opencode
|
|
157
|
+
model: openai/gpt-5.5-xhigh
|
|
153
158
|
description: Refine a baseline schedule into a specialized approved-plan artifact.
|
|
154
159
|
instructions: { inline: "Generate exactly one workflow named root as an explicit schedule graph. Return YAML only." }
|
|
155
160
|
timeout_ms: 300000
|
|
@@ -230,6 +235,7 @@ profiles:
|
|
|
230
235
|
repair: { enabled: true, max_attempts: 1 }
|
|
231
236
|
moka-learner:
|
|
232
237
|
runner: opencode
|
|
238
|
+
model: openai/gpt-5.5-low
|
|
233
239
|
description: Store durable lessons from the completed run.
|
|
234
240
|
instructions: { inline: "Store durable lessons from the completed run when useful." }
|
|
235
241
|
skills: [migrate]
|
|
@@ -289,54 +295,54 @@ scheduler:
|
|
|
289
295
|
backlog-intake:
|
|
290
296
|
category: intake
|
|
291
297
|
profile: moka-researcher
|
|
292
|
-
models: [openai/gpt-5.5-
|
|
298
|
+
models: [openai/gpt-5.5-medium]
|
|
293
299
|
red-tests:
|
|
294
300
|
category: red
|
|
295
301
|
profile: moka-test-writer
|
|
296
|
-
models: [openai/gpt-5.5, kimi-for-coding/kimi-k2-thinking]
|
|
302
|
+
models: [openai/gpt-5.5-high, kimi-for-coding/kimi-k2-thinking]
|
|
297
303
|
green-implementation:
|
|
298
304
|
category: green
|
|
299
305
|
profile: moka-code-writer
|
|
300
|
-
models: [openai/gpt-5.5, kimi-for-coding/k2p6, opencode-go/qwen3.7-max]
|
|
306
|
+
models: [openai/gpt-5.5-high, kimi-for-coding/k2p6, opencode-go/qwen3.7-max]
|
|
301
307
|
verification:
|
|
302
308
|
category: verification
|
|
303
309
|
profile: moka-verifier
|
|
304
|
-
models: [openai/gpt-5.5]
|
|
310
|
+
models: [openai/gpt-5.5-medium]
|
|
305
311
|
execute:
|
|
306
312
|
required_categories: [intake, research, red, green, mechanical, acceptance, verification, learn]
|
|
307
313
|
nodes:
|
|
308
314
|
backlog-intake:
|
|
309
315
|
category: intake
|
|
310
316
|
profile: moka-researcher
|
|
311
|
-
models: [openai/gpt-5.5-
|
|
317
|
+
models: [openai/gpt-5.5-medium]
|
|
312
318
|
research:
|
|
313
319
|
category: research
|
|
314
320
|
profile: moka-researcher
|
|
315
|
-
models: [openai/gpt-5.5-
|
|
321
|
+
models: [openai/gpt-5.5-medium, kimi-for-coding/k2p6]
|
|
316
322
|
red-tests:
|
|
317
323
|
category: red
|
|
318
324
|
profile: moka-test-writer
|
|
319
|
-
models: [openai/gpt-5.5, kimi-for-coding/kimi-k2-thinking]
|
|
325
|
+
models: [openai/gpt-5.5-high, kimi-for-coding/kimi-k2-thinking]
|
|
320
326
|
green-backend:
|
|
321
327
|
category: green
|
|
322
328
|
profile: moka-code-writer
|
|
323
|
-
models: [openai/gpt-5.5, kimi-for-coding/k2p6, opencode-go/qwen3.7-max]
|
|
329
|
+
models: [openai/gpt-5.5-high, kimi-for-coding/k2p6, opencode-go/qwen3.7-max]
|
|
324
330
|
green-frontend:
|
|
325
331
|
category: green
|
|
326
332
|
profile: moka-code-writer
|
|
327
|
-
models: [openai/gpt-5.5, kimi-for-coding/k2p6, opencode-go/qwen3.7-max]
|
|
333
|
+
models: [openai/gpt-5.5-high, kimi-for-coding/k2p6, opencode-go/qwen3.7-max]
|
|
328
334
|
acceptance-review:
|
|
329
335
|
category: acceptance
|
|
330
336
|
profile: moka-acceptance-reviewer
|
|
331
|
-
models: [openai/gpt-5.5]
|
|
337
|
+
models: [openai/gpt-5.5-medium]
|
|
332
338
|
verification:
|
|
333
339
|
category: verification
|
|
334
340
|
profile: moka-verifier
|
|
335
|
-
models: [openai/gpt-5.5]
|
|
341
|
+
models: [openai/gpt-5.5-medium]
|
|
336
342
|
learn:
|
|
337
343
|
category: learn
|
|
338
344
|
profile: moka-learner
|
|
339
|
-
models: [openai/gpt-5.5-
|
|
345
|
+
models: [openai/gpt-5.5-low]
|
|
340
346
|
schedules:
|
|
341
347
|
quick-schedule:
|
|
342
348
|
baseline: quick
|
|
@@ -385,6 +391,29 @@ const ecosystemCodeSchema = z.object({
|
|
|
385
391
|
role: z.string().min(1),
|
|
386
392
|
source: z.string().url()
|
|
387
393
|
}).strict();
|
|
394
|
+
const ecosystemProviderModelOptionsSchema = z.object({
|
|
395
|
+
include: ecosystemStringArraySchema,
|
|
396
|
+
reasoningEffort: z.enum([
|
|
397
|
+
"none",
|
|
398
|
+
"low",
|
|
399
|
+
"medium",
|
|
400
|
+
"high",
|
|
401
|
+
"xhigh"
|
|
402
|
+
]),
|
|
403
|
+
reasoningSummary: z.enum(["auto", "detailed"]),
|
|
404
|
+
store: z.literal(false),
|
|
405
|
+
textVerbosity: z.enum([
|
|
406
|
+
"low",
|
|
407
|
+
"medium",
|
|
408
|
+
"high"
|
|
409
|
+
])
|
|
410
|
+
}).strict();
|
|
411
|
+
const ecosystemProviderModelSchema = z.object({
|
|
412
|
+
id: z.string().min(1),
|
|
413
|
+
options: ecosystemProviderModelOptionsSchema,
|
|
414
|
+
provider: z.string().min(1),
|
|
415
|
+
role: z.string().min(1)
|
|
416
|
+
}).strict();
|
|
388
417
|
const ecosystemMcpBackendSchema = z.object({
|
|
389
418
|
credentials: ecosystemStringArraySchema,
|
|
390
419
|
id: z.string().min(1),
|
|
@@ -421,6 +450,7 @@ const openCodeEcosystemManifestSchema = z.object({
|
|
|
421
450
|
mcp_backends: z.array(ecosystemMcpBackendSchema).min(1),
|
|
422
451
|
official_dependencies: z.array(ecosystemDependencySchema).min(1),
|
|
423
452
|
prompts: z.array(ecosystemProfileResourceSchema).min(1),
|
|
453
|
+
provider_models: z.array(ecosystemProviderModelSchema).min(1),
|
|
424
454
|
runtime: ecosystemRuntimeSchema,
|
|
425
455
|
skills: z.array(ecosystemProfileResourceSchema).min(1),
|
|
426
456
|
sources: z.array(ecosystemSourceSchema).min(1),
|
package/dist/config/schemas.d.ts
CHANGED
|
@@ -343,8 +343,8 @@ declare const configSchema: z.ZodObject<{
|
|
|
343
343
|
rules: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
344
344
|
path: z.ZodString;
|
|
345
345
|
source_root: z.ZodDefault<z.ZodEnum<{
|
|
346
|
-
package: "package";
|
|
347
346
|
project: "project";
|
|
347
|
+
package: "package";
|
|
348
348
|
}>>;
|
|
349
349
|
}, z.core.$strict>>>;
|
|
350
350
|
runners: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
@@ -471,8 +471,8 @@ declare const configSchema: z.ZodObject<{
|
|
|
471
471
|
schedules: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
472
472
|
description: z.ZodOptional<z.ZodString>;
|
|
473
473
|
baseline: z.ZodEnum<{
|
|
474
|
-
execute: "execute";
|
|
475
474
|
quick: "quick";
|
|
475
|
+
execute: "execute";
|
|
476
476
|
}>;
|
|
477
477
|
max_parallel_nodes: z.ZodOptional<z.ZodNumber>;
|
|
478
478
|
node_catalog: z.ZodOptional<z.ZodString>;
|
|
@@ -484,8 +484,8 @@ declare const configSchema: z.ZodObject<{
|
|
|
484
484
|
skills: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
485
485
|
path: z.ZodString;
|
|
486
486
|
source_root: z.ZodDefault<z.ZodEnum<{
|
|
487
|
-
package: "package";
|
|
488
487
|
project: "project";
|
|
488
|
+
package: "package";
|
|
489
489
|
}>>;
|
|
490
490
|
}, z.core.$strict>>>;
|
|
491
491
|
task_context: z.ZodOptional<z.ZodObject<{
|
package/dist/hooks.d.ts
CHANGED
|
@@ -13,8 +13,8 @@ declare const hookResultSchema: z.ZodObject<{
|
|
|
13
13
|
taskContext: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
14
14
|
}, z.core.$strict>>;
|
|
15
15
|
status: z.ZodEnum<{
|
|
16
|
-
fail: "fail";
|
|
17
16
|
pass: "pass";
|
|
17
|
+
fail: "fail";
|
|
18
18
|
skip: "skip";
|
|
19
19
|
}>;
|
|
20
20
|
summary: z.ZodOptional<z.ZodString>;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { resolvePackageAssetPath } from "../package-assets.js";
|
|
2
|
+
import { GENERATED_MARKER, OWNER_MARKER_PREFIX, invocationForHost } from "./shared.js";
|
|
3
|
+
import { readFileSync } from "node:fs";
|
|
4
|
+
//#region src/install-commands/claude-code.ts
|
|
5
|
+
const CLAUDE_CODE_OPENCODE_EXECUTE_SKILL = "claude-code-opencode-execute";
|
|
6
|
+
const PACKAGE_SKILL_PATH = `.agents/skills/${CLAUDE_CODE_OPENCODE_EXECUTE_SKILL}/SKILL.md`;
|
|
7
|
+
function generatedClaudeSkillContent() {
|
|
8
|
+
return readFileSync(resolvePackageAssetPath(PACKAGE_SKILL_PATH), "utf8").replace("# Claude Code OpenCode Execute", [
|
|
9
|
+
GENERATED_MARKER,
|
|
10
|
+
`${OWNER_MARKER_PREFIX}host=claude-code -->`,
|
|
11
|
+
"",
|
|
12
|
+
"# Claude Code OpenCode Execute"
|
|
13
|
+
].join("\n"));
|
|
14
|
+
}
|
|
15
|
+
function claudeCodeDefinitions() {
|
|
16
|
+
return [{
|
|
17
|
+
content: generatedClaudeSkillContent(),
|
|
18
|
+
host: "claude-code",
|
|
19
|
+
invocation: invocationForHost("claude-code", CLAUDE_CODE_OPENCODE_EXECUTE_SKILL),
|
|
20
|
+
path: `.claude/skills/${CLAUDE_CODE_OPENCODE_EXECUTE_SKILL}/SKILL.md`
|
|
21
|
+
}];
|
|
22
|
+
}
|
|
23
|
+
//#endregion
|
|
24
|
+
export { claudeCodeDefinitions };
|
|
@@ -222,7 +222,10 @@ function hostSpecificDispatchGuard(host, nativeRoutes, cliRoutes) {
|
|
|
222
222
|
if (cliRoutes.length > 0 && nativeRoutes.length === 0) return `Do not claim these nodes are ${hostDisplayName(host)} subagents.`;
|
|
223
223
|
}
|
|
224
224
|
function hostDisplayName(host) {
|
|
225
|
-
return {
|
|
225
|
+
return {
|
|
226
|
+
"claude-code": "Claude Code",
|
|
227
|
+
opencode: "OpenCode"
|
|
228
|
+
}[host];
|
|
226
229
|
}
|
|
227
230
|
function needsSummary(needs) {
|
|
228
231
|
return needs.length > 0 ? needs.join(",") : "none";
|
|
@@ -271,9 +274,18 @@ function renderOpenCodeProjectConfig(config) {
|
|
|
271
274
|
return formatOpenCodeProjectJson({
|
|
272
275
|
...config.mcp_gateway ? JSON.parse(renderOpenCodeGatewayConfig(config)) : { $schema: "https://opencode.ai/config.json" },
|
|
273
276
|
lsp: true,
|
|
274
|
-
...opencodePluginConfig()
|
|
277
|
+
...opencodePluginConfig(),
|
|
278
|
+
...opencodeProviderConfig()
|
|
275
279
|
});
|
|
276
280
|
}
|
|
281
|
+
function opencodeProviderConfig() {
|
|
282
|
+
const provider = {};
|
|
283
|
+
for (const model of DEFAULT_OPENCODE_ECOSYSTEM_MANIFEST.provider_models) {
|
|
284
|
+
provider[model.provider] ??= { models: {} };
|
|
285
|
+
provider[model.provider].models[model.id] = { options: model.options };
|
|
286
|
+
}
|
|
287
|
+
return Object.keys(provider).length > 0 ? { provider } : {};
|
|
288
|
+
}
|
|
277
289
|
function opencodePluginConfig() {
|
|
278
290
|
const plugins = DEFAULT_OPENCODE_ECOSYSTEM_MANIFEST.ecosystem_code.flatMap((item) => npmPluginPackage(item)).sort((a, b) => a.localeCompare(b));
|
|
279
291
|
return plugins.length > 0 ? { plugin: plugins } : {};
|
|
@@ -10,10 +10,16 @@ const AGENTS_MD_END = "<!-- @oisincoveney/pipeline:agents:end -->";
|
|
|
10
10
|
const SINGLE_OPENCODE_PLUGIN_ARRAY_RE = /\n {2}"plugin": \[\n {4}("[^"]+")\n {2}\]/;
|
|
11
11
|
const OPENCODE_PROJECT_CONFIG_PATH = ".opencode/opencode.json";
|
|
12
12
|
const OPENCODE_COMMAND_PREFIX = "moka-";
|
|
13
|
-
const ENTRYPOINT_PATH_PATTERNS = {
|
|
14
|
-
|
|
13
|
+
const ENTRYPOINT_PATH_PATTERNS = {
|
|
14
|
+
"claude-code": [],
|
|
15
|
+
opencode: [/^\.opencode\/commands\/(?:moka-)?([^/]+)\.md$/]
|
|
16
|
+
};
|
|
17
|
+
const COMMAND_HOSTS = ["opencode", "claude-code"];
|
|
15
18
|
function invocationForHost(host, entrypointId = "execute") {
|
|
16
|
-
return `${{
|
|
19
|
+
return `${{
|
|
20
|
+
"claude-code": "/",
|
|
21
|
+
opencode: "/"
|
|
22
|
+
}[host]}${commandIdForHost(host, entrypointId)} <task description>`;
|
|
17
23
|
}
|
|
18
24
|
function commandIdForHost(host, entrypointId) {
|
|
19
25
|
if (host === "opencode") return `${OPENCODE_COMMAND_PREFIX}${entrypointId}`;
|
package/dist/install-commands.js
CHANGED
|
@@ -2,13 +2,17 @@ import { loadPipelineConfig } from "./config/load.js";
|
|
|
2
2
|
import "./config.js";
|
|
3
3
|
import { mergeOpenCodeProjectConfig } from "./opencode-project-config.js";
|
|
4
4
|
import { COMMAND_HOSTS, ENTRYPOINT_PATH_PATTERNS, invocationForHost } from "./install-commands/shared.js";
|
|
5
|
+
import { claudeCodeDefinitions } from "./install-commands/claude-code.js";
|
|
5
6
|
import { opencodeDefinitions } from "./install-commands/opencode.js";
|
|
6
7
|
import { existsSync, readFileSync, statSync } from "node:fs";
|
|
7
8
|
import { dirname, join, relative } from "node:path";
|
|
8
9
|
import { mkdir, readdir, rm, writeFile } from "node:fs/promises";
|
|
9
10
|
//#region src/install-commands.ts
|
|
10
11
|
function definitionsFor(host, config, cwd) {
|
|
11
|
-
const definitions = {
|
|
12
|
+
const definitions = {
|
|
13
|
+
"claude-code": () => claudeCodeDefinitions(),
|
|
14
|
+
opencode: () => opencodeDefinitions(config, cwd)
|
|
15
|
+
};
|
|
12
16
|
return dedupeDefinitionsByPath((host === "all" ? COMMAND_HOSTS : [host]).flatMap((name) => definitions[name]()));
|
|
13
17
|
}
|
|
14
18
|
function dedupeDefinitionsByPath(definitions) {
|
|
@@ -21,12 +25,15 @@ function dedupeDefinitionsByPath(definitions) {
|
|
|
21
25
|
function selectedHosts(host) {
|
|
22
26
|
return host === "all" ? [...COMMAND_HOSTS] : [host];
|
|
23
27
|
}
|
|
24
|
-
const GENERATED_RESOURCE_ROOTS = {
|
|
25
|
-
".
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
28
|
+
const GENERATED_RESOURCE_ROOTS = {
|
|
29
|
+
"claude-code": [".claude/skills"],
|
|
30
|
+
opencode: [
|
|
31
|
+
".opencode/commands",
|
|
32
|
+
".opencode/agents",
|
|
33
|
+
".opencode/plugins",
|
|
34
|
+
".opencode/skills"
|
|
35
|
+
]
|
|
36
|
+
};
|
|
30
37
|
async function listFiles(root) {
|
|
31
38
|
if (!existsSync(root)) return [];
|
|
32
39
|
if (statSync(root).isFile()) return [root];
|
package/dist/moka-submit.d.ts
CHANGED
|
@@ -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
|
-
quick: "quick";
|
|
165
164
|
full: "full";
|
|
165
|
+
quick: "quick";
|
|
166
166
|
}>;
|
|
167
167
|
schedulePath: z.ZodOptional<z.ZodString>;
|
|
168
168
|
scheduleYaml: z.ZodOptional<z.ZodString>;
|
|
@@ -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
|
|
58
|
-
const
|
|
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 }));
|
|
@@ -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
|
-
quick: "quick";
|
|
47
46
|
full: "full";
|
|
47
|
+
quick: "quick";
|
|
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
|
-
quick: "quick";
|
|
108
107
|
full: "full";
|
|
108
|
+
quick: "quick";
|
|
109
109
|
}>;
|
|
110
110
|
}, z.core.$strict>, z.ZodObject<{
|
|
111
111
|
argv: z.ZodArray<z.ZodString>;
|
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
|
|
118
|
+
"version": "2.1.0",
|
|
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",
|