@fdcn/sourcefed 0.3.5 → 0.3.7
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 +2 -7
- package/dist/{chunk-X3BZSHKZ.js → chunk-E6J3BAXP.js} +198 -160
- package/dist/cli.js +215 -222
- package/dist/daemon.js +200 -162
- package/dist/mcp.js +1 -1
- package/dist/opencode.js +258 -121
- package/dist/pi.js +1 -1
- package/dist/tui-compiled.mjs +57 -67
- package/dist.dts/adapters/opencode/bridge.d.ts +66 -22
- package/dist.dts/adapters/opencode/subscriptions.d.ts +46 -0
- package/dist.dts/adapters/opencode/tool-result.d.ts +2 -1
- package/dist.dts/adapters/opencode/tools/monitor_create.d.ts +3 -2
- package/dist.dts/adapters/opencode/tools/monitor_list.d.ts +3 -2
- package/dist.dts/adapters/opencode/tools/monitor_start.d.ts +3 -2
- package/dist.dts/adapters/opencode/tools/monitor_status.d.ts +3 -2
- package/dist.dts/adapters/opencode/tools/monitor_stop.d.ts +3 -2
- package/dist.dts/packages/cli/src/utils/setup.d.ts +0 -1
- package/dist.dts/packages/daemon/src/event-stream.d.ts +26 -0
- package/dist.dts/packages/daemon/src/types/client.d.ts +3 -1
- package/dist.dts/packages/daemon/src/utils/index.d.ts +0 -1
- package/package.json +1 -1
- package/dist.dts/packages/daemon/src/utils/forward.d.ts +0 -32
- package/dist.dts/packages/daemon/src/utils/gate.d.ts +0 -33
- package/dist.dts/packages/daemon/src/utils/request-router.d.ts +0 -11
- /package/dist.dts/{packages/daemon/src/forward.test.d.ts → adapters/opencode/lifecycle.test.d.ts} +0 -0
- /package/dist.dts/packages/daemon/src/{gate.test.d.ts → stream-lifecycle.test.d.ts} +0 -0
package/dist/opencode.js
CHANGED
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
daemonCommand,
|
|
8
8
|
daemonEnvironment,
|
|
9
9
|
spawnLocalDaemon
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-E6J3BAXP.js";
|
|
11
11
|
import "./chunk-MLKGABMK.js";
|
|
12
12
|
|
|
13
13
|
// packages/sourcefed/src/server.ts
|
|
@@ -22,9 +22,193 @@ import { Plugin } from "@opencode/plugin";
|
|
|
22
22
|
import { existsSync } from "node:fs";
|
|
23
23
|
import { fileURLToPath } from "node:url";
|
|
24
24
|
import { Rpc } from "@opencode/plugin";
|
|
25
|
+
|
|
26
|
+
// adapters/opencode/subscriptions.ts
|
|
27
|
+
var REFRESH_MS = 15e3;
|
|
28
|
+
var OpenCodeSubscriptions = class {
|
|
29
|
+
constructor(connect) {
|
|
30
|
+
this.connect = connect;
|
|
31
|
+
}
|
|
32
|
+
owners = /* @__PURE__ */ new Set();
|
|
33
|
+
subscriptions = /* @__PURE__ */ new Map();
|
|
34
|
+
lifetime = new AbortController();
|
|
35
|
+
daemon;
|
|
36
|
+
connecting;
|
|
37
|
+
refreshing;
|
|
38
|
+
dirty = false;
|
|
39
|
+
lastAttemptAt = -Infinity;
|
|
40
|
+
timer;
|
|
41
|
+
get closed() {
|
|
42
|
+
return this.lifetime.signal.aborted;
|
|
43
|
+
}
|
|
44
|
+
async add(owner) {
|
|
45
|
+
if (this.closed) throw new Error("sourcefed subscription hub is closed");
|
|
46
|
+
this.owners.add(owner);
|
|
47
|
+
if (!this.timer) {
|
|
48
|
+
this.timer = setInterval(() => void this.refresh(), REFRESH_MS);
|
|
49
|
+
this.timer.unref?.();
|
|
50
|
+
}
|
|
51
|
+
await this.refresh();
|
|
52
|
+
}
|
|
53
|
+
async remove(owner) {
|
|
54
|
+
this.owners.delete(owner);
|
|
55
|
+
const closing = [];
|
|
56
|
+
for (const [id, subscription] of this.subscriptions) {
|
|
57
|
+
if (this.ownerFor(subscription.info)) continue;
|
|
58
|
+
this.subscriptions.delete(id);
|
|
59
|
+
closing.push(this.closeSubscription(subscription));
|
|
60
|
+
}
|
|
61
|
+
if (this.owners.size > 0) {
|
|
62
|
+
await Promise.all(closing);
|
|
63
|
+
await this.refresh();
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
this.lifetime.abort();
|
|
67
|
+
clearInterval(this.timer);
|
|
68
|
+
this.timer = void 0;
|
|
69
|
+
await Promise.all(closing);
|
|
70
|
+
await this.daemon?.close();
|
|
71
|
+
this.daemon = void 0;
|
|
72
|
+
await this.connecting;
|
|
73
|
+
await this.refreshing;
|
|
74
|
+
}
|
|
75
|
+
async request(method, params) {
|
|
76
|
+
const daemon = await this.ensureDaemon();
|
|
77
|
+
if (!daemon || this.closed) throw new Error("sourcefed daemon unavailable or bridge closed");
|
|
78
|
+
return daemon.request(method, params);
|
|
79
|
+
}
|
|
80
|
+
refresh() {
|
|
81
|
+
if (this.closed) return Promise.resolve();
|
|
82
|
+
this.dirty = true;
|
|
83
|
+
if (!this.refreshing) {
|
|
84
|
+
this.refreshing = this.refreshLoop();
|
|
85
|
+
}
|
|
86
|
+
return this.refreshing;
|
|
87
|
+
}
|
|
88
|
+
async refreshLoop() {
|
|
89
|
+
try {
|
|
90
|
+
do {
|
|
91
|
+
this.dirty = false;
|
|
92
|
+
try {
|
|
93
|
+
const daemon = await this.ensureDaemon();
|
|
94
|
+
if (daemon && !this.closed) await this.reconcile(daemon);
|
|
95
|
+
} catch (error) {
|
|
96
|
+
if (!this.closed) console.error(`[sourcefed] refresh failed: ${String(error)}`);
|
|
97
|
+
}
|
|
98
|
+
} while (this.dirty && !this.closed);
|
|
99
|
+
} finally {
|
|
100
|
+
this.refreshing = void 0;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
async ensureDaemon() {
|
|
104
|
+
if (this.closed) return void 0;
|
|
105
|
+
if (this.daemon) return this.daemon;
|
|
106
|
+
if (this.connecting) return this.connecting;
|
|
107
|
+
if (Date.now() - this.lastAttemptAt < REFRESH_MS) return void 0;
|
|
108
|
+
this.lastAttemptAt = Date.now();
|
|
109
|
+
this.connecting = this.connect().then(async (daemon) => {
|
|
110
|
+
if (this.closed) {
|
|
111
|
+
await daemon.close();
|
|
112
|
+
return void 0;
|
|
113
|
+
}
|
|
114
|
+
this.daemon = daemon;
|
|
115
|
+
return daemon;
|
|
116
|
+
}).catch((error) => {
|
|
117
|
+
console.error(`[sourcefed] daemon unavailable: ${String(error)}`);
|
|
118
|
+
return void 0;
|
|
119
|
+
}).finally(() => {
|
|
120
|
+
this.connecting = void 0;
|
|
121
|
+
});
|
|
122
|
+
return this.connecting;
|
|
123
|
+
}
|
|
124
|
+
async reconcile(daemon) {
|
|
125
|
+
const result = await daemon.request("monitor.targets", { kind: "opencode-session" });
|
|
126
|
+
const targets = enabledSessions(result);
|
|
127
|
+
for (const [id, subscription] of this.subscriptions) {
|
|
128
|
+
if (targets.has(id)) continue;
|
|
129
|
+
this.subscriptions.delete(id);
|
|
130
|
+
await this.closeSubscription(subscription);
|
|
131
|
+
}
|
|
132
|
+
for (const id of targets) {
|
|
133
|
+
if (this.closed) return;
|
|
134
|
+
const reader = this.owners.values().next().value;
|
|
135
|
+
if (!reader) return;
|
|
136
|
+
let info;
|
|
137
|
+
try {
|
|
138
|
+
info = await reader.getSession(id, this.lifetime.signal);
|
|
139
|
+
} catch (error) {
|
|
140
|
+
if (!error || typeof error !== "object" || !("_tag" in error) || error._tag !== "SessionNotFoundError") {
|
|
141
|
+
if (!this.closed) console.error(`[sourcefed] session ${id} lookup failed: ${String(error)}`);
|
|
142
|
+
continue;
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
if (this.closed) return;
|
|
146
|
+
const owner = info && this.ownerFor(info);
|
|
147
|
+
const existing = this.subscriptions.get(id);
|
|
148
|
+
if (!owner || !info) {
|
|
149
|
+
if (existing) {
|
|
150
|
+
this.subscriptions.delete(id);
|
|
151
|
+
await this.closeSubscription(existing);
|
|
152
|
+
}
|
|
153
|
+
} else if (existing) {
|
|
154
|
+
existing.info = info;
|
|
155
|
+
} else {
|
|
156
|
+
await this.subscribe(daemon, id, info);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
ownerFor(info) {
|
|
161
|
+
const candidates = [...this.owners].filter((owner) => owner.location.project.id === info.projectID);
|
|
162
|
+
return candidates.find((owner) => owner.location.directory === info.location.directory) ?? candidates[0];
|
|
163
|
+
}
|
|
164
|
+
async subscribe(daemon, id, info) {
|
|
165
|
+
const controller = new AbortController();
|
|
166
|
+
const subscription = {
|
|
167
|
+
info,
|
|
168
|
+
controller,
|
|
169
|
+
listener: daemon.subscribe({ kind: "opencode-session", id }, async (events) => {
|
|
170
|
+
await this.route(id, subscription, events);
|
|
171
|
+
}, { signal: controller.signal })
|
|
172
|
+
};
|
|
173
|
+
this.subscriptions.set(id, subscription);
|
|
174
|
+
try {
|
|
175
|
+
await subscription.listener;
|
|
176
|
+
} catch (error) {
|
|
177
|
+
if (this.subscriptions.get(id) === subscription) this.subscriptions.delete(id);
|
|
178
|
+
if (!controller.signal.aborted) console.error(`[sourcefed] subscribe ${id} failed: ${String(error)}`);
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
async route(id, subscription, events) {
|
|
182
|
+
const reader = this.owners.values().next().value;
|
|
183
|
+
if (!reader) throw new Error("sourcefed session owner unloaded");
|
|
184
|
+
const info = await reader.getSession(id, this.lifetime.signal);
|
|
185
|
+
const owner = this.ownerFor(info);
|
|
186
|
+
if (!owner) throw new Error("sourcefed session has no loaded project owner");
|
|
187
|
+
subscription.info = info;
|
|
188
|
+
await owner.routeEvents(events);
|
|
189
|
+
}
|
|
190
|
+
async closeSubscription(subscription) {
|
|
191
|
+
subscription.controller.abort();
|
|
192
|
+
await subscription.listener.then((listener) => listener.close(), () => void 0);
|
|
193
|
+
}
|
|
194
|
+
};
|
|
195
|
+
function enabledSessions(result) {
|
|
196
|
+
if (!result || typeof result !== "object" || !("targets" in result) || !Array.isArray(result.targets)) {
|
|
197
|
+
throw new Error("invalid monitor.targets response");
|
|
198
|
+
}
|
|
199
|
+
const ids = /* @__PURE__ */ new Set();
|
|
200
|
+
for (const target of result.targets) {
|
|
201
|
+
if (!target || target.kind !== "opencode-session" || typeof target.id !== "string") {
|
|
202
|
+
throw new Error("invalid opencode-session target");
|
|
203
|
+
}
|
|
204
|
+
ids.add(target.id);
|
|
205
|
+
}
|
|
206
|
+
return ids;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
// adapters/opencode/bridge.ts
|
|
25
210
|
var TARGET_KIND = "opencode-session";
|
|
26
211
|
var GATE_TIMEOUT_MS = 3e3;
|
|
27
|
-
var RESUBSCRIBE_MS = 15e3;
|
|
28
212
|
var ChauffeurGate = Rpc.define({
|
|
29
213
|
id: "chauffeur",
|
|
30
214
|
methods: {
|
|
@@ -52,97 +236,53 @@ var ChauffeurGate = Rpc.define({
|
|
|
52
236
|
},
|
|
53
237
|
events: {}
|
|
54
238
|
});
|
|
55
|
-
var
|
|
239
|
+
var HUB = Symbol.for("sourcefed.opencode.subscriptions.v1");
|
|
240
|
+
var shared = globalThis;
|
|
241
|
+
function subscriptions() {
|
|
242
|
+
if (!shared[HUB] || shared[HUB].closed) shared[HUB] = new OpenCodeSubscriptions(connectDaemon);
|
|
243
|
+
return shared[HUB];
|
|
244
|
+
}
|
|
56
245
|
var OpenCodeBridge = class {
|
|
57
|
-
constructor(session, rpc) {
|
|
246
|
+
constructor(session, rpc, location, hub = subscriptions()) {
|
|
58
247
|
this.session = session;
|
|
59
248
|
this.rpc = rpc;
|
|
249
|
+
this.location = location;
|
|
250
|
+
this.hub = hub;
|
|
60
251
|
}
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
lastError;
|
|
65
|
-
timer;
|
|
252
|
+
started;
|
|
253
|
+
closed = false;
|
|
254
|
+
closing;
|
|
66
255
|
/**
|
|
67
256
|
* Chauffeur or the CLI can create a monitor for a session here at any time,
|
|
68
257
|
* without this bridge's tools, so check for new targets periodically too.
|
|
69
258
|
*/
|
|
70
259
|
async start() {
|
|
71
|
-
|
|
72
|
-
this.
|
|
73
|
-
this.
|
|
260
|
+
if (this.closed) throw new Error("sourcefed bridge is closed");
|
|
261
|
+
this.started ??= this.hub.add(this);
|
|
262
|
+
await this.started;
|
|
74
263
|
}
|
|
75
|
-
async
|
|
76
|
-
await this.ensureDaemon();
|
|
77
|
-
const existing = this.listeners.get(sessionID);
|
|
78
|
-
if (existing) {
|
|
79
|
-
await existing;
|
|
80
|
-
return;
|
|
81
|
-
}
|
|
82
|
-
const pending = this.daemon.subscribe(this.target(sessionID), async (events) => {
|
|
83
|
-
await this.routeEvents(events);
|
|
84
|
-
});
|
|
85
|
-
this.listeners.set(sessionID, pending);
|
|
264
|
+
async callTool(name, arguments_, sessionID) {
|
|
86
265
|
try {
|
|
87
|
-
await
|
|
266
|
+
await this.start();
|
|
267
|
+
const method = name.replace(/_/g, ".");
|
|
268
|
+
const result = await this.hub.request(method, { ...arguments_, target: this.target(sessionID) });
|
|
269
|
+
if (["monitor.create", "monitor.start", "monitor.stop", "monitor.remove"].includes(method)) await this.hub.refresh();
|
|
270
|
+
return result;
|
|
88
271
|
} catch (error) {
|
|
89
|
-
|
|
90
|
-
throw error;
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
async callTool(name, arguments_, sessionID) {
|
|
94
|
-
await this.ensureDaemon();
|
|
95
|
-
if (!this.daemon) {
|
|
96
|
-
return { ok: false, error: `sourcefed daemon unavailable: ${this.lastError ?? "not started"}` };
|
|
272
|
+
return { ok: false, error: String(error) };
|
|
97
273
|
}
|
|
98
|
-
await this.ensureTarget(sessionID);
|
|
99
|
-
return this.daemon.request(name.replace(/_/g, "."), { ...arguments_, target: this.target(sessionID) });
|
|
100
274
|
}
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
this.
|
|
104
|
-
|
|
105
|
-
this.
|
|
106
|
-
await this.daemon?.close();
|
|
107
|
-
this.daemon = void 0;
|
|
275
|
+
close() {
|
|
276
|
+
if (this.closing) return this.closing;
|
|
277
|
+
this.closed = true;
|
|
278
|
+
this.closing = this.started ? this.hub.remove(this) : Promise.resolve();
|
|
279
|
+
return this.closing;
|
|
108
280
|
}
|
|
109
281
|
async refresh() {
|
|
110
|
-
if (!this.
|
|
111
|
-
await this.resubscribe();
|
|
282
|
+
if (!this.closed) await this.hub.refresh();
|
|
112
283
|
}
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
if (Date.now() - this.lastAttemptAt < 15e3) return;
|
|
116
|
-
this.lastAttemptAt = Date.now();
|
|
117
|
-
try {
|
|
118
|
-
this.daemon = await connectDaemon();
|
|
119
|
-
void this.resubscribe();
|
|
120
|
-
} catch (error) {
|
|
121
|
-
this.lastError = error instanceof Error ? error.message : String(error);
|
|
122
|
-
console.error(`[sourcefed] daemon unavailable: ${this.lastError}`);
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
/**
|
|
126
|
-
* Monitors outlive this process, so after a restart nothing listens for their
|
|
127
|
-
* sessions until something subscribes. Subscribe every session that has an
|
|
128
|
-
* enabled monitor and still exists here; a deleted session is skipped, since
|
|
129
|
-
* delivering to it would fail and retry forever.
|
|
130
|
-
*/
|
|
131
|
-
async resubscribe() {
|
|
132
|
-
try {
|
|
133
|
-
const { targets } = await this.daemon.request("monitor.targets", { kind: TARGET_KIND });
|
|
134
|
-
await Promise.all(targets.map((target) => this.resubscribeTarget(target.id)));
|
|
135
|
-
} catch (error) {
|
|
136
|
-
console.error(`[sourcefed] resubscribe failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
137
|
-
}
|
|
138
|
-
}
|
|
139
|
-
async resubscribeTarget(sessionID) {
|
|
140
|
-
if (this.listeners.has(sessionID)) return;
|
|
141
|
-
const exists = await this.session.get({ sessionID }).then(() => true, () => false);
|
|
142
|
-
if (!exists) return;
|
|
143
|
-
await this.ensureTarget(sessionID).catch((error) => {
|
|
144
|
-
console.error(`[sourcefed] subscribe ${sessionID} failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
145
|
-
});
|
|
284
|
+
getSession(sessionID, signal) {
|
|
285
|
+
return this.session.get({ sessionID }, { signal: AbortSignal.any([signal, AbortSignal.timeout(3e3)]) });
|
|
146
286
|
}
|
|
147
287
|
// Every event arrives as a synthetic message, never as a user prompt, so it is
|
|
148
288
|
// not mistaken for the user's own words. Actionable events resume an idle
|
|
@@ -182,7 +322,7 @@ var OpenCodeBridge = class {
|
|
|
182
322
|
},
|
|
183
323
|
{ signal: AbortSignal.timeout(GATE_TIMEOUT_MS) }
|
|
184
324
|
);
|
|
185
|
-
return reply.deliver
|
|
325
|
+
return !(reply && typeof reply === "object" && "deliver" in reply && reply.deliver === false);
|
|
186
326
|
} catch {
|
|
187
327
|
return true;
|
|
188
328
|
}
|
|
@@ -207,22 +347,15 @@ function cliEntry() {
|
|
|
207
347
|
if (existsSync(bundled)) return bundled;
|
|
208
348
|
return fileURLToPath(import.meta.resolve("@sourcefed/cli"));
|
|
209
349
|
}
|
|
210
|
-
function setOpenCodeBridge(bridge) {
|
|
211
|
-
activeBridge = bridge;
|
|
212
|
-
}
|
|
213
|
-
function getOpenCodeBridge() {
|
|
214
|
-
if (!activeBridge) throw new Error("Sourcefed OpenCode bridge is not initialized");
|
|
215
|
-
return activeBridge;
|
|
216
|
-
}
|
|
217
350
|
|
|
218
351
|
// adapters/opencode/tool-result.ts
|
|
219
|
-
async function callMonitorTool(name, arguments_, sessionID) {
|
|
220
|
-
const result = await
|
|
352
|
+
async function callMonitorTool(bridge, name, arguments_, sessionID) {
|
|
353
|
+
const result = await bridge.callTool(name, arguments_, sessionID);
|
|
221
354
|
return JSON.stringify(result);
|
|
222
355
|
}
|
|
223
356
|
|
|
224
357
|
// adapters/opencode/tools/monitor_create.ts
|
|
225
|
-
var
|
|
358
|
+
var monitor_create_default = (bridge) => ({
|
|
226
359
|
name: "monitor_create",
|
|
227
360
|
description: "Create a detect-only monitor that watches a Jira issue, GitHub PR, Slack thread, or Slack DM and routes NEW events into the current session. Slack monitors only read and notify; they never reply. GitHub and Slack use webhooks when configured and polling otherwise; Jira uses polling.",
|
|
228
361
|
input: {
|
|
@@ -242,13 +375,12 @@ var definition = {
|
|
|
242
375
|
additionalProperties: false
|
|
243
376
|
},
|
|
244
377
|
async execute(input, context) {
|
|
245
|
-
return { content: await callMonitorTool("monitor_create", input ?? {}, context.sessionID) };
|
|
378
|
+
return { content: await callMonitorTool(bridge, "monitor_create", input ?? {}, context.sessionID) };
|
|
246
379
|
}
|
|
247
|
-
};
|
|
248
|
-
var monitor_create_default = definition;
|
|
380
|
+
});
|
|
249
381
|
|
|
250
382
|
// adapters/opencode/tools/monitor_list.ts
|
|
251
|
-
var
|
|
383
|
+
var monitor_list_default = (bridge) => ({
|
|
252
384
|
name: "monitor_list",
|
|
253
385
|
description: "List monitors created by the current session (id, name, source, delivery, enabled).",
|
|
254
386
|
input: {
|
|
@@ -257,13 +389,12 @@ var definition2 = {
|
|
|
257
389
|
additionalProperties: false
|
|
258
390
|
},
|
|
259
391
|
async execute(_input, context) {
|
|
260
|
-
return { content: await callMonitorTool("monitor_list", {}, context.sessionID) };
|
|
392
|
+
return { content: await callMonitorTool(bridge, "monitor_list", {}, context.sessionID) };
|
|
261
393
|
}
|
|
262
|
-
};
|
|
263
|
-
var monitor_list_default = definition2;
|
|
394
|
+
});
|
|
264
395
|
|
|
265
396
|
// adapters/opencode/tools/monitor_status.ts
|
|
266
|
-
var
|
|
397
|
+
var monitor_status_default = (bridge) => ({
|
|
267
398
|
name: "monitor_status",
|
|
268
399
|
description: "Get the status of a monitor created by the current session.",
|
|
269
400
|
input: {
|
|
@@ -276,13 +407,12 @@ var definition3 = {
|
|
|
276
407
|
},
|
|
277
408
|
async execute(input, context) {
|
|
278
409
|
const args = input ?? {};
|
|
279
|
-
return { content: await callMonitorTool("monitor_status", { id: args.id }, context.sessionID) };
|
|
410
|
+
return { content: await callMonitorTool(bridge, "monitor_status", { id: args.id }, context.sessionID) };
|
|
280
411
|
}
|
|
281
|
-
};
|
|
282
|
-
var monitor_status_default = definition3;
|
|
412
|
+
});
|
|
283
413
|
|
|
284
414
|
// adapters/opencode/tools/monitor_start.ts
|
|
285
|
-
var
|
|
415
|
+
var monitor_start_default = (bridge) => ({
|
|
286
416
|
name: "monitor_start",
|
|
287
417
|
description: "Start (re-enable) a stopped monitor created by the current session.",
|
|
288
418
|
input: {
|
|
@@ -295,13 +425,12 @@ var definition4 = {
|
|
|
295
425
|
},
|
|
296
426
|
async execute(input, context) {
|
|
297
427
|
const args = input ?? {};
|
|
298
|
-
return { content: await callMonitorTool("monitor_start", { id: args.id }, context.sessionID) };
|
|
428
|
+
return { content: await callMonitorTool(bridge, "monitor_start", { id: args.id }, context.sessionID) };
|
|
299
429
|
}
|
|
300
|
-
};
|
|
301
|
-
var monitor_start_default = definition4;
|
|
430
|
+
});
|
|
302
431
|
|
|
303
432
|
// adapters/opencode/tools/monitor_stop.ts
|
|
304
|
-
var
|
|
433
|
+
var monitor_stop_default = (bridge) => ({
|
|
305
434
|
name: "monitor_stop",
|
|
306
435
|
description: "Stop a monitor created by the current session.",
|
|
307
436
|
input: {
|
|
@@ -314,23 +443,26 @@ var definition5 = {
|
|
|
314
443
|
},
|
|
315
444
|
async execute(input, context) {
|
|
316
445
|
const args = input ?? {};
|
|
317
|
-
return { content: await callMonitorTool("monitor_stop", { id: args.id }, context.sessionID) };
|
|
446
|
+
return { content: await callMonitorTool(bridge, "monitor_stop", { id: args.id }, context.sessionID) };
|
|
318
447
|
}
|
|
319
|
-
};
|
|
320
|
-
var monitor_stop_default = definition5;
|
|
448
|
+
});
|
|
321
449
|
|
|
322
450
|
// adapters/opencode/index.ts
|
|
323
451
|
async function setupSourcefed(ctx) {
|
|
324
|
-
const bridge = new OpenCodeBridge(ctx.session, ctx.rpc);
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
452
|
+
const bridge = new OpenCodeBridge(ctx.session, ctx.rpc, ctx.location);
|
|
453
|
+
try {
|
|
454
|
+
await bridge.start();
|
|
455
|
+
await ctx.tool.transform((editor) => {
|
|
456
|
+
editor.add(monitor_create_default(bridge));
|
|
457
|
+
editor.add(monitor_list_default(bridge));
|
|
458
|
+
editor.add(monitor_status_default(bridge));
|
|
459
|
+
editor.add(monitor_start_default(bridge));
|
|
460
|
+
editor.add(monitor_stop_default(bridge));
|
|
461
|
+
});
|
|
462
|
+
} catch (error) {
|
|
463
|
+
await bridge.close();
|
|
464
|
+
throw error;
|
|
465
|
+
}
|
|
334
466
|
return () => bridge.close();
|
|
335
467
|
}
|
|
336
468
|
var opencode_default = Plugin.define({
|
|
@@ -345,11 +477,16 @@ var server_default = Plugin2.define({
|
|
|
345
477
|
id: "sourcefed",
|
|
346
478
|
async setup(ctx) {
|
|
347
479
|
const cleanup = await setupSourcefed(ctx);
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
event.system.
|
|
351
|
-
|
|
352
|
-
|
|
480
|
+
try {
|
|
481
|
+
await ctx.session.hook("context", (event) => {
|
|
482
|
+
if (!event.system.some((part) => part.type === "text" && part.text.includes(heading))) {
|
|
483
|
+
event.system.push({ type: "text", text: guidance });
|
|
484
|
+
}
|
|
485
|
+
});
|
|
486
|
+
} catch (error) {
|
|
487
|
+
await cleanup?.();
|
|
488
|
+
throw error;
|
|
489
|
+
}
|
|
353
490
|
return cleanup;
|
|
354
491
|
}
|
|
355
492
|
});
|
package/dist/pi.js
CHANGED
package/dist/tui-compiled.mjs
CHANGED
|
@@ -59,38 +59,43 @@ function Sidebar(props) {
|
|
|
59
59
|
void refresh();
|
|
60
60
|
const timer = setInterval(() => void refresh(), REFRESH_MS);
|
|
61
61
|
onCleanup(() => clearInterval(timer));
|
|
62
|
-
return (
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
62
|
+
return _$createComponent(Show, {
|
|
63
|
+
get when() {
|
|
64
|
+
return active().length > 0;
|
|
65
|
+
},
|
|
66
|
+
get children() {
|
|
67
|
+
var _el$ = _$createElement("box"), _el$2 = _$createElement("box"), _el$3 = _$createElement("text"), _el$5 = _$createElement("text"), _el$6 = _$createTextNode(` (`), _el$7 = _$createTextNode(`)`);
|
|
68
|
+
_$insertNode(_el$, _el$2);
|
|
69
|
+
_$setProp(_el$, "flexDirection", "column");
|
|
70
|
+
_$setProp(_el$, "width", "100%");
|
|
71
|
+
_$setProp(_el$, "marginTop", 1);
|
|
72
|
+
_$insertNode(_el$2, _el$3);
|
|
73
|
+
_$insertNode(_el$2, _el$5);
|
|
74
|
+
_$setProp(_el$2, "flexDirection", "row");
|
|
75
|
+
_$setProp(_el$2, "width", "100%");
|
|
76
|
+
_$insertNode(_el$3, _$createTextNode(`Sourcefed`));
|
|
77
|
+
_$insertNode(_el$5, _el$6);
|
|
78
|
+
_$insertNode(_el$5, _el$7);
|
|
79
|
+
_$insert(_el$5, () => active().length, _el$7);
|
|
80
|
+
_$insert(_el$, _$createComponent(MonitorRows, {
|
|
81
|
+
monitors: active,
|
|
82
|
+
get tone() {
|
|
83
|
+
return palette();
|
|
84
|
+
},
|
|
85
|
+
compact: true
|
|
86
|
+
}), null);
|
|
87
|
+
_$effect((_p$) => {
|
|
88
|
+
var _v$ = palette().accent, _v$2 = palette().textMuted;
|
|
89
|
+
_v$ !== _p$.e && (_p$.e = _$setProp(_el$3, "fg", _v$, _p$.e));
|
|
90
|
+
_v$2 !== _p$.t && (_p$.t = _$setProp(_el$5, "fg", _v$2, _p$.t));
|
|
91
|
+
return _p$;
|
|
92
|
+
}, {
|
|
93
|
+
e: void 0,
|
|
94
|
+
t: void 0
|
|
95
|
+
});
|
|
96
|
+
return _el$;
|
|
97
|
+
}
|
|
98
|
+
});
|
|
94
99
|
}
|
|
95
100
|
function MonitorRows(props) {
|
|
96
101
|
const visible = createMemo(() => props.monitors().slice(0, 4));
|
|
@@ -98,41 +103,26 @@ function MonitorRows(props) {
|
|
|
98
103
|
var _el$8 = _$createElement("box");
|
|
99
104
|
_$setProp(_el$8, "flexDirection", "column");
|
|
100
105
|
_$setProp(_el$8, "width", "100%");
|
|
101
|
-
_$insert(_el$8,
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
return
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
_$insertNode(_el$13, _el$14);
|
|
122
|
-
_$insert(_el$13, () => monitor.name, null);
|
|
123
|
-
_$effect((_p$) => {
|
|
124
|
-
var _v$3 = monitorTone(monitor, props.tone), _v$4 = props.tone.textMuted;
|
|
125
|
-
_v$3 !== _p$.e && (_p$.e = _$setProp(_el$12, "fg", _v$3, _p$.e));
|
|
126
|
-
_v$4 !== _p$.t && (_p$.t = _$setProp(_el$13, "fg", _v$4, _p$.t));
|
|
127
|
-
return _p$;
|
|
128
|
-
}, {
|
|
129
|
-
e: void 0,
|
|
130
|
-
t: void 0
|
|
131
|
-
});
|
|
132
|
-
return _el$11;
|
|
133
|
-
})());
|
|
134
|
-
}
|
|
135
|
-
}), null);
|
|
106
|
+
_$insert(_el$8, () => visible().map((monitor) => (() => {
|
|
107
|
+
var _el$1 = _$createElement("box"), _el$10 = _$createElement("text"), _el$11 = _$createElement("text"), _el$12 = _$createTextNode(` `);
|
|
108
|
+
_$insertNode(_el$1, _el$10);
|
|
109
|
+
_$insertNode(_el$1, _el$11);
|
|
110
|
+
_$setProp(_el$1, "flexDirection", "row");
|
|
111
|
+
_$setProp(_el$1, "width", "100%");
|
|
112
|
+
_$insert(_el$10, () => monitor.icon);
|
|
113
|
+
_$insertNode(_el$11, _el$12);
|
|
114
|
+
_$insert(_el$11, () => monitor.name, null);
|
|
115
|
+
_$effect((_p$) => {
|
|
116
|
+
var _v$3 = monitorTone(monitor, props.tone), _v$4 = props.tone.textMuted;
|
|
117
|
+
_v$3 !== _p$.e && (_p$.e = _$setProp(_el$10, "fg", _v$3, _p$.e));
|
|
118
|
+
_v$4 !== _p$.t && (_p$.t = _$setProp(_el$11, "fg", _v$4, _p$.t));
|
|
119
|
+
return _p$;
|
|
120
|
+
}, {
|
|
121
|
+
e: void 0,
|
|
122
|
+
t: void 0
|
|
123
|
+
});
|
|
124
|
+
return _el$1;
|
|
125
|
+
})()), null);
|
|
136
126
|
_$insert(_el$8, _$createComponent(Show, {
|
|
137
127
|
get when() {
|
|
138
128
|
return _$memo(() => !!props.compact)() && visible().length < props.monitors().length;
|