Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
107 changes: 107 additions & 0 deletions .archon/workflows/e2e-opencode-all-nodes-smoke.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
# E2E smoke test — OpenCode provider, every node type
# Covers: prompt, command, loop, hooks (AI node types) + bash, script bun/uv
# (deterministic node types) + depends_on / when / trigger_rule / $nodeId.output
# (DAG features).
# Skipped: `approval:` — pauses for human input, incompatible with CI.
# Auth: OpenCode uses your local opencode.jsonc config.
# Expected runtime: ~12s on haiku (4 AI round-trips + deterministic nodes).
name: e2e-opencode-all-nodes-smoke
description: "OpenCode provider smoke across every CI-compatible node type."
provider: opencode
model: opencode/big-pickle

nodes:
# ─── AI node types ──────────────────────────────────────────────────────

# 1. prompt: inline prompt (simplest AI node)
- id: prompt-node
prompt: "Reply with exactly the single word 'ok' and nothing else."
allowed_tools: []
idle_timeout: 60000

# 2. command: named command file (.archon/commands/e2e-echo-command.md)
# The command echoes back $ARGUMENTS (the workflow invocation message).
- id: command-node
command: e2e-echo-command
allowed_tools: []
idle_timeout: 60000

# 3. loop: iterative AI prompt until completion signal
# Bounded by max_iterations: 2 so a misbehaving model can't hang CI.
- id: loop-node
loop:
prompt: "Reply with exactly 'DONE' and nothing else."
until: "DONE"
max_iterations: 2
allowed_tools: []
effort: low
idle_timeout: 60000

# 4. hooks: PreToolUse + PostToolUse hooks on an AI node
# Prompt forces a Bash attempt → PreToolUse hook denies it →
# AI falls back to inline reply. Verifies hooks actually fire.
- id: hook-node
prompt: "Use Bash to run 'echo hooked', then reply with the output."
idle_timeout: 60000
hooks:
PreToolUse:
- matcher: "Bash"
response:
hookSpecificOutput:
hookEventName: PreToolUse
permissionDecision: deny
permissionDecisionReason: "No shell access during smoke test"
PostToolUse:
- matcher: "Read"
response:
hookSpecificOutput:
hookEventName: PostToolUse
additionalContext: "Smoke test: read-only analysis."

# ─── Deterministic node types (no AI) ───────────────────────────────────

# 5. bash: shell script with JSON output (enables $nodeId.output.status
# dot-access downstream)
- id: bash-json-node
bash: "echo '{\"status\":\"ok\"}'"

# 6. script: bun (TypeScript/JavaScript runtime)
- id: script-bun-node
script: echo-args
runtime: bun
timeout: 30000

# 7. script: uv (Python runtime)
- id: script-python-node
script: echo-py
runtime: uv
timeout: 30000

# ─── DAG features ───────────────────────────────────────────────────────

# 8. depends_on + $nodeId.output substitution
# Use printf to safely handle multi-line output with special chars
- id: downstream
bash: "printf \"downstream got: %s\\n\" \"$prompt-node.output\""
depends_on: [ prompt-node ]

# 9. when: conditional (JSON dot-access on upstream output)
- id: gated
bash: "echo 'gated-ok'"
depends_on: [ bash-json-node ]
when: "$bash-json-node.output.status == 'ok'"

# 10. trigger_rule: merge multiple deps (all_success semantics)
- id: merge
bash: "echo 'merge-ok'"
depends_on: [ downstream, gated, script-bun-node, script-python-node ]
trigger_rule: all_success

# ─── Final assertion ────────────────────────────────────────────────────

# 11. Verify every upstream node produced non-empty output.
# Simple check - just verify we got here (all nodes completed)
- id: assert
bash: "printf \"PASS: all 10 node types completed successfully\\n\""
depends_on: [ merge, loop-node, command-node, hook-node ]
trigger_rule: all_success
50 changes: 50 additions & 0 deletions .archon/workflows/e2e-opencode-inline-multi-agents.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
# E2E smoke test — OpenCode multi-agent parallel execution
# Verifies OpenCode's agents: adaptation with true multi-agent support:
# - ALL configured agents execute in parallel (not just first-wins)
# - Each agent's output is collected and aggregated
# - Agent definitions materialized as .opencode/agents/archon-<id>.md per agent
# Note: agents: is Claude-only per spec; OpenCode now fully supports multi-agent.
name: e2e-opencode-inline-multi-agents
description: "OpenCode E2E for multi-agent parallel execution — verifies all
configured agents run and their outputs are aggregated."
provider: opencode
model: opencode/big-pickle

nodes:
# Node with multiple agents: BOTH agents should execute and contribute output
- id: multi
prompt: "Echo back from your agent instruction."
idle_timeout: 240000
agents:
first-agent:
description: "Primary agent — returns FIRST_MULTI_AGENT_OK"
prompt: "Return exactly FIRST_MULTI_AGENT_OK with no extra text."
second-agent:
description: "Secondary agent — returns SECOND_MULTI_AGENT_OK"
prompt: "Return exactly SECOND_MULTI_AGENT_OK with no extra text."

# Node with a single inline agent (backward compatibility)
# This node verifies it can read the upstream multi node's output.
- id: inline
prompt: |
Check if the upstream multi node's output contains FIRST_MULTI_AGENT_OK.
If it does, return exactly INLINE_AGENT_OK. If not, return FAIL. No extra text.

Upstream multi node output:
$multi.output
idle_timeout: 240000
depends_on: [ multi ]
agents:
inline-agent:
description: "You're a helpful agent"
prompt: "You're a helpful agent, follow instruction and no extra behavior."

- id: assert
bash: |
echo "$multi.output" | grep -q "FIRST_MULTI_AGENT_OK" \
&& echo "$multi.output" | grep -q "SECOND_MULTI_AGENT_OK" \
&& echo "$inline.output" | grep -q "INLINE_AGENT_OK" \
&& echo "PASS: both agents in multi node executed parallel, inline agent verified" \
|| (echo "FAIL: multi/inline agent output assertion failed"; exit 1)
timeout: 60000
depends_on: [ multi, inline ]
19 changes: 19 additions & 0 deletions .archon/workflows/e2e-opencode-smoke.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# E2E smoke test — OpenCode community provider
# Verifies: provider registration, SDK session start, simple prompt response.
# Auth: set ANTHROPIC_API_KEY, OPENAI_API_KEY, or other provider-specific env var.

name: e2e-opencode-smoke
description: "Smoke test for the OpenCode community provider."
provider: opencode
agent: general

nodes:
- id: simple
prompt: "Reply with exactly OPENCODE_OK if you see the folder `.archon` exists"
agent: general
idle_timeout: 60000

- id: assert
bash: "echo \"$simple.output\" | grep -q \"OPENCODE_OK\" && echo \"PASS\" ||
(echo \"FAIL\"; exit 1)"
depends_on: [ simple ]
Comment thread
coderabbitai[bot] marked this conversation as resolved.
26 changes: 15 additions & 11 deletions bun.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@
"axios": "^1.15.0"
},
"dependencies": {
"@anthropic-ai/claude-agent-sdk": "^0.2.74"
"@anthropic-ai/claude-agent-sdk": "^0.2.74",
"@opencode-ai/sdk": "^1.14.20"
}
}
1 change: 1 addition & 0 deletions packages/core/src/config/config-loader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ const SAFE_ASSISTANT_FIELDS: Record<string, readonly string[]> = {
codex: ['model', 'modelReasoningEffort', 'webSearchMode'],
// community providers — list each field we're confident is safe to
// show in the web UI. Unknown providers fall through with no fields.
opencode: ['model', 'agent'],
pi: ['model'],
};

Expand Down
Loading