@bojackduy/opencode-loopd 1.9.7 → 1.10.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/dist/server.js +234 -5
- package/dist/tui.js +163 -1
- package/package.json +2 -1
package/dist/server.js
CHANGED
|
@@ -487,7 +487,7 @@ var CURRENT_VERSION = 6, LOCK_STALE_MS = 1e4;
|
|
|
487
487
|
var init_state_repository = () => {};
|
|
488
488
|
|
|
489
489
|
// src/server/plugin.ts
|
|
490
|
-
import {
|
|
490
|
+
import { tool as v1Tool } from "@opencode-ai/plugin/tool";
|
|
491
491
|
|
|
492
492
|
// src/application/control-worker.ts
|
|
493
493
|
init_state_repository();
|
|
@@ -2103,6 +2103,115 @@ function createRealHost(client, directory) {
|
|
|
2103
2103
|
}
|
|
2104
2104
|
};
|
|
2105
2105
|
}
|
|
2106
|
+
function createV2Host(context, statuses) {
|
|
2107
|
+
const directory = context.location.directory;
|
|
2108
|
+
return {
|
|
2109
|
+
async createWorker({ parentID, title, agent, model }) {
|
|
2110
|
+
const session = await context.session.create({
|
|
2111
|
+
title,
|
|
2112
|
+
agent,
|
|
2113
|
+
model: model ? { id: model.modelID, providerID: model.providerID } : undefined,
|
|
2114
|
+
location: { directory },
|
|
2115
|
+
metadata: { "loopd.parentID": parentID }
|
|
2116
|
+
});
|
|
2117
|
+
statuses.set(session.id, "idle");
|
|
2118
|
+
await logServerEvent(directory, "worker.created", { parentID, workerSessionID: session.id, title });
|
|
2119
|
+
return session.id;
|
|
2120
|
+
},
|
|
2121
|
+
async promptWorker({ sessionID, prompt, messageID, model, agent }) {
|
|
2122
|
+
if (agent)
|
|
2123
|
+
await context.session.switchAgent({ sessionID, agent });
|
|
2124
|
+
if (model) {
|
|
2125
|
+
await context.session.switchModel({
|
|
2126
|
+
sessionID,
|
|
2127
|
+
model: { id: model.modelID, providerID: model.providerID }
|
|
2128
|
+
});
|
|
2129
|
+
}
|
|
2130
|
+
const result = await context.session.prompt({
|
|
2131
|
+
sessionID,
|
|
2132
|
+
id: messageID,
|
|
2133
|
+
text: prompt
|
|
2134
|
+
});
|
|
2135
|
+
statuses.set(sessionID, "busy");
|
|
2136
|
+
await logServerEvent(directory, "worker.prompted", { sessionID });
|
|
2137
|
+
return { messageID: result.id };
|
|
2138
|
+
},
|
|
2139
|
+
async readSession(sessionID) {
|
|
2140
|
+
try {
|
|
2141
|
+
const session = await context.session.get({ sessionID });
|
|
2142
|
+
const model = session.model ? { providerID: session.model.providerID, modelID: session.model.id } : undefined;
|
|
2143
|
+
if (!session.agent && !model)
|
|
2144
|
+
return;
|
|
2145
|
+
return { agent: session.agent, model };
|
|
2146
|
+
} catch {
|
|
2147
|
+
return;
|
|
2148
|
+
}
|
|
2149
|
+
},
|
|
2150
|
+
async sessionStatus(sessionID) {
|
|
2151
|
+
return statuses.get(sessionID) ?? "unknown";
|
|
2152
|
+
},
|
|
2153
|
+
async abortSession(sessionID) {
|
|
2154
|
+
try {
|
|
2155
|
+
await context.session.interrupt({ sessionID });
|
|
2156
|
+
statuses.set(sessionID, "idle");
|
|
2157
|
+
} catch {}
|
|
2158
|
+
},
|
|
2159
|
+
async readMessages(sessionID, limit = 10) {
|
|
2160
|
+
try {
|
|
2161
|
+
const messages = await context.session.context({ sessionID });
|
|
2162
|
+
let parentMessageID;
|
|
2163
|
+
return messages.flatMap((message) => {
|
|
2164
|
+
if (message.type === "user") {
|
|
2165
|
+
parentMessageID = message.id;
|
|
2166
|
+
return [{
|
|
2167
|
+
role: "user",
|
|
2168
|
+
content: message.text,
|
|
2169
|
+
timestamp: new Date(message.time.created).toISOString(),
|
|
2170
|
+
messageID: message.id
|
|
2171
|
+
}];
|
|
2172
|
+
}
|
|
2173
|
+
if (message.type !== "assistant")
|
|
2174
|
+
return [];
|
|
2175
|
+
const created = message.time.created;
|
|
2176
|
+
const completed = message.time.completed;
|
|
2177
|
+
return [{
|
|
2178
|
+
role: "assistant",
|
|
2179
|
+
content: message.content.filter((part) => part.type === "text").map((part) => part.text).join(`
|
|
2180
|
+
`),
|
|
2181
|
+
timestamp: new Date(completed ?? created).toISOString(),
|
|
2182
|
+
messageID: message.id,
|
|
2183
|
+
parentMessageID,
|
|
2184
|
+
completedAt: completed ? new Date(completed).toISOString() : undefined,
|
|
2185
|
+
tokens: message.tokens ? {
|
|
2186
|
+
input: message.tokens.input,
|
|
2187
|
+
output: message.tokens.output,
|
|
2188
|
+
reasoning: message.tokens.reasoning,
|
|
2189
|
+
cacheRead: message.tokens.cache.read,
|
|
2190
|
+
cacheWrite: message.tokens.cache.write
|
|
2191
|
+
} : undefined,
|
|
2192
|
+
cost: message.cost,
|
|
2193
|
+
durationMs: completed && completed >= created ? completed - created : undefined
|
|
2194
|
+
}];
|
|
2195
|
+
}).slice(-limit);
|
|
2196
|
+
} catch {
|
|
2197
|
+
return [];
|
|
2198
|
+
}
|
|
2199
|
+
},
|
|
2200
|
+
async compactSession(sessionID) {
|
|
2201
|
+
try {
|
|
2202
|
+
await context.session.command({ sessionID, name: "compact", text: "" });
|
|
2203
|
+
} catch {}
|
|
2204
|
+
},
|
|
2205
|
+
async notifyOwner(ownerSessionID, message) {
|
|
2206
|
+
try {
|
|
2207
|
+
await context.session.prompt({ sessionID: ownerSessionID, text: message });
|
|
2208
|
+
await logServerEvent(directory, "parent.notified", { ownerSessionID, preview: message.slice(0, 160) });
|
|
2209
|
+
} catch (error) {
|
|
2210
|
+
await logServerEvent(directory, "parent.notify.failed", { ownerSessionID, detail: describeError(error) });
|
|
2211
|
+
}
|
|
2212
|
+
}
|
|
2213
|
+
};
|
|
2214
|
+
}
|
|
2106
2215
|
async function withTimeout(promise, timeoutMs, operation) {
|
|
2107
2216
|
let timer;
|
|
2108
2217
|
try {
|
|
@@ -4337,6 +4446,9 @@ var PLUGIN_ID = "opencode-loopd.server";
|
|
|
4337
4446
|
var server = async ({ client, directory }, pluginOptions) => {
|
|
4338
4447
|
const defaults = parsePluginDefaults(pluginOptions);
|
|
4339
4448
|
const host = createRealHost(client, directory);
|
|
4449
|
+
return createServerHooks(directory, host, defaults);
|
|
4450
|
+
};
|
|
4451
|
+
function createServerHooks(directory, host, defaults) {
|
|
4340
4452
|
const goalService = createGoalService(host);
|
|
4341
4453
|
const worker = createControlWorker({
|
|
4342
4454
|
directory,
|
|
@@ -4465,7 +4577,7 @@ var server = async ({ client, directory }, pluginOptions) => {
|
|
|
4465
4577
|
scheduleWorker.stop();
|
|
4466
4578
|
}
|
|
4467
4579
|
};
|
|
4468
|
-
}
|
|
4580
|
+
}
|
|
4469
4581
|
function parsePluginDefaults(options) {
|
|
4470
4582
|
const agent = typeof options?.defaultAgent === "string" ? options.defaultAgent.trim() : "";
|
|
4471
4583
|
const model = typeof options?.defaultModel === "string" ? options.defaultModel.trim() : "";
|
|
@@ -4476,10 +4588,127 @@ function parsePluginDefaults(options) {
|
|
|
4476
4588
|
defaultChecks: checks.length > 0 ? checks : undefined
|
|
4477
4589
|
};
|
|
4478
4590
|
}
|
|
4479
|
-
var v2 =
|
|
4591
|
+
var v2 = {
|
|
4480
4592
|
id: PLUGIN_ID,
|
|
4481
|
-
async setup() {
|
|
4482
|
-
|
|
4593
|
+
async setup(context) {
|
|
4594
|
+
const directory = context.location.directory;
|
|
4595
|
+
const statuses = new Map;
|
|
4596
|
+
const host = createV2Host(context, statuses);
|
|
4597
|
+
const hooks = createServerHooks(directory, host, parsePluginDefaults(context.options));
|
|
4598
|
+
const registrations = [];
|
|
4599
|
+
const eventController = new AbortController;
|
|
4600
|
+
let eventTask = Promise.resolve();
|
|
4601
|
+
let disposed = false;
|
|
4602
|
+
const cleanup = async () => {
|
|
4603
|
+
if (disposed)
|
|
4604
|
+
return;
|
|
4605
|
+
disposed = true;
|
|
4606
|
+
eventController.abort();
|
|
4607
|
+
await eventTask;
|
|
4608
|
+
try {
|
|
4609
|
+
await Promise.allSettled(registrations.reverse().map((registration) => registration.dispose()));
|
|
4610
|
+
} finally {
|
|
4611
|
+
await hooks.dispose?.();
|
|
4612
|
+
}
|
|
4613
|
+
};
|
|
4614
|
+
try {
|
|
4615
|
+
registrations.push(await context.tool.transform((editor) => {
|
|
4616
|
+
for (const [id, definition] of Object.entries(hooks.tool ?? {})) {
|
|
4617
|
+
editor.add(toV2Tool(id, definition, directory));
|
|
4618
|
+
}
|
|
4619
|
+
}));
|
|
4620
|
+
registrations.push(await context.tool.hook("execute.before", async (input) => {
|
|
4621
|
+
await hooks["tool.execute.before"]?.({
|
|
4622
|
+
tool: input.tool,
|
|
4623
|
+
sessionID: input.sessionID,
|
|
4624
|
+
callID: input.id
|
|
4625
|
+
}, { args: input.input });
|
|
4626
|
+
}));
|
|
4627
|
+
registrations.push(await context.tool.hook("execute.after", async (input) => {
|
|
4628
|
+
const output = input.status === "completed" ? input.result : { content: JSON.stringify(input.error) };
|
|
4629
|
+
await hooks["tool.execute.after"]?.({
|
|
4630
|
+
tool: input.tool,
|
|
4631
|
+
sessionID: input.sessionID,
|
|
4632
|
+
callID: input.id,
|
|
4633
|
+
args: input.input
|
|
4634
|
+
}, {
|
|
4635
|
+
title: "",
|
|
4636
|
+
output: typeof output.content === "string" ? output.content : JSON.stringify(output.content ?? ""),
|
|
4637
|
+
metadata: output.metadata ?? {}
|
|
4638
|
+
});
|
|
4639
|
+
}));
|
|
4640
|
+
eventTask = consumeV2Events(context, eventController.signal, statuses, hooks).catch(async (error) => {
|
|
4641
|
+
if (!eventController.signal.aborted) {
|
|
4642
|
+
await logServerEvent(directory, "events.failed", { detail: describeError(error) });
|
|
4643
|
+
}
|
|
4644
|
+
});
|
|
4645
|
+
return cleanup;
|
|
4646
|
+
} catch (error) {
|
|
4647
|
+
await cleanup();
|
|
4648
|
+
throw error;
|
|
4649
|
+
}
|
|
4650
|
+
}
|
|
4651
|
+
};
|
|
4652
|
+
function toV2Tool(id, definition, directory) {
|
|
4653
|
+
return {
|
|
4654
|
+
name: id,
|
|
4655
|
+
description: definition.description,
|
|
4656
|
+
input: v1Tool.schema.object(definition.args),
|
|
4657
|
+
async execute(input, context) {
|
|
4658
|
+
const result = await definition.execute(input, {
|
|
4659
|
+
sessionID: context.sessionID,
|
|
4660
|
+
agent: context.agent,
|
|
4661
|
+
messageID: context.messageID,
|
|
4662
|
+
directory,
|
|
4663
|
+
worktree: directory,
|
|
4664
|
+
abort: new AbortController().signal,
|
|
4665
|
+
metadata() {},
|
|
4666
|
+
async ask() {}
|
|
4667
|
+
});
|
|
4668
|
+
if (typeof result === "string")
|
|
4669
|
+
return { content: result };
|
|
4670
|
+
return {
|
|
4671
|
+
content: result.output,
|
|
4672
|
+
metadata: {
|
|
4673
|
+
...result.metadata,
|
|
4674
|
+
...result.title ? { title: result.title } : {}
|
|
4675
|
+
}
|
|
4676
|
+
};
|
|
4677
|
+
}
|
|
4678
|
+
};
|
|
4679
|
+
}
|
|
4680
|
+
async function consumeV2Events(context, signal, statuses, hooks) {
|
|
4681
|
+
for await (const event of context.event.subscribe({ signal })) {
|
|
4682
|
+
const data = "data" in event && event.data && typeof event.data === "object" ? event.data : {};
|
|
4683
|
+
const sessionID = typeof data.sessionID === "string" ? data.sessionID : undefined;
|
|
4684
|
+
if (sessionID) {
|
|
4685
|
+
if (event.type === "session.status")
|
|
4686
|
+
statuses.set(sessionID, data.status?.type ?? "unknown");
|
|
4687
|
+
else if (event.type === "session.idle")
|
|
4688
|
+
statuses.set(sessionID, "idle");
|
|
4689
|
+
else if (event.type === "session.execution.started")
|
|
4690
|
+
statuses.set(sessionID, "busy");
|
|
4691
|
+
}
|
|
4692
|
+
await hooks.event?.({ event: normalizeV2Event(event) });
|
|
4693
|
+
}
|
|
4694
|
+
}
|
|
4695
|
+
function normalizeV2Event(event) {
|
|
4696
|
+
const properties = event?.data && typeof event.data === "object" ? event.data : {};
|
|
4697
|
+
if (event?.type === "session.compaction.ended")
|
|
4698
|
+
return { type: "session.compacted", properties };
|
|
4699
|
+
if (event?.type === "session.execution.failed")
|
|
4700
|
+
return { type: "session.error", properties };
|
|
4701
|
+
if (event?.type === "session.message.content.updated") {
|
|
4702
|
+
return {
|
|
4703
|
+
type: "message.part.updated",
|
|
4704
|
+
properties: {
|
|
4705
|
+
sessionID: properties.sessionID,
|
|
4706
|
+
part: { messageID: properties.messageID }
|
|
4707
|
+
}
|
|
4708
|
+
};
|
|
4709
|
+
}
|
|
4710
|
+
return { type: event?.type, properties };
|
|
4711
|
+
}
|
|
4483
4712
|
var plugin_default = {
|
|
4484
4713
|
id: PLUGIN_ID,
|
|
4485
4714
|
server,
|
package/dist/tui.js
CHANGED
|
@@ -2373,9 +2373,171 @@ var tui = async (api) => {
|
|
|
2373
2373
|
});
|
|
2374
2374
|
api.lifecycle.onDispose(() => {});
|
|
2375
2375
|
};
|
|
2376
|
+
function adaptThemeV2(theme) {
|
|
2377
|
+
const t = theme ?? {};
|
|
2378
|
+
const text = t.text ?? {};
|
|
2379
|
+
const fb = text.feedback ?? {};
|
|
2380
|
+
const bg = t.background ?? {};
|
|
2381
|
+
const surface = bg.surface ?? {};
|
|
2382
|
+
const diff = t.diff ?? {};
|
|
2383
|
+
const diffText = diff.text ?? {};
|
|
2384
|
+
const diffBg = diff.background ?? {};
|
|
2385
|
+
const diffHi = diff.highlight ?? {};
|
|
2386
|
+
const diffLn = diff.lineNumber ?? {};
|
|
2387
|
+
const syntax = t.syntax ?? {};
|
|
2388
|
+
const md = t.markdown ?? {};
|
|
2389
|
+
const dv = (v, fallback) => typeof v === "string" ? v : fallback;
|
|
2390
|
+
const base = dv(text.default, "#ffffff");
|
|
2391
|
+
const muted = dv(text.subdued, "#888888");
|
|
2392
|
+
return {
|
|
2393
|
+
text: base,
|
|
2394
|
+
textMuted: muted,
|
|
2395
|
+
primary: base,
|
|
2396
|
+
accent: base,
|
|
2397
|
+
success: dv(fb.success?.default, "#22c55e"),
|
|
2398
|
+
warning: dv(fb.warning?.default, "#eab308"),
|
|
2399
|
+
error: dv(fb.error?.default, "#ef4444"),
|
|
2400
|
+
info: dv(fb.info?.default, base),
|
|
2401
|
+
background: dv(bg.default, "#000000"),
|
|
2402
|
+
backgroundPanel: dv(surface.overlay, dv(bg.default, "#000000")),
|
|
2403
|
+
backgroundElement: dv(surface.offset, dv(bg.default, "#000000")),
|
|
2404
|
+
diffAdded: dv(diffText.added, base),
|
|
2405
|
+
diffRemoved: dv(diffText.removed, base),
|
|
2406
|
+
diffContext: dv(diffText.context, muted),
|
|
2407
|
+
diffAddedBg: dv(diffBg.added, dv(bg.default, "#000000")),
|
|
2408
|
+
diffRemovedBg: dv(diffBg.removed, dv(bg.default, "#000000")),
|
|
2409
|
+
diffContextBg: dv(diffBg.context, dv(bg.default, "#000000")),
|
|
2410
|
+
diffHighlightAdded: dv(diffHi.added, base),
|
|
2411
|
+
diffHighlightRemoved: dv(diffHi.removed, base),
|
|
2412
|
+
diffLineNumber: dv(diffLn.text, muted),
|
|
2413
|
+
diffAddedLineNumberBg: dv(diffLn.background?.added, dv(bg.default, "#000000")),
|
|
2414
|
+
diffRemovedLineNumberBg: dv(diffLn.background?.removed, dv(bg.default, "#000000")),
|
|
2415
|
+
syntaxComment: dv(syntax.comment, muted),
|
|
2416
|
+
syntaxKeyword: dv(syntax.keyword, base),
|
|
2417
|
+
syntaxFunction: dv(syntax.function, base),
|
|
2418
|
+
syntaxVariable: dv(syntax.variable, base),
|
|
2419
|
+
syntaxString: dv(syntax.string, base),
|
|
2420
|
+
syntaxNumber: dv(syntax.number, base),
|
|
2421
|
+
syntaxType: dv(syntax.type, base),
|
|
2422
|
+
syntaxOperator: dv(syntax.operator, base),
|
|
2423
|
+
syntaxPunctuation: dv(syntax.punctuation, muted),
|
|
2424
|
+
markdownText: dv(md.text, base),
|
|
2425
|
+
markdownHeading: dv(md.heading, base),
|
|
2426
|
+
markdownLink: dv(md.link, base),
|
|
2427
|
+
markdownLinkText: dv(md.linkText, base),
|
|
2428
|
+
markdownCode: dv(md.code, base),
|
|
2429
|
+
markdownBlockQuote: dv(md.blockQuote, muted),
|
|
2430
|
+
markdownEmph: dv(md.emphasis, base),
|
|
2431
|
+
markdownStrong: dv(md.strong, base),
|
|
2432
|
+
markdownListItem: dv(md.listItem, base)
|
|
2433
|
+
};
|
|
2434
|
+
}
|
|
2435
|
+
var v2setup = (ctx) => {
|
|
2436
|
+
const directory = ctx.location?.directory ?? ctx.data.location.default().directory;
|
|
2437
|
+
let dialogOpen = false;
|
|
2438
|
+
const closeDialog = () => {
|
|
2439
|
+
dialogOpen = false;
|
|
2440
|
+
ctx.ui.dialog.clear();
|
|
2441
|
+
};
|
|
2442
|
+
const facade = {
|
|
2443
|
+
theme: {
|
|
2444
|
+
get current() {
|
|
2445
|
+
return adaptThemeV2(ctx.theme);
|
|
2446
|
+
}
|
|
2447
|
+
},
|
|
2448
|
+
mode: {
|
|
2449
|
+
push: (name) => ctx.keymap.mode.push(name)
|
|
2450
|
+
},
|
|
2451
|
+
renderer: ctx.renderer,
|
|
2452
|
+
client: ctx.client,
|
|
2453
|
+
event: {
|
|
2454
|
+
on: (name, callback) => {
|
|
2455
|
+
if (name === "session.idle")
|
|
2456
|
+
return ctx.data.on("session.idle", callback);
|
|
2457
|
+
if (name === "session.status") {
|
|
2458
|
+
const unsubs = [ctx.data.on("session.execution.started", callback), ctx.data.on("session.execution.succeeded", callback)];
|
|
2459
|
+
return () => void unsubs.forEach((un) => un());
|
|
2460
|
+
}
|
|
2461
|
+
if (name === "session.error")
|
|
2462
|
+
return ctx.data.on("session.execution.failed", callback);
|
|
2463
|
+
if (name === "session.compacted")
|
|
2464
|
+
return ctx.data.on("session.compaction.ended", callback);
|
|
2465
|
+
return ctx.data.on(name, callback);
|
|
2466
|
+
}
|
|
2467
|
+
},
|
|
2468
|
+
ui: {
|
|
2469
|
+
dialog: {
|
|
2470
|
+
clear: closeDialog,
|
|
2471
|
+
get open() {
|
|
2472
|
+
return dialogOpen;
|
|
2473
|
+
},
|
|
2474
|
+
replace: (render) => {
|
|
2475
|
+
dialogOpen = true;
|
|
2476
|
+
ctx.ui.dialog.show(render);
|
|
2477
|
+
},
|
|
2478
|
+
setSize: (_size) => ctx.ui.dialog.set({
|
|
2479
|
+
size: "xlarge"
|
|
2480
|
+
})
|
|
2481
|
+
}
|
|
2482
|
+
},
|
|
2483
|
+
route: {
|
|
2484
|
+
navigate: (name, params) => {
|
|
2485
|
+
if (name === "session")
|
|
2486
|
+
ctx.ui.router.navigate({
|
|
2487
|
+
type: "session",
|
|
2488
|
+
sessionID: params?.sessionID
|
|
2489
|
+
});
|
|
2490
|
+
}
|
|
2491
|
+
}
|
|
2492
|
+
};
|
|
2493
|
+
const open = () => {
|
|
2494
|
+
const previousFocus = ctx.renderer.currentFocusedRenderable;
|
|
2495
|
+
dialogOpen = true;
|
|
2496
|
+
ctx.ui.dialog.show(() => _$createComponent2(LoopDashboard, {
|
|
2497
|
+
api: facade,
|
|
2498
|
+
directory
|
|
2499
|
+
}), () => {
|
|
2500
|
+
dialogOpen = false;
|
|
2501
|
+
});
|
|
2502
|
+
ctx.ui.dialog.set({
|
|
2503
|
+
size: "xlarge"
|
|
2504
|
+
});
|
|
2505
|
+
previousFocus?.blur();
|
|
2506
|
+
};
|
|
2507
|
+
const command = "opencode.loopd.dashboard";
|
|
2508
|
+
let layerRegistered = false;
|
|
2509
|
+
const unclaimSlot = ctx.ui.slot({
|
|
2510
|
+
append: "app",
|
|
2511
|
+
render: () => {
|
|
2512
|
+
if (!layerRegistered) {
|
|
2513
|
+
layerRegistered = true;
|
|
2514
|
+
ctx.keymap.layer(() => ({
|
|
2515
|
+
commands: [{
|
|
2516
|
+
id: command,
|
|
2517
|
+
title: "Loop Dashboard",
|
|
2518
|
+
group: "Loop",
|
|
2519
|
+
palette: true,
|
|
2520
|
+
slash: {
|
|
2521
|
+
name: "loop"
|
|
2522
|
+
},
|
|
2523
|
+
bind: "<leader>o",
|
|
2524
|
+
run: open
|
|
2525
|
+
}],
|
|
2526
|
+
bindings: [command]
|
|
2527
|
+
}));
|
|
2528
|
+
}
|
|
2529
|
+
return null;
|
|
2530
|
+
}
|
|
2531
|
+
});
|
|
2532
|
+
return () => {
|
|
2533
|
+
closeDialog();
|
|
2534
|
+
unclaimSlot();
|
|
2535
|
+
};
|
|
2536
|
+
};
|
|
2376
2537
|
var plugin_default = {
|
|
2377
2538
|
id: PLUGIN_ID,
|
|
2378
|
-
tui
|
|
2539
|
+
tui,
|
|
2540
|
+
setup: v2setup
|
|
2379
2541
|
};
|
|
2380
2542
|
export {
|
|
2381
2543
|
plugin_default as default
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://json.schemastore.org/package.json",
|
|
3
3
|
"name": "@bojackduy/opencode-loopd",
|
|
4
|
-
"version": "1.
|
|
4
|
+
"version": "1.10.0",
|
|
5
5
|
"description": "Codex-inspired background goal engine for OpenCode — autonomous subagents, engine-driven loop, child worker sessions and modal TUI dashboard. Like Claude Code loop for OpenCode.",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"license": "AGPL-3.0-or-later",
|
|
@@ -80,6 +80,7 @@
|
|
|
80
80
|
},
|
|
81
81
|
"devDependencies": {
|
|
82
82
|
"@opencode-ai/plugin": "^1.18.30",
|
|
83
|
+
"@opencode/plugin": "^2.0.11",
|
|
83
84
|
"@opentui/core": "^0.4.1",
|
|
84
85
|
"@opentui/solid": "^0.4.1",
|
|
85
86
|
"@types/bun": "^1.3.14",
|