@fdcn/sourcefed 0.3.6 → 0.3.8
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 +1 -1
- package/dist/{chunk-X3BZSHKZ.js → chunk-5JL3UV72.js} +1328 -399
- package/dist/cli.js +9888 -8063
- package/dist/daemon.js +1194 -263
- package/dist/data/core/SKILL.md +9 -4
- package/dist/data/core/references/commands.md +6 -1
- package/dist/data/sourcefed/SKILL.md +3 -2
- package/dist/guidance.md +6 -2
- package/dist/mcp.js +6 -2
- package/dist/opencode.js +263 -122
- package/dist/pi.js +161 -39
- package/dist/tui-compiled.mjs +306 -166
- 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 +19 -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/adapters/pi/src/dialog.d.ts +1 -2
- package/dist.dts/adapters/pi/src/monitors-dialog.d.ts +32 -0
- package/dist.dts/packages/core/src/types/monitor-create-input.d.ts +4 -0
- package/dist.dts/packages/daemon/src/event-stream.d.ts +26 -0
- package/dist.dts/packages/daemon/src/registry.d.ts +2 -0
- package/dist.dts/packages/daemon/src/stream-lifecycle.test.d.ts +1 -0
- package/dist.dts/packages/daemon/src/types/client.d.ts +3 -1
- package/dist.dts/packages/daemon/src/types/daemon.d.ts +4 -0
- package/dist.dts/packages/daemon/src/utils/index.d.ts +0 -1
- package/dist.dts/providers/yab/src/index.d.ts +2 -0
- package/dist.dts/providers/yab/src/monitor.d.ts +14 -0
- package/dist.dts/providers/yab/src/poll/index.d.ts +2 -0
- package/dist.dts/providers/yab/src/poll/monitor.d.ts +3 -0
- package/dist.dts/providers/yab/src/poll/utils/feed-events.d.ts +5 -0
- package/dist.dts/providers/yab/src/poll/utils/index.d.ts +4 -0
- package/dist.dts/providers/yab/src/poll/utils/parse-feed.d.ts +3 -0
- package/dist.dts/providers/yab/src/poll/utils/poll-yab.d.ts +7 -0
- package/dist.dts/providers/yab/src/poll/utils/yab-mcp.d.ts +10 -0
- package/dist.dts/providers/yab/src/schema.d.ts +12 -0
- package/dist.dts/providers/yab/src/types/cursor.d.ts +4 -0
- package/dist.dts/providers/yab/src/types/event.d.ts +8 -0
- package/dist.dts/providers/yab/src/types/feed-entry.d.ts +8 -0
- package/dist.dts/providers/yab/src/types/index.d.ts +5 -0
- package/dist.dts/providers/yab/src/types/page.d.ts +6 -0
- package/dist.dts/providers/yab/src/types/source-record.d.ts +7 -0
- package/dist.dts/providers/yab/src/yab.test.d.ts +1 -0
- 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 → adapters/pi/src/monitors-dialog.test.d.ts} +0 -0
package/dist/pi.js
CHANGED
|
@@ -6,7 +6,7 @@ import {
|
|
|
6
6
|
daemonCommand,
|
|
7
7
|
daemonEnvironment,
|
|
8
8
|
spawnLocalDaemon
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-5JL3UV72.js";
|
|
10
10
|
import "./chunk-MLKGABMK.js";
|
|
11
11
|
|
|
12
12
|
// adapters/pi/src/index.ts
|
|
@@ -39,35 +39,6 @@ function showSourcefedDialog(_tui, theme, done, title, lines) {
|
|
|
39
39
|
}
|
|
40
40
|
};
|
|
41
41
|
}
|
|
42
|
-
function monitorLines(monitors, theme) {
|
|
43
|
-
const active = monitors.filter((monitor) => monitor.enabled);
|
|
44
|
-
if (active.length === 0) return [{ text: theme.fg("dim", "No active monitors") }];
|
|
45
|
-
return active.flatMap((monitor) => {
|
|
46
|
-
const status = monitor.unresponsive ? theme.fg("error", "\u25CF") : theme.fg("success", "\u25CF");
|
|
47
|
-
const describe = theme.fg("text", monitor.describe);
|
|
48
|
-
const detail = monitor.detail ? theme.fg("muted", monitor.detail) : "";
|
|
49
|
-
const statusLabel = monitor.unresponsive ? "recovering connection" : "healthy";
|
|
50
|
-
const rows = [
|
|
51
|
-
["Name", monitor.name],
|
|
52
|
-
["Delivery", monitor.delivery],
|
|
53
|
-
["Poll interval", `${monitor.pollIntervalSec}s`],
|
|
54
|
-
["Created", formatTime(monitor.createdAt)],
|
|
55
|
-
["Updated", formatTime(monitor.updatedAt)],
|
|
56
|
-
["Last poll", formatTime(monitor.lastPolledAt)],
|
|
57
|
-
["Webhook heartbeat", formatTime(monitor.webhookHeartbeatAt)]
|
|
58
|
-
];
|
|
59
|
-
return [
|
|
60
|
-
{ text: `${status} ${monitor.icon} ${describe}${detail} [${statusLabel}]` },
|
|
61
|
-
...rows.map(([label, value]) => ({ text: theme.fg("muted", ` ${label}: ${value}`) }))
|
|
62
|
-
];
|
|
63
|
-
});
|
|
64
|
-
}
|
|
65
|
-
function formatTime(value) {
|
|
66
|
-
if (!value) return "never";
|
|
67
|
-
const date = new Date(value);
|
|
68
|
-
if (Number.isNaN(date.getTime())) return value;
|
|
69
|
-
return date.toLocaleString();
|
|
70
|
-
}
|
|
71
42
|
function logLines(logs, theme) {
|
|
72
43
|
if (logs.length === 0) return [{ text: theme.fg("dim", "No notifications sent yet") }];
|
|
73
44
|
return logs.flatMap((entry) => {
|
|
@@ -80,12 +51,145 @@ function logLines(logs, theme) {
|
|
|
80
51
|
});
|
|
81
52
|
}
|
|
82
53
|
|
|
54
|
+
// adapters/pi/src/monitors-dialog.ts
|
|
55
|
+
import { truncateToWidth as truncateToWidth2 } from "@earendil-works/pi-tui";
|
|
56
|
+
var PROGRESS = { stop: "Stopping", start: "Starting", remove: "Deleting" };
|
|
57
|
+
var MonitorManager = class {
|
|
58
|
+
constructor(monitors, deps) {
|
|
59
|
+
this.deps = deps;
|
|
60
|
+
this.monitors = monitors;
|
|
61
|
+
}
|
|
62
|
+
monitors;
|
|
63
|
+
selected = 0;
|
|
64
|
+
mode = { kind: "browse" };
|
|
65
|
+
error;
|
|
66
|
+
handleInput(data) {
|
|
67
|
+
switch (this.mode.kind) {
|
|
68
|
+
case "busy":
|
|
69
|
+
return;
|
|
70
|
+
case "confirm-remove":
|
|
71
|
+
return this.handleConfirm(data, this.mode.monitor);
|
|
72
|
+
case "browse":
|
|
73
|
+
return this.handleBrowse(data);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
render(width) {
|
|
77
|
+
const { theme } = this.deps;
|
|
78
|
+
const active = this.monitors.filter((monitor) => monitor.enabled).length;
|
|
79
|
+
const border = theme.fg("accent", "\u2500".repeat(Math.max(0, width)));
|
|
80
|
+
const lines = [
|
|
81
|
+
border,
|
|
82
|
+
` ${theme.fg("accent", theme.bold(`Sourcefed monitors (${active} active)`))}`,
|
|
83
|
+
"",
|
|
84
|
+
...this.listLines(),
|
|
85
|
+
"",
|
|
86
|
+
...this.statusLines(),
|
|
87
|
+
border
|
|
88
|
+
];
|
|
89
|
+
return lines.map((line) => truncateToWidth2(line, width));
|
|
90
|
+
}
|
|
91
|
+
invalidate() {
|
|
92
|
+
}
|
|
93
|
+
handleBrowse(data) {
|
|
94
|
+
if (this.matches(data, "tui.select.cancel") || this.matches(data, "tui.select.confirm")) return this.deps.close();
|
|
95
|
+
if (this.matches(data, "tui.select.up")) return this.select(this.selected - 1);
|
|
96
|
+
if (this.matches(data, "tui.select.down")) return this.select(this.selected + 1);
|
|
97
|
+
const monitor = this.monitors[this.selected];
|
|
98
|
+
if (!monitor) return;
|
|
99
|
+
if (data === "s") void this.perform(monitor.enabled ? "stop" : "start", monitor);
|
|
100
|
+
if (data === "d") this.setMode({ kind: "confirm-remove", monitor });
|
|
101
|
+
}
|
|
102
|
+
handleConfirm(data, monitor) {
|
|
103
|
+
if (data === "y") void this.perform("remove", monitor);
|
|
104
|
+
else if (data === "n" || this.matches(data, "tui.select.cancel")) this.setMode({ kind: "browse" });
|
|
105
|
+
}
|
|
106
|
+
async perform(action, monitor) {
|
|
107
|
+
this.error = void 0;
|
|
108
|
+
this.setMode({ kind: "busy", label: `${PROGRESS[action]} ${monitor.name}\u2026` });
|
|
109
|
+
try {
|
|
110
|
+
this.monitors = await this.deps.run(action, monitor.id);
|
|
111
|
+
const kept = this.monitors.findIndex((candidate) => candidate.id === monitor.id);
|
|
112
|
+
this.selected = clamp(kept >= 0 ? kept : this.selected, this.monitors.length);
|
|
113
|
+
} catch (error) {
|
|
114
|
+
this.error = error instanceof Error ? error.message : String(error);
|
|
115
|
+
}
|
|
116
|
+
this.setMode({ kind: "browse" });
|
|
117
|
+
}
|
|
118
|
+
select(index) {
|
|
119
|
+
this.selected = clamp(index, this.monitors.length);
|
|
120
|
+
this.deps.requestRender();
|
|
121
|
+
}
|
|
122
|
+
setMode(mode) {
|
|
123
|
+
this.mode = mode;
|
|
124
|
+
this.deps.requestRender();
|
|
125
|
+
}
|
|
126
|
+
matches(data, keybinding) {
|
|
127
|
+
return this.deps.keys.matches(data, keybinding);
|
|
128
|
+
}
|
|
129
|
+
listLines() {
|
|
130
|
+
const { theme } = this.deps;
|
|
131
|
+
if (this.monitors.length === 0) return [` ${theme.fg("dim", "No monitors")}`];
|
|
132
|
+
return this.monitors.flatMap((monitor, index) => {
|
|
133
|
+
const selected = index === this.selected;
|
|
134
|
+
const marker = selected ? theme.fg("accent", "\u203A") : " ";
|
|
135
|
+
const header = ` ${marker} ${statusDot(monitor, theme)} ${monitor.icon} ${theme.fg("text", monitor.describe)} [${statusLabel(monitor)}]`;
|
|
136
|
+
return selected ? [header, ...detailLines(monitor, theme)] : [header];
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
statusLines() {
|
|
140
|
+
const { theme } = this.deps;
|
|
141
|
+
const lines = [];
|
|
142
|
+
if (this.error) lines.push(` ${theme.fg("error", this.error)}`);
|
|
143
|
+
switch (this.mode.kind) {
|
|
144
|
+
case "busy":
|
|
145
|
+
lines.push(` ${theme.fg("muted", this.mode.label)}`);
|
|
146
|
+
break;
|
|
147
|
+
case "confirm-remove":
|
|
148
|
+
lines.push(` ${theme.fg("warning", `Delete ${this.mode.monitor.name}? It stops watching and its record is removed. y/n`)}`);
|
|
149
|
+
break;
|
|
150
|
+
case "browse":
|
|
151
|
+
lines.push(` ${theme.fg("dim", "\u2191\u2193 select \xB7 s stop/start \xB7 d delete \xB7 esc close")}`);
|
|
152
|
+
}
|
|
153
|
+
return lines;
|
|
154
|
+
}
|
|
155
|
+
};
|
|
156
|
+
function clamp(index, length) {
|
|
157
|
+
return Math.min(Math.max(index, 0), Math.max(length - 1, 0));
|
|
158
|
+
}
|
|
159
|
+
function statusLabel(monitor) {
|
|
160
|
+
if (!monitor.enabled) return "stopped";
|
|
161
|
+
return monitor.unresponsive ? "recovering connection" : "healthy";
|
|
162
|
+
}
|
|
163
|
+
function statusDot(monitor, theme) {
|
|
164
|
+
if (!monitor.enabled) return theme.fg("dim", "\u25CF");
|
|
165
|
+
return theme.fg(monitor.unresponsive ? "error" : "success", "\u25CF");
|
|
166
|
+
}
|
|
167
|
+
function detailLines(monitor, theme) {
|
|
168
|
+
const rows = [
|
|
169
|
+
["Name", monitor.name],
|
|
170
|
+
["Delivery", monitor.delivery],
|
|
171
|
+
["Poll interval", `${monitor.pollIntervalSec}s`],
|
|
172
|
+
["Created", formatTime(monitor.createdAt)],
|
|
173
|
+
["Updated", formatTime(monitor.updatedAt)],
|
|
174
|
+
["Last poll", formatTime(monitor.lastPolledAt)],
|
|
175
|
+
["Webhook heartbeat", formatTime(monitor.webhookHeartbeatAt)]
|
|
176
|
+
];
|
|
177
|
+
return rows.map(([label, value]) => theme.fg("muted", ` ${label}: ${value}`));
|
|
178
|
+
}
|
|
179
|
+
function formatTime(value) {
|
|
180
|
+
if (!value) return "never";
|
|
181
|
+
const date = new Date(value);
|
|
182
|
+
if (Number.isNaN(date.getTime())) return value;
|
|
183
|
+
return date.toLocaleString();
|
|
184
|
+
}
|
|
185
|
+
|
|
83
186
|
// adapters/pi/src/index.ts
|
|
84
187
|
var STATUS_REFRESH_MS = 3e3;
|
|
85
188
|
var SOURCE_ICONS = {
|
|
86
189
|
jira: "\u{F0303}",
|
|
87
190
|
github: "\u{F02A4}",
|
|
88
|
-
slack: "\u{F04B1}"
|
|
191
|
+
slack: "\u{F04B1}",
|
|
192
|
+
yab: "\u{F059F}"
|
|
89
193
|
};
|
|
90
194
|
async function sourcefedExtension(pi) {
|
|
91
195
|
const listeners = /* @__PURE__ */ new Map();
|
|
@@ -113,16 +217,20 @@ async function sourcefedExtension(pi) {
|
|
|
113
217
|
pi.registerTool({
|
|
114
218
|
name: "sourcefed_monitor_create",
|
|
115
219
|
label: "Sourcefed monitor create",
|
|
116
|
-
description: "Create or reuse a Jira, GitHub PR, Slack thread,
|
|
220
|
+
description: "Create or reuse a Jira, GitHub PR, Slack thread, Slack DM, or Yab feed monitor for the current Pi session.",
|
|
117
221
|
parameters: Type.Object({
|
|
118
222
|
name: Type.String(),
|
|
119
|
-
sourceType: Type.Unsafe({ type: "string", enum: ["jira", "github", "slack"] }),
|
|
223
|
+
sourceType: Type.Unsafe({ type: "string", enum: ["jira", "github", "slack", "yab"] }),
|
|
120
224
|
issueKey: Type.Optional(Type.String()),
|
|
121
225
|
repo: Type.Optional(Type.String()),
|
|
122
226
|
prNumber: Type.Optional(Type.Number()),
|
|
123
227
|
channelId: Type.Optional(Type.String()),
|
|
124
228
|
threadTs: Type.Optional(Type.String()),
|
|
125
229
|
threadUrl: Type.Optional(Type.String()),
|
|
230
|
+
url: Type.Optional(Type.String()),
|
|
231
|
+
space: Type.Optional(Type.String()),
|
|
232
|
+
match: Type.Optional(Type.String()),
|
|
233
|
+
exclude: Type.Optional(Type.String()),
|
|
126
234
|
pollIntervalSec: Type.Optional(Type.Number())
|
|
127
235
|
}),
|
|
128
236
|
execute: async (_toolCallID, input, _signal, _onUpdate, ctx) => toolResult(await call(ctx, "monitor_create", input))
|
|
@@ -156,12 +264,23 @@ async function sourcefedExtension(pi) {
|
|
|
156
264
|
execute: async (_toolCallID, input, _signal, _onUpdate, ctx) => toolResult(await call(ctx, "monitor_start", input))
|
|
157
265
|
});
|
|
158
266
|
pi.registerCommand("sourcefed", {
|
|
159
|
-
description: "
|
|
267
|
+
description: "Show, stop, start, or delete Sourcefed monitors for the current Pi session",
|
|
160
268
|
handler: async (_args, ctx) => {
|
|
161
|
-
const
|
|
162
|
-
const
|
|
269
|
+
const monitors = await listMonitors(ctx);
|
|
270
|
+
const run = async (action, id) => {
|
|
271
|
+
const result = await call(ctx, `monitor_${action}`, { id });
|
|
272
|
+
if (result?.ok === false) throw new Error(result.error ?? `monitor ${action} failed`);
|
|
273
|
+
void refreshStatus();
|
|
274
|
+
return listMonitors(ctx);
|
|
275
|
+
};
|
|
163
276
|
await ctx.ui.custom(
|
|
164
|
-
(tui, theme,
|
|
277
|
+
(tui, theme, keybindings, done) => new MonitorManager(monitors, {
|
|
278
|
+
theme,
|
|
279
|
+
keys: keybindings,
|
|
280
|
+
run,
|
|
281
|
+
requestRender: () => tui.requestRender(),
|
|
282
|
+
close: () => done(null)
|
|
283
|
+
})
|
|
165
284
|
);
|
|
166
285
|
}
|
|
167
286
|
});
|
|
@@ -185,9 +304,12 @@ async function sourcefedExtension(pi) {
|
|
|
185
304
|
statusTimer = void 0;
|
|
186
305
|
}
|
|
187
306
|
}
|
|
188
|
-
async function
|
|
307
|
+
async function listMonitors(ctx) {
|
|
189
308
|
const result = await call(ctx, "monitor_list", {});
|
|
190
|
-
|
|
309
|
+
return Array.isArray(result?.monitors) ? result.monitors : [];
|
|
310
|
+
}
|
|
311
|
+
async function updateStatus(ctx) {
|
|
312
|
+
const monitors = await listMonitors(ctx);
|
|
191
313
|
const active = monitors.filter((monitor) => monitor.enabled);
|
|
192
314
|
if (active.length === 0) {
|
|
193
315
|
ctx.ui.setStatus("sourcefed", void 0);
|