opencode-akane 0.1.1 → 0.1.3
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 +28 -1
- package/dist/artifacts.d.ts +2 -1
- package/dist/artifacts.js +1 -0
- package/dist/config.d.ts +1 -1
- package/dist/config.js +55 -11
- package/dist/constants.d.ts +1 -0
- package/dist/constants.js +10 -0
- package/dist/plugin.js +12 -0
- package/dist/tools/akane-implement.d.ts +15 -0
- package/dist/tools/akane-implement.js +53 -0
- package/dist/tools/akane-plan-review.d.ts +15 -0
- package/dist/tools/akane-plan-review.js +53 -0
- package/dist/tools/akane-plan.d.ts +15 -0
- package/dist/tools/akane-plan.js +50 -0
- package/dist/tools/akane-review.d.ts +21 -0
- package/dist/tools/akane-review.js +57 -0
- package/dist/tools/akane-run.d.ts +24 -0
- package/dist/tools/akane-run.js +66 -0
- package/dist/tools/akane-synthesize.d.ts +15 -0
- package/dist/tools/akane-synthesize.js +53 -0
- package/dist/types.d.ts +5 -0
- package/dist/workflow.d.ts +55 -0
- package/dist/workflow.js +727 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -19,6 +19,13 @@ This repository now contains the first MVP skeleton for the plugin:
|
|
|
19
19
|
- `src/artifacts.ts`: `.opencode/akane/` artifact and `state.json` helpers
|
|
20
20
|
- `src/tools/akane-init.ts`: initializes the per-project workspace
|
|
21
21
|
- `src/tools/akane-stage-artifact.ts`: writes stage artifacts deterministically
|
|
22
|
+
- `src/workflow.ts`: child-session orchestration, stage prompts, and artifact handoff
|
|
23
|
+
- `src/tools/akane-plan.ts`: planner stage
|
|
24
|
+
- `src/tools/akane-plan-review.ts`: plan review stage
|
|
25
|
+
- `src/tools/akane-implement.ts`: implementation stage
|
|
26
|
+
- `src/tools/akane-review.ts`: review stage
|
|
27
|
+
- `src/tools/akane-synthesize.ts`: final synthesis stage
|
|
28
|
+
- `src/tools/akane-run.ts`: end-to-end MVP workflow runner
|
|
22
29
|
- `examples/akane.example.json`: example global Akane config
|
|
23
30
|
|
|
24
31
|
## Local development
|
|
@@ -31,6 +38,24 @@ bun run build
|
|
|
31
38
|
|
|
32
39
|
The build emits `dist/index.js` as the package entrypoint and also keeps `dist/akane.js` for local file-based linking.
|
|
33
40
|
|
|
41
|
+
## Available tools
|
|
42
|
+
|
|
43
|
+
Once the plugin is loaded in OpenCode, the current MVP exposes these tools:
|
|
44
|
+
|
|
45
|
+
- `akane_init`
|
|
46
|
+
- `akane_stage_artifact`
|
|
47
|
+
- `akane_plan`
|
|
48
|
+
- `akane_plan_review`
|
|
49
|
+
- `akane_implement`
|
|
50
|
+
- `akane_review`
|
|
51
|
+
- `akane_synthesize`
|
|
52
|
+
- `akane_run`
|
|
53
|
+
|
|
54
|
+
Notes:
|
|
55
|
+
|
|
56
|
+
- `akane_init` is optional because the stage tools lazily create `.opencode/akane/` on first use
|
|
57
|
+
- `akane_run` is the main MVP entrypoint when you want to test the full workflow
|
|
58
|
+
|
|
34
59
|
## Package install
|
|
35
60
|
|
|
36
61
|
For package-based installation, publish this repository to npm and add it to the OpenCode plugin array in `~/.config/opencode/opencode.json`:
|
|
@@ -40,12 +65,14 @@ For package-based installation, publish this repository to npm and add it to the
|
|
|
40
65
|
"$schema": "https://opencode.ai/config.json",
|
|
41
66
|
"plugin": [
|
|
42
67
|
"oh-my-opencode@latest",
|
|
43
|
-
"opencode-akane@
|
|
68
|
+
"opencode-akane@latest"
|
|
44
69
|
]
|
|
45
70
|
}
|
|
46
71
|
```
|
|
47
72
|
|
|
48
73
|
Akane still reads its runtime config from `~/.config/opencode/akane.json`.
|
|
74
|
+
If that file does not exist yet, the plugin now bootstraps it automatically on first load with the default config.
|
|
75
|
+
You only need to edit it when you want to override the default role or artifact settings.
|
|
49
76
|
|
|
50
77
|
## Publish flow
|
|
51
78
|
|
package/dist/artifacts.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { AkaneConfig, AkaneStageId, AkaneState, ArtifactWriteMode } from "./types.js";
|
|
1
|
+
import type { AkaneConfig, AkaneStageId, AkaneStageState, AkaneState, ArtifactWriteMode } from "./types.js";
|
|
2
2
|
export declare function resolveProjectRoot(input: {
|
|
3
3
|
directory: string;
|
|
4
4
|
worktree?: string;
|
|
@@ -30,6 +30,7 @@ export declare function writeStageArtifact(input: {
|
|
|
30
30
|
stage: AkaneStageId;
|
|
31
31
|
content: string;
|
|
32
32
|
mode: ArtifactWriteMode;
|
|
33
|
+
details?: Partial<Omit<AkaneStageState, "path" | "status" | "updatedAt">>;
|
|
33
34
|
}): Promise<{
|
|
34
35
|
artifactDir: string;
|
|
35
36
|
artifactPath: string;
|
package/dist/artifacts.js
CHANGED
package/dist/config.d.ts
CHANGED
|
@@ -3,7 +3,7 @@ type DeepPartial<T> = {
|
|
|
3
3
|
[K in keyof T]?: T[K] extends Array<infer U> ? U[] : T[K] extends Record<string, unknown> ? DeepPartial<T[K]> : T[K];
|
|
4
4
|
};
|
|
5
5
|
export declare function expandHome(inputPath: string): string;
|
|
6
|
-
export declare function defaultAkaneConfig(): AkaneConfig;
|
|
6
|
+
export declare function defaultAkaneConfig(configPath?: string): AkaneConfig;
|
|
7
7
|
export declare function mergeAkaneConfig(base: AkaneConfig, overrides: DeepPartial<AkaneConfig>): AkaneConfig;
|
|
8
8
|
export declare function loadAkaneConfig(configPath?: string): Promise<LoadedAkaneConfig>;
|
|
9
9
|
export {};
|
package/dist/config.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { readFile } from "node:fs/promises";
|
|
1
|
+
import { mkdir, readFile, writeFile } from "node:fs/promises";
|
|
2
2
|
import os from "node:os";
|
|
3
3
|
import path from "node:path";
|
|
4
4
|
import { AKANE_SERVICE_NAME, AKANE_STAGE_IDS, DEFAULT_ARTIFACT_DIR, DEFAULT_GLOBAL_CONFIG_PATH, DEFAULT_PLUGIN_OUTPUT_PATH, DEFAULT_ROLE_MODELS, DEFAULT_STAGE_FILES, DEFAULT_STAGE_ORDER, DEFAULT_STATE_FILE, } from "./constants.js";
|
|
@@ -14,12 +14,35 @@ export function expandHome(inputPath) {
|
|
|
14
14
|
}
|
|
15
15
|
return inputPath;
|
|
16
16
|
}
|
|
17
|
-
|
|
17
|
+
function formatAkaneConfig(config) {
|
|
18
|
+
return `${JSON.stringify(config, null, 2)}\n`;
|
|
19
|
+
}
|
|
20
|
+
async function readAkaneConfigFile(filePath) {
|
|
21
|
+
const raw = await readFile(filePath, "utf8");
|
|
22
|
+
return parseJsonFile(raw, filePath);
|
|
23
|
+
}
|
|
24
|
+
async function bootstrapAkaneConfigFile(filePath, config) {
|
|
25
|
+
await mkdir(path.dirname(filePath), { recursive: true });
|
|
26
|
+
try {
|
|
27
|
+
await writeFile(filePath, formatAkaneConfig(config), {
|
|
28
|
+
encoding: "utf8",
|
|
29
|
+
flag: "wx",
|
|
30
|
+
});
|
|
31
|
+
return true;
|
|
32
|
+
}
|
|
33
|
+
catch (error) {
|
|
34
|
+
if (error.code === "EEXIST") {
|
|
35
|
+
return false;
|
|
36
|
+
}
|
|
37
|
+
throw error;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
export function defaultAkaneConfig(configPath = DEFAULT_GLOBAL_CONFIG_PATH) {
|
|
18
41
|
return {
|
|
19
42
|
version: 1,
|
|
20
43
|
serviceName: AKANE_SERVICE_NAME,
|
|
21
44
|
pluginOutputPath: DEFAULT_PLUGIN_OUTPUT_PATH,
|
|
22
|
-
globalConfigPath:
|
|
45
|
+
globalConfigPath: configPath,
|
|
23
46
|
artifacts: {
|
|
24
47
|
dir: DEFAULT_ARTIFACT_DIR,
|
|
25
48
|
stateFile: DEFAULT_STATE_FILE,
|
|
@@ -109,10 +132,9 @@ export function mergeAkaneConfig(base, overrides) {
|
|
|
109
132
|
}
|
|
110
133
|
export async function loadAkaneConfig(configPath = process.env.AKANE_CONFIG_PATH ?? DEFAULT_GLOBAL_CONFIG_PATH) {
|
|
111
134
|
const resolvedPath = expandHome(configPath);
|
|
112
|
-
const defaults = defaultAkaneConfig();
|
|
135
|
+
const defaults = defaultAkaneConfig(configPath);
|
|
113
136
|
try {
|
|
114
|
-
const
|
|
115
|
-
const parsed = parseJsonFile(raw, resolvedPath);
|
|
137
|
+
const parsed = await readAkaneConfigFile(resolvedPath);
|
|
116
138
|
return {
|
|
117
139
|
path: resolvedPath,
|
|
118
140
|
exists: true,
|
|
@@ -121,11 +143,33 @@ export async function loadAkaneConfig(configPath = process.env.AKANE_CONFIG_PATH
|
|
|
121
143
|
}
|
|
122
144
|
catch (error) {
|
|
123
145
|
if (error.code === "ENOENT") {
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
146
|
+
try {
|
|
147
|
+
const created = await bootstrapAkaneConfigFile(resolvedPath, defaults);
|
|
148
|
+
if (!created) {
|
|
149
|
+
const parsed = await readAkaneConfigFile(resolvedPath);
|
|
150
|
+
return {
|
|
151
|
+
path: resolvedPath,
|
|
152
|
+
exists: true,
|
|
153
|
+
config: mergeAkaneConfig(defaults, parsed),
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
return {
|
|
157
|
+
path: resolvedPath,
|
|
158
|
+
exists: true,
|
|
159
|
+
config: defaults,
|
|
160
|
+
};
|
|
161
|
+
}
|
|
162
|
+
catch (bootstrapError) {
|
|
163
|
+
const message = bootstrapError instanceof Error
|
|
164
|
+
? bootstrapError.message
|
|
165
|
+
: "unknown bootstrap error";
|
|
166
|
+
console.warn(`Akane: failed to auto-create config at ${resolvedPath}: ${message}`);
|
|
167
|
+
return {
|
|
168
|
+
path: resolvedPath,
|
|
169
|
+
exists: false,
|
|
170
|
+
config: defaults,
|
|
171
|
+
};
|
|
172
|
+
}
|
|
129
173
|
}
|
|
130
174
|
throw error;
|
|
131
175
|
}
|
package/dist/constants.d.ts
CHANGED
|
@@ -4,6 +4,7 @@ export declare const DEFAULT_PLUGIN_OUTPUT_PATH = "~/.config/opencode/plugins/ak
|
|
|
4
4
|
export declare const DEFAULT_ARTIFACT_DIR = ".opencode/akane";
|
|
5
5
|
export declare const DEFAULT_STATE_FILE = "state.json";
|
|
6
6
|
export declare const AKANE_STAGE_IDS: readonly ["plan", "plan-review", "implementation-context", "review-codex", "review-claude", "final-synthesis"];
|
|
7
|
+
export declare const AKANE_TOOL_IDS: readonly ["akane_init", "akane_stage_artifact", "akane_plan", "akane_plan_review", "akane_implement", "akane_review", "akane_synthesize", "akane_run"];
|
|
7
8
|
export declare const AKANE_ROLE_IDS: readonly ["planner", "plan_reviewer", "implementer", "consultant_primary", "consultant_secondary", "reviewer_codex", "reviewer_claude", "synthesizer"];
|
|
8
9
|
export declare const DEFAULT_ROLE_MODELS: {
|
|
9
10
|
readonly planner: "anthropic/claude-opus-4-6";
|
package/dist/constants.js
CHANGED
|
@@ -11,6 +11,16 @@ export const AKANE_STAGE_IDS = [
|
|
|
11
11
|
"review-claude",
|
|
12
12
|
"final-synthesis",
|
|
13
13
|
];
|
|
14
|
+
export const AKANE_TOOL_IDS = [
|
|
15
|
+
"akane_init",
|
|
16
|
+
"akane_stage_artifact",
|
|
17
|
+
"akane_plan",
|
|
18
|
+
"akane_plan_review",
|
|
19
|
+
"akane_implement",
|
|
20
|
+
"akane_review",
|
|
21
|
+
"akane_synthesize",
|
|
22
|
+
"akane_run",
|
|
23
|
+
];
|
|
14
24
|
export const AKANE_ROLE_IDS = [
|
|
15
25
|
"planner",
|
|
16
26
|
"plan_reviewer",
|
package/dist/plugin.js
CHANGED
|
@@ -2,12 +2,24 @@ import { loadAkaneConfig } from "./config.js";
|
|
|
2
2
|
import { resolveArtifactDir } from "./artifacts.js";
|
|
3
3
|
import { createAkaneInitTool } from "./tools/akane-init.js";
|
|
4
4
|
import { createAkaneStageArtifactTool } from "./tools/akane-stage-artifact.js";
|
|
5
|
+
import { createAkanePlanTool } from "./tools/akane-plan.js";
|
|
6
|
+
import { createAkanePlanReviewTool } from "./tools/akane-plan-review.js";
|
|
7
|
+
import { createAkaneImplementTool } from "./tools/akane-implement.js";
|
|
8
|
+
import { createAkaneReviewTool } from "./tools/akane-review.js";
|
|
9
|
+
import { createAkaneSynthesizeTool } from "./tools/akane-synthesize.js";
|
|
10
|
+
import { createAkaneRunTool } from "./tools/akane-run.js";
|
|
5
11
|
export const AkanePlugin = async (input) => {
|
|
6
12
|
const configInfo = await loadAkaneConfig();
|
|
7
13
|
return {
|
|
8
14
|
tool: {
|
|
9
15
|
akane_init: createAkaneInitTool(configInfo),
|
|
10
16
|
akane_stage_artifact: createAkaneStageArtifactTool(configInfo),
|
|
17
|
+
akane_plan: createAkanePlanTool(input, configInfo),
|
|
18
|
+
akane_plan_review: createAkanePlanReviewTool(input, configInfo),
|
|
19
|
+
akane_implement: createAkaneImplementTool(input, configInfo),
|
|
20
|
+
akane_review: createAkaneReviewTool(input, configInfo),
|
|
21
|
+
akane_synthesize: createAkaneSynthesizeTool(input, configInfo),
|
|
22
|
+
akane_run: createAkaneRunTool(input, configInfo),
|
|
11
23
|
},
|
|
12
24
|
"shell.env": async (_event, output) => {
|
|
13
25
|
const projectRoot = input.worktree || input.directory;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { PluginInput } from "@opencode-ai/plugin";
|
|
2
|
+
import type { LoadedAkaneConfig } from "../types.js";
|
|
3
|
+
export declare function createAkaneImplementTool(pluginInput: PluginInput, configInfo: LoadedAkaneConfig): {
|
|
4
|
+
description: string;
|
|
5
|
+
args: {
|
|
6
|
+
task: import("zod").ZodOptional<import("zod").ZodString>;
|
|
7
|
+
notes: import("zod").ZodOptional<import("zod").ZodString>;
|
|
8
|
+
projectRoot: import("zod").ZodOptional<import("zod").ZodString>;
|
|
9
|
+
};
|
|
10
|
+
execute(args: {
|
|
11
|
+
task?: string | undefined;
|
|
12
|
+
notes?: string | undefined;
|
|
13
|
+
projectRoot?: string | undefined;
|
|
14
|
+
}, context: import("@opencode-ai/plugin/tool").ToolContext): Promise<string>;
|
|
15
|
+
};
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { tool } from "@opencode-ai/plugin/tool";
|
|
2
|
+
import { executeImplementStage, resolveProjectRootFromArgs, } from "../workflow.js";
|
|
3
|
+
export function createAkaneImplementTool(pluginInput, configInfo) {
|
|
4
|
+
return tool({
|
|
5
|
+
description: "Implement the approved Akane plan in the repository and write implementation-context.md.",
|
|
6
|
+
args: {
|
|
7
|
+
task: tool.schema
|
|
8
|
+
.string()
|
|
9
|
+
.optional()
|
|
10
|
+
.describe("Optional task restatement for the implementer stage."),
|
|
11
|
+
notes: tool.schema
|
|
12
|
+
.string()
|
|
13
|
+
.optional()
|
|
14
|
+
.describe("Optional additional implementation constraints."),
|
|
15
|
+
projectRoot: tool.schema
|
|
16
|
+
.string()
|
|
17
|
+
.optional()
|
|
18
|
+
.describe("Optional project root override. Defaults to the current session worktree."),
|
|
19
|
+
},
|
|
20
|
+
async execute(args, context) {
|
|
21
|
+
try {
|
|
22
|
+
const projectRoot = resolveProjectRootFromArgs({
|
|
23
|
+
toolContext: context,
|
|
24
|
+
projectRoot: args.projectRoot,
|
|
25
|
+
});
|
|
26
|
+
context.metadata({
|
|
27
|
+
title: "Akane implement",
|
|
28
|
+
metadata: {
|
|
29
|
+
stage: "implementation-context",
|
|
30
|
+
projectRoot,
|
|
31
|
+
},
|
|
32
|
+
});
|
|
33
|
+
const result = await executeImplementStage({
|
|
34
|
+
pluginInput,
|
|
35
|
+
configInfo,
|
|
36
|
+
toolContext: context,
|
|
37
|
+
projectRoot,
|
|
38
|
+
task: args.task,
|
|
39
|
+
notes: args.notes,
|
|
40
|
+
});
|
|
41
|
+
return [
|
|
42
|
+
`Created Akane implementation artifact.`,
|
|
43
|
+
`Artifact: ${result.artifactPath}`,
|
|
44
|
+
`Session: ${result.sessionID}`,
|
|
45
|
+
`Model: ${result.model}`,
|
|
46
|
+
].join("\n");
|
|
47
|
+
}
|
|
48
|
+
catch (error) {
|
|
49
|
+
return `Akane implement failed: ${error instanceof Error ? error.message : String(error)}`;
|
|
50
|
+
}
|
|
51
|
+
},
|
|
52
|
+
});
|
|
53
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { PluginInput } from "@opencode-ai/plugin";
|
|
2
|
+
import type { LoadedAkaneConfig } from "../types.js";
|
|
3
|
+
export declare function createAkanePlanReviewTool(pluginInput: PluginInput, configInfo: LoadedAkaneConfig): {
|
|
4
|
+
description: string;
|
|
5
|
+
args: {
|
|
6
|
+
task: import("zod").ZodOptional<import("zod").ZodString>;
|
|
7
|
+
notes: import("zod").ZodOptional<import("zod").ZodString>;
|
|
8
|
+
projectRoot: import("zod").ZodOptional<import("zod").ZodString>;
|
|
9
|
+
};
|
|
10
|
+
execute(args: {
|
|
11
|
+
task?: string | undefined;
|
|
12
|
+
notes?: string | undefined;
|
|
13
|
+
projectRoot?: string | undefined;
|
|
14
|
+
}, context: import("@opencode-ai/plugin/tool").ToolContext): Promise<string>;
|
|
15
|
+
};
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { tool } from "@opencode-ai/plugin/tool";
|
|
2
|
+
import { executePlanReviewStage, resolveProjectRootFromArgs, } from "../workflow.js";
|
|
3
|
+
export function createAkanePlanReviewTool(pluginInput, configInfo) {
|
|
4
|
+
return tool({
|
|
5
|
+
description: "Review the current Akane plan artifact and write plan-review.md using the configured review model.",
|
|
6
|
+
args: {
|
|
7
|
+
task: tool.schema
|
|
8
|
+
.string()
|
|
9
|
+
.optional()
|
|
10
|
+
.describe("Optional task restatement to include during review."),
|
|
11
|
+
notes: tool.schema
|
|
12
|
+
.string()
|
|
13
|
+
.optional()
|
|
14
|
+
.describe("Optional additional review constraints."),
|
|
15
|
+
projectRoot: tool.schema
|
|
16
|
+
.string()
|
|
17
|
+
.optional()
|
|
18
|
+
.describe("Optional project root override. Defaults to the current session worktree."),
|
|
19
|
+
},
|
|
20
|
+
async execute(args, context) {
|
|
21
|
+
try {
|
|
22
|
+
const projectRoot = resolveProjectRootFromArgs({
|
|
23
|
+
toolContext: context,
|
|
24
|
+
projectRoot: args.projectRoot,
|
|
25
|
+
});
|
|
26
|
+
context.metadata({
|
|
27
|
+
title: "Akane plan review",
|
|
28
|
+
metadata: {
|
|
29
|
+
stage: "plan-review",
|
|
30
|
+
projectRoot,
|
|
31
|
+
},
|
|
32
|
+
});
|
|
33
|
+
const result = await executePlanReviewStage({
|
|
34
|
+
pluginInput,
|
|
35
|
+
configInfo,
|
|
36
|
+
toolContext: context,
|
|
37
|
+
projectRoot,
|
|
38
|
+
task: args.task,
|
|
39
|
+
notes: args.notes,
|
|
40
|
+
});
|
|
41
|
+
return [
|
|
42
|
+
`Created Akane plan review.`,
|
|
43
|
+
`Artifact: ${result.artifactPath}`,
|
|
44
|
+
`Session: ${result.sessionID}`,
|
|
45
|
+
`Model: ${result.model}`,
|
|
46
|
+
].join("\n");
|
|
47
|
+
}
|
|
48
|
+
catch (error) {
|
|
49
|
+
return `Akane plan review failed: ${error instanceof Error ? error.message : String(error)}`;
|
|
50
|
+
}
|
|
51
|
+
},
|
|
52
|
+
});
|
|
53
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { PluginInput } from "@opencode-ai/plugin";
|
|
2
|
+
import type { LoadedAkaneConfig } from "../types.js";
|
|
3
|
+
export declare function createAkanePlanTool(pluginInput: PluginInput, configInfo: LoadedAkaneConfig): {
|
|
4
|
+
description: string;
|
|
5
|
+
args: {
|
|
6
|
+
task: import("zod").ZodString;
|
|
7
|
+
notes: import("zod").ZodOptional<import("zod").ZodString>;
|
|
8
|
+
projectRoot: import("zod").ZodOptional<import("zod").ZodString>;
|
|
9
|
+
};
|
|
10
|
+
execute(args: {
|
|
11
|
+
task: string;
|
|
12
|
+
notes?: string | undefined;
|
|
13
|
+
projectRoot?: string | undefined;
|
|
14
|
+
}, context: import("@opencode-ai/plugin/tool").ToolContext): Promise<string>;
|
|
15
|
+
};
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { tool } from "@opencode-ai/plugin/tool";
|
|
2
|
+
import { executePlanStage, resolveProjectRootFromArgs, } from "../workflow.js";
|
|
3
|
+
export function createAkanePlanTool(pluginInput, configInfo) {
|
|
4
|
+
return tool({
|
|
5
|
+
description: "Create the Akane plan artifact for a task by running the planner role in a child OpenCode session.",
|
|
6
|
+
args: {
|
|
7
|
+
task: tool.schema.string().describe("The task or change request to plan."),
|
|
8
|
+
notes: tool.schema
|
|
9
|
+
.string()
|
|
10
|
+
.optional()
|
|
11
|
+
.describe("Optional additional constraints or context for the plan."),
|
|
12
|
+
projectRoot: tool.schema
|
|
13
|
+
.string()
|
|
14
|
+
.optional()
|
|
15
|
+
.describe("Optional project root override. Defaults to the current session worktree."),
|
|
16
|
+
},
|
|
17
|
+
async execute(args, context) {
|
|
18
|
+
try {
|
|
19
|
+
const projectRoot = resolveProjectRootFromArgs({
|
|
20
|
+
toolContext: context,
|
|
21
|
+
projectRoot: args.projectRoot,
|
|
22
|
+
});
|
|
23
|
+
context.metadata({
|
|
24
|
+
title: "Akane plan",
|
|
25
|
+
metadata: {
|
|
26
|
+
stage: "plan",
|
|
27
|
+
projectRoot,
|
|
28
|
+
},
|
|
29
|
+
});
|
|
30
|
+
const result = await executePlanStage({
|
|
31
|
+
pluginInput,
|
|
32
|
+
configInfo,
|
|
33
|
+
toolContext: context,
|
|
34
|
+
projectRoot,
|
|
35
|
+
task: args.task,
|
|
36
|
+
notes: args.notes,
|
|
37
|
+
});
|
|
38
|
+
return [
|
|
39
|
+
`Created Akane plan.`,
|
|
40
|
+
`Artifact: ${result.artifactPath}`,
|
|
41
|
+
`Session: ${result.sessionID}`,
|
|
42
|
+
`Model: ${result.model}`,
|
|
43
|
+
].join("\n");
|
|
44
|
+
}
|
|
45
|
+
catch (error) {
|
|
46
|
+
return `Akane plan failed: ${error instanceof Error ? error.message : String(error)}`;
|
|
47
|
+
}
|
|
48
|
+
},
|
|
49
|
+
});
|
|
50
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { PluginInput } from "@opencode-ai/plugin";
|
|
2
|
+
import type { LoadedAkaneConfig } from "../types.js";
|
|
3
|
+
export declare function createAkaneReviewTool(pluginInput: PluginInput, configInfo: LoadedAkaneConfig): {
|
|
4
|
+
description: string;
|
|
5
|
+
args: {
|
|
6
|
+
reviewer: import("zod").ZodDefault<import("zod").ZodEnum<{
|
|
7
|
+
codex: "codex";
|
|
8
|
+
claude: "claude";
|
|
9
|
+
both: "both";
|
|
10
|
+
}>>;
|
|
11
|
+
task: import("zod").ZodOptional<import("zod").ZodString>;
|
|
12
|
+
notes: import("zod").ZodOptional<import("zod").ZodString>;
|
|
13
|
+
projectRoot: import("zod").ZodOptional<import("zod").ZodString>;
|
|
14
|
+
};
|
|
15
|
+
execute(args: {
|
|
16
|
+
reviewer: "codex" | "claude" | "both";
|
|
17
|
+
task?: string | undefined;
|
|
18
|
+
notes?: string | undefined;
|
|
19
|
+
projectRoot?: string | undefined;
|
|
20
|
+
}, context: import("@opencode-ai/plugin/tool").ToolContext): Promise<string>;
|
|
21
|
+
};
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { tool } from "@opencode-ai/plugin/tool";
|
|
2
|
+
import { executeReviewStage, resolveProjectRootFromArgs, reviewSelectionLabel, } from "../workflow.js";
|
|
3
|
+
export function createAkaneReviewTool(pluginInput, configInfo) {
|
|
4
|
+
return tool({
|
|
5
|
+
description: "Run the Akane review stage. By default this runs both Codex and Claude reviews in parallel.",
|
|
6
|
+
args: {
|
|
7
|
+
reviewer: tool.schema
|
|
8
|
+
.enum(["codex", "claude", "both"])
|
|
9
|
+
.default("both")
|
|
10
|
+
.describe("Which reviewer to run. 'both' runs both review artifacts in parallel."),
|
|
11
|
+
task: tool.schema
|
|
12
|
+
.string()
|
|
13
|
+
.optional()
|
|
14
|
+
.describe("Optional task restatement for the reviewers."),
|
|
15
|
+
notes: tool.schema
|
|
16
|
+
.string()
|
|
17
|
+
.optional()
|
|
18
|
+
.describe("Optional additional review constraints."),
|
|
19
|
+
projectRoot: tool.schema
|
|
20
|
+
.string()
|
|
21
|
+
.optional()
|
|
22
|
+
.describe("Optional project root override. Defaults to the current session worktree."),
|
|
23
|
+
},
|
|
24
|
+
async execute(args, context) {
|
|
25
|
+
try {
|
|
26
|
+
const projectRoot = resolveProjectRootFromArgs({
|
|
27
|
+
toolContext: context,
|
|
28
|
+
projectRoot: args.projectRoot,
|
|
29
|
+
});
|
|
30
|
+
context.metadata({
|
|
31
|
+
title: "Akane review",
|
|
32
|
+
metadata: {
|
|
33
|
+
stage: "review",
|
|
34
|
+
reviewer: args.reviewer,
|
|
35
|
+
projectRoot,
|
|
36
|
+
},
|
|
37
|
+
});
|
|
38
|
+
const result = await executeReviewStage({
|
|
39
|
+
pluginInput,
|
|
40
|
+
configInfo,
|
|
41
|
+
toolContext: context,
|
|
42
|
+
projectRoot,
|
|
43
|
+
reviewer: args.reviewer,
|
|
44
|
+
task: args.task,
|
|
45
|
+
notes: args.notes,
|
|
46
|
+
});
|
|
47
|
+
return [
|
|
48
|
+
`Created Akane review artifact(s): ${reviewSelectionLabel(result.requested)}.`,
|
|
49
|
+
...result.results.map((item) => `- ${item.stage}: ${item.artifactPath} (${item.model})`),
|
|
50
|
+
].join("\n");
|
|
51
|
+
}
|
|
52
|
+
catch (error) {
|
|
53
|
+
return `Akane review failed: ${error instanceof Error ? error.message : String(error)}`;
|
|
54
|
+
}
|
|
55
|
+
},
|
|
56
|
+
});
|
|
57
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { PluginInput } from "@opencode-ai/plugin";
|
|
2
|
+
import type { LoadedAkaneConfig } from "../types.js";
|
|
3
|
+
export declare function createAkaneRunTool(pluginInput: PluginInput, configInfo: LoadedAkaneConfig): {
|
|
4
|
+
description: string;
|
|
5
|
+
args: {
|
|
6
|
+
task: import("zod").ZodString;
|
|
7
|
+
notes: import("zod").ZodOptional<import("zod").ZodString>;
|
|
8
|
+
throughStage: import("zod").ZodDefault<import("zod").ZodEnum<{
|
|
9
|
+
plan: "plan";
|
|
10
|
+
"plan-review": "plan-review";
|
|
11
|
+
"implementation-context": "implementation-context";
|
|
12
|
+
"review-codex": "review-codex";
|
|
13
|
+
"review-claude": "review-claude";
|
|
14
|
+
"final-synthesis": "final-synthesis";
|
|
15
|
+
}>>;
|
|
16
|
+
projectRoot: import("zod").ZodOptional<import("zod").ZodString>;
|
|
17
|
+
};
|
|
18
|
+
execute(args: {
|
|
19
|
+
task: string;
|
|
20
|
+
throughStage: "plan" | "plan-review" | "implementation-context" | "review-codex" | "review-claude" | "final-synthesis";
|
|
21
|
+
notes?: string | undefined;
|
|
22
|
+
projectRoot?: string | undefined;
|
|
23
|
+
}, context: import("@opencode-ai/plugin/tool").ToolContext): Promise<string>;
|
|
24
|
+
};
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { tool } from "@opencode-ai/plugin/tool";
|
|
2
|
+
import { executeRunWorkflow, resolveProjectRootFromArgs, } from "../workflow.js";
|
|
3
|
+
import { AKANE_STAGE_IDS } from "../constants.js";
|
|
4
|
+
export function createAkaneRunTool(pluginInput, configInfo) {
|
|
5
|
+
return tool({
|
|
6
|
+
description: "Run the Akane MVP workflow from planning through synthesis, writing artifacts at each stage.",
|
|
7
|
+
args: {
|
|
8
|
+
task: tool.schema.string().describe("The task or change request to run through Akane."),
|
|
9
|
+
notes: tool.schema
|
|
10
|
+
.string()
|
|
11
|
+
.optional()
|
|
12
|
+
.describe("Optional additional constraints or context for the workflow."),
|
|
13
|
+
throughStage: tool.schema
|
|
14
|
+
.enum(AKANE_STAGE_IDS)
|
|
15
|
+
.default("final-synthesis")
|
|
16
|
+
.describe("Optional stop point for partial workflow runs."),
|
|
17
|
+
projectRoot: tool.schema
|
|
18
|
+
.string()
|
|
19
|
+
.optional()
|
|
20
|
+
.describe("Optional project root override. Defaults to the current session worktree."),
|
|
21
|
+
},
|
|
22
|
+
async execute(args, context) {
|
|
23
|
+
try {
|
|
24
|
+
const projectRoot = resolveProjectRootFromArgs({
|
|
25
|
+
toolContext: context,
|
|
26
|
+
projectRoot: args.projectRoot,
|
|
27
|
+
});
|
|
28
|
+
context.metadata({
|
|
29
|
+
title: "Akane run",
|
|
30
|
+
metadata: {
|
|
31
|
+
stage: "workflow",
|
|
32
|
+
throughStage: args.throughStage,
|
|
33
|
+
projectRoot,
|
|
34
|
+
},
|
|
35
|
+
});
|
|
36
|
+
const result = await executeRunWorkflow({
|
|
37
|
+
pluginInput,
|
|
38
|
+
configInfo,
|
|
39
|
+
toolContext: context,
|
|
40
|
+
projectRoot,
|
|
41
|
+
task: args.task,
|
|
42
|
+
notes: args.notes,
|
|
43
|
+
throughStage: args.throughStage,
|
|
44
|
+
});
|
|
45
|
+
return [
|
|
46
|
+
`Completed Akane workflow through ${args.throughStage}.`,
|
|
47
|
+
`Stages: ${result.completedStages.join(", ")}`,
|
|
48
|
+
`Plan: ${result.plan.artifactPath}`,
|
|
49
|
+
...(result.planReview ? [`Plan review: ${result.planReview.artifactPath}`] : []),
|
|
50
|
+
...(result.implementation
|
|
51
|
+
? [`Implementation: ${result.implementation.artifactPath}`]
|
|
52
|
+
: []),
|
|
53
|
+
...(result.reviews
|
|
54
|
+
? result.reviews.map((review) => `${review.stage}: ${review.artifactPath}`)
|
|
55
|
+
: []),
|
|
56
|
+
...(result.synthesis
|
|
57
|
+
? [`Final synthesis: ${result.synthesis.artifactPath}`]
|
|
58
|
+
: []),
|
|
59
|
+
].join("\n");
|
|
60
|
+
}
|
|
61
|
+
catch (error) {
|
|
62
|
+
return `Akane workflow failed: ${error instanceof Error ? error.message : String(error)}`;
|
|
63
|
+
}
|
|
64
|
+
},
|
|
65
|
+
});
|
|
66
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { PluginInput } from "@opencode-ai/plugin";
|
|
2
|
+
import type { LoadedAkaneConfig } from "../types.js";
|
|
3
|
+
export declare function createAkaneSynthesizeTool(pluginInput: PluginInput, configInfo: LoadedAkaneConfig): {
|
|
4
|
+
description: string;
|
|
5
|
+
args: {
|
|
6
|
+
task: import("zod").ZodOptional<import("zod").ZodString>;
|
|
7
|
+
notes: import("zod").ZodOptional<import("zod").ZodString>;
|
|
8
|
+
projectRoot: import("zod").ZodOptional<import("zod").ZodString>;
|
|
9
|
+
};
|
|
10
|
+
execute(args: {
|
|
11
|
+
task?: string | undefined;
|
|
12
|
+
notes?: string | undefined;
|
|
13
|
+
projectRoot?: string | undefined;
|
|
14
|
+
}, context: import("@opencode-ai/plugin/tool").ToolContext): Promise<string>;
|
|
15
|
+
};
|