@treenity/mods 3.0.1 → 3.0.2
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/board/view.tsx +1 -1
- package/brahman/helpers.ts +7 -7
- package/brahman/service.ts +24 -24
- package/brahman/types.ts +21 -21
- package/brahman/views/action-cards.tsx +33 -23
- package/brahman/views/bot-view.tsx +3 -2
- package/brahman/views/chat-editor.tsx +119 -124
- package/brahman/views/menu-editor.tsx +75 -89
- package/brahman/views/page-layout.tsx +10 -8
- package/brahman/views/tstring-input.tsx +25 -15
- package/canary/service.ts +18 -18
- package/dist/board/view.js +1 -1
- package/dist/board/view.js.map +1 -1
- package/dist/brahman/helpers.d.ts +1 -1
- package/dist/brahman/helpers.d.ts.map +1 -1
- package/dist/brahman/helpers.js +6 -6
- package/dist/brahman/helpers.js.map +1 -1
- package/dist/brahman/service.js +24 -24
- package/dist/brahman/service.js.map +1 -1
- package/dist/brahman/types.d.ts +1 -1
- package/dist/brahman/types.d.ts.map +1 -1
- package/dist/brahman/types.js +21 -21
- package/dist/brahman/types.js.map +1 -1
- package/dist/brahman/views/action-cards.d.ts.map +1 -1
- package/dist/brahman/views/action-cards.js +7 -4
- package/dist/brahman/views/action-cards.js.map +1 -1
- package/dist/brahman/views/bot-view.d.ts.map +1 -1
- package/dist/brahman/views/bot-view.js +2 -1
- package/dist/brahman/views/bot-view.js.map +1 -1
- package/dist/brahman/views/chat-editor.d.ts.map +1 -1
- package/dist/brahman/views/chat-editor.js +27 -18
- package/dist/brahman/views/chat-editor.js.map +1 -1
- package/dist/brahman/views/menu-editor.d.ts.map +1 -1
- package/dist/brahman/views/menu-editor.js +12 -16
- package/dist/brahman/views/menu-editor.js.map +1 -1
- package/dist/brahman/views/page-layout.d.ts.map +1 -1
- package/dist/brahman/views/page-layout.js +1 -1
- package/dist/brahman/views/page-layout.js.map +1 -1
- package/dist/brahman/views/tstring-input.d.ts.map +1 -1
- package/dist/brahman/views/tstring-input.js +7 -3
- package/dist/brahman/views/tstring-input.js.map +1 -1
- package/dist/canary/service.js +18 -18
- package/dist/canary/service.js.map +1 -1
- package/dist/doc/fs-codec.js +1 -1
- package/dist/doc/fs-codec.js.map +1 -1
- package/dist/doc/renderers.d.ts.map +1 -1
- package/dist/doc/renderers.js +2 -1
- package/dist/doc/renderers.js.map +1 -1
- package/dist/doc/toolbar.d.ts.map +1 -1
- package/dist/doc/toolbar.js +5 -5
- package/dist/doc/toolbar.js.map +1 -1
- package/dist/launcher/types.js +2 -2
- package/dist/launcher/types.js.map +1 -1
- package/dist/launcher/view.js +2 -2
- package/dist/launcher/view.js.map +1 -1
- package/dist/mindmap/branch.d.ts +10 -0
- package/dist/mindmap/branch.d.ts.map +1 -1
- package/dist/mindmap/branch.js +42 -9
- package/dist/mindmap/branch.js.map +1 -1
- package/dist/mindmap/sidebar.d.ts.map +1 -1
- package/dist/mindmap/sidebar.js +4 -3
- package/dist/mindmap/sidebar.js.map +1 -1
- package/dist/mindmap/view.d.ts.map +1 -1
- package/dist/mindmap/view.js +35 -4
- package/dist/mindmap/view.js.map +1 -1
- package/dist/sensor-demo/service.js +6 -5
- package/dist/sensor-demo/service.js.map +1 -1
- package/dist/sensor-generator/action.js +1 -1
- package/dist/sensor-generator/action.js.map +1 -1
- package/dist/sim/service.js +41 -41
- package/dist/sim/service.js.map +1 -1
- package/dist/table/view.js.map +1 -1
- package/dist/todo/types.js +2 -2
- package/dist/todo/types.js.map +1 -1
- package/dist/todo/view.js +6 -4
- package/dist/todo/view.js.map +1 -1
- package/dist/whisper/inbox.js +3 -3
- package/dist/whisper/inbox.js.map +1 -1
- package/dist/whisper/route.d.ts +1 -1
- package/dist/whisper/route.d.ts.map +1 -1
- package/dist/whisper/route.js +13 -13
- package/dist/whisper/route.js.map +1 -1
- package/doc/CLAUDE.md +1 -1
- package/doc/fs-codec.ts +1 -1
- package/doc/renderers.tsx +4 -3
- package/doc/toolbar.tsx +12 -9
- package/launcher/types.ts +2 -2
- package/launcher/view.tsx +12 -8
- package/mindmap/branch.tsx +121 -22
- package/mindmap/mindmap.css +52 -0
- package/mindmap/sidebar.tsx +9 -6
- package/mindmap/view.tsx +40 -4
- package/package.json +27 -3
- package/sensor-demo/service.ts +6 -5
- package/sensor-generator/action.ts +1 -1
- package/sim/service.ts +41 -41
- package/table/view.tsx +7 -2
- package/todo/types.ts +2 -2
- package/todo/view.tsx +9 -10
- package/whisper/inbox.ts +3 -3
- package/whisper/route.ts +13 -13
- package/board/board.test.ts +0 -212
- package/brahman/brahman.test.ts +0 -855
- package/doc/fs-codec.test.ts +0 -119
- package/doc/markdown.test.ts +0 -152
- package/sim/sim.test.ts +0 -282
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 {
|
|
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,
|
|
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
|
|
117
|
-
await
|
|
118
|
-
checklist:
|
|
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:
|
|
126
|
-
text:
|
|
127
|
-
meta:
|
|
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
|
|
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
|
|
159
|
+
const updated = await tree.get(nodePath);
|
|
160
160
|
if (!updated) return;
|
|
161
|
-
updated.text =
|
|
162
|
-
updated.meta =
|
|
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
|
|
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))
|
package/board/board.test.ts
DELETED
|
@@ -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
|
-
});
|