@treenity/mods 3.0.1 → 3.0.3

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.
Files changed (125) hide show
  1. package/agent/client.ts +2 -0
  2. package/agent/guardian.ts +492 -0
  3. package/agent/seed.ts +74 -0
  4. package/agent/server.ts +4 -0
  5. package/agent/service.ts +644 -0
  6. package/agent/types.ts +184 -0
  7. package/agent/view.tsx +431 -0
  8. package/board/view.tsx +1 -1
  9. package/brahman/helpers.ts +7 -7
  10. package/brahman/service.ts +24 -24
  11. package/brahman/types.ts +21 -21
  12. package/brahman/views/action-cards.tsx +33 -23
  13. package/brahman/views/bot-view.tsx +3 -2
  14. package/brahman/views/chat-editor.tsx +119 -124
  15. package/brahman/views/menu-editor.tsx +75 -89
  16. package/brahman/views/page-layout.tsx +10 -8
  17. package/brahman/views/tstring-input.tsx +25 -15
  18. package/canary/service.ts +18 -18
  19. package/dist/board/view.js +1 -1
  20. package/dist/board/view.js.map +1 -1
  21. package/dist/brahman/helpers.d.ts +1 -1
  22. package/dist/brahman/helpers.d.ts.map +1 -1
  23. package/dist/brahman/helpers.js +6 -6
  24. package/dist/brahman/helpers.js.map +1 -1
  25. package/dist/brahman/service.js +24 -24
  26. package/dist/brahman/service.js.map +1 -1
  27. package/dist/brahman/types.d.ts +1 -1
  28. package/dist/brahman/types.d.ts.map +1 -1
  29. package/dist/brahman/types.js +21 -21
  30. package/dist/brahman/types.js.map +1 -1
  31. package/dist/brahman/views/action-cards.d.ts.map +1 -1
  32. package/dist/brahman/views/action-cards.js +7 -4
  33. package/dist/brahman/views/action-cards.js.map +1 -1
  34. package/dist/brahman/views/bot-view.d.ts.map +1 -1
  35. package/dist/brahman/views/bot-view.js +2 -1
  36. package/dist/brahman/views/bot-view.js.map +1 -1
  37. package/dist/brahman/views/chat-editor.d.ts.map +1 -1
  38. package/dist/brahman/views/chat-editor.js +27 -18
  39. package/dist/brahman/views/chat-editor.js.map +1 -1
  40. package/dist/brahman/views/menu-editor.d.ts.map +1 -1
  41. package/dist/brahman/views/menu-editor.js +12 -16
  42. package/dist/brahman/views/menu-editor.js.map +1 -1
  43. package/dist/brahman/views/page-layout.d.ts.map +1 -1
  44. package/dist/brahman/views/page-layout.js +1 -1
  45. package/dist/brahman/views/page-layout.js.map +1 -1
  46. package/dist/brahman/views/tstring-input.d.ts.map +1 -1
  47. package/dist/brahman/views/tstring-input.js +7 -3
  48. package/dist/brahman/views/tstring-input.js.map +1 -1
  49. package/dist/canary/service.js +18 -18
  50. package/dist/canary/service.js.map +1 -1
  51. package/dist/doc/fs-codec.js +1 -1
  52. package/dist/doc/fs-codec.js.map +1 -1
  53. package/dist/doc/renderers.d.ts.map +1 -1
  54. package/dist/doc/renderers.js +2 -1
  55. package/dist/doc/renderers.js.map +1 -1
  56. package/dist/doc/toolbar.d.ts.map +1 -1
  57. package/dist/doc/toolbar.js +5 -5
  58. package/dist/doc/toolbar.js.map +1 -1
  59. package/dist/launcher/types.js +2 -2
  60. package/dist/launcher/types.js.map +1 -1
  61. package/dist/launcher/view.js +2 -2
  62. package/dist/launcher/view.js.map +1 -1
  63. package/dist/mindmap/branch.d.ts +10 -0
  64. package/dist/mindmap/branch.d.ts.map +1 -1
  65. package/dist/mindmap/branch.js +42 -9
  66. package/dist/mindmap/branch.js.map +1 -1
  67. package/dist/mindmap/sidebar.d.ts.map +1 -1
  68. package/dist/mindmap/sidebar.js +4 -3
  69. package/dist/mindmap/sidebar.js.map +1 -1
  70. package/dist/mindmap/view.d.ts.map +1 -1
  71. package/dist/mindmap/view.js +35 -4
  72. package/dist/mindmap/view.js.map +1 -1
  73. package/dist/sensor-demo/service.js +6 -5
  74. package/dist/sensor-demo/service.js.map +1 -1
  75. package/dist/sensor-generator/action.js +1 -1
  76. package/dist/sensor-generator/action.js.map +1 -1
  77. package/dist/sim/service.js +41 -41
  78. package/dist/sim/service.js.map +1 -1
  79. package/dist/table/view.js.map +1 -1
  80. package/dist/todo/types.js +2 -2
  81. package/dist/todo/types.js.map +1 -1
  82. package/dist/todo/view.js +6 -4
  83. package/dist/todo/view.js.map +1 -1
  84. package/dist/whisper/inbox.js +3 -3
  85. package/dist/whisper/inbox.js.map +1 -1
  86. package/dist/whisper/route.d.ts +1 -1
  87. package/dist/whisper/route.d.ts.map +1 -1
  88. package/dist/whisper/route.js +13 -13
  89. package/dist/whisper/route.js.map +1 -1
  90. package/doc/CLAUDE.md +1 -1
  91. package/doc/fs-codec.ts +1 -1
  92. package/doc/renderers.tsx +4 -3
  93. package/doc/toolbar.tsx +12 -9
  94. package/launcher/types.ts +2 -2
  95. package/launcher/view.tsx +12 -8
  96. package/mcp/mcp-server.ts +393 -0
  97. package/mcp/server.ts +2 -0
  98. package/mcp/service.ts +18 -0
  99. package/mcp/types.ts +6 -0
  100. package/mindmap/branch.tsx +121 -22
  101. package/mindmap/mindmap.css +52 -0
  102. package/mindmap/sidebar.tsx +9 -6
  103. package/mindmap/view.tsx +40 -4
  104. package/package.json +30 -3
  105. package/sensor-demo/service.ts +6 -5
  106. package/sensor-generator/action.ts +1 -1
  107. package/sim/service.ts +41 -41
  108. package/table/view.tsx +7 -2
  109. package/todo/types.ts +2 -2
  110. package/todo/view.tsx +9 -10
  111. package/whisper/inbox.ts +3 -3
  112. package/whisper/route.ts +13 -13
  113. package/board/board.test.ts +0 -212
  114. package/brahman/brahman.test.ts +0 -855
  115. package/dist/mindmap/radial-tree.d.ts +0 -14
  116. package/dist/mindmap/radial-tree.d.ts.map +0 -1
  117. package/dist/mindmap/radial-tree.js +0 -184
  118. package/dist/mindmap/radial-tree.js.map +0 -1
  119. package/dist/mindmap/use-tree-data.d.ts +0 -14
  120. package/dist/mindmap/use-tree-data.d.ts.map +0 -1
  121. package/dist/mindmap/use-tree-data.js +0 -95
  122. package/dist/mindmap/use-tree-data.js.map +0 -1
  123. package/doc/fs-codec.test.ts +0 -119
  124. package/doc/markdown.test.ts +0 -152
  125. package/sim/sim.test.ts +0 -282
package/whisper/inbox.ts CHANGED
@@ -19,7 +19,7 @@ register('whisper.inbox', 'service', async (node, ctx) => {
19
19
  const sent = new Set<string>();
20
20
 
21
21
  // Mark existing COMPLETED transcriptions as already processed
22
- const { items } = await ctx.store.getChildren(config.source);
22
+ const { items } = await ctx.tree.getChildren(config.source);
23
23
  for (const child of items) {
24
24
  if (child.$type !== 'whisper.transcription') continue;
25
25
  if (getText(child)) sent.add(child.$path);
@@ -29,7 +29,7 @@ register('whisper.inbox', 'service', async (node, ctx) => {
29
29
  const unsub = ctx.subscribe(config.source, (event) => {
30
30
  if (event.type !== 'set' && event.type !== 'patch') return;
31
31
 
32
- ctx.store.get(event.path).then(async (n) => {
32
+ ctx.tree.get(event.path).then(async (n) => {
33
33
  if (!n || n.$type !== 'whisper.transcription') return;
34
34
  if (sent.has(n.$path)) return;
35
35
 
@@ -40,7 +40,7 @@ register('whisper.inbox', 'service', async (node, ctx) => {
40
40
 
41
41
  const taskId = `t-${Date.now()}`;
42
42
  const taskPath = `${config.target}/tasks/${taskId}`;
43
- await ctx.store.set(createNode(taskPath, 'agent.task', {
43
+ await ctx.tree.set(createNode(taskPath, 'agent.task', {
44
44
  prompt: text,
45
45
  status: 'pending',
46
46
  createdAt: Date.now(),
package/whisper/route.ts CHANGED
@@ -3,7 +3,7 @@
3
3
 
4
4
  import { type AutomaticSpeechRecognitionPipeline, pipeline } from '@huggingface/transformers';
5
5
  import { createNode } from '@treenity/core';
6
- import { newComp } from '@treenity/core/comp';
6
+ import { newComponent } from '@treenity/core/comp';
7
7
  import type { Tree } from '@treenity/core/tree';
8
8
  import { execFile } from 'node:child_process';
9
9
  import { mkdir, readFile, unlink, writeFile } from 'node:fs/promises';
@@ -76,7 +76,7 @@ export function createWhisperHandler(cfg: WhisperRouteConfig) {
76
76
  // Pre-warm the pipeline
77
77
  getTranscriber(cfg.model);
78
78
 
79
- return async (req: IncomingMessage, res: ServerResponse, store: Tree) => {
79
+ return async (req: IncomingMessage, res: ServerResponse, tree: Tree) => {
80
80
  if (req.method !== 'POST') {
81
81
  return respond(res, 405, { error: 'Method not allowed' });
82
82
  }
@@ -113,18 +113,18 @@ export function createWhisperHandler(cfg: WhisperRouteConfig) {
113
113
 
114
114
  // Ensure {servicePath}/{id} dir exists
115
115
  const idDirPath = `${cfg.nodePath}/${id}`;
116
- if (!(await store.get(idDirPath))) {
117
- await store.set(createNode(idDirPath, 'whisper.channel', {}, {
118
- checklist: newComp(WhisperChecklist, {}),
116
+ if (!(await tree.get(idDirPath))) {
117
+ await tree.set(createNode(idDirPath, 'whisper.channel', {}, {
118
+ checklist: newComponent(WhisperChecklist, {}),
119
119
  }));
120
120
  }
121
121
 
122
122
  // 1. Create node immediately with audio — appears in tree right away
123
123
  const nodePath = `${idDirPath}/${noteId}`;
124
124
  const node = createNode(nodePath, 'whisper.transcription', {}, {
125
- audio: newComp(WhisperAudio, { filename, size: body.length, mime }),
126
- text: newComp(WhisperText, { content: '...' }),
127
- meta: newComp(WhisperMeta, {
125
+ audio: newComponent(WhisperAudio, { filename, size: body.length, mime }),
126
+ text: newComponent(WhisperText, { content: '...' }),
127
+ meta: newComponent(WhisperMeta, {
128
128
  model: cfg.model,
129
129
  language: cfg.language,
130
130
  duration: 0,
@@ -132,7 +132,7 @@ export function createWhisperHandler(cfg: WhisperRouteConfig) {
132
132
  transcribedAt: Date.now(),
133
133
  }),
134
134
  });
135
- await store.set(node);
135
+ await tree.set(node);
136
136
  console.log(`[whisper] ${filename} → ${nodePath} (processing...)`);
137
137
 
138
138
  // 2. Respond immediately — client sees the node path
@@ -156,17 +156,17 @@ export function createWhisperHandler(cfg: WhisperRouteConfig) {
156
156
  ? (outputChunks[outputChunks.length - 1].timestamp[1] ?? 0)
157
157
  : 0;
158
158
 
159
- const updated = await store.get(nodePath);
159
+ const updated = await tree.get(nodePath);
160
160
  if (!updated) return;
161
- updated.text = newComp(WhisperText, { content: text });
162
- updated.meta = newComp(WhisperMeta, {
161
+ updated.text = newComponent(WhisperText, { content: text });
162
+ updated.meta = newComponent(WhisperMeta, {
163
163
  model: cfg.model,
164
164
  language: cfg.language,
165
165
  duration,
166
166
  segments: outputChunks?.length ?? 0,
167
167
  transcribedAt: Date.now(),
168
168
  });
169
- await store.set(updated);
169
+ await tree.set(updated);
170
170
  console.log(`[whisper] ${nodePath} done (${outputChunks?.length ?? 0} seg, ${duration}s)`);
171
171
  })
172
172
  .catch((err) => console.error(`[whisper] ${nodePath} transcription failed:`, err))
@@ -1,212 +0,0 @@
1
- // Board task tests — status flow, actions, field updates
2
-
3
- import { type NodeData, resolve } from '@treenity/core';
4
- import './types';
5
- import { createMemoryTree } from '@treenity/core/tree';
6
- import assert from 'node:assert/strict';
7
- import { describe, it } from 'node:test';
8
-
9
- function makeTask(overrides?: Partial<NodeData>): NodeData {
10
- return {
11
- $path: '/board/data/t-1',
12
- $type: 'board.task',
13
- title: 'Test task',
14
- description: '',
15
- status: 'backlog',
16
- assignee: '',
17
- priority: 'normal',
18
- result: '',
19
- createdAt: Date.now(),
20
- updatedAt: 0,
21
- ...overrides,
22
- } as NodeData;
23
- }
24
-
25
- async function execAction(store: ReturnType<typeof createMemoryTree>, path: string, action: string, data?: unknown) {
26
- const handler = resolve('board.task', `action:${action}`) as any;
27
- assert.ok(handler, `action:${action} must be registered`);
28
- const node = await store.get(path);
29
- assert.ok(node, `node at ${path} must exist`);
30
- await handler({ node, comp: node, store, signal: AbortSignal.timeout(5000) }, data);
31
- return node;
32
- }
33
-
34
- describe('board.task registration', () => {
35
- it('registers all expected actions', () => {
36
- const actions = ['assign', 'start', 'submit', 'approve', 'reject', 'reopen'];
37
- for (const action of actions) {
38
- assert.ok(resolve('board.task', `action:${action}`), `action:${action} should be registered`);
39
- }
40
- });
41
- });
42
-
43
- describe('board.task.assign', () => {
44
- it('sets assignee and moves to todo', async () => {
45
- const store = createMemoryTree();
46
- await store.set(makeTask());
47
-
48
- const node = await execAction(store, '/board/data/t-1', 'assign', { to: 'alice' });
49
- assert.equal(node.assignee, 'alice');
50
- assert.equal(node.status, 'todo');
51
- assert.ok((node.updatedAt as number) > 0);
52
- });
53
-
54
- it('trims whitespace from assignee', async () => {
55
- const store = createMemoryTree();
56
- await store.set(makeTask());
57
-
58
- const node = await execAction(store, '/board/data/t-1', 'assign', { to: ' bob ' });
59
- assert.equal(node.assignee, 'bob');
60
- });
61
-
62
- it('throws on empty assignee', async () => {
63
- const store = createMemoryTree();
64
- await store.set(makeTask());
65
-
66
- await assert.rejects(
67
- () => execAction(store, '/board/data/t-1', 'assign', { to: '' }),
68
- (err: Error) => err.message.includes('assignee'),
69
- );
70
- });
71
- });
72
-
73
- describe('board.task.start', () => {
74
- it('moves from backlog to doing', async () => {
75
- const store = createMemoryTree();
76
- await store.set(makeTask({ status: 'backlog' }));
77
-
78
- const node = await execAction(store, '/board/data/t-1', 'start');
79
- assert.equal(node.status, 'doing');
80
- });
81
-
82
- it('moves from todo to doing', async () => {
83
- const store = createMemoryTree();
84
- await store.set(makeTask({ status: 'todo' }));
85
-
86
- const node = await execAction(store, '/board/data/t-1', 'start');
87
- assert.equal(node.status, 'doing');
88
- });
89
-
90
- it('throws from review', async () => {
91
- const store = createMemoryTree();
92
- await store.set(makeTask({ status: 'review' }));
93
-
94
- await assert.rejects(
95
- () => execAction(store, '/board/data/t-1', 'start'),
96
- (err: Error) => err.message.includes('review'),
97
- );
98
- });
99
- });
100
-
101
- describe('board.task.submit', () => {
102
- it('moves from doing to review', async () => {
103
- const store = createMemoryTree();
104
- await store.set(makeTask({ status: 'doing' }));
105
-
106
- const node = await execAction(store, '/board/data/t-1', 'submit');
107
- assert.equal(node.status, 'review');
108
- });
109
-
110
- it('stores result in result field', async () => {
111
- const store = createMemoryTree();
112
- await store.set(makeTask({ status: 'doing' }));
113
-
114
- const node = await execAction(store, '/board/data/t-1', 'submit', { result: 'done it' });
115
- assert.equal(node.result, 'done it');
116
- });
117
-
118
- it('throws from backlog', async () => {
119
- const store = createMemoryTree();
120
- await store.set(makeTask({ status: 'backlog' }));
121
-
122
- await assert.rejects(
123
- () => execAction(store, '/board/data/t-1', 'submit'),
124
- (err: Error) => err.message.includes('backlog'),
125
- );
126
- });
127
- });
128
-
129
- describe('board.task.approve', () => {
130
- it('moves from review to done', async () => {
131
- const store = createMemoryTree();
132
- await store.set(makeTask({ status: 'review' }));
133
-
134
- const node = await execAction(store, '/board/data/t-1', 'approve');
135
- assert.equal(node.status, 'done');
136
- });
137
-
138
- it('throws from doing', async () => {
139
- const store = createMemoryTree();
140
- await store.set(makeTask({ status: 'doing' }));
141
-
142
- await assert.rejects(
143
- () => execAction(store, '/board/data/t-1', 'approve'),
144
- (err: Error) => err.message.includes('doing'),
145
- );
146
- });
147
- });
148
-
149
- describe('board.task.reject', () => {
150
- it('moves from review back to doing', async () => {
151
- const store = createMemoryTree();
152
- await store.set(makeTask({ status: 'review' }));
153
-
154
- const node = await execAction(store, '/board/data/t-1', 'reject');
155
- assert.equal(node.status, 'doing');
156
- });
157
-
158
- it('stores rejection reason in result', async () => {
159
- const store = createMemoryTree();
160
- await store.set(makeTask({ status: 'review' }));
161
-
162
- const node = await execAction(store, '/board/data/t-1', 'reject', { reason: 'needs tests' });
163
- assert.ok((node.result as string).includes('needs tests'));
164
- });
165
-
166
- it('throws from backlog', async () => {
167
- const store = createMemoryTree();
168
- await store.set(makeTask({ status: 'backlog' }));
169
-
170
- await assert.rejects(
171
- () => execAction(store, '/board/data/t-1', 'reject'),
172
- (err: Error) => err.message.includes('backlog'),
173
- );
174
- });
175
- });
176
-
177
- describe('board.task.reopen', () => {
178
- it('resets to backlog, clears assignee and result', async () => {
179
- const store = createMemoryTree();
180
- await store.set(makeTask({ status: 'done', assignee: 'alice', result: 'old result' }));
181
-
182
- const node = await execAction(store, '/board/data/t-1', 'reopen');
183
- assert.equal(node.status, 'backlog');
184
- assert.equal(node.assignee, '');
185
- assert.equal(node.result, '');
186
- assert.ok((node.updatedAt as number) > 0);
187
- });
188
- });
189
-
190
- describe('board.task full lifecycle', () => {
191
- it('backlog → assign → start → submit → approve', async () => {
192
- const store = createMemoryTree();
193
- await store.set(makeTask());
194
-
195
- await execAction(store, '/board/data/t-1', 'assign', { to: 'ai-agent' });
196
- const a1 = await store.get('/board/data/t-1');
197
- assert.equal(a1?.status, 'todo');
198
-
199
- await execAction(store, '/board/data/t-1', 'start');
200
- const a2 = await store.get('/board/data/t-1');
201
- assert.equal(a2?.status, 'doing');
202
-
203
- await execAction(store, '/board/data/t-1', 'submit', { result: 'implemented' });
204
- const a3 = await store.get('/board/data/t-1');
205
- assert.equal(a3?.status, 'review');
206
- assert.equal(a3?.result, 'implemented');
207
-
208
- await execAction(store, '/board/data/t-1', 'approve');
209
- const a4 = await store.get('/board/data/t-1');
210
- assert.equal(a4?.status, 'done');
211
- });
212
- });