fullerdev 0.1.0 → 0.1.1

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.
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,YAAY,EAAS,MAAM,qBAAqB,CAAC;AAoBvE,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAC5D,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAGhD,YAAY,EAAE,YAAY,EAAE,MAAM,EAAE,WAAW,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AAC5F,OAAO,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AAErD;;;;;;;;;;;;;;;;GAgBG;AACH,eAAO,MAAM,eAAe,EAAE,MAsJ7B,CAAC;AAIF,QAAA,MAAM,qBAAqB,EAAE,YAG5B,CAAC;AAEF,eAAe,qBAAqB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,YAAY,EAAS,MAAM,qBAAqB,CAAC;AAqBvE,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAC5D,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAGhD,YAAY,EAAE,YAAY,EAAE,MAAM,EAAE,WAAW,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AAC5F,OAAO,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AAErD;;;;;;;;;;;;;;;;GAgBG;AACH,eAAO,MAAM,eAAe,EAAE,MAsK7B,CAAC;AAIF,QAAA,MAAM,qBAAqB,EAAE,YAG5B,CAAC;AAEF,eAAe,qBAAqB,CAAC"}
package/dist/index.js CHANGED
@@ -200,6 +200,62 @@ function getActivePreset(config) {
200
200
  return preset;
201
201
  }
202
202
 
203
+ // src/tui/tui-state.ts
204
+ import * as fs from "node:fs";
205
+ import * as os from "node:os";
206
+ import * as path from "node:path";
207
+ var STORAGE_DIR = "fullerdev";
208
+ var STATE_FILE = "tui-state.json";
209
+ function dataDir() {
210
+ return process.env.XDG_DATA_HOME ?? path.join(os.homedir(), ".local", "share");
211
+ }
212
+ function getTuiStatePath() {
213
+ return path.join(dataDir(), "opencode", "storage", STORAGE_DIR, STATE_FILE);
214
+ }
215
+ function emptySnapshot() {
216
+ return {
217
+ version: 1,
218
+ updatedAt: Date.now(),
219
+ agentModels: {}
220
+ };
221
+ }
222
+ function parseSnapshot(value) {
223
+ const parsed = JSON.parse(value);
224
+ if (parsed?.version !== 1)
225
+ return emptySnapshot();
226
+ return {
227
+ version: 1,
228
+ updatedAt: typeof parsed.updatedAt === "number" ? parsed.updatedAt : Date.now(),
229
+ agentModels: parsed.agentModels ?? {}
230
+ };
231
+ }
232
+ function readTuiSnapshot() {
233
+ try {
234
+ return parseSnapshot(fs.readFileSync(getTuiStatePath(), "utf8"));
235
+ } catch {
236
+ return emptySnapshot();
237
+ }
238
+ }
239
+ function writeTuiSnapshot(snapshot) {
240
+ try {
241
+ const filePath = getTuiStatePath();
242
+ fs.mkdirSync(path.dirname(filePath), { recursive: true });
243
+ fs.writeFileSync(filePath, `${JSON.stringify(snapshot)}
244
+ `);
245
+ } catch {}
246
+ }
247
+ function updateSnapshot(mutator) {
248
+ const snapshot = readTuiSnapshot();
249
+ mutator(snapshot);
250
+ snapshot.updatedAt = Date.now();
251
+ writeTuiSnapshot(snapshot);
252
+ }
253
+ function recordTuiAgentModels(input) {
254
+ updateSnapshot((snapshot) => {
255
+ snapshot.agentModels = { ...input.agentModels };
256
+ });
257
+ }
258
+
203
259
  // src/tools/azure/work-items.ts
204
260
  import { tool } from "@opencode-ai/plugin";
205
261
  var WORKITEM_QUERY_TOOL = tool({
@@ -1151,6 +1207,17 @@ var FullerDevPlugin = async (ctx) => {
1151
1207
  console.error("[fullerdev] Config load failed:", err);
1152
1208
  throw err;
1153
1209
  }
1210
+ recordTuiAgentModels({
1211
+ agentModels: {
1212
+ orchestrator: preset.orchestrator.model,
1213
+ oracle: preset.oracle.model,
1214
+ librarian: preset.librarian.model,
1215
+ explorer: preset.explorer.model,
1216
+ designer: preset.designer.model,
1217
+ fixer: preset.fixer.model,
1218
+ devops: preset.devops.model
1219
+ }
1220
+ });
1154
1221
  const coreTools = createCoreTools();
1155
1222
  const devopsTools = createDevOpsTools();
1156
1223
  const builtinMcps = getBuiltinMcps(config);
@@ -1161,6 +1228,7 @@ var FullerDevPlugin = async (ctx) => {
1161
1228
  console.log("[fullerdev] config hook called, registering agents & MCPs...");
1162
1229
  input.agent ??= {};
1163
1230
  input.mcp ??= {};
1231
+ input.default_agent = "orchestrator";
1164
1232
  input.agent["orchestrator"] = {
1165
1233
  mode: "primary",
1166
1234
  color: "primary",
@@ -0,0 +1,6 @@
1
+ import type { TuiPluginModule } from "@opencode-ai/plugin/tui";
2
+ declare const plugin: TuiPluginModule & {
3
+ id: string;
4
+ };
5
+ export default plugin;
6
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/tui/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAwL/D,QAAA,MAAM,MAAM,EAAE,eAAe,GAAG;IAAE,EAAE,EAAE,MAAM,CAAA;CAoC3C,CAAC;AAEF,eAAe,MAAM,CAAC"}
@@ -0,0 +1,170 @@
1
+ // src/tui/index.ts
2
+ import { createElement, insert, setProp } from "@opentui/solid";
3
+
4
+ // src/tui/tui-state.ts
5
+ import * as fs from "node:fs";
6
+ import * as os from "node:os";
7
+ import * as path from "node:path";
8
+ var STORAGE_DIR = "fullerdev";
9
+ var STATE_FILE = "tui-state.json";
10
+ function dataDir() {
11
+ return process.env.XDG_DATA_HOME ?? path.join(os.homedir(), ".local", "share");
12
+ }
13
+ function getTuiStatePath() {
14
+ return path.join(dataDir(), "opencode", "storage", STORAGE_DIR, STATE_FILE);
15
+ }
16
+ function emptySnapshot() {
17
+ return {
18
+ version: 1,
19
+ updatedAt: Date.now(),
20
+ agentModels: {}
21
+ };
22
+ }
23
+ function parseSnapshot(value) {
24
+ const parsed = JSON.parse(value);
25
+ if (parsed?.version !== 1)
26
+ return emptySnapshot();
27
+ return {
28
+ version: 1,
29
+ updatedAt: typeof parsed.updatedAt === "number" ? parsed.updatedAt : Date.now(),
30
+ agentModels: parsed.agentModels ?? {}
31
+ };
32
+ }
33
+ function readTuiSnapshot() {
34
+ try {
35
+ return parseSnapshot(fs.readFileSync(getTuiStatePath(), "utf8"));
36
+ } catch {
37
+ return emptySnapshot();
38
+ }
39
+ }
40
+ async function readTuiSnapshotAsync() {
41
+ try {
42
+ return parseSnapshot(await fs.promises.readFile(getTuiStatePath(), "utf8"));
43
+ } catch {
44
+ return emptySnapshot();
45
+ }
46
+ }
47
+
48
+ // src/tui/index.ts
49
+ var PLUGIN_NAME = "fullerdev";
50
+ var PLUGIN_VERSION = "0.1.0";
51
+ var SIDEBAR_AGENTS = [
52
+ "orchestrator",
53
+ "explorer",
54
+ "oracle",
55
+ "librarian",
56
+ "designer",
57
+ "fixer",
58
+ "devops"
59
+ ];
60
+ var BORDER = { type: "single" };
61
+ function element(tag, props, children = []) {
62
+ const node = createElement(tag);
63
+ for (const [key, value] of Object.entries(props)) {
64
+ if (value !== undefined)
65
+ setProp(node, key, value);
66
+ }
67
+ for (const child of children) {
68
+ if (child === null || child === undefined || child === false)
69
+ continue;
70
+ insert(node, child);
71
+ }
72
+ return node;
73
+ }
74
+ function text(props, children) {
75
+ return element("text", props, children);
76
+ }
77
+ function box(props, children = []) {
78
+ return element("box", props, children);
79
+ }
80
+ function truncate(value, max = 28) {
81
+ return value.length > max ? `${value.slice(0, max - 1)}…` : value;
82
+ }
83
+ function formatModelName(model) {
84
+ const lastSlash = model.lastIndexOf("/");
85
+ return lastSlash === -1 ? model : model.slice(lastSlash + 1);
86
+ }
87
+ function getSidebarAgentNames(snapshot) {
88
+ const configured = Object.keys(snapshot.agentModels);
89
+ return configured.length > 0 ? configured : SIDEBAR_AGENTS;
90
+ }
91
+ function row(label, value, theme, valueColor) {
92
+ return box({ width: "100%", flexDirection: "row", justifyContent: "space-between" }, [
93
+ text({ fg: theme.textMuted }, [label]),
94
+ text({ fg: valueColor ?? theme.text }, [value])
95
+ ]);
96
+ }
97
+ function buildConfigStatusRow(configInvalid, theme) {
98
+ if (!configInvalid)
99
+ return null;
100
+ return box({ width: "100%", flexDirection: "column", marginTop: 1, marginBottom: 1 }, [
101
+ text({ fg: "orange" }, ["Config invalid"]),
102
+ text({ fg: theme.textMuted }, ["Run doctor for details"])
103
+ ]);
104
+ }
105
+ function buildVersionBadge(version, theme) {
106
+ return box({
107
+ width: "100%",
108
+ flexDirection: "row",
109
+ justifyContent: "space-between",
110
+ alignItems: "center"
111
+ }, [
112
+ box({ paddingLeft: 1, paddingRight: 1, backgroundColor: theme.accent }, [
113
+ text({ fg: theme.background }, [PLUGIN_NAME])
114
+ ]),
115
+ text({ fg: theme.textMuted }, [`v${version}`])
116
+ ]);
117
+ }
118
+ function buildAgentSection(snapshot, theme) {
119
+ return getSidebarAgentNames(snapshot).map((agentName) => {
120
+ const model = snapshot.agentModels[agentName] ?? "pending";
121
+ return row(agentName, truncate(formatModelName(model), 26), theme, theme.textMuted);
122
+ });
123
+ }
124
+ function renderSidebar(snapshot, version, theme, configInvalid) {
125
+ return box({
126
+ width: "100%",
127
+ flexDirection: "column",
128
+ border: BORDER,
129
+ borderColor: theme.borderActive,
130
+ paddingTop: 1,
131
+ paddingBottom: 1,
132
+ paddingLeft: 1,
133
+ paddingRight: 1
134
+ }, [
135
+ buildVersionBadge(version, theme),
136
+ buildConfigStatusRow(configInvalid, theme),
137
+ box({ width: "100%", marginTop: 1 }, [
138
+ text({ fg: theme.text }, ["Agents"])
139
+ ]),
140
+ ...buildAgentSection(snapshot, theme)
141
+ ]);
142
+ }
143
+ var plugin = {
144
+ id: `${PLUGIN_NAME}:tui`,
145
+ tui: async (api, _options, meta) => {
146
+ const version = meta.version ?? PLUGIN_VERSION;
147
+ let snapshot = readTuiSnapshot();
148
+ const renderTimer = setInterval(async () => {
149
+ try {
150
+ snapshot = await readTuiSnapshotAsync();
151
+ api.renderer.requestRender();
152
+ } catch {}
153
+ }, 2000);
154
+ api.lifecycle.onDispose(() => {
155
+ clearInterval(renderTimer);
156
+ });
157
+ api.slots.register({
158
+ order: 900,
159
+ slots: {
160
+ sidebar_content() {
161
+ return renderSidebar(snapshot, version, api.theme.current, false);
162
+ }
163
+ }
164
+ });
165
+ }
166
+ };
167
+ var tui_default = plugin;
168
+ export {
169
+ tui_default as default
170
+ };
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Snapshot of agent→model mappings written by the server plugin
3
+ * and consumed by the TUI plugin for sidebar display.
4
+ */
5
+ export interface TuiSnapshot {
6
+ version: 1;
7
+ updatedAt: number;
8
+ agentModels: Record<string, string>;
9
+ }
10
+ export declare function getTuiStatePath(): string;
11
+ export declare function readTuiSnapshot(): TuiSnapshot;
12
+ export declare function readTuiSnapshotAsync(): Promise<TuiSnapshot>;
13
+ /**
14
+ * Record the full agent→model mapping at once.
15
+ * Called from the server plugin after loading the preset.
16
+ */
17
+ export declare function recordTuiAgentModels(input: {
18
+ agentModels: Record<string, string>;
19
+ }): void;
20
+ //# sourceMappingURL=tui-state.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tui-state.d.ts","sourceRoot":"","sources":["../../src/tui/tui-state.ts"],"names":[],"mappings":"AAIA;;;GAGG;AACH,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,CAAC,CAAC;IACX,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACrC;AAWD,wBAAgB,eAAe,IAAI,MAAM,CAExC;AAsBD,wBAAgB,eAAe,IAAI,WAAW,CAM7C;AAED,wBAAsB,oBAAoB,IAAI,OAAO,CAAC,WAAW,CAAC,CAQjE;AAmBD;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,EAAE;IAC1C,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACrC,GAAG,IAAI,CAIP"}
package/package.json CHANGED
@@ -1,17 +1,28 @@
1
1
  {
2
2
  "name": "fullerdev",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "description": "Opinionated OpenCode plugin for multi-agent orchestration. Specialized subagents, built-in MCPs, skills, hooks, tools — tuned for Azure DevOps workflows (Work Items, Git, Wiki, Pipelines).",
5
5
  "license": "MIT",
6
6
  "author": "Arthur",
7
7
  "type": "module",
8
8
  "main": "dist/index.js",
9
9
  "types": "dist/index.d.ts",
10
+ "exports": {
11
+ ".": {
12
+ "import": "./dist/index.js",
13
+ "types": "./dist/index.d.ts"
14
+ },
15
+ "./tui": {
16
+ "import": "./dist/tui/index.js",
17
+ "types": "./dist/tui/index.d.ts"
18
+ }
19
+ },
10
20
  "bin": {
11
21
  "fullerdev": "./bin/setup.js"
12
22
  },
13
23
  "files": [
14
24
  "dist/",
25
+ "dist/tui/",
15
26
  "src/skills/",
16
27
  "bin/",
17
28
  "fullerdev.schema.json",
@@ -19,7 +30,7 @@
19
30
  "LICENSE"
20
31
  ],
21
32
  "scripts": {
22
- "build": "bun build src/index.ts --outdir dist --target node --external @opencode-ai/plugin --external azure-devops-node-api --external zod && bun run build:declarations",
33
+ "build": "bun build src/index.ts --outdir dist --target node --external @opencode-ai/plugin --external azure-devops-node-api --external zod && bun build src/tui/index.ts --outdir dist/tui --target node --external @opentui/core --external @opentui/solid --external @opencode-ai/plugin && bun run build:declarations",
23
34
  "build:declarations": "tsc -p tsconfig.build.json",
24
35
  "dev": "bun build src/index.ts --outdir dist --target node --external @opencode-ai/plugin --external azure-devops-node-api --external zod --watch",
25
36
  "typecheck": "tsc --noEmit",
@@ -27,9 +38,9 @@
27
38
  "check:ci": "bun run typecheck && bun run build",
28
39
  "prepare": "bun run build",
29
40
  "prepublishOnly": "bun run build",
30
- "release:patch": "bun version patch && git push --follow-tags && bun publish",
31
- "release:minor": "bun version minor && git push --follow-tags && bun publish",
32
- "release:major": "bun version major && git push --follow-tags && bun publish"
41
+ "release:patch": "bun x bumpx patch && git push --follow-tags && bun publish",
42
+ "release:minor": "bun x bumpx minor && git push --follow-tags && bun publish",
43
+ "release:major": "bun x bumpx major && git push --follow-tags && bun publish"
33
44
  },
34
45
  "dependencies": {
35
46
  "@opencode-ai/plugin": "^1.0.85",
@@ -37,6 +48,8 @@
37
48
  "zod": "^3.23.0"
38
49
  },
39
50
  "devDependencies": {
51
+ "@opentui/core": "0.2.6",
52
+ "@opentui/solid": "0.2.6",
40
53
  "@types/node": "^20.11.0",
41
54
  "bun-types": "latest",
42
55
  "typescript": "^5.4.0"