@fdcn/sourcefed 0.3.5 → 0.3.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/README.md +2 -7
- package/dist/cli.js +15 -57
- package/dist/tui-compiled.mjs +57 -67
- package/dist.dts/packages/cli/src/utils/setup.d.ts +0 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -29,16 +29,11 @@ import { createSourcefedMcp } from "@fdcn/sourcefed/mcp"
|
|
|
29
29
|
|
|
30
30
|
## Host plugins
|
|
31
31
|
|
|
32
|
-
OpenCode loads this package as both a server and a TUI plugin:
|
|
32
|
+
OpenCode loads this package as both a server and a TUI plugin from one entry:
|
|
33
33
|
|
|
34
34
|
```json
|
|
35
35
|
// ~/.config/opencode/opencode.jsonc
|
|
36
|
-
{ "plugins": ["@fdcn/sourcefed@0.3.
|
|
37
|
-
```
|
|
38
|
-
|
|
39
|
-
```json
|
|
40
|
-
// ~/.config/opencode/cli.json
|
|
41
|
-
{ "plugins": ["@fdcn/sourcefed@0.3.5"] }
|
|
36
|
+
{ "plugins": ["@fdcn/sourcefed@0.3.6"] }
|
|
42
37
|
```
|
|
43
38
|
|
|
44
39
|
The package exposes `./server`, `./tui`, `./opencode`, `./opencode/tui`, and `./pi` entrypoints for hosts that load them directly.
|
package/dist/cli.js
CHANGED
|
@@ -44192,9 +44192,7 @@ async function runMonitor(argv) {
|
|
|
44192
44192
|
|
|
44193
44193
|
// packages/cli/src/utils/setup.ts
|
|
44194
44194
|
import { execFile } from "node:child_process";
|
|
44195
|
-
import {
|
|
44196
|
-
import os8 from "node:os";
|
|
44197
|
-
import path8 from "node:path";
|
|
44195
|
+
import { readFileSync } from "node:fs";
|
|
44198
44196
|
import { fileURLToPath } from "node:url";
|
|
44199
44197
|
function setupSpec() {
|
|
44200
44198
|
const manifest = JSON.parse(readFileSync(fileURLToPath(new URL("../package.json", import.meta.url)), "utf8"));
|
|
@@ -44211,59 +44209,19 @@ async function setupHost(name, args, spec) {
|
|
|
44211
44209
|
const code = error2 && typeof error2 === "object" && "code" in error2 ? String(error2.code) : "";
|
|
44212
44210
|
if (code === "ENOENT") {
|
|
44213
44211
|
console.error(`[sourcefed] ${name} is not on PATH \u2014 install it manually:`);
|
|
44214
|
-
console.error(name === "opencode" ? ` add "${spec}" to the plugins array in ~/.config/opencode/opencode.jsonc
|
|
44212
|
+
console.error(name === "opencode" ? ` add "${spec}" to the plugins array in ~/.config/opencode/opencode.jsonc` : ` run: pi install ${spec}`);
|
|
44215
44213
|
return false;
|
|
44216
44214
|
}
|
|
44217
44215
|
throw error2;
|
|
44218
44216
|
}
|
|
44219
44217
|
}
|
|
44220
|
-
function configureOpenCodeCliPlugin(spec) {
|
|
44221
|
-
const file = openCodeCliConfigPath();
|
|
44222
|
-
const config2 = readOpenCodeCliConfig(file);
|
|
44223
|
-
const plugins = config2.plugins;
|
|
44224
|
-
if (plugins === void 0) {
|
|
44225
|
-
config2.plugins = [spec];
|
|
44226
|
-
} else if (!Array.isArray(plugins)) {
|
|
44227
|
-
throw new Error(`OpenCode CLI config has a non-array plugins setting: ${file}`);
|
|
44228
|
-
} else if (!plugins.some((plugin) => isPluginEntry(plugin, spec))) {
|
|
44229
|
-
config2.plugins = [...plugins, spec];
|
|
44230
|
-
} else {
|
|
44231
|
-
return;
|
|
44232
|
-
}
|
|
44233
|
-
mkdirSync(path8.dirname(file), { recursive: true });
|
|
44234
|
-
writeFileSync(file, `${JSON.stringify(config2, null, 2)}
|
|
44235
|
-
`);
|
|
44236
|
-
}
|
|
44237
|
-
function openCodeCliConfigPath() {
|
|
44238
|
-
const configHome = process.env.XDG_CONFIG_HOME ?? path8.join(os8.homedir(), ".config");
|
|
44239
|
-
return path8.join(configHome, "opencode", "cli.json");
|
|
44240
|
-
}
|
|
44241
|
-
function readOpenCodeCliConfig(file) {
|
|
44242
|
-
try {
|
|
44243
|
-
const value = JSON.parse(readFileSync(file, "utf8"));
|
|
44244
|
-
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
44245
|
-
throw new Error(`OpenCode CLI config must contain a JSON object: ${file}`);
|
|
44246
|
-
}
|
|
44247
|
-
return value;
|
|
44248
|
-
} catch (error2) {
|
|
44249
|
-
if (error2 instanceof Error && "code" in error2 && error2.code === "ENOENT") return {};
|
|
44250
|
-
if (error2 instanceof SyntaxError) throw new Error(`OpenCode CLI config is not valid JSON: ${file}`);
|
|
44251
|
-
throw error2;
|
|
44252
|
-
}
|
|
44253
|
-
}
|
|
44254
|
-
function isPluginEntry(value, spec) {
|
|
44255
|
-
if (value === spec) return true;
|
|
44256
|
-
if (!value || typeof value !== "object" || Array.isArray(value)) return false;
|
|
44257
|
-
return "package" in value && value.package === spec;
|
|
44258
|
-
}
|
|
44259
44218
|
|
|
44260
44219
|
// packages/cli/src/commands/setup.ts
|
|
44261
44220
|
async function runSetup(args) {
|
|
44262
44221
|
const spec = setupSpec();
|
|
44263
44222
|
const requested = args[0] ?? "all";
|
|
44264
44223
|
if (requested === "opencode" || requested === "all") {
|
|
44265
|
-
|
|
44266
|
-
if (installed) configureOpenCodeCliPlugin(spec);
|
|
44224
|
+
await setupHost("opencode", ["plugin", "add", spec], spec);
|
|
44267
44225
|
}
|
|
44268
44226
|
if (requested === "pi" || requested === "all") {
|
|
44269
44227
|
await setupHost("pi", ["install", `npm:${spec}`], `npm:${spec}`);
|
|
@@ -44272,12 +44230,12 @@ async function runSetup(args) {
|
|
|
44272
44230
|
|
|
44273
44231
|
// packages/cli/src/skills/command.ts
|
|
44274
44232
|
import { readFile as readFile7, readdir as readdir2, stat as stat2 } from "node:fs/promises";
|
|
44275
|
-
import
|
|
44233
|
+
import path9 from "node:path";
|
|
44276
44234
|
|
|
44277
44235
|
// packages/cli/src/skills/discovery.ts
|
|
44278
44236
|
import { statSync } from "node:fs";
|
|
44279
44237
|
import { readdir, readFile as readFile6, stat } from "node:fs/promises";
|
|
44280
|
-
import
|
|
44238
|
+
import path8 from "node:path";
|
|
44281
44239
|
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
44282
44240
|
|
|
44283
44241
|
// packages/cli/src/skills/frontmatter.ts
|
|
@@ -44325,7 +44283,7 @@ async function skillsDirs() {
|
|
|
44325
44283
|
}
|
|
44326
44284
|
const directories = [];
|
|
44327
44285
|
for (const name of SKILL_DIRS) {
|
|
44328
|
-
const candidate =
|
|
44286
|
+
const candidate = path8.join(skillRoot(), name);
|
|
44329
44287
|
try {
|
|
44330
44288
|
if ((await stat(candidate)).isDirectory()) directories.push(candidate);
|
|
44331
44289
|
} catch {
|
|
@@ -44337,7 +44295,7 @@ async function discoverSkills() {
|
|
|
44337
44295
|
const skills = [];
|
|
44338
44296
|
for (const dir of await skillsDirs()) {
|
|
44339
44297
|
for (const entry of await readdir(dir)) {
|
|
44340
|
-
const skillDir =
|
|
44298
|
+
const skillDir = path8.join(dir, entry);
|
|
44341
44299
|
let entryStat;
|
|
44342
44300
|
try {
|
|
44343
44301
|
entryStat = await stat(skillDir);
|
|
@@ -44345,7 +44303,7 @@ async function discoverSkills() {
|
|
|
44345
44303
|
continue;
|
|
44346
44304
|
}
|
|
44347
44305
|
if (!entryStat.isDirectory()) continue;
|
|
44348
|
-
const skillFile =
|
|
44306
|
+
const skillFile = path8.join(skillDir, "SKILL.md");
|
|
44349
44307
|
try {
|
|
44350
44308
|
const content = await readFile6(skillFile, "utf8");
|
|
44351
44309
|
const parsed = parseFrontmatter(content);
|
|
@@ -44358,15 +44316,15 @@ async function discoverSkills() {
|
|
|
44358
44316
|
return skills;
|
|
44359
44317
|
}
|
|
44360
44318
|
function skillRoot() {
|
|
44361
|
-
let dir =
|
|
44319
|
+
let dir = path8.dirname(fileURLToPath2(import.meta.url));
|
|
44362
44320
|
for (let depth = 0; depth < 6; depth++) {
|
|
44363
|
-
const marker =
|
|
44321
|
+
const marker = path8.join(dir, "data");
|
|
44364
44322
|
if (statSync(marker, { throwIfNoEntry: false })?.isDirectory()) return dir;
|
|
44365
|
-
const parent =
|
|
44323
|
+
const parent = path8.dirname(dir);
|
|
44366
44324
|
if (parent === dir) break;
|
|
44367
44325
|
dir = parent;
|
|
44368
44326
|
}
|
|
44369
|
-
return
|
|
44327
|
+
return path8.dirname(fileURLToPath2(import.meta.url));
|
|
44370
44328
|
}
|
|
44371
44329
|
|
|
44372
44330
|
// packages/cli/src/skills/command.ts
|
|
@@ -44413,7 +44371,7 @@ async function runGet(args) {
|
|
|
44413
44371
|
output += `# ${skill.name}
|
|
44414
44372
|
|
|
44415
44373
|
`;
|
|
44416
|
-
output += await readFile7(
|
|
44374
|
+
output += await readFile7(path9.join(skill.dir, "SKILL.md"), "utf8");
|
|
44417
44375
|
output += "\n";
|
|
44418
44376
|
if (full) output += await supplementaryFiles(skill.dir);
|
|
44419
44377
|
}
|
|
@@ -44436,7 +44394,7 @@ async function runPath(name) {
|
|
|
44436
44394
|
async function supplementaryFiles(skillDir) {
|
|
44437
44395
|
let output = "";
|
|
44438
44396
|
for (const subdirName of ["references", "templates"]) {
|
|
44439
|
-
const subdir =
|
|
44397
|
+
const subdir = path9.join(skillDir, subdirName);
|
|
44440
44398
|
try {
|
|
44441
44399
|
if (!(await stat2(subdir)).isDirectory()) continue;
|
|
44442
44400
|
} catch {
|
|
@@ -44444,7 +44402,7 @@ async function supplementaryFiles(skillDir) {
|
|
|
44444
44402
|
}
|
|
44445
44403
|
const entries = (await readdir2(subdir)).sort();
|
|
44446
44404
|
for (const entry of entries) {
|
|
44447
|
-
const filePath =
|
|
44405
|
+
const filePath = path9.join(subdir, entry);
|
|
44448
44406
|
try {
|
|
44449
44407
|
if (!(await stat2(filePath)).isFile()) continue;
|
|
44450
44408
|
} catch {
|
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;
|