ac-framework 1.9.4 → 1.9.6
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/LICENSE +1 -0
- package/README.md +21 -1
- package/bin/postinstall.js +2 -0
- package/framework/mobile_development/.agent/workflows/ac-lite.md +70 -179
- package/framework/mobile_development/.agent/workflows/ac.md +273 -404
- package/framework/mobile_development/.amazonq/prompts/ac-lite.md +70 -179
- package/framework/mobile_development/.amazonq/prompts/ac.md +273 -404
- package/framework/mobile_development/.antigravity/workflows/ac-lite.md +70 -179
- package/framework/mobile_development/.antigravity/workflows/ac.md +273 -404
- package/framework/mobile_development/.augment/commands/ac-lite.md +70 -179
- package/framework/mobile_development/.augment/commands/ac.md +273 -404
- package/framework/mobile_development/.claude/commands/opsx/ac-lite.md +70 -179
- package/framework/mobile_development/.claude/commands/opsx/ac.md +273 -404
- package/framework/mobile_development/.cline/commands/opsx/ac-lite.md +70 -179
- package/framework/mobile_development/.cline/commands/opsx/ac.md +273 -404
- package/framework/mobile_development/.clinerules/workflows/ac-lite.md +70 -179
- package/framework/mobile_development/.clinerules/workflows/ac.md +273 -404
- package/framework/mobile_development/.codebuddy/commands/opsx/ac-lite.md +70 -179
- package/framework/mobile_development/.codebuddy/commands/opsx/ac.md +273 -404
- package/framework/mobile_development/.continue/prompts/ac-lite.md +70 -179
- package/framework/mobile_development/.continue/prompts/ac.md +273 -404
- package/framework/mobile_development/.cospec/openspec/commands/ac-lite.md +70 -179
- package/framework/mobile_development/.cospec/openspec/commands/ac.md +273 -404
- package/framework/mobile_development/.crush/commands/opsx/ac-lite.md +70 -179
- package/framework/mobile_development/.crush/commands/opsx/ac.md +273 -404
- package/framework/mobile_development/.cursor/commands/ac-lite.md +70 -179
- package/framework/mobile_development/.cursor/commands/ac.md +273 -404
- package/framework/mobile_development/.factory/commands/ac-lite.md +70 -179
- package/framework/mobile_development/.factory/commands/ac.md +273 -404
- package/framework/mobile_development/.gemini/commands/opsx/ac-lite.md +70 -179
- package/framework/mobile_development/.gemini/commands/opsx/ac.md +273 -404
- package/framework/mobile_development/.github/prompts/ac-lite.md +70 -179
- package/framework/mobile_development/.github/prompts/ac.md +273 -404
- package/framework/mobile_development/.github/prompts/ac.prompt.md +282 -177
- package/framework/mobile_development/.iflow/commands/ac-lite.md +70 -179
- package/framework/mobile_development/.iflow/commands/ac.md +273 -404
- package/framework/mobile_development/.kilocode/workflows/ac-lite.md +70 -179
- package/framework/mobile_development/.kilocode/workflows/ac.md +273 -404
- package/framework/mobile_development/.kimi/workflows/ac-lite.md +70 -179
- package/framework/mobile_development/.kimi/workflows/ac.md +273 -404
- package/framework/mobile_development/.opencode/command/ac-lite.md +70 -179
- package/framework/mobile_development/.opencode/command/ac.md +273 -404
- package/framework/mobile_development/.qoder/commands/opsx/ac-lite.md +70 -179
- package/framework/mobile_development/.qoder/commands/opsx/ac.md +273 -404
- package/framework/mobile_development/.qwen/commands/ac-lite.md +70 -179
- package/framework/mobile_development/.qwen/commands/ac.md +273 -404
- package/framework/mobile_development/.roo/commands/ac-lite.md +70 -179
- package/framework/mobile_development/.roo/commands/ac.md +273 -404
- package/framework/mobile_development/.windsurf/workflows/ac-lite.md +70 -179
- package/framework/mobile_development/.windsurf/workflows/ac.md +273 -404
- package/framework/mobile_development/AGENTS.md +205 -416
- package/framework/mobile_development/CLAUDE.md +205 -416
- package/framework/mobile_development/GEMINI.md +205 -416
- package/framework/mobile_development/copilot-instructions.md +205 -416
- package/framework/new_project/.agent/workflows/ac.md +39 -0
- package/framework/new_project/.amazonq/prompts/ac.md +39 -0
- package/framework/new_project/.antigravity/workflows/ac.md +39 -0
- package/framework/new_project/.augment/commands/ac.md +39 -0
- package/framework/new_project/.claude/commands/opsx/ac.md +39 -0
- package/framework/new_project/.cline/commands/opsx/ac.md +39 -0
- package/framework/new_project/.clinerules/workflows/ac.md +39 -0
- package/framework/new_project/.codebuddy/commands/opsx/ac.md +39 -0
- package/framework/new_project/.continue/prompts/ac.md +39 -0
- package/framework/new_project/.cospec/openspec/commands/ac.md +39 -0
- package/framework/new_project/.crush/commands/opsx/ac.md +39 -0
- package/framework/new_project/.cursor/commands/ac.md +39 -0
- package/framework/new_project/.factory/commands/ac.md +39 -0
- package/framework/new_project/.gemini/commands/opsx/ac.md +39 -0
- package/framework/new_project/.github/prompts/ac.md +39 -0
- package/framework/new_project/.iflow/commands/ac.md +39 -0
- package/framework/new_project/.kilocode/workflows/ac.md +39 -0
- package/framework/new_project/.kimi/workflows/ac.md +39 -0
- package/framework/new_project/.opencode/command/ac.md +39 -0
- package/framework/new_project/.qoder/commands/opsx/ac.md +39 -0
- package/framework/new_project/.qwen/commands/ac.md +39 -0
- package/framework/new_project/.roo/commands/ac.md +39 -0
- package/framework/new_project/.windsurf/workflows/ac.md +39 -0
- package/framework/new_project/AGENTS.md +27 -0
- package/framework/web_development/.agent/workflows/ac.md +39 -0
- package/framework/web_development/.amazonq/prompts/ac.md +39 -0
- package/framework/web_development/.antigravity/workflows/ac.md +39 -0
- package/framework/web_development/.augment/commands/ac.md +39 -0
- package/framework/web_development/.claude/commands/opsx/ac.md +39 -0
- package/framework/web_development/.cline/commands/opsx/ac.md +39 -0
- package/framework/web_development/.clinerules/workflows/ac.md +39 -0
- package/framework/web_development/.codebuddy/commands/opsx/ac.md +39 -0
- package/framework/web_development/.continue/prompts/ac.md +39 -0
- package/framework/web_development/.cospec/openspec/commands/ac.md +39 -0
- package/framework/web_development/.crush/commands/opsx/ac.md +39 -0
- package/framework/web_development/.cursor/commands/ac.md +39 -0
- package/framework/web_development/.factory/commands/ac.md +39 -0
- package/framework/web_development/.gemini/commands/opsx/ac.md +39 -0
- package/framework/web_development/.github/prompts/ac.md +39 -0
- package/framework/web_development/.iflow/commands/ac.md +39 -0
- package/framework/web_development/.kilocode/workflows/ac.md +39 -0
- package/framework/web_development/.kimi/workflows/ac.md +39 -0
- package/framework/web_development/.opencode/command/ac.md +39 -0
- package/framework/web_development/.qoder/commands/opsx/ac.md +39 -0
- package/framework/web_development/.qwen/commands/ac.md +39 -0
- package/framework/web_development/.roo/commands/ac.md +39 -0
- package/framework/web_development/.windsurf/workflows/ac.md +39 -0
- package/framework/web_development/AGENTS.md +27 -0
- package/package.json +1 -1
- package/src/agents/config-store.js +48 -0
- package/src/agents/model-selection.js +38 -0
- package/src/agents/opencode-client.js +3 -2
- package/src/agents/orchestrator.js +10 -3
- package/src/agents/runtime.js +80 -0
- package/src/agents/state-store.js +3 -0
- package/src/commands/agents.js +301 -85
- package/src/commands/init.js +33 -0
- package/src/mcp/collab-server.js +299 -0
- package/src/services/dependency-installer.js +20 -1
- package/src/services/mcp-installer.js +82 -54
|
@@ -98,6 +98,45 @@ acfm memory stats
|
|
|
98
98
|
|
|
99
99
|
**User communication:** "Memory saved: [brief description]" when auto-saving occurs.
|
|
100
100
|
|
|
101
|
+
### SynapseGrid Collaborative MCP Protocol (Optional)
|
|
102
|
+
|
|
103
|
+
If SynapseGrid is enabled in `acfm init`, AC Framework installs the collaborative MCP server automatically for detected assistants.
|
|
104
|
+
|
|
105
|
+
**Session-start requirement when collaboration is enabled:**
|
|
106
|
+
1. Prefer the available SynapseGrid MCP tools for collaborative session control before falling back to direct CLI.
|
|
107
|
+
2. Use shared session state and transcript as the source of truth for role-by-role collaboration.
|
|
108
|
+
3. If collaborative MCP is unavailable, use CLI fallback commands and keep behavior equivalent.
|
|
109
|
+
|
|
110
|
+
**How to use SynapseGrid collaboration:**
|
|
111
|
+
```text
|
|
112
|
+
Preferred: use SynapseGrid MCP tools (ac-framework-collab) for start/status/step/resume/stop.
|
|
113
|
+
Fallback: use AC Framework agents CLI commands directly.
|
|
114
|
+
```
|
|
115
|
+
```bash
|
|
116
|
+
# Install/update collaborative MCP server integrations
|
|
117
|
+
acfm agents install-mcps
|
|
118
|
+
|
|
119
|
+
# Start collaborative runtime with visible 4-pane tmux war-room
|
|
120
|
+
acfm agents start --task "design and implement feature X" --attach --model-coder provider/model
|
|
121
|
+
|
|
122
|
+
# If already running in background, attach to panes and inspect logs
|
|
123
|
+
acfm agents live
|
|
124
|
+
acfm agents logs --role all --lines 120
|
|
125
|
+
|
|
126
|
+
# Resume/list/export operations
|
|
127
|
+
acfm agents resume
|
|
128
|
+
acfm agents list
|
|
129
|
+
acfm agents export --format md --out synapse-session.md
|
|
130
|
+
|
|
131
|
+
# Fast diagnostics for OpenCode resolution errors
|
|
132
|
+
acfm agents setup
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
**Troubleshooting notes:**
|
|
136
|
+
- If transcript shows `Agent failed: spawn opencode ENOENT`, run `acfm agents setup` and restart/resume session.
|
|
137
|
+
- If session exists but panes are not visible, use `acfm agents live` (or `acfm agents attach`) or `tmux attach -t <session-name>`.
|
|
138
|
+
- For MCP-first flows, ensure session start enables worker spawning so tmux panes are created.
|
|
139
|
+
- Per-role models can be set at start (`--model-planner`, `--model-critic`, `--model-coder`, `--model-reviewer`) or persisted via `acfm agents model set`.
|
|
101
140
|
|
|
102
141
|
### OpenSpec Skills (The heart of the framework)
|
|
103
142
|
|
|
@@ -98,6 +98,45 @@ acfm memory stats
|
|
|
98
98
|
|
|
99
99
|
**User communication:** "Memory saved: [brief description]" when auto-saving occurs.
|
|
100
100
|
|
|
101
|
+
### SynapseGrid Collaborative MCP Protocol (Optional)
|
|
102
|
+
|
|
103
|
+
If SynapseGrid is enabled in `acfm init`, AC Framework installs the collaborative MCP server automatically for detected assistants.
|
|
104
|
+
|
|
105
|
+
**Session-start requirement when collaboration is enabled:**
|
|
106
|
+
1. Prefer the available SynapseGrid MCP tools for collaborative session control before falling back to direct CLI.
|
|
107
|
+
2. Use shared session state and transcript as the source of truth for role-by-role collaboration.
|
|
108
|
+
3. If collaborative MCP is unavailable, use CLI fallback commands and keep behavior equivalent.
|
|
109
|
+
|
|
110
|
+
**How to use SynapseGrid collaboration:**
|
|
111
|
+
```text
|
|
112
|
+
Preferred: use SynapseGrid MCP tools (ac-framework-collab) for start/status/step/resume/stop.
|
|
113
|
+
Fallback: use AC Framework agents CLI commands directly.
|
|
114
|
+
```
|
|
115
|
+
```bash
|
|
116
|
+
# Install/update collaborative MCP server integrations
|
|
117
|
+
acfm agents install-mcps
|
|
118
|
+
|
|
119
|
+
# Start collaborative runtime with visible 4-pane tmux war-room
|
|
120
|
+
acfm agents start --task "design and implement feature X" --attach --model-coder provider/model
|
|
121
|
+
|
|
122
|
+
# If already running in background, attach to panes and inspect logs
|
|
123
|
+
acfm agents live
|
|
124
|
+
acfm agents logs --role all --lines 120
|
|
125
|
+
|
|
126
|
+
# Resume/list/export operations
|
|
127
|
+
acfm agents resume
|
|
128
|
+
acfm agents list
|
|
129
|
+
acfm agents export --format md --out synapse-session.md
|
|
130
|
+
|
|
131
|
+
# Fast diagnostics for OpenCode resolution errors
|
|
132
|
+
acfm agents setup
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
**Troubleshooting notes:**
|
|
136
|
+
- If transcript shows `Agent failed: spawn opencode ENOENT`, run `acfm agents setup` and restart/resume session.
|
|
137
|
+
- If session exists but panes are not visible, use `acfm agents live` (or `acfm agents attach`) or `tmux attach -t <session-name>`.
|
|
138
|
+
- For MCP-first flows, ensure session start enables worker spawning so tmux panes are created.
|
|
139
|
+
- Per-role models can be set at start (`--model-planner`, `--model-critic`, `--model-coder`, `--model-reviewer`) or persisted via `acfm agents model set`.
|
|
101
140
|
|
|
102
141
|
### OpenSpec Skills (The heart of the framework)
|
|
103
142
|
|
|
@@ -98,6 +98,45 @@ acfm memory stats
|
|
|
98
98
|
|
|
99
99
|
**User communication:** "Memory saved: [brief description]" when auto-saving occurs.
|
|
100
100
|
|
|
101
|
+
### SynapseGrid Collaborative MCP Protocol (Optional)
|
|
102
|
+
|
|
103
|
+
If SynapseGrid is enabled in `acfm init`, AC Framework installs the collaborative MCP server automatically for detected assistants.
|
|
104
|
+
|
|
105
|
+
**Session-start requirement when collaboration is enabled:**
|
|
106
|
+
1. Prefer the available SynapseGrid MCP tools for collaborative session control before falling back to direct CLI.
|
|
107
|
+
2. Use shared session state and transcript as the source of truth for role-by-role collaboration.
|
|
108
|
+
3. If collaborative MCP is unavailable, use CLI fallback commands and keep behavior equivalent.
|
|
109
|
+
|
|
110
|
+
**How to use SynapseGrid collaboration:**
|
|
111
|
+
```text
|
|
112
|
+
Preferred: use SynapseGrid MCP tools (ac-framework-collab) for start/status/step/resume/stop.
|
|
113
|
+
Fallback: use AC Framework agents CLI commands directly.
|
|
114
|
+
```
|
|
115
|
+
```bash
|
|
116
|
+
# Install/update collaborative MCP server integrations
|
|
117
|
+
acfm agents install-mcps
|
|
118
|
+
|
|
119
|
+
# Start collaborative runtime with visible 4-pane tmux war-room
|
|
120
|
+
acfm agents start --task "design and implement feature X" --attach --model-coder provider/model
|
|
121
|
+
|
|
122
|
+
# If already running in background, attach to panes and inspect logs
|
|
123
|
+
acfm agents live
|
|
124
|
+
acfm agents logs --role all --lines 120
|
|
125
|
+
|
|
126
|
+
# Resume/list/export operations
|
|
127
|
+
acfm agents resume
|
|
128
|
+
acfm agents list
|
|
129
|
+
acfm agents export --format md --out synapse-session.md
|
|
130
|
+
|
|
131
|
+
# Fast diagnostics for OpenCode resolution errors
|
|
132
|
+
acfm agents setup
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
**Troubleshooting notes:**
|
|
136
|
+
- If transcript shows `Agent failed: spawn opencode ENOENT`, run `acfm agents setup` and restart/resume session.
|
|
137
|
+
- If session exists but panes are not visible, use `acfm agents live` (or `acfm agents attach`) or `tmux attach -t <session-name>`.
|
|
138
|
+
- For MCP-first flows, ensure session start enables worker spawning so tmux panes are created.
|
|
139
|
+
- Per-role models can be set at start (`--model-planner`, `--model-critic`, `--model-coder`, `--model-reviewer`) or persisted via `acfm agents model set`.
|
|
101
140
|
|
|
102
141
|
### OpenSpec Skills (The heart of the framework)
|
|
103
142
|
|
|
@@ -98,6 +98,45 @@ acfm memory stats
|
|
|
98
98
|
|
|
99
99
|
**User communication:** "Memory saved: [brief description]" when auto-saving occurs.
|
|
100
100
|
|
|
101
|
+
### SynapseGrid Collaborative MCP Protocol (Optional)
|
|
102
|
+
|
|
103
|
+
If SynapseGrid is enabled in `acfm init`, AC Framework installs the collaborative MCP server automatically for detected assistants.
|
|
104
|
+
|
|
105
|
+
**Session-start requirement when collaboration is enabled:**
|
|
106
|
+
1. Prefer the available SynapseGrid MCP tools for collaborative session control before falling back to direct CLI.
|
|
107
|
+
2. Use shared session state and transcript as the source of truth for role-by-role collaboration.
|
|
108
|
+
3. If collaborative MCP is unavailable, use CLI fallback commands and keep behavior equivalent.
|
|
109
|
+
|
|
110
|
+
**How to use SynapseGrid collaboration:**
|
|
111
|
+
```text
|
|
112
|
+
Preferred: use SynapseGrid MCP tools (ac-framework-collab) for start/status/step/resume/stop.
|
|
113
|
+
Fallback: use AC Framework agents CLI commands directly.
|
|
114
|
+
```
|
|
115
|
+
```bash
|
|
116
|
+
# Install/update collaborative MCP server integrations
|
|
117
|
+
acfm agents install-mcps
|
|
118
|
+
|
|
119
|
+
# Start collaborative runtime with visible 4-pane tmux war-room
|
|
120
|
+
acfm agents start --task "design and implement feature X" --attach --model-coder provider/model
|
|
121
|
+
|
|
122
|
+
# If already running in background, attach to panes and inspect logs
|
|
123
|
+
acfm agents live
|
|
124
|
+
acfm agents logs --role all --lines 120
|
|
125
|
+
|
|
126
|
+
# Resume/list/export operations
|
|
127
|
+
acfm agents resume
|
|
128
|
+
acfm agents list
|
|
129
|
+
acfm agents export --format md --out synapse-session.md
|
|
130
|
+
|
|
131
|
+
# Fast diagnostics for OpenCode resolution errors
|
|
132
|
+
acfm agents setup
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
**Troubleshooting notes:**
|
|
136
|
+
- If transcript shows `Agent failed: spawn opencode ENOENT`, run `acfm agents setup` and restart/resume session.
|
|
137
|
+
- If session exists but panes are not visible, use `acfm agents live` (or `acfm agents attach`) or `tmux attach -t <session-name>`.
|
|
138
|
+
- For MCP-first flows, ensure session start enables worker spawning so tmux panes are created.
|
|
139
|
+
- Per-role models can be set at start (`--model-planner`, `--model-critic`, `--model-coder`, `--model-reviewer`) or persisted via `acfm agents model set`.
|
|
101
140
|
|
|
102
141
|
### OpenSpec Skills (The heart of the framework)
|
|
103
142
|
|
|
@@ -98,6 +98,45 @@ acfm memory stats
|
|
|
98
98
|
|
|
99
99
|
**User communication:** "Memory saved: [brief description]" when auto-saving occurs.
|
|
100
100
|
|
|
101
|
+
### SynapseGrid Collaborative MCP Protocol (Optional)
|
|
102
|
+
|
|
103
|
+
If SynapseGrid is enabled in `acfm init`, AC Framework installs the collaborative MCP server automatically for detected assistants.
|
|
104
|
+
|
|
105
|
+
**Session-start requirement when collaboration is enabled:**
|
|
106
|
+
1. Prefer the available SynapseGrid MCP tools for collaborative session control before falling back to direct CLI.
|
|
107
|
+
2. Use shared session state and transcript as the source of truth for role-by-role collaboration.
|
|
108
|
+
3. If collaborative MCP is unavailable, use CLI fallback commands and keep behavior equivalent.
|
|
109
|
+
|
|
110
|
+
**How to use SynapseGrid collaboration:**
|
|
111
|
+
```text
|
|
112
|
+
Preferred: use SynapseGrid MCP tools (ac-framework-collab) for start/status/step/resume/stop.
|
|
113
|
+
Fallback: use AC Framework agents CLI commands directly.
|
|
114
|
+
```
|
|
115
|
+
```bash
|
|
116
|
+
# Install/update collaborative MCP server integrations
|
|
117
|
+
acfm agents install-mcps
|
|
118
|
+
|
|
119
|
+
# Start collaborative runtime with visible 4-pane tmux war-room
|
|
120
|
+
acfm agents start --task "design and implement feature X" --attach --model-coder provider/model
|
|
121
|
+
|
|
122
|
+
# If already running in background, attach to panes and inspect logs
|
|
123
|
+
acfm agents live
|
|
124
|
+
acfm agents logs --role all --lines 120
|
|
125
|
+
|
|
126
|
+
# Resume/list/export operations
|
|
127
|
+
acfm agents resume
|
|
128
|
+
acfm agents list
|
|
129
|
+
acfm agents export --format md --out synapse-session.md
|
|
130
|
+
|
|
131
|
+
# Fast diagnostics for OpenCode resolution errors
|
|
132
|
+
acfm agents setup
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
**Troubleshooting notes:**
|
|
136
|
+
- If transcript shows `Agent failed: spawn opencode ENOENT`, run `acfm agents setup` and restart/resume session.
|
|
137
|
+
- If session exists but panes are not visible, use `acfm agents live` (or `acfm agents attach`) or `tmux attach -t <session-name>`.
|
|
138
|
+
- For MCP-first flows, ensure session start enables worker spawning so tmux panes are created.
|
|
139
|
+
- Per-role models can be set at start (`--model-planner`, `--model-critic`, `--model-coder`, `--model-reviewer`) or persisted via `acfm agents model set`.
|
|
101
140
|
|
|
102
141
|
### OpenSpec Skills (The heart of the framework)
|
|
103
142
|
|
|
@@ -98,6 +98,33 @@ acfm memory stats
|
|
|
98
98
|
|
|
99
99
|
**User communication:** "Memory saved: [brief description]" when auto-saving occurs.
|
|
100
100
|
|
|
101
|
+
### SynapseGrid Collaborative MCP Protocol (Optional)
|
|
102
|
+
|
|
103
|
+
If SynapseGrid is enabled in `acfm init`, AC Framework installs the collaborative MCP server automatically for detected assistants.
|
|
104
|
+
|
|
105
|
+
**Session-start requirement when collaboration is enabled:**
|
|
106
|
+
1. Prefer the available SynapseGrid MCP tools for collaborative session control before falling back to direct CLI.
|
|
107
|
+
2. Use shared session state and transcript as the source of truth for role-by-role collaboration.
|
|
108
|
+
3. If collaborative MCP is unavailable, use CLI fallback commands and keep behavior equivalent.
|
|
109
|
+
|
|
110
|
+
**How to use SynapseGrid collaboration:**
|
|
111
|
+
```text
|
|
112
|
+
Preferred: use SynapseGrid MCP tools (ac-framework-collab) for session start/status/step/stop.
|
|
113
|
+
Fallback: use AC Framework agents CLI commands directly.
|
|
114
|
+
```
|
|
115
|
+
```bash
|
|
116
|
+
# Optional install/reinstall of collaborative MCP servers
|
|
117
|
+
acfm agents install-mcps
|
|
118
|
+
|
|
119
|
+
# Start collaborative runtime manually
|
|
120
|
+
acfm agents start --task "design and implement feature X"
|
|
121
|
+
|
|
122
|
+
# Resume/list/export operations
|
|
123
|
+
acfm agents resume
|
|
124
|
+
acfm agents list
|
|
125
|
+
acfm agents export --format md --out synapse-session.md
|
|
126
|
+
```
|
|
127
|
+
|
|
101
128
|
|
|
102
129
|
### OpenSpec Skills (The heart of the framework)
|
|
103
130
|
|
package/package.json
CHANGED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { existsSync } from 'node:fs';
|
|
2
|
+
import { mkdir, readFile, writeFile } from 'node:fs/promises';
|
|
3
|
+
import { homedir } from 'node:os';
|
|
4
|
+
import { join } from 'node:path';
|
|
5
|
+
import { sanitizeRoleModels, normalizeModelId } from './model-selection.js';
|
|
6
|
+
|
|
7
|
+
const ACFM_DIR = join(homedir(), '.acfm');
|
|
8
|
+
const CONFIG_PATH = join(ACFM_DIR, 'config.json');
|
|
9
|
+
|
|
10
|
+
function normalizeConfig(raw) {
|
|
11
|
+
const agents = raw?.agents && typeof raw.agents === 'object' ? raw.agents : {};
|
|
12
|
+
return {
|
|
13
|
+
agents: {
|
|
14
|
+
defaultModel: normalizeModelId(agents.defaultModel) || null,
|
|
15
|
+
defaultRoleModels: sanitizeRoleModels(agents.defaultRoleModels),
|
|
16
|
+
},
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export async function loadAgentsConfig() {
|
|
21
|
+
if (!existsSync(CONFIG_PATH)) {
|
|
22
|
+
return normalizeConfig({});
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
try {
|
|
26
|
+
const raw = JSON.parse(await readFile(CONFIG_PATH, 'utf8'));
|
|
27
|
+
return normalizeConfig(raw);
|
|
28
|
+
} catch {
|
|
29
|
+
return normalizeConfig({});
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export async function saveAgentsConfig(config) {
|
|
34
|
+
const normalized = normalizeConfig(config);
|
|
35
|
+
await mkdir(ACFM_DIR, { recursive: true });
|
|
36
|
+
await writeFile(CONFIG_PATH, JSON.stringify(normalized, null, 2) + '\n', 'utf8');
|
|
37
|
+
return normalized;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export async function updateAgentsConfig(mutator) {
|
|
41
|
+
const current = await loadAgentsConfig();
|
|
42
|
+
const next = await mutator(current);
|
|
43
|
+
return saveAgentsConfig(next);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export function getAgentsConfigPath() {
|
|
47
|
+
return CONFIG_PATH;
|
|
48
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { COLLAB_ROLES } from './constants.js';
|
|
2
|
+
|
|
3
|
+
export function normalizeModelId(value) {
|
|
4
|
+
if (typeof value !== 'string') return null;
|
|
5
|
+
const trimmed = value.trim();
|
|
6
|
+
return trimmed.length > 0 ? trimmed : null;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export function isValidModelId(value) {
|
|
10
|
+
const normalized = normalizeModelId(value);
|
|
11
|
+
if (!normalized) return false;
|
|
12
|
+
return normalized.includes('/');
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export function sanitizeRoleModels(input) {
|
|
16
|
+
const out = {};
|
|
17
|
+
if (!input || typeof input !== 'object') return out;
|
|
18
|
+
for (const role of COLLAB_ROLES) {
|
|
19
|
+
const normalized = normalizeModelId(input[role]);
|
|
20
|
+
if (normalized) out[role] = normalized;
|
|
21
|
+
}
|
|
22
|
+
return out;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export function resolveRoleModel(state, role, fallbackModel = null) {
|
|
26
|
+
const roleModels = sanitizeRoleModels(state?.roleModels);
|
|
27
|
+
const roleModel = roleModels[role] || null;
|
|
28
|
+
const globalModel = normalizeModelId(state?.model) || normalizeModelId(fallbackModel);
|
|
29
|
+
return roleModel || globalModel || null;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export function buildEffectiveRoleModels(state, fallbackModel = null) {
|
|
33
|
+
const effective = {};
|
|
34
|
+
for (const role of COLLAB_ROLES) {
|
|
35
|
+
effective[role] = resolveRoleModel(state, role, fallbackModel);
|
|
36
|
+
}
|
|
37
|
+
return effective;
|
|
38
|
+
}
|
|
@@ -22,7 +22,8 @@ function parseOpenCodeRunOutput(stdout) {
|
|
|
22
22
|
return stdout.trim();
|
|
23
23
|
}
|
|
24
24
|
|
|
25
|
-
export async function runOpenCodePrompt({ prompt, cwd, model, agent, timeoutMs = 180000 }) {
|
|
25
|
+
export async function runOpenCodePrompt({ prompt, cwd, model, agent, timeoutMs = 180000, binaryPath }) {
|
|
26
|
+
const binary = binaryPath || process.env.ACFM_OPENCODE_BIN || 'opencode';
|
|
26
27
|
const args = ['run', '--format', 'json'];
|
|
27
28
|
if (model) {
|
|
28
29
|
args.push('--model', model);
|
|
@@ -32,7 +33,7 @@ export async function runOpenCodePrompt({ prompt, cwd, model, agent, timeoutMs =
|
|
|
32
33
|
}
|
|
33
34
|
args.push('--', prompt);
|
|
34
35
|
|
|
35
|
-
const { stdout, stderr } = await execFileAsync(
|
|
36
|
+
const { stdout, stderr } = await execFileAsync(binary, args, {
|
|
36
37
|
cwd,
|
|
37
38
|
timeout: timeoutMs,
|
|
38
39
|
maxBuffer: 10 * 1024 * 1024,
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { buildAgentPrompt, ROLE_SYSTEM_PROMPTS } from './role-prompts.js';
|
|
2
2
|
import { runOpenCodePrompt } from './opencode-client.js';
|
|
3
3
|
import { nextRole, shouldStop } from './scheduler.js';
|
|
4
|
+
import { resolveRoleModel } from './model-selection.js';
|
|
4
5
|
import {
|
|
5
6
|
addAgentMessage,
|
|
6
7
|
loadSessionState,
|
|
@@ -42,11 +43,13 @@ export async function runTurn(sessionId, options = {}) {
|
|
|
42
43
|
const prompt = buildRuntimePrompt({ state, role: scheduled.role });
|
|
43
44
|
let content;
|
|
44
45
|
try {
|
|
46
|
+
const effectiveModel = resolveRoleModel(state, scheduled.role, options.model);
|
|
45
47
|
content = await runOpenCodePrompt({
|
|
46
48
|
prompt,
|
|
47
49
|
cwd: options.cwd || process.cwd(),
|
|
48
|
-
model:
|
|
50
|
+
model: effectiveModel,
|
|
49
51
|
agent: options.agent,
|
|
52
|
+
binaryPath: options.opencodeBin,
|
|
50
53
|
timeoutMs: options.timeoutMs,
|
|
51
54
|
});
|
|
52
55
|
} catch (error) {
|
|
@@ -105,11 +108,13 @@ export async function executeActiveTurn(sessionId, role, options = {}) {
|
|
|
105
108
|
const prompt = buildRuntimePrompt({ state, role });
|
|
106
109
|
let content;
|
|
107
110
|
try {
|
|
111
|
+
const effectiveModel = resolveRoleModel(state, role, options.model);
|
|
108
112
|
content = await runOpenCodePrompt({
|
|
109
113
|
prompt,
|
|
110
114
|
cwd: options.cwd || process.cwd(),
|
|
111
|
-
model:
|
|
115
|
+
model: effectiveModel,
|
|
112
116
|
agent: options.agent,
|
|
117
|
+
binaryPath: options.opencodeBin,
|
|
113
118
|
timeoutMs: options.timeoutMs,
|
|
114
119
|
});
|
|
115
120
|
} catch (error) {
|
|
@@ -153,11 +158,13 @@ export async function runWorkerIteration(sessionId, role, options = {}) {
|
|
|
153
158
|
const prompt = buildRuntimePrompt({ state, role });
|
|
154
159
|
let content;
|
|
155
160
|
try {
|
|
161
|
+
const effectiveModel = resolveRoleModel(state, role, options.model);
|
|
156
162
|
content = await runOpenCodePrompt({
|
|
157
163
|
prompt,
|
|
158
164
|
cwd: options.cwd || process.cwd(),
|
|
159
|
-
model:
|
|
165
|
+
model: effectiveModel,
|
|
160
166
|
agent: options.agent,
|
|
167
|
+
binaryPath: options.opencodeBin,
|
|
161
168
|
timeoutMs: options.timeoutMs,
|
|
162
169
|
});
|
|
163
170
|
} catch (error) {
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { spawn } from 'node:child_process';
|
|
2
|
+
import { dirname, resolve } from 'node:path';
|
|
3
|
+
import { fileURLToPath } from 'node:url';
|
|
4
|
+
import { COLLAB_ROLES } from './constants.js';
|
|
5
|
+
|
|
6
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
7
|
+
const runnerPath = resolve(__dirname, '../../bin/acfm.js');
|
|
8
|
+
|
|
9
|
+
export function roleLogPath(sessionDir, role) {
|
|
10
|
+
return resolve(sessionDir, `${role}.log`);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export function runTmux(command, args, options = {}) {
|
|
14
|
+
return new Promise((resolvePromise, rejectPromise) => {
|
|
15
|
+
const child = spawn(command, args, {
|
|
16
|
+
cwd: options.cwd || process.cwd(),
|
|
17
|
+
stdio: options.stdio || 'pipe',
|
|
18
|
+
env: process.env,
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
let stderr = '';
|
|
22
|
+
let stdout = '';
|
|
23
|
+
if (child.stderr) {
|
|
24
|
+
child.stderr.on('data', (chunk) => {
|
|
25
|
+
stderr += chunk.toString();
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
if (child.stdout) {
|
|
29
|
+
child.stdout.on('data', (chunk) => {
|
|
30
|
+
stdout += chunk.toString();
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
child.on('error', rejectPromise);
|
|
35
|
+
child.on('close', (code) => {
|
|
36
|
+
if (code === 0) {
|
|
37
|
+
resolvePromise({ stdout, stderr });
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
rejectPromise(new Error(stderr.trim() || `${command} exited with code ${code}`));
|
|
41
|
+
});
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export async function spawnTmuxSession({ sessionName, sessionDir, sessionId }) {
|
|
46
|
+
const role0 = COLLAB_ROLES[0];
|
|
47
|
+
await runTmux('tmux', [
|
|
48
|
+
'new-session',
|
|
49
|
+
'-d',
|
|
50
|
+
'-s',
|
|
51
|
+
sessionName,
|
|
52
|
+
'-n',
|
|
53
|
+
role0,
|
|
54
|
+
`bash -lc 'node "${runnerPath}" agents worker --session ${sessionId} --role ${role0} >> "${roleLogPath(sessionDir, role0)}" 2>&1'`,
|
|
55
|
+
]);
|
|
56
|
+
|
|
57
|
+
for (let idx = 1; idx < COLLAB_ROLES.length; idx += 1) {
|
|
58
|
+
const role = COLLAB_ROLES[idx];
|
|
59
|
+
await runTmux('tmux', [
|
|
60
|
+
'split-window',
|
|
61
|
+
'-t',
|
|
62
|
+
sessionName,
|
|
63
|
+
'-v',
|
|
64
|
+
`bash -lc 'node "${runnerPath}" agents worker --session ${sessionId} --role ${role} >> "${roleLogPath(sessionDir, role)}" 2>&1'`,
|
|
65
|
+
]);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
await runTmux('tmux', ['select-layout', '-t', sessionName, 'tiled']);
|
|
69
|
+
await runTmux('tmux', ['set-option', '-t', sessionName, 'pane-border-status', 'top']);
|
|
70
|
+
await runTmux('tmux', ['set-option', '-t', sessionName, 'pane-border-format', '#{pane_index}:#{pane_title}']);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export async function tmuxSessionExists(sessionName) {
|
|
74
|
+
try {
|
|
75
|
+
await runTmux('tmux', ['has-session', '-t', sessionName]);
|
|
76
|
+
return true;
|
|
77
|
+
} catch {
|
|
78
|
+
return false;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
@@ -8,6 +8,7 @@ import {
|
|
|
8
8
|
SESSION_ROOT_DIR,
|
|
9
9
|
CURRENT_SESSION_FILE,
|
|
10
10
|
} from './constants.js';
|
|
11
|
+
import { sanitizeRoleModels } from './model-selection.js';
|
|
11
12
|
|
|
12
13
|
function sleep(ms) {
|
|
13
14
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
@@ -53,6 +54,8 @@ function initialState(task, options = {}) {
|
|
|
53
54
|
roles: options.roles?.length ? options.roles : COLLAB_ROLES,
|
|
54
55
|
workingDirectory: options.workingDirectory || process.cwd(),
|
|
55
56
|
model: options.model || null,
|
|
57
|
+
roleModels: sanitizeRoleModels(options.roleModels),
|
|
58
|
+
opencodeBin: options.opencodeBin || null,
|
|
56
59
|
tmuxSessionName: options.tmuxSessionName || null,
|
|
57
60
|
messages: [
|
|
58
61
|
{
|