@syntesseraai/opencode-feature-factory 0.7.3 → 0.9.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/README.md +14 -0
- package/agents/building.md +24 -0
- package/agents/documenting.md +20 -1
- package/agents/feature-factory.md +16 -7
- package/agents/ff-research.md +26 -0
- package/agents/planning.md +23 -0
- package/agents/reviewing.md +16 -0
- package/bin/ff-deploy.js +1 -1
- package/dist/plugin-config.js +1 -1
- package/dist/tools/index.d.ts +2 -2
- package/dist/tools/index.js +4 -2
- package/dist/tools/list-models.d.ts +13 -0
- package/dist/tools/list-models.js +67 -0
- package/dist/tools/mini-loop.js +11 -11
- package/dist/workflow/fan-out.d.ts +28 -1
- package/dist/workflow/fan-out.js +12 -5
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -56,6 +56,20 @@ These colors are intentionally unique to avoid collisions in OpenCode agent UIs
|
|
|
56
56
|
- Coordinator and synthesis model defaults to ChatGPT 5.4 via frontmatter `model:` declarations in orchestrator commands.
|
|
57
57
|
- All orchestrator commands include an explicit **orchestrator constraint**: they must NOT directly read, edit, modify, write, or create any code/config/repository files — they only dispatch sub-commands, pass structured data via `{as:name}` / `$RESULT[name]`, and evaluate gate/loop conditions.
|
|
58
58
|
|
|
59
|
+
## Tools
|
|
60
|
+
|
|
61
|
+
The plugin exposes three MCP tools via the `feature-factory` agent:
|
|
62
|
+
|
|
63
|
+
| Tool | Description |
|
|
64
|
+
|------|-------------|
|
|
65
|
+
| `ff_pipeline` | Full multi-model pipeline: planning → build → review → documentation. Uses hardcoded per-role model defaults (see Model Routing below). |
|
|
66
|
+
| `ff_mini_loop` | Lightweight build → review → documentation loop. **Does not hardcode model defaults** — all roles inherit the current session model when omitted. |
|
|
67
|
+
| `ff_list_models` | Read-only discovery tool. Queries the OpenCode SDK to list all available providers, models, capability badges, connected status, and defaults. |
|
|
68
|
+
|
|
69
|
+
### Mini-Loop Model Inheritance
|
|
70
|
+
|
|
71
|
+
When `ff_mini_loop` model parameters are omitted, child sessions inherit the parent session's model (the SDK `model` field is omitted entirely from the prompt body). The `doc_model` has a cascade: if `build_model` is explicitly set but `doc_model` is not, the documentation step uses the same model as build. Users can call `ff_list_models` to discover available `provider/model` strings before overriding.
|
|
72
|
+
|
|
59
73
|
## Command Tree
|
|
60
74
|
|
|
61
75
|
- `/pipeline/start`
|
package/agents/building.md
CHANGED
|
@@ -7,6 +7,7 @@ tools:
|
|
|
7
7
|
write: true
|
|
8
8
|
edit: true
|
|
9
9
|
bash: true
|
|
10
|
+
hashline_edit: true
|
|
10
11
|
skill: true
|
|
11
12
|
task: true
|
|
12
13
|
permission:
|
|
@@ -33,6 +34,29 @@ You are the building specialist.
|
|
|
33
34
|
- Do not rely on intermediate artifact files for pipeline progression.
|
|
34
35
|
- Persist only when explicitly requested by the user.
|
|
35
36
|
|
|
37
|
+
## Hashline Workflow (Required)
|
|
38
|
+
|
|
39
|
+
File reads and edits use hashline-annotated tools. The `read` tool returns lines annotated with `#HL <line>:<hash>|<content>` and a `#HL REV:<hash>` header. Follow this workflow:
|
|
40
|
+
|
|
41
|
+
1. **Always `read` before editing.** Note the `REV` value from the `#HL REV:<hash>` header — you need it for edits.
|
|
42
|
+
2. **Use `hashline_edit`** for targeted, hash-referenced edits. Operations: `replace`, `delete`, `insert_before`, `insert_after`. Example:
|
|
43
|
+
```json
|
|
44
|
+
{ "path": "src/app.ts", "operation": "replace", "startRef": "5:a3f", "replacement": "const value = 2", "fileRev": "72c4946c" }
|
|
45
|
+
```
|
|
46
|
+
3. **Use built-in `edit`/`write`** for standard edits — hashline prefixes are automatically stripped before the tool executes.
|
|
47
|
+
4. **After any edit/write**, re-read the file to get fresh refs before further edits.
|
|
48
|
+
|
|
49
|
+
Never fabricate refs — always use exactly the refs returned by `read`.
|
|
50
|
+
|
|
51
|
+
## Semantic Code Search
|
|
52
|
+
|
|
53
|
+
Use `cocoindex-code_search` for semantic code search when you need to:
|
|
54
|
+
- Find implementations by meaning, not just text matching (e.g., "authentication logic", "database connection handling")
|
|
55
|
+
- Locate related code without knowing exact names or keywords
|
|
56
|
+
- Understand how features work across the codebase
|
|
57
|
+
|
|
58
|
+
Prefer this over `grep` when searching by concept rather than exact text.
|
|
59
|
+
|
|
36
60
|
## Execution Rules
|
|
37
61
|
|
|
38
62
|
1. Implement task batches in dependency order.
|
package/agents/documenting.md
CHANGED
|
@@ -6,7 +6,8 @@ tools:
|
|
|
6
6
|
read: true
|
|
7
7
|
write: true
|
|
8
8
|
edit: true
|
|
9
|
-
bash:
|
|
9
|
+
bash: false
|
|
10
|
+
hashline_edit: true
|
|
10
11
|
skill: true
|
|
11
12
|
task: true
|
|
12
13
|
permission:
|
|
@@ -25,6 +26,24 @@ You are the documenting specialist.
|
|
|
25
26
|
- Keep docs concise, consistent, and free of stale references.
|
|
26
27
|
- Return a structured summary for documentation review.
|
|
27
28
|
|
|
29
|
+
## Hashline Workflow (Required)
|
|
30
|
+
|
|
31
|
+
File reads and edits use hashline-annotated tools. The `read` tool returns lines annotated with `#HL <line>:<hash>|<content>` and a `#HL REV:<hash>` header. Follow this workflow:
|
|
32
|
+
|
|
33
|
+
1. **Always `read` before editing.** Note the `REV` value — you need it for edits.
|
|
34
|
+
2. **Use `hashline_edit`** for targeted, hash-referenced edits. Operations: `replace`, `delete`, `insert_before`, `insert_after`. Example:
|
|
35
|
+
```json
|
|
36
|
+
{ "path": "docs/FILE.md", "operation": "replace", "startRef": "5:a3f", "replacement": "Updated text", "fileRev": "72c4946c" }
|
|
37
|
+
```
|
|
38
|
+
3. **Use built-in `edit`/`write`** for standard edits — hashline prefixes are automatically stripped.
|
|
39
|
+
4. **After any edit/write**, re-read the file to get fresh refs before further edits.
|
|
40
|
+
|
|
41
|
+
Never fabricate refs — always use exactly the refs returned by `read`.
|
|
42
|
+
|
|
43
|
+
## Semantic Code Search
|
|
44
|
+
|
|
45
|
+
Use `cocoindex-code_search` to understand how code actually works before documenting it. Search by meaning (e.g., "how are users authenticated", "error handling middleware") rather than exact text.
|
|
46
|
+
|
|
28
47
|
## Rules
|
|
29
48
|
|
|
30
49
|
1. Do not change product behavior while editing docs.
|
|
@@ -7,10 +7,12 @@ tools:
|
|
|
7
7
|
write: false
|
|
8
8
|
edit: false
|
|
9
9
|
bash: false
|
|
10
|
+
hashline_edit: false
|
|
10
11
|
skill: true
|
|
11
12
|
task: true
|
|
12
13
|
ff_pipeline: true
|
|
13
14
|
ff_mini_loop: true
|
|
15
|
+
ff_list_models: true
|
|
14
16
|
permission:
|
|
15
17
|
skill:
|
|
16
18
|
'*': allow
|
|
@@ -27,6 +29,12 @@ You are the Feature Factory workflow assistant. Your job is to guide the user th
|
|
|
27
29
|
|
|
28
30
|
Work through this process step by step. Do NOT skip steps or launch a tool until all steps are complete.
|
|
29
31
|
|
|
32
|
+
## Semantic Code Search
|
|
33
|
+
|
|
34
|
+
Use `cocoindex-code_search` to quickly understand the codebase when clarifying requirements:
|
|
35
|
+
- Search by meaning (e.g., "user authentication flow", "API rate limiting") to understand existing architecture
|
|
36
|
+
- Use this to give informed answers when the user asks about current behavior
|
|
37
|
+
|
|
30
38
|
---
|
|
31
39
|
|
|
32
40
|
## Step 1: Understand the request
|
|
@@ -64,7 +72,7 @@ Ask the user which workflow they prefer. If they are unsure, recommend one based
|
|
|
64
72
|
|
|
65
73
|
Present the default models that will be used for the chosen workflow:
|
|
66
74
|
|
|
67
|
-
**Pipeline defaults:**
|
|
75
|
+
**Pipeline defaults:** (hardcoded per-role model assignments)
|
|
68
76
|
- Planning fan-out: opus (anthropic/claude-opus-4-6), gemini (opencode/gemini-3.1-pro), codex (openai/gpt-5.3-codex)
|
|
69
77
|
- Review fan-out: same as planning
|
|
70
78
|
- Orchestrator (synthesis/triage): openai/gpt-5.4
|
|
@@ -73,13 +81,14 @@ Present the default models that will be used for the chosen workflow:
|
|
|
73
81
|
- Documentation: openai/gpt-5.3-codex
|
|
74
82
|
- Doc review: opencode/gemini-3.1-pro
|
|
75
83
|
|
|
76
|
-
**Mini-loop defaults:**
|
|
77
|
-
-
|
|
78
|
-
-
|
|
79
|
-
-
|
|
80
|
-
|
|
84
|
+
**Mini-loop defaults:** (inherits the current session model)
|
|
85
|
+
- All roles (build, review, documentation, doc review) default to the **current session model** — no hardcoded model is forced.
|
|
86
|
+
- This means the mini-loop automatically uses whatever model you're currently chatting with.
|
|
87
|
+
- You can override any individual role if desired (e.g., use a different model for review).
|
|
88
|
+
|
|
89
|
+
For the **Pipeline**, ask: "Would you like to use these default models, or would you like to override any of them?"
|
|
81
90
|
|
|
82
|
-
|
|
91
|
+
For the **Mini-loop**, ask: "The mini-loop will use your current session model for all roles by default. Would you like to override any specific roles (build, review, doc, doc_review)? You can call `ff_list_models` to see available providers and models."
|
|
83
92
|
|
|
84
93
|
If they want to override, collect the provider/model strings for each role they want to change.
|
|
85
94
|
|
package/agents/ff-research.md
CHANGED
|
@@ -7,6 +7,7 @@ tools:
|
|
|
7
7
|
write: false
|
|
8
8
|
edit: false
|
|
9
9
|
bash: false
|
|
10
|
+
hashline_edit: false
|
|
10
11
|
skill: true
|
|
11
12
|
task: false
|
|
12
13
|
permission:
|
|
@@ -22,6 +23,31 @@ You are the research specialist.
|
|
|
22
23
|
- Compare trade-offs and recommend practical defaults.
|
|
23
24
|
- Provide source-backed outputs that planning/building/reviewing can apply directly.
|
|
24
25
|
|
|
26
|
+
## Available MCP Tools
|
|
27
|
+
|
|
28
|
+
You have access to powerful external research tools. **Use them proactively:**
|
|
29
|
+
|
|
30
|
+
### Web Search & Reading
|
|
31
|
+
- **`jina-ai_search_web`** — Search the web for current information, docs, articles. Use for up-to-date library info, best practices, changelogs.
|
|
32
|
+
- **`jina-ai_read_url`** — Read and extract content from any URL. Use to read official documentation, blog posts, READMEs.
|
|
33
|
+
- **`jina-ai_expand_query`** — Expand search queries for broader coverage.
|
|
34
|
+
- **`jina-ai_parallel_search_web`** — Run multiple searches in parallel for comprehensive coverage.
|
|
35
|
+
- **`jina-ai_parallel_read_url`** — Read multiple URLs in parallel.
|
|
36
|
+
|
|
37
|
+
### Library Documentation
|
|
38
|
+
- **`context7_resolve-library-id`** — Resolve a library name to a Context7 ID. Call this first before querying docs.
|
|
39
|
+
- **`context7_query-docs`** — Query up-to-date library documentation with code examples. Excellent for API usage, configuration, and best practices.
|
|
40
|
+
|
|
41
|
+
### Code Examples
|
|
42
|
+
- **`gh_grep_searchGitHub`** — Find real-world code examples from public GitHub repos. Search for literal code patterns (e.g., `useState(`, `import React from`), NOT keywords. Use to see how real projects implement specific patterns.
|
|
43
|
+
|
|
44
|
+
### Academic Papers
|
|
45
|
+
- **`jina-ai_search_arxiv`** — Search arXiv for research papers (AI, CS, physics, math).
|
|
46
|
+
- **`jina-ai_search_ssrn`** — Search SSRN for social science research.
|
|
47
|
+
|
|
48
|
+
### Semantic Code Search
|
|
49
|
+
- **`cocoindex-code_search`** — Search the local codebase by meaning. Use to understand the project's existing patterns before recommending changes.
|
|
50
|
+
|
|
25
51
|
## Method
|
|
26
52
|
|
|
27
53
|
1. Load `ff-research-methods`.
|
package/agents/planning.md
CHANGED
|
@@ -7,6 +7,7 @@ tools:
|
|
|
7
7
|
write: false
|
|
8
8
|
edit: false
|
|
9
9
|
bash: false
|
|
10
|
+
hashline_edit: false
|
|
10
11
|
skill: true
|
|
11
12
|
task: true
|
|
12
13
|
permission:
|
|
@@ -25,6 +26,28 @@ You are the planning specialist.
|
|
|
25
26
|
- Identify risks, assumptions, and validation strategy.
|
|
26
27
|
- Apply planning gate criteria and emit explicit status lines.
|
|
27
28
|
|
|
29
|
+
## Hashline Workflow (Required)
|
|
30
|
+
|
|
31
|
+
Use the `read` tool to inspect files. Lines are annotated with `#HL <line>:<hash>|<content>` and a `#HL REV:<hash>` header. Use these refs when planning edit operations — include the `startRef` values in your implementation steps so the builder can apply them directly.
|
|
32
|
+
|
|
33
|
+
You are a read-only agent — you do not write or edit files.
|
|
34
|
+
|
|
35
|
+
## Semantic Code Search
|
|
36
|
+
|
|
37
|
+
Use `cocoindex-code_search` for semantic code search when planning:
|
|
38
|
+
- Understand existing architecture by meaning (e.g., "authentication logic", "API routing")
|
|
39
|
+
- Find related implementations before proposing changes
|
|
40
|
+
- Verify assumptions about how code works
|
|
41
|
+
|
|
42
|
+
Prefer this over `grep` when searching by concept rather than exact text.
|
|
43
|
+
|
|
44
|
+
## External Research
|
|
45
|
+
|
|
46
|
+
Use `@ff-research` for external/library uncertainty. The research agent has access to:
|
|
47
|
+
- `jina-ai_search_web` / `jina-ai_read_url` for web search and documentation
|
|
48
|
+
- `context7_query-docs` for library-specific documentation
|
|
49
|
+
- `gh_grep_searchGitHub` for real-world code examples
|
|
50
|
+
|
|
28
51
|
## Operating Mode
|
|
29
52
|
|
|
30
53
|
- Prefer deterministic, structured output sections.
|
package/agents/reviewing.md
CHANGED
|
@@ -7,6 +7,7 @@ tools:
|
|
|
7
7
|
write: false
|
|
8
8
|
edit: false
|
|
9
9
|
bash: false
|
|
10
|
+
hashline_edit: false
|
|
10
11
|
skill: true
|
|
11
12
|
task: true
|
|
12
13
|
permission:
|
|
@@ -25,6 +26,21 @@ You are the unified reviewing specialist.
|
|
|
25
26
|
- Apply scope based on context: acceptance, code quality, security, architecture, documentation.
|
|
26
27
|
- Return actionable findings with severity and confidence.
|
|
27
28
|
|
|
29
|
+
## Hashline Workflow (Required)
|
|
30
|
+
|
|
31
|
+
Use the `read` tool to inspect files. Lines are annotated with `#HL <line>:<hash>|<content>` and a `#HL REV:<hash>` header. Use these refs to cite specific lines in your review findings.
|
|
32
|
+
|
|
33
|
+
You are a read-only agent — you do not write or edit files.
|
|
34
|
+
|
|
35
|
+
## Semantic Code Search
|
|
36
|
+
|
|
37
|
+
Use `cocoindex-code_search` for semantic code search when reviewing:
|
|
38
|
+
- Search by meaning to find related code (e.g., "input validation", "access control checks")
|
|
39
|
+
- Verify that implementations match architectural patterns across the codebase
|
|
40
|
+
- Find similar code to check for consistency
|
|
41
|
+
|
|
42
|
+
Prefer this over `grep` when searching by concept rather than exact text.
|
|
43
|
+
|
|
28
44
|
## Skills to Load by Scope
|
|
29
45
|
|
|
30
46
|
- `ff-reviewing-code-quality`
|
package/bin/ff-deploy.js
CHANGED
|
@@ -57,7 +57,7 @@ const DEFAULT_PLUGINS = [
|
|
|
57
57
|
'@franlol/opencode-md-table-formatter@latest',
|
|
58
58
|
'@spoons-and-mirrors/subtask2@latest',
|
|
59
59
|
'opencode-pty@latest',
|
|
60
|
-
'
|
|
60
|
+
'opencode-hashline@latest',
|
|
61
61
|
];
|
|
62
62
|
|
|
63
63
|
function getPackageBaseName(plugin) {
|
package/dist/plugin-config.js
CHANGED
|
@@ -10,7 +10,7 @@ export const DEFAULT_PLUGINS = [
|
|
|
10
10
|
'@franlol/opencode-md-table-formatter@latest',
|
|
11
11
|
'@spoons-and-mirrors/subtask2@latest',
|
|
12
12
|
'opencode-pty@latest',
|
|
13
|
-
'
|
|
13
|
+
'opencode-hashline@latest',
|
|
14
14
|
];
|
|
15
15
|
/**
|
|
16
16
|
* Extract the base package name from a plugin specifier, stripping the
|
package/dist/tools/index.d.ts
CHANGED
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
* Tool registry for Feature Factory.
|
|
3
3
|
*
|
|
4
4
|
* Exports a function that creates all FF tools given the SDK client.
|
|
5
|
-
* Only entrypoint tools (pipeline, mini-loop)
|
|
5
|
+
* Only entrypoint tools (pipeline, mini-loop) and discovery tools
|
|
6
6
|
* Internal workflow steps are orchestrated programmatically, not as
|
|
7
|
-
* individually callable tools.
|
|
7
|
+
* individually callable tools. The list-models tool is a read-only discovery helper.
|
|
8
8
|
*/
|
|
9
9
|
import type { ToolDefinition } from '@opencode-ai/plugin/tool';
|
|
10
10
|
import type { Client } from '../workflow/fan-out.js';
|
package/dist/tools/index.js
CHANGED
|
@@ -2,12 +2,13 @@
|
|
|
2
2
|
* Tool registry for Feature Factory.
|
|
3
3
|
*
|
|
4
4
|
* Exports a function that creates all FF tools given the SDK client.
|
|
5
|
-
* Only entrypoint tools (pipeline, mini-loop)
|
|
5
|
+
* Only entrypoint tools (pipeline, mini-loop) and discovery tools
|
|
6
6
|
* Internal workflow steps are orchestrated programmatically, not as
|
|
7
|
-
* individually callable tools.
|
|
7
|
+
* individually callable tools. The list-models tool is a read-only discovery helper.
|
|
8
8
|
*/
|
|
9
9
|
import { createPipelineTool } from './pipeline.js';
|
|
10
10
|
import { createMiniLoopTool } from './mini-loop.js';
|
|
11
|
+
import { createListModelsTool } from './list-models.js';
|
|
11
12
|
/**
|
|
12
13
|
* Build the tool map to be merged into the plugin's `Hooks.tool` output.
|
|
13
14
|
*
|
|
@@ -17,5 +18,6 @@ export function createWorkflowTools(client) {
|
|
|
17
18
|
return {
|
|
18
19
|
ff_pipeline: createPipelineTool(client),
|
|
19
20
|
ff_mini_loop: createMiniLoopTool(client),
|
|
21
|
+
ff_list_models: createListModelsTool(client),
|
|
20
22
|
};
|
|
21
23
|
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ff_list_models — Discovery tool for available providers and models.
|
|
3
|
+
*
|
|
4
|
+
* Read-only tool that queries the OpenCode SDK to list all available
|
|
5
|
+
* providers and their models, so users can see what's available before
|
|
6
|
+
* overriding mini-loop or pipeline model parameters.
|
|
7
|
+
*/
|
|
8
|
+
import type { Client } from '../workflow/fan-out.js';
|
|
9
|
+
export declare function createListModelsTool(client: Client): {
|
|
10
|
+
description: string;
|
|
11
|
+
args: {};
|
|
12
|
+
execute(args: Record<string, never>, context: import("@opencode-ai/plugin/tool").ToolContext): Promise<string>;
|
|
13
|
+
};
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ff_list_models — Discovery tool for available providers and models.
|
|
3
|
+
*
|
|
4
|
+
* Read-only tool that queries the OpenCode SDK to list all available
|
|
5
|
+
* providers and their models, so users can see what's available before
|
|
6
|
+
* overriding mini-loop or pipeline model parameters.
|
|
7
|
+
*/
|
|
8
|
+
import { tool } from '@opencode-ai/plugin/tool';
|
|
9
|
+
// ---------------------------------------------------------------------------
|
|
10
|
+
// Tool factory
|
|
11
|
+
// ---------------------------------------------------------------------------
|
|
12
|
+
export function createListModelsTool(client) {
|
|
13
|
+
return tool({
|
|
14
|
+
description: 'List all available AI providers and their models. ' +
|
|
15
|
+
'Use this to discover which provider/model strings can be passed to ff_pipeline or ff_mini_loop.',
|
|
16
|
+
args: {},
|
|
17
|
+
async execute() {
|
|
18
|
+
const response = await client.provider.list();
|
|
19
|
+
const data = response.data;
|
|
20
|
+
if (!data) {
|
|
21
|
+
return 'Unable to retrieve provider list from the OpenCode SDK.';
|
|
22
|
+
}
|
|
23
|
+
const { all: providers, connected, default: defaults } = data;
|
|
24
|
+
const lines = ['# Available Providers and Models\n'];
|
|
25
|
+
// Show default model assignments
|
|
26
|
+
if (defaults && Object.keys(defaults).length > 0) {
|
|
27
|
+
lines.push('## Defaults\n');
|
|
28
|
+
for (const [role, model] of Object.entries(defaults)) {
|
|
29
|
+
lines.push(`- **${role}**: ${model}`);
|
|
30
|
+
}
|
|
31
|
+
lines.push('');
|
|
32
|
+
}
|
|
33
|
+
// Show connected providers
|
|
34
|
+
if (connected.length > 0) {
|
|
35
|
+
lines.push(`## Connected Providers\n`);
|
|
36
|
+
lines.push(connected.map((p) => `\`${p}\``).join(', '));
|
|
37
|
+
lines.push('');
|
|
38
|
+
}
|
|
39
|
+
// List all providers and their models
|
|
40
|
+
for (const provider of providers) {
|
|
41
|
+
const isConnected = connected.includes(provider.id);
|
|
42
|
+
const statusBadge = isConnected ? '✅' : '⚠️ (not connected)';
|
|
43
|
+
lines.push(`## ${provider.name} ${statusBadge}\n`);
|
|
44
|
+
lines.push(`Provider ID: \`${provider.id}\`\n`);
|
|
45
|
+
const modelEntries = Object.entries(provider.models);
|
|
46
|
+
if (modelEntries.length === 0) {
|
|
47
|
+
lines.push('_No models available._\n');
|
|
48
|
+
continue;
|
|
49
|
+
}
|
|
50
|
+
lines.push('| Model ID | Name | Reasoning | Tool Calls | Attachments |');
|
|
51
|
+
lines.push('|----------|------|-----------|------------|-------------|');
|
|
52
|
+
for (const [, model] of modelEntries) {
|
|
53
|
+
const flags = [
|
|
54
|
+
model.reasoning ? '✅' : '—',
|
|
55
|
+
model.tool_call ? '✅' : '—',
|
|
56
|
+
model.attachment ? '✅' : '—',
|
|
57
|
+
];
|
|
58
|
+
lines.push(`| \`${provider.id}/${model.id}\` | ${model.name} | ${flags[0]} | ${flags[1]} | ${flags[2]} |`);
|
|
59
|
+
}
|
|
60
|
+
lines.push('');
|
|
61
|
+
}
|
|
62
|
+
lines.push('---\n' +
|
|
63
|
+
'Use the `provider_id/model_id` format when overriding models in `ff_mini_loop` or `ff_pipeline`.');
|
|
64
|
+
return lines.join('\n');
|
|
65
|
+
},
|
|
66
|
+
});
|
|
67
|
+
}
|
package/dist/tools/mini-loop.js
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* Implements a build/review loop, then a documentation loop.
|
|
6
6
|
*/
|
|
7
7
|
import { tool } from '@opencode-ai/plugin/tool';
|
|
8
|
-
import { promptSession, evaluateMiniLoopImplGate, evaluateMiniLoopDocGate,
|
|
8
|
+
import { promptSession, evaluateMiniLoopImplGate, evaluateMiniLoopDocGate, parseModelString, } from '../workflow/orchestrator.js';
|
|
9
9
|
import { miniBuildPrompt, miniReviewPrompt, documentPrompt, docReviewPrompt } from './prompts.js';
|
|
10
10
|
import { parseMiniReview, parseDocReview } from './parsers.js';
|
|
11
11
|
// ---------------------------------------------------------------------------
|
|
@@ -16,7 +16,7 @@ export function createMiniLoopTool(client) {
|
|
|
16
16
|
return tool({
|
|
17
17
|
description: 'Run the Feature Factory mini-loop: build → review (with rework loop) → documentation. ' +
|
|
18
18
|
'Lighter weight than the full pipeline — no multi-model planning phase. ' +
|
|
19
|
-
'All model parameters are optional
|
|
19
|
+
'All model parameters are optional — when omitted, child sessions inherit the current session model.',
|
|
20
20
|
args: {
|
|
21
21
|
requirements: tool.schema
|
|
22
22
|
.string()
|
|
@@ -24,39 +24,39 @@ export function createMiniLoopTool(client) {
|
|
|
24
24
|
build_model: tool.schema
|
|
25
25
|
.string()
|
|
26
26
|
.optional()
|
|
27
|
-
.describe('provider/model for building and implementation.
|
|
27
|
+
.describe('provider/model for building and implementation. When omitted, inherits the session model.'),
|
|
28
28
|
review_model: tool.schema
|
|
29
29
|
.string()
|
|
30
30
|
.optional()
|
|
31
|
-
.describe('provider/model for implementation review.
|
|
31
|
+
.describe('provider/model for implementation review. When omitted, inherits the session model.'),
|
|
32
32
|
doc_model: tool.schema
|
|
33
33
|
.string()
|
|
34
34
|
.optional()
|
|
35
|
-
.describe('provider/model for documentation writing.
|
|
35
|
+
.describe('provider/model for documentation writing. When omitted, defaults to build_model if provided, otherwise inherits the session model.'),
|
|
36
36
|
doc_review_model: tool.schema
|
|
37
37
|
.string()
|
|
38
38
|
.optional()
|
|
39
|
-
.describe('provider/model for documentation review.
|
|
39
|
+
.describe('provider/model for documentation review. When omitted, inherits the session model.'),
|
|
40
40
|
},
|
|
41
41
|
async execute(args, context) {
|
|
42
42
|
const totalStartMs = Date.now();
|
|
43
43
|
const sessionId = context.sessionID;
|
|
44
44
|
const { requirements } = args;
|
|
45
|
-
// Resolve models — use provided overrides or
|
|
45
|
+
// Resolve models — use provided overrides or undefined (inherit session model)
|
|
46
46
|
const buildModel = args.build_model
|
|
47
47
|
? parseModelString(args.build_model)
|
|
48
|
-
:
|
|
48
|
+
: undefined;
|
|
49
49
|
const reviewModel = args.review_model
|
|
50
50
|
? parseModelString(args.review_model)
|
|
51
|
-
:
|
|
51
|
+
: undefined;
|
|
52
52
|
const docModel = args.doc_model
|
|
53
53
|
? parseModelString(args.doc_model)
|
|
54
54
|
: args.build_model
|
|
55
55
|
? buildModel
|
|
56
|
-
:
|
|
56
|
+
: undefined;
|
|
57
57
|
const docReviewModel = args.doc_review_model
|
|
58
58
|
? parseModelString(args.doc_review_model)
|
|
59
|
-
:
|
|
59
|
+
: undefined;
|
|
60
60
|
const report = [];
|
|
61
61
|
const addReport = (phase, msg) => {
|
|
62
62
|
report.push(`## ${phase}\n${msg}`);
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
import type { NamedModel, ModelId } from './types.js';
|
|
13
13
|
/**
|
|
14
14
|
* Opaque client type — the plugin receives `ReturnType<typeof createOpencodeClient>`
|
|
15
|
-
* but we only need
|
|
15
|
+
* but we only need a subset of the SDK surface.
|
|
16
16
|
* We keep it loosely typed so this module doesn't import the full SDK.
|
|
17
17
|
*/
|
|
18
18
|
export type Client = {
|
|
@@ -53,6 +53,33 @@ export type Client = {
|
|
|
53
53
|
};
|
|
54
54
|
}>;
|
|
55
55
|
};
|
|
56
|
+
provider: {
|
|
57
|
+
list(options?: {
|
|
58
|
+
query?: {
|
|
59
|
+
directory?: string;
|
|
60
|
+
};
|
|
61
|
+
}): Promise<{
|
|
62
|
+
data?: {
|
|
63
|
+
all: Array<{
|
|
64
|
+
id: string;
|
|
65
|
+
name: string;
|
|
66
|
+
models: {
|
|
67
|
+
[key: string]: {
|
|
68
|
+
id: string;
|
|
69
|
+
name: string;
|
|
70
|
+
attachment: boolean;
|
|
71
|
+
reasoning: boolean;
|
|
72
|
+
tool_call: boolean;
|
|
73
|
+
};
|
|
74
|
+
};
|
|
75
|
+
}>;
|
|
76
|
+
connected: Array<string>;
|
|
77
|
+
default: {
|
|
78
|
+
[key: string]: string;
|
|
79
|
+
};
|
|
80
|
+
};
|
|
81
|
+
}>;
|
|
82
|
+
};
|
|
56
83
|
};
|
|
57
84
|
/** Extract all text parts from an SDK prompt response. */
|
|
58
85
|
export declare function extractText(parts: Array<{
|
package/dist/workflow/fan-out.js
CHANGED
|
@@ -41,13 +41,20 @@ async function promptInChildSession(client, parentSessionId, prompt, options) {
|
|
|
41
41
|
throw new Error('Failed to create child session');
|
|
42
42
|
}
|
|
43
43
|
// 2. Send the prompt to the child session
|
|
44
|
+
// When model is undefined, omit it entirely so the child session
|
|
45
|
+
// inherits the parent session's model (SDK default behavior).
|
|
46
|
+
const body = {
|
|
47
|
+
parts: [{ type: 'text', text: prompt }],
|
|
48
|
+
};
|
|
49
|
+
if (options?.model) {
|
|
50
|
+
body.model = options.model;
|
|
51
|
+
}
|
|
52
|
+
if (options?.agent) {
|
|
53
|
+
body.agent = options.agent;
|
|
54
|
+
}
|
|
44
55
|
const response = await client.session.prompt({
|
|
45
56
|
path: { id: childId },
|
|
46
|
-
body
|
|
47
|
-
model: options?.model,
|
|
48
|
-
agent: options?.agent,
|
|
49
|
-
parts: [{ type: 'text', text: prompt }],
|
|
50
|
-
},
|
|
57
|
+
body,
|
|
51
58
|
});
|
|
52
59
|
// 3. Extract and return the text
|
|
53
60
|
return extractText(response.data?.parts ?? []);
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://json.schemastore.org/package.json",
|
|
3
3
|
"name": "@syntesseraai/opencode-feature-factory",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.9.0",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"description": "OpenCode plugin for Feature Factory agents - provides sub-agents and skills for validation, review, security, and architecture assessment",
|
|
7
7
|
"license": "MIT",
|