@openspoon/subtask2 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,56 @@
1
+ # @openspoon/subtask2
2
+
3
+ OpenCode plugin for enhanced subtask control with **return context injection** and **prompt chaining**.
4
+
5
+ ## Features
6
+
7
+ - **`return`**: Append context to subtask output, ensuring the parent agent receives specific information
8
+ - **`chain`**: Queue follow-up user messages that execute sequentially after the subtask completes
9
+
10
+ ## Installation
11
+
12
+ Add to your `opencode.json`:
13
+
14
+ ```json
15
+ {
16
+ "plugins": ["@openspoon/subtask2"]
17
+ }
18
+ ```
19
+
20
+ or
21
+
22
+ ```bash
23
+ npm install @openspoon/subtask2
24
+ ```
25
+
26
+ ## Usage
27
+
28
+ Add `return` and/or `chain` to your command frontmatter:
29
+
30
+ ### Example: Code Review Command
31
+
32
+ `.opencode/command/review.md`
33
+
34
+ ```markdown
35
+ ---
36
+ description: Review code changes and create summary
37
+ agent: general
38
+ subtask: true
39
+ return: You are the agent in charge of assessing the bug review, challenge, verify and validate it, then discard it or implement it.
40
+ chain:
41
+ - Let's now rinse and repeat with PR#356, use the task tool to review it for bugs etc... then assess, challenge, validate -> discard or implement.
42
+ - Rinse and repeat, with next PR.
43
+ ---
44
+
45
+ Review PR#355 for bugs, security issues, and code style problems.
46
+ ```
47
+
48
+ ## How It Works
49
+
50
+ 1. When a subtask command with `return` executes, the return text is appended to the task output
51
+ 2. When the subtask completes, each `chain` prompt is sent as a synthetic user message
52
+ 3. Chain prompts execute sequentially, each waiting for the previous to complete
53
+
54
+ ## License
55
+
56
+ MIT
@@ -0,0 +1,4 @@
1
+ import type { Plugin } from "@opencode-ai/plugin";
2
+ declare const plugin: Plugin;
3
+ export default plugin;
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAiElD,QAAA,MAAM,MAAM,EAAE,MAqCb,CAAC;AAEF,eAAe,MAAM,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,98 @@
1
+ function parseFrontmatter(content) {
2
+ const match = content.match(/^---\n([\s\S]*?)\n---/);
3
+ if (!match)
4
+ return {};
5
+ const fm = {};
6
+ const lines = match[1].split("\n");
7
+ for (let i = 0; i < lines.length; i++) {
8
+ const line = lines[i];
9
+ const keyMatch = line.match(/^(\w+):\s*(.*)/);
10
+ if (!keyMatch)
11
+ continue;
12
+ const [, key, value] = keyMatch;
13
+ if (!value.trim()) {
14
+ const items = [];
15
+ while (i + 1 < lines.length && lines[i + 1].match(/^\s+-\s+/)) {
16
+ i++;
17
+ items.push(lines[i].replace(/^\s+-\s+/, "").trim());
18
+ }
19
+ if (items.length) {
20
+ fm[key] = items;
21
+ continue;
22
+ }
23
+ }
24
+ fm[key] = value.trim();
25
+ }
26
+ return fm;
27
+ }
28
+ async function buildManifest() {
29
+ const manifest = {};
30
+ const home = Bun.env.HOME ?? "";
31
+ const dirs = [`${home}/.config/opencode/command`, `${Bun.env.PWD ?? "."}/.opencode/command`];
32
+ for (const dir of dirs) {
33
+ try {
34
+ const glob = new Bun.Glob("*.md");
35
+ for await (const file of glob.scan(dir)) {
36
+ const name = file.replace(/\.md$/, "");
37
+ const content = await Bun.file(`${dir}/${file}`).text();
38
+ const fm = parseFrontmatter(content);
39
+ const chain = fm.chain;
40
+ const chainArr = chain ? (Array.isArray(chain) ? chain : [chain]) : [];
41
+ if (fm.return || chainArr.length) {
42
+ manifest[name] = {
43
+ return: fm.return,
44
+ chain: chainArr,
45
+ };
46
+ }
47
+ }
48
+ }
49
+ catch { }
50
+ }
51
+ return manifest;
52
+ }
53
+ let configs = {};
54
+ let client = null;
55
+ const callState = new Map();
56
+ const chainState = new Map();
57
+ const plugin = async (ctx) => {
58
+ configs = await buildManifest();
59
+ client = ctx.client;
60
+ return {
61
+ "tool.execute.before": async (input, output) => {
62
+ if (input.tool !== "task")
63
+ return;
64
+ const cmd = output.args?.command;
65
+ if (cmd && configs[cmd]) {
66
+ callState.set(input.callID, cmd);
67
+ if (configs[cmd].chain.length) {
68
+ chainState.set(input.sessionID, [...configs[cmd].chain]);
69
+ }
70
+ }
71
+ },
72
+ "tool.execute.after": async (input, output) => {
73
+ if (input.tool !== "task")
74
+ return;
75
+ const cmd = callState.get(input.callID);
76
+ if (!cmd)
77
+ return;
78
+ if (configs[cmd]?.return) {
79
+ output.output += `\n\n${configs[cmd].return}`;
80
+ }
81
+ callState.delete(input.callID);
82
+ },
83
+ "experimental.text.complete": async (input) => {
84
+ const chain = chainState.get(input.sessionID);
85
+ if (!chain?.length || !client)
86
+ return;
87
+ const next = chain.shift();
88
+ if (!chain.length)
89
+ chainState.delete(input.sessionID);
90
+ await client.session.promptAsync({
91
+ path: { id: input.sessionID },
92
+ body: { parts: [{ type: "text", text: next, synthetic: true }] },
93
+ });
94
+ },
95
+ };
96
+ };
97
+ export default plugin;
98
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,48 @@
1
+ {
2
+ "$schema": "https://json.schemastore.org/package.json",
3
+ "name": "@openspoon/subtask2",
4
+ "version": "0.1.0",
5
+ "type": "module",
6
+ "description": "Opencode plugin for enhanced subtask control with return context and prompt chaining",
7
+ "main": "./dist/subtask2/index.js",
8
+ "types": "./dist/subtask2/index.d.ts",
9
+ "scripts": {
10
+ "clean": "rm -rf dist",
11
+ "build": "npm run clean && tsc",
12
+ "prepublishOnly": "npm run build"
13
+ },
14
+ "keywords": [
15
+ "opencode",
16
+ "opencode-plugin",
17
+ "plugin",
18
+ "subtask",
19
+ "chaining",
20
+ "automation"
21
+ ],
22
+ "repository": {
23
+ "type": "git",
24
+ "url": "git+https://github.com/spoons-and-mirrors/subtask2.git"
25
+ },
26
+ "author": "openspoon",
27
+ "license": "MIT",
28
+ "publishConfig": {
29
+ "access": "public"
30
+ },
31
+ "peerDependencies": {
32
+ "@opencode-ai/plugin": ">=0.13.7"
33
+ },
34
+ "dependencies": {
35
+ "@opencode-ai/sdk": "latest"
36
+ },
37
+ "devDependencies": {
38
+ "@opencode-ai/plugin": "^1.0.143",
39
+ "@types/node": "^24.10.1",
40
+ "bun-types": "^1.3.4",
41
+ "typescript": "^5.9.3"
42
+ },
43
+ "files": [
44
+ "dist/",
45
+ "README.md",
46
+ "LICENSE"
47
+ ]
48
+ }