@bluelovers/opencode-arise 0.1.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 +21 -0
- package/README.md +286 -0
- package/assets/arise-banner.txt +13 -0
- package/dist/agents/index.d.ts +1 -0
- package/dist/agents/index.js +2 -0
- package/dist/agents/index.js.map +1 -0
- package/dist/agents/shadows.d.ts +28 -0
- package/dist/agents/shadows.js +182 -0
- package/dist/agents/shadows.js.map +1 -0
- package/dist/cli/index.d.ts +2 -0
- package/dist/cli/index.js +221 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/config/paths.d.ts +91 -0
- package/dist/config/paths.js +166 -0
- package/dist/config/paths.js.map +1 -0
- package/dist/config/schema.d.ts +64 -0
- package/dist/config/schema.js +55 -0
- package/dist/config/schema.js.map +1 -0
- package/dist/hooks/arise-banner.d.ts +6 -0
- package/dist/hooks/arise-banner.js +50 -0
- package/dist/hooks/arise-banner.js.map +1 -0
- package/dist/hooks/compaction-preserver.d.ts +3 -0
- package/dist/hooks/compaction-preserver.js +17 -0
- package/dist/hooks/compaction-preserver.js.map +1 -0
- package/dist/hooks/index.d.ts +4 -0
- package/dist/hooks/index.js +5 -0
- package/dist/hooks/index.js.map +1 -0
- package/dist/hooks/output-shaper.d.ts +4 -0
- package/dist/hooks/output-shaper.js +52 -0
- package/dist/hooks/output-shaper.js.map +1 -0
- package/dist/hooks/todo-enforcer.d.ts +9 -0
- package/dist/hooks/todo-enforcer.js +43 -0
- package/dist/hooks/todo-enforcer.js.map +1 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.js +166 -0
- package/dist/index.js.map +1 -0
- package/dist/tools/background-manager.d.ts +35 -0
- package/dist/tools/background-manager.js +163 -0
- package/dist/tools/background-manager.js.map +1 -0
- package/dist/tools/background-tools.d.ts +6 -0
- package/dist/tools/background-tools.js +121 -0
- package/dist/tools/background-tools.js.map +1 -0
- package/dist/tools/call-arise-agent.d.ts +3 -0
- package/dist/tools/call-arise-agent.js +95 -0
- package/dist/tools/call-arise-agent.js.map +1 -0
- package/dist/tools/index.d.ts +3 -0
- package/dist/tools/index.js +4 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/utils/bun-shim.d.ts +88 -0
- package/dist/utils/bun-shim.js +147 -0
- package/dist/utils/bun-shim.js.map +1 -0
- package/package.json +64 -0
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export function createCompactionPreserverHook() {
|
|
2
|
+
return {
|
|
3
|
+
getPreservationContext() {
|
|
4
|
+
return `[opencode-arise] Compaction preservation rules:
|
|
5
|
+
- PRESERVE: All TODO items (pending, in_progress, completed)
|
|
6
|
+
- PRESERVE: Key decisions and assumptions made
|
|
7
|
+
- PRESERVE: File paths that were touched/edited
|
|
8
|
+
- PRESERVE: Commands run and their key outputs (especially errors)
|
|
9
|
+
- PRESERVE: Shadow delegations and their results
|
|
10
|
+
- PRUNE: Verbose tool outputs (grep results, large file contents)
|
|
11
|
+
- PRUNE: Repetitive exploration that didn't yield results
|
|
12
|
+
|
|
13
|
+
Summarize work done, but keep enough context for the Monarch to continue.`;
|
|
14
|
+
},
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=compaction-preserver.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"compaction-preserver.js","sourceRoot":"","sources":["../../src/hooks/compaction-preserver.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,6BAA6B;IAC3C,OAAO;QACL,sBAAsB;YACpB,OAAO;;;;;;;;;0EAS6D,CAAC;QACvE,CAAC;KACF,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export { createAriseBannerHook, getBanner, printBannerToConsole } from "./arise-banner";
|
|
2
|
+
export { createOutputShaperHook } from "./output-shaper";
|
|
3
|
+
export { createTodoEnforcerHook } from "./todo-enforcer";
|
|
4
|
+
export { createCompactionPreserverHook } from "./compaction-preserver";
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { createAriseBannerHook, getBanner, printBannerToConsole } from "./arise-banner";
|
|
2
|
+
export { createOutputShaperHook } from "./output-shaper";
|
|
3
|
+
export { createTodoEnforcerHook } from "./todo-enforcer";
|
|
4
|
+
export { createCompactionPreserverHook } from "./compaction-preserver";
|
|
5
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/hooks/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,SAAS,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;AACxF,OAAO,EAAE,sBAAsB,EAAE,MAAM,iBAAiB,CAAC;AACzD,OAAO,EAAE,sBAAsB,EAAE,MAAM,iBAAiB,CAAC;AACzD,OAAO,EAAE,6BAA6B,EAAE,MAAM,wBAAwB,CAAC"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
const DEFAULT_MAX_CHARS = 12000;
|
|
2
|
+
const HEAD_RATIO = 0.7;
|
|
3
|
+
const TAIL_RATIO = 0.2;
|
|
4
|
+
export function createOutputShaperHook(config) {
|
|
5
|
+
const maxChars = config.output_shaping?.max_chars ?? DEFAULT_MAX_CHARS;
|
|
6
|
+
const preserveErrors = config.output_shaping?.preserve_errors ?? true;
|
|
7
|
+
const headChars = Math.floor(maxChars * HEAD_RATIO);
|
|
8
|
+
const tailChars = Math.floor(maxChars * TAIL_RATIO);
|
|
9
|
+
return {
|
|
10
|
+
async shapeOutput(toolName, output, metadata) {
|
|
11
|
+
if (typeof output !== "string")
|
|
12
|
+
return output;
|
|
13
|
+
if (output.length <= maxChars)
|
|
14
|
+
return output;
|
|
15
|
+
// Never truncate error outputs
|
|
16
|
+
if (preserveErrors) {
|
|
17
|
+
const exitCode = metadata?.exitCode ?? metadata?.code ?? metadata?.status;
|
|
18
|
+
if (typeof exitCode === "number" && exitCode !== 0) {
|
|
19
|
+
return output;
|
|
20
|
+
}
|
|
21
|
+
// Check for error patterns in output
|
|
22
|
+
const errorPatterns = [
|
|
23
|
+
/error:/i,
|
|
24
|
+
/exception:/i,
|
|
25
|
+
/failed:/i,
|
|
26
|
+
/traceback/i,
|
|
27
|
+
/stack trace/i,
|
|
28
|
+
/ENOENT/,
|
|
29
|
+
/EACCES/,
|
|
30
|
+
/TypeError/,
|
|
31
|
+
/ReferenceError/,
|
|
32
|
+
/SyntaxError/,
|
|
33
|
+
];
|
|
34
|
+
if (errorPatterns.some((p) => p.test(output))) {
|
|
35
|
+
// Still truncate but keep more
|
|
36
|
+
if (output.length <= maxChars * 2)
|
|
37
|
+
return output;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
const head = output.slice(0, headChars);
|
|
41
|
+
const tail = output.slice(-tailChars);
|
|
42
|
+
const truncatedChars = output.length - headChars - tailChars;
|
|
43
|
+
return `${head}
|
|
44
|
+
|
|
45
|
+
[opencode-arise] Output truncated (${output.length.toLocaleString()} chars, ${truncatedChars.toLocaleString()} removed).
|
|
46
|
+
Use a more specific query or read a targeted file section if needed.
|
|
47
|
+
|
|
48
|
+
${tail}`;
|
|
49
|
+
},
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
//# sourceMappingURL=output-shaper.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"output-shaper.js","sourceRoot":"","sources":["../../src/hooks/output-shaper.ts"],"names":[],"mappings":"AAEA,MAAM,iBAAiB,GAAG,KAAK,CAAC;AAChC,MAAM,UAAU,GAAG,GAAG,CAAC;AACvB,MAAM,UAAU,GAAG,GAAG,CAAC;AAEvB,MAAM,UAAU,sBAAsB,CAAC,MAAmB;IACxD,MAAM,QAAQ,GAAG,MAAM,CAAC,cAAc,EAAE,SAAS,IAAI,iBAAiB,CAAC;IACvE,MAAM,cAAc,GAAG,MAAM,CAAC,cAAc,EAAE,eAAe,IAAI,IAAI,CAAC;IACtE,MAAM,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC,QAAQ,GAAG,UAAU,CAAC,CAAC;IACpD,MAAM,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC,QAAQ,GAAG,UAAU,CAAC,CAAC;IAEpD,OAAO;QACL,KAAK,CAAC,WAAW,CACf,QAAgB,EAChB,MAAc,EACd,QAAkC;YAElC,IAAI,OAAO,MAAM,KAAK,QAAQ;gBAAE,OAAO,MAAM,CAAC;YAC9C,IAAI,MAAM,CAAC,MAAM,IAAI,QAAQ;gBAAE,OAAO,MAAM,CAAC;YAE7C,+BAA+B;YAC/B,IAAI,cAAc,EAAE,CAAC;gBACnB,MAAM,QAAQ,GAAG,QAAQ,EAAE,QAAQ,IAAI,QAAQ,EAAE,IAAI,IAAI,QAAQ,EAAE,MAAM,CAAC;gBAC1E,IAAI,OAAO,QAAQ,KAAK,QAAQ,IAAI,QAAQ,KAAK,CAAC,EAAE,CAAC;oBACnD,OAAO,MAAM,CAAC;gBAChB,CAAC;gBAED,qCAAqC;gBACrC,MAAM,aAAa,GAAG;oBACpB,SAAS;oBACT,aAAa;oBACb,UAAU;oBACV,YAAY;oBACZ,cAAc;oBACd,QAAQ;oBACR,QAAQ;oBACR,WAAW;oBACX,gBAAgB;oBAChB,aAAa;iBACd,CAAC;gBACF,IAAI,aAAa,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC;oBAC9C,+BAA+B;oBAC/B,IAAI,MAAM,CAAC,MAAM,IAAI,QAAQ,GAAG,CAAC;wBAAE,OAAO,MAAM,CAAC;gBACnD,CAAC;YACH,CAAC;YAED,MAAM,IAAI,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,SAAS,CAAC,CAAC;YACxC,MAAM,IAAI,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,SAAS,CAAC,CAAC;YACtC,MAAM,cAAc,GAAG,MAAM,CAAC,MAAM,GAAG,SAAS,GAAG,SAAS,CAAC;YAE7D,OAAO,GAAG,IAAI;;qCAEiB,MAAM,CAAC,MAAM,CAAC,cAAc,EAAE,WAAW,cAAc,CAAC,cAAc,EAAE;;;EAG3G,IAAI,EAAE,CAAC;QACL,CAAC;KACF,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { PluginInput } from "@opencode-ai/plugin";
|
|
2
|
+
export declare function createTodoEnforcerHook(_ctx: PluginInput): {
|
|
3
|
+
checkCompletion(messages: Array<{
|
|
4
|
+
content: string;
|
|
5
|
+
}>): Promise<{
|
|
6
|
+
hasIncompleteTodos: boolean;
|
|
7
|
+
reminderMessage?: string;
|
|
8
|
+
}>;
|
|
9
|
+
};
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
const TODO_PATTERNS = [
|
|
2
|
+
/\[pending\]/i,
|
|
3
|
+
/\[in_progress\]/i,
|
|
4
|
+
/- \[ \]/,
|
|
5
|
+
/TODO:/i,
|
|
6
|
+
/FIXME:/i,
|
|
7
|
+
];
|
|
8
|
+
const COMPLETION_PATTERNS = [
|
|
9
|
+
/\[completed\]/i,
|
|
10
|
+
/\[done\]/i,
|
|
11
|
+
/- \[x\]/i,
|
|
12
|
+
];
|
|
13
|
+
export function createTodoEnforcerHook(_ctx) {
|
|
14
|
+
return {
|
|
15
|
+
async checkCompletion(messages) {
|
|
16
|
+
const lastAssistantMessages = messages
|
|
17
|
+
.filter((m) => m.content)
|
|
18
|
+
.slice(-5);
|
|
19
|
+
let hasPending = false;
|
|
20
|
+
let hasInProgress = false;
|
|
21
|
+
for (const msg of lastAssistantMessages) {
|
|
22
|
+
const content = msg.content;
|
|
23
|
+
if (TODO_PATTERNS.some((p) => p.test(content))) {
|
|
24
|
+
if (/\[pending\]/i.test(content) || /- \[ \]/.test(content)) {
|
|
25
|
+
hasPending = true;
|
|
26
|
+
}
|
|
27
|
+
if (/\[in_progress\]/i.test(content)) {
|
|
28
|
+
hasInProgress = true;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
const hasIncompleteTodos = hasPending || hasInProgress;
|
|
33
|
+
if (hasIncompleteTodos) {
|
|
34
|
+
return {
|
|
35
|
+
hasIncompleteTodos: true,
|
|
36
|
+
reminderMessage: `[opencode-arise] Shadow Monarch notice: You have incomplete TODOs. ${hasInProgress ? "Tasks are in_progress." : ""} ${hasPending ? "Tasks are pending." : ""} Complete them before stopping.`,
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
return { hasIncompleteTodos: false };
|
|
40
|
+
},
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=todo-enforcer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"todo-enforcer.js","sourceRoot":"","sources":["../../src/hooks/todo-enforcer.ts"],"names":[],"mappings":"AAEA,MAAM,aAAa,GAAG;IACpB,cAAc;IACd,kBAAkB;IAClB,SAAS;IACT,QAAQ;IACR,SAAS;CACV,CAAC;AAEF,MAAM,mBAAmB,GAAG;IAC1B,gBAAgB;IAChB,WAAW;IACX,UAAU;CACX,CAAC;AAEF,MAAM,UAAU,sBAAsB,CAAC,IAAiB;IACtD,OAAO;QACL,KAAK,CAAC,eAAe,CAAC,QAAoC;YAIxD,MAAM,qBAAqB,GAAG,QAAQ;iBACnC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC;iBACxB,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;YAEb,IAAI,UAAU,GAAG,KAAK,CAAC;YACvB,IAAI,aAAa,GAAG,KAAK,CAAC;YAE1B,KAAK,MAAM,GAAG,IAAI,qBAAqB,EAAE,CAAC;gBACxC,MAAM,OAAO,GAAG,GAAG,CAAC,OAAO,CAAC;gBAC5B,IAAI,aAAa,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,EAAE,CAAC;oBAC/C,IAAI,cAAc,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;wBAC5D,UAAU,GAAG,IAAI,CAAC;oBACpB,CAAC;oBACD,IAAI,kBAAkB,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;wBACrC,aAAa,GAAG,IAAI,CAAC;oBACvB,CAAC;gBACH,CAAC;YACH,CAAC;YAED,MAAM,kBAAkB,GAAG,UAAU,IAAI,aAAa,CAAC;YAEvD,IAAI,kBAAkB,EAAE,CAAC;gBACvB,OAAO;oBACL,kBAAkB,EAAE,IAAI;oBACxB,eAAe,EAAE,sEACf,aAAa,CAAC,CAAC,CAAC,wBAAwB,CAAC,CAAC,CAAC,EAC7C,IAAI,UAAU,CAAC,CAAC,CAAC,oBAAoB,CAAC,CAAC,CAAC,EAAE,iCAAiC;iBAC5E,CAAC;YACJ,CAAC;YAED,OAAO,EAAE,kBAAkB,EAAE,KAAK,EAAE,CAAC;QACvC,CAAC;KACF,CAAC;AACJ,CAAC"}
|
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
import { AriseConfigSchema, DEFAULT_CONFIG } from "./config/schema";
|
|
2
|
+
import { getAriseConfigPaths } from "./config/paths";
|
|
3
|
+
import { SHADOW_AGENTS, OPENCODE_OVERRIDES } from "./agents";
|
|
4
|
+
import { createAriseBannerHook, createOutputShaperHook, createCompactionPreserverHook, createTodoEnforcerHook, } from "./hooks";
|
|
5
|
+
import { createCallAriseAgentTool, BackgroundManager, createBackgroundTaskTool, createBackgroundOutputTool, createBackgroundStatusTool, createBackgroundCancelTool, } from "./tools";
|
|
6
|
+
import { Bun } from './utils/bun-shim';
|
|
7
|
+
const CONFIG_FILENAME = "opencode-arise.json";
|
|
8
|
+
async function loadAriseConfig(ctx) {
|
|
9
|
+
const paths = getAriseConfigPaths(ctx.worktree);
|
|
10
|
+
let merged = { ...DEFAULT_CONFIG };
|
|
11
|
+
for (const path of paths.reverse()) {
|
|
12
|
+
try {
|
|
13
|
+
const file = Bun.file(path);
|
|
14
|
+
if (await file.exists()) {
|
|
15
|
+
const content = await file.text();
|
|
16
|
+
const parsed = JSON.parse(content);
|
|
17
|
+
merged = deepMerge(merged, parsed);
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
catch {
|
|
21
|
+
// Config file doesn't exist or is invalid, continue
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
const result = AriseConfigSchema.safeParse(merged);
|
|
25
|
+
if (!result.success) {
|
|
26
|
+
console.warn("[opencode-arise] Invalid config, using defaults:", result.error.message);
|
|
27
|
+
return DEFAULT_CONFIG;
|
|
28
|
+
}
|
|
29
|
+
return result.data;
|
|
30
|
+
}
|
|
31
|
+
function deepMerge(base, override) {
|
|
32
|
+
const result = { ...base };
|
|
33
|
+
for (const [key, value] of Object.entries(override)) {
|
|
34
|
+
if (typeof value === "object" &&
|
|
35
|
+
value !== null &&
|
|
36
|
+
!Array.isArray(value) &&
|
|
37
|
+
typeof result[key] === "object" &&
|
|
38
|
+
result[key] !== null &&
|
|
39
|
+
!Array.isArray(result[key])) {
|
|
40
|
+
result[key] = deepMerge(result[key], value);
|
|
41
|
+
}
|
|
42
|
+
else {
|
|
43
|
+
result[key] = value;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
return result;
|
|
47
|
+
}
|
|
48
|
+
function isHookEnabled(config, hookName) {
|
|
49
|
+
return !(config.disabled_hooks ?? []).includes(hookName);
|
|
50
|
+
}
|
|
51
|
+
const OpencodeArise = async (ctx) => {
|
|
52
|
+
const config = await loadAriseConfig(ctx);
|
|
53
|
+
// Initialize background manager
|
|
54
|
+
const backgroundManager = new BackgroundManager(ctx);
|
|
55
|
+
// Initialize hooks
|
|
56
|
+
const bannerHook = isHookEnabled(config, "arise-banner") && config.show_banner
|
|
57
|
+
? createAriseBannerHook(ctx)
|
|
58
|
+
: null;
|
|
59
|
+
const outputShaper = isHookEnabled(config, "output-shaper")
|
|
60
|
+
? createOutputShaperHook(config)
|
|
61
|
+
: null;
|
|
62
|
+
const compactionPreserver = isHookEnabled(config, "compaction-preserver")
|
|
63
|
+
? createCompactionPreserverHook()
|
|
64
|
+
: null;
|
|
65
|
+
const todoEnforcer = isHookEnabled(config, "todo-enforcer")
|
|
66
|
+
? createTodoEnforcerHook(ctx)
|
|
67
|
+
: null;
|
|
68
|
+
return {
|
|
69
|
+
// Register custom tools
|
|
70
|
+
tool: {
|
|
71
|
+
arise_summon: createCallAriseAgentTool(ctx),
|
|
72
|
+
arise_background: createBackgroundTaskTool(backgroundManager),
|
|
73
|
+
arise_background_output: createBackgroundOutputTool(backgroundManager),
|
|
74
|
+
arise_background_status: createBackgroundStatusTool(backgroundManager),
|
|
75
|
+
arise_background_cancel: createBackgroundCancelTool(backgroundManager),
|
|
76
|
+
},
|
|
77
|
+
async config(opencodeConfig) {
|
|
78
|
+
const cfg = opencodeConfig;
|
|
79
|
+
// Set monarch as default agent
|
|
80
|
+
cfg.default_agent = "monarch";
|
|
81
|
+
// Initialize agent config if needed
|
|
82
|
+
cfg.agent = cfg.agent ?? {};
|
|
83
|
+
const agents = cfg.agent;
|
|
84
|
+
// Add shadow soldiers
|
|
85
|
+
const disabledShadows = new Set(config.disabled_shadows ?? []);
|
|
86
|
+
for (const [name, shadow] of Object.entries(SHADOW_AGENTS)) {
|
|
87
|
+
const shadowName = name;
|
|
88
|
+
if (disabledShadows.has(shadowName))
|
|
89
|
+
continue;
|
|
90
|
+
const userOverride = config.agents?.[shadowName];
|
|
91
|
+
if (userOverride?.disabled)
|
|
92
|
+
continue;
|
|
93
|
+
agents[name] = {
|
|
94
|
+
description: shadow.description,
|
|
95
|
+
mode: shadow.mode,
|
|
96
|
+
model: userOverride?.model ?? shadow.model,
|
|
97
|
+
steps: shadow.steps,
|
|
98
|
+
...(shadow.prompt && { prompt: shadow.prompt }),
|
|
99
|
+
...(shadow.permission && { permission: shadow.permission }),
|
|
100
|
+
...(shadow.options && { options: shadow.options }),
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
// Apply OpenCode agent overrides (make build/plan invokable, hide explore/general)
|
|
104
|
+
for (const [name, override] of Object.entries(OPENCODE_OVERRIDES)) {
|
|
105
|
+
agents[name] = deepMerge(agents[name] ?? {}, override);
|
|
106
|
+
}
|
|
107
|
+
},
|
|
108
|
+
async "tool.execute.after"(input, output) {
|
|
109
|
+
if (outputShaper) {
|
|
110
|
+
output.output = await outputShaper.shapeOutput(input.tool, output.output, output.metadata);
|
|
111
|
+
}
|
|
112
|
+
},
|
|
113
|
+
async "experimental.session.compacting"(_input, output) {
|
|
114
|
+
if (compactionPreserver) {
|
|
115
|
+
output.context.push(compactionPreserver.getPreservationContext());
|
|
116
|
+
}
|
|
117
|
+
},
|
|
118
|
+
async event(input) {
|
|
119
|
+
const event = input.event;
|
|
120
|
+
// Let background manager handle events
|
|
121
|
+
backgroundManager.handleEvent(event);
|
|
122
|
+
// Show banner toast on session creation
|
|
123
|
+
if (event.type === "session.created" && bannerHook) {
|
|
124
|
+
await bannerHook.onSessionCreated();
|
|
125
|
+
}
|
|
126
|
+
// Handle session.idle for todo enforcement
|
|
127
|
+
if (event.type === "session.idle" && todoEnforcer) {
|
|
128
|
+
const sessionId = event.properties?.sessionID;
|
|
129
|
+
if (sessionId) {
|
|
130
|
+
try {
|
|
131
|
+
// Get recent messages to check for incomplete todos
|
|
132
|
+
const messages = await ctx.client.session.messages({
|
|
133
|
+
path: { id: sessionId },
|
|
134
|
+
});
|
|
135
|
+
if (messages.data) {
|
|
136
|
+
// Extract text content from message parts
|
|
137
|
+
const recentMessages = messages.data.slice(-5).map((m) => {
|
|
138
|
+
const textContent = m.parts
|
|
139
|
+
?.filter((p) => p.type === "text")
|
|
140
|
+
.map((p) => p.text ?? "")
|
|
141
|
+
.join("\n") ?? "";
|
|
142
|
+
return { content: textContent };
|
|
143
|
+
});
|
|
144
|
+
const result = await todoEnforcer.checkCompletion(recentMessages);
|
|
145
|
+
if (result.hasIncompleteTodos && result.reminderMessage) {
|
|
146
|
+
await ctx.client.tui.showToast({
|
|
147
|
+
body: {
|
|
148
|
+
title: "Arise - Incomplete Tasks",
|
|
149
|
+
message: "You have pending TODOs. Complete them before stopping.",
|
|
150
|
+
variant: "warning",
|
|
151
|
+
duration: 5000,
|
|
152
|
+
},
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
catch {
|
|
158
|
+
// Ignore errors in todo enforcement
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
},
|
|
163
|
+
};
|
|
164
|
+
};
|
|
165
|
+
export default OpencodeArise;
|
|
166
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import type { PluginInput } from "@opencode-ai/plugin";
|
|
2
|
+
import type { Event } from "@opencode-ai/sdk";
|
|
3
|
+
export interface BackgroundTask {
|
|
4
|
+
id: string;
|
|
5
|
+
sessionId: string;
|
|
6
|
+
parentSessionId: string;
|
|
7
|
+
shadow: string;
|
|
8
|
+
description: string;
|
|
9
|
+
status: "running" | "completed" | "error";
|
|
10
|
+
startedAt: number;
|
|
11
|
+
completedAt?: number;
|
|
12
|
+
result?: string;
|
|
13
|
+
error?: string;
|
|
14
|
+
}
|
|
15
|
+
export declare class BackgroundManager {
|
|
16
|
+
private tasks;
|
|
17
|
+
private ctx;
|
|
18
|
+
constructor(ctx: PluginInput);
|
|
19
|
+
generateTaskId(): string;
|
|
20
|
+
launch(opts: {
|
|
21
|
+
shadow: string;
|
|
22
|
+
prompt: string;
|
|
23
|
+
description: string;
|
|
24
|
+
parentSessionId: string;
|
|
25
|
+
}): Promise<BackgroundTask>;
|
|
26
|
+
private schedulePolling;
|
|
27
|
+
private pollTaskCompletion;
|
|
28
|
+
private extractResult;
|
|
29
|
+
private notifyParent;
|
|
30
|
+
getTask(taskId: string): BackgroundTask | undefined;
|
|
31
|
+
getAllTasks(): BackgroundTask[];
|
|
32
|
+
getTasksForSession(sessionId: string): BackgroundTask[];
|
|
33
|
+
cancelTask(taskId: string): Promise<boolean>;
|
|
34
|
+
handleEvent(event: Event): void;
|
|
35
|
+
}
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
export class BackgroundManager {
|
|
2
|
+
tasks = new Map();
|
|
3
|
+
ctx;
|
|
4
|
+
constructor(ctx) {
|
|
5
|
+
this.ctx = ctx;
|
|
6
|
+
}
|
|
7
|
+
generateTaskId() {
|
|
8
|
+
return `arise_${Date.now().toString(36)}_${Math.random().toString(36).slice(2, 6)}`;
|
|
9
|
+
}
|
|
10
|
+
async launch(opts) {
|
|
11
|
+
const taskId = this.generateTaskId();
|
|
12
|
+
// Create a new session for the background task
|
|
13
|
+
const session = await this.ctx.client.session.create({
|
|
14
|
+
body: { title: `[arise:${taskId}] ${opts.description}` },
|
|
15
|
+
});
|
|
16
|
+
const sessionId = session.data?.id;
|
|
17
|
+
if (!sessionId) {
|
|
18
|
+
throw new Error("Failed to create background session");
|
|
19
|
+
}
|
|
20
|
+
const task = {
|
|
21
|
+
id: taskId,
|
|
22
|
+
sessionId,
|
|
23
|
+
parentSessionId: opts.parentSessionId,
|
|
24
|
+
shadow: opts.shadow,
|
|
25
|
+
description: opts.description,
|
|
26
|
+
status: "running",
|
|
27
|
+
startedAt: Date.now(),
|
|
28
|
+
};
|
|
29
|
+
this.tasks.set(taskId, task);
|
|
30
|
+
// Fire the prompt asynchronously
|
|
31
|
+
this.ctx.client.session
|
|
32
|
+
.promptAsync({
|
|
33
|
+
path: { id: sessionId },
|
|
34
|
+
body: {
|
|
35
|
+
agent: opts.shadow,
|
|
36
|
+
parts: [{ type: "text", text: opts.prompt }],
|
|
37
|
+
},
|
|
38
|
+
})
|
|
39
|
+
.then(() => this.schedulePolling(taskId))
|
|
40
|
+
.catch((err) => {
|
|
41
|
+
task.status = "error";
|
|
42
|
+
task.error = err instanceof Error ? err.message : String(err);
|
|
43
|
+
task.completedAt = Date.now();
|
|
44
|
+
});
|
|
45
|
+
return task;
|
|
46
|
+
}
|
|
47
|
+
schedulePolling(taskId) {
|
|
48
|
+
setTimeout(() => this.pollTaskCompletion(taskId), 2000);
|
|
49
|
+
}
|
|
50
|
+
async pollTaskCompletion(taskId) {
|
|
51
|
+
const task = this.tasks.get(taskId);
|
|
52
|
+
if (!task || task.status !== "running")
|
|
53
|
+
return;
|
|
54
|
+
try {
|
|
55
|
+
// Check session status
|
|
56
|
+
const statusResult = await this.ctx.client.session.status({});
|
|
57
|
+
const statuses = statusResult.data;
|
|
58
|
+
if (statuses && task.sessionId in statuses) {
|
|
59
|
+
const status = statuses[task.sessionId];
|
|
60
|
+
if (status.type === "idle") {
|
|
61
|
+
await this.extractResult(task);
|
|
62
|
+
task.status = "completed";
|
|
63
|
+
task.completedAt = Date.now();
|
|
64
|
+
await this.notifyParent(task);
|
|
65
|
+
}
|
|
66
|
+
else if (status.type === "busy" || status.type === "retry") {
|
|
67
|
+
this.schedulePolling(taskId);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
else {
|
|
71
|
+
// Session not in status map, assume idle
|
|
72
|
+
await this.extractResult(task);
|
|
73
|
+
task.status = "completed";
|
|
74
|
+
task.completedAt = Date.now();
|
|
75
|
+
await this.notifyParent(task);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
catch (err) {
|
|
79
|
+
task.status = "error";
|
|
80
|
+
task.error = err instanceof Error ? err.message : String(err);
|
|
81
|
+
task.completedAt = Date.now();
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
async extractResult(task) {
|
|
85
|
+
try {
|
|
86
|
+
const messages = await this.ctx.client.session.messages({
|
|
87
|
+
path: { id: task.sessionId },
|
|
88
|
+
});
|
|
89
|
+
const lastAssistant = messages.data
|
|
90
|
+
?.filter((m) => m.info.role === "assistant")
|
|
91
|
+
.pop();
|
|
92
|
+
if (lastAssistant) {
|
|
93
|
+
const textContent = lastAssistant.parts
|
|
94
|
+
?.filter((p) => p.type === "text")
|
|
95
|
+
.map((p) => p.text ?? "")
|
|
96
|
+
.join("\n");
|
|
97
|
+
task.result = textContent || "(No response)";
|
|
98
|
+
}
|
|
99
|
+
else {
|
|
100
|
+
task.result = "(No assistant response)";
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
catch {
|
|
104
|
+
task.result = "(Failed to retrieve result)";
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
async notifyParent(task) {
|
|
108
|
+
const duration = task.completedAt
|
|
109
|
+
? Math.round((task.completedAt - task.startedAt) / 1000)
|
|
110
|
+
: 0;
|
|
111
|
+
try {
|
|
112
|
+
await this.ctx.client.tui.showToast({
|
|
113
|
+
body: {
|
|
114
|
+
title: "Shadow Complete",
|
|
115
|
+
message: `${task.shadow} finished: ${task.description} (${duration}s)`,
|
|
116
|
+
variant: "success",
|
|
117
|
+
duration: 3000,
|
|
118
|
+
},
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
catch {
|
|
122
|
+
// TUI might not be available
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
getTask(taskId) {
|
|
126
|
+
return this.tasks.get(taskId);
|
|
127
|
+
}
|
|
128
|
+
getAllTasks() {
|
|
129
|
+
return Array.from(this.tasks.values());
|
|
130
|
+
}
|
|
131
|
+
getTasksForSession(sessionId) {
|
|
132
|
+
return Array.from(this.tasks.values()).filter((t) => t.parentSessionId === sessionId);
|
|
133
|
+
}
|
|
134
|
+
async cancelTask(taskId) {
|
|
135
|
+
const task = this.tasks.get(taskId);
|
|
136
|
+
if (!task || task.status !== "running")
|
|
137
|
+
return false;
|
|
138
|
+
try {
|
|
139
|
+
await this.ctx.client.session.abort({ path: { id: task.sessionId } });
|
|
140
|
+
}
|
|
141
|
+
catch {
|
|
142
|
+
// Ignore abort errors
|
|
143
|
+
}
|
|
144
|
+
task.status = "error";
|
|
145
|
+
task.error = "Cancelled";
|
|
146
|
+
task.completedAt = Date.now();
|
|
147
|
+
return true;
|
|
148
|
+
}
|
|
149
|
+
handleEvent(event) {
|
|
150
|
+
// Handle session.idle events to mark tasks as complete
|
|
151
|
+
if (event.type === "session.idle") {
|
|
152
|
+
const sessionId = event.properties?.sessionID;
|
|
153
|
+
if (sessionId) {
|
|
154
|
+
for (const task of this.tasks.values()) {
|
|
155
|
+
if (task.sessionId === sessionId && task.status === "running") {
|
|
156
|
+
this.pollTaskCompletion(task.id);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
//# sourceMappingURL=background-manager.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"background-manager.js","sourceRoot":"","sources":["../../src/tools/background-manager.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { tool } from "@opencode-ai/plugin";
|
|
2
|
+
import type { BackgroundManager } from "./background-manager";
|
|
3
|
+
export declare function createBackgroundTaskTool(manager: BackgroundManager): ReturnType<typeof tool>;
|
|
4
|
+
export declare function createBackgroundOutputTool(manager: BackgroundManager): ReturnType<typeof tool>;
|
|
5
|
+
export declare function createBackgroundStatusTool(manager: BackgroundManager): ReturnType<typeof tool>;
|
|
6
|
+
export declare function createBackgroundCancelTool(manager: BackgroundManager): ReturnType<typeof tool>;
|