@cmodjs/core 4.0.2 → 4.1.0
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/docs/commands.md +43 -8
- package/docs/index.md +3 -3
- package/docs/install-steps.md +6 -6
- package/docs/jobs.md +2 -1
- package/docs/mod.md +1 -1
- package/docs/options.md +1 -1
- package/docs/permissions.md +1 -1
- package/docs/session.md +44 -13
- package/docs/testing.md +14 -10
- package/docs/ui.md +43 -11
- package/installer.d.ts +3 -2
- package/installer.d.ts.map +1 -1
- package/jobs/program.d.ts +1 -0
- package/jobs/program.d.ts.map +1 -1
- package/jobs/program.js +39 -23
- package/mod.d.ts +3 -2
- package/mod.d.ts.map +1 -1
- package/mod.js +1 -0
- package/package.json +1 -1
- package/records.d.ts +15 -1
- package/records.d.ts.map +1 -1
- package/records.js +39 -1
- package/register.d.ts.map +1 -1
- package/register.js +5 -2
- package/runtime/before.d.ts +6 -2
- package/runtime/before.d.ts.map +1 -1
- package/runtime/before.js +56 -18
- package/runtime/buttons.d.ts +10 -0
- package/runtime/buttons.d.ts.map +1 -0
- package/runtime/buttons.js +12 -0
- package/runtime/conversations.d.ts.map +1 -1
- package/runtime/conversations.js +134 -25
- package/runtime/engine.d.ts +2 -0
- package/runtime/engine.d.ts.map +1 -1
- package/runtime/grants.d.ts +1 -0
- package/runtime/grants.d.ts.map +1 -1
- package/runtime/grants.js +5 -2
- package/runtime/hotkeys.d.ts.map +1 -1
- package/runtime/hotkeys.js +7 -4
- package/runtime/installer.d.ts +9 -6
- package/runtime/installer.d.ts.map +1 -1
- package/runtime/installer.js +104 -47
- package/runtime/lifecycle.d.ts.map +1 -1
- package/runtime/lifecycle.js +121 -40
- package/runtime/pages.d.ts +3 -1
- package/runtime/pages.d.ts.map +1 -1
- package/runtime/pages.js +34 -10
- package/runtime/parts.d.ts +1 -0
- package/runtime/parts.d.ts.map +1 -1
- package/runtime/parts.js +6 -3
- package/runtime/programs.d.ts +1 -0
- package/runtime/programs.d.ts.map +1 -1
- package/runtime/programs.js +4 -1
- package/runtime/sessions.d.ts +2 -2
- package/runtime/sessions.d.ts.map +1 -1
- package/runtime/sessions.js +88 -58
- package/runtime/toaster.d.ts.map +1 -1
- package/runtime/toaster.js +23 -9
- package/runtime/ui.d.ts +21 -4
- package/runtime/ui.d.ts.map +1 -1
- package/runtime/ui.js +158 -58
- package/runtime/watches.d.ts.map +1 -1
- package/runtime/watches.js +18 -4
- package/runtime/widgets.d.ts +7 -5
- package/runtime/widgets.d.ts.map +1 -1
- package/runtime/widgets.js +29 -20
- package/session/context/turn/message/attached-file.d.ts +13 -0
- package/session/context/turn/message/attached-file.d.ts.map +1 -0
- package/session/context/turn/message/attached-file.js +21 -0
- package/session/context/turn/message/message.d.ts +3 -2
- package/session/context/turn/message/message.d.ts.map +1 -1
- package/session/context/turn/message/message.js +20 -6
- package/session/conversation.d.ts +14 -3
- package/session/conversation.d.ts.map +1 -1
- package/session/conversation.js +23 -4
- package/session/goal/task.d.ts +5 -0
- package/session/goal/task.d.ts.map +1 -1
- package/session/session.d.ts +35 -7
- package/session/session.d.ts.map +1 -1
- package/session/session.js +2 -1
- package/src/installer.ts +3 -2
- package/src/jobs/program.ts +41 -21
- package/src/mod.ts +3 -2
- package/src/records.ts +49 -1
- package/src/register.ts +9 -6
- package/src/runtime/before.ts +61 -22
- package/src/runtime/buttons.ts +22 -0
- package/src/runtime/conversations.ts +138 -32
- package/src/runtime/engine.ts +2 -0
- package/src/runtime/grants.ts +6 -2
- package/src/runtime/hotkeys.ts +7 -4
- package/src/runtime/installer.ts +144 -82
- package/src/runtime/lifecycle.ts +128 -43
- package/src/runtime/pages.ts +45 -8
- package/src/runtime/parts.ts +8 -4
- package/src/runtime/programs.ts +5 -1
- package/src/runtime/sessions.ts +83 -57
- package/src/runtime/toaster.ts +27 -9
- package/src/runtime/ui.ts +163 -61
- package/src/runtime/watches.ts +20 -5
- package/src/runtime/widgets.ts +34 -22
- package/src/session/context/turn/message/attached-file.ts +36 -0
- package/src/session/context/turn/message/message.ts +20 -7
- package/src/session/conversation.ts +30 -6
- package/src/session/goal/task.ts +6 -0
- package/src/session/session.ts +17 -7
- package/src/testing/fake-claude.ts +21 -6
- package/src/testing/fake-elements.ts +51 -8
- package/src/testing/fake-sessions.ts +60 -23
- package/src/testing.ts +86 -28
- package/src/ui/areas.ts +1 -0
- package/src/ui/components.ts +14 -8
- package/src/ui/elements.ts +6 -2
- package/src/ui/markdown.ts +3 -3
- package/src/ui/panes.ts +2 -2
- package/src/ui/styles.ts +6 -2
- package/testing/fake-claude.d.ts +3 -0
- package/testing/fake-claude.d.ts.map +1 -1
- package/testing/fake-claude.js +18 -5
- package/testing/fake-elements.d.ts.map +1 -1
- package/testing/fake-elements.js +46 -7
- package/testing/fake-sessions.d.ts +21 -10
- package/testing/fake-sessions.d.ts.map +1 -1
- package/testing/fake-sessions.js +58 -20
- package/testing.d.ts +8 -12
- package/testing.d.ts.map +1 -1
- package/testing.js +82 -21
- package/ui/areas.d.ts +4 -0
- package/ui/areas.d.ts.map +1 -1
- package/ui/components.d.ts +1 -0
- package/ui/components.d.ts.map +1 -1
- package/ui/components.js +11 -7
- package/ui/elements.d.ts +3 -0
- package/ui/elements.d.ts.map +1 -1
- package/ui/elements.js +6 -1
- package/ui/markdown.d.ts +2 -2
- package/ui/markdown.d.ts.map +1 -1
- package/ui/panes.d.ts +2 -1
- package/ui/panes.d.ts.map +1 -1
- package/ui/styles.d.ts +11 -2
- package/ui/styles.d.ts.map +1 -1
package/runtime/ui.d.ts
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
|
+
import type { Args, ElementTable, Frozen, MarkdownProps, RenderElement } from 'claude-code';
|
|
1
2
|
import type { Mod, Turn } from '../mod.js';
|
|
2
|
-
import { type Area } from '../ui/areas.js';
|
|
3
|
+
import { type Area, type WidgetInit } from '../ui/areas.js';
|
|
3
4
|
import { type ScrollOptions, type ScrollTarget } from '../ui/panes.js';
|
|
5
|
+
import { type StyledAt } from '../ui/styles.js';
|
|
4
6
|
import type { Claude } from './claude.js';
|
|
5
7
|
import type { Router } from './router.js';
|
|
6
8
|
import type { Failure } from './toaster.js';
|
|
@@ -10,12 +12,14 @@ export declare const partMethods: {
|
|
|
10
12
|
readonly press: 'cmod:press';
|
|
11
13
|
readonly shown: 'cmod:shown';
|
|
12
14
|
readonly changed: 'cmod:partsChanged';
|
|
15
|
+
readonly stylers: 'cmod:markdownStylers';
|
|
13
16
|
};
|
|
14
17
|
export type PagePlace = 'sidebar' | 'settings';
|
|
15
18
|
export type WidgetDeclaration = {
|
|
16
19
|
readonly id: string;
|
|
17
20
|
readonly title: string;
|
|
18
21
|
readonly areas: readonly Area[];
|
|
22
|
+
readonly place?: NonNullable<WidgetInit['place']>;
|
|
19
23
|
};
|
|
20
24
|
export type PageDeclaration = {
|
|
21
25
|
readonly id: string;
|
|
@@ -25,6 +29,7 @@ export type PageDeclaration = {
|
|
|
25
29
|
export type PartList = {
|
|
26
30
|
readonly widgets: readonly WidgetDeclaration[];
|
|
27
31
|
readonly pages: readonly PageDeclaration[];
|
|
32
|
+
readonly stylesMarkdown?: true;
|
|
28
33
|
};
|
|
29
34
|
export type PartDraw = {
|
|
30
35
|
readonly widget: string;
|
|
@@ -36,7 +41,14 @@ export type PartDraw = {
|
|
|
36
41
|
readonly params: unknown;
|
|
37
42
|
readonly columns: number;
|
|
38
43
|
readonly isFocused: boolean;
|
|
39
|
-
}
|
|
44
|
+
} | ({
|
|
45
|
+
readonly markdown: string;
|
|
46
|
+
} & StyledAt);
|
|
47
|
+
export type BorrowedMarkdown = (mod: string, cached: string, input: {
|
|
48
|
+
readonly markdown: string;
|
|
49
|
+
} & StyledAt) => RenderElement | undefined;
|
|
50
|
+
export declare function viewportColumns(e: Frozen<Args<'ui.render'>>): number;
|
|
51
|
+
export declare function styledAt(e: Frozen<Args<'ui.render'>>, columns?: number): StyledAt;
|
|
40
52
|
export type PartPress = {
|
|
41
53
|
readonly draw: number;
|
|
42
54
|
readonly handler: number;
|
|
@@ -75,6 +87,7 @@ export type ShownPages = {
|
|
|
75
87
|
readonly shown: string | null;
|
|
76
88
|
readonly isFocused: boolean;
|
|
77
89
|
};
|
|
90
|
+
export declare function merged(updates: readonly PartsUpdate[]): PartsUpdate;
|
|
78
91
|
export type UiOptions<State extends object> = {
|
|
79
92
|
readonly name: string;
|
|
80
93
|
readonly claude: Claude;
|
|
@@ -82,6 +95,8 @@ export type UiOptions<State extends object> = {
|
|
|
82
95
|
readonly report: (failure: Failure) => void;
|
|
83
96
|
readonly announce: (feature: string) => void;
|
|
84
97
|
readonly mod: () => Mod<State>;
|
|
98
|
+
readonly borrowed: BorrowedMarkdown;
|
|
99
|
+
readonly nextDraw: () => number;
|
|
85
100
|
};
|
|
86
101
|
export type UiArea<State extends object> = {
|
|
87
102
|
readonly panes: Mod<State>['panes'];
|
|
@@ -91,12 +106,14 @@ export type UiArea<State extends object> = {
|
|
|
91
106
|
readonly styles: Mod<State>['styles'];
|
|
92
107
|
asked<Value>(run: () => Value | Promise<Value>): Promise<Value>;
|
|
93
108
|
answerInput<Answer>(run: () => Promise<Answer>, passOn: () => Promise<unknown>): Promise<Answer>;
|
|
94
|
-
answer(method: string, input: unknown): Promise<{
|
|
109
|
+
answer(method: string, input: unknown, caller: string): Promise<{
|
|
95
110
|
readonly value: unknown;
|
|
96
111
|
}> | undefined;
|
|
112
|
+
markdownIn(table: ElementTable, at: StyledAt): ((props: MarkdownProps) => RenderElement) | undefined;
|
|
113
|
+
restyled(stylers: readonly string[]): void;
|
|
97
114
|
started(): void;
|
|
98
115
|
changed(): void;
|
|
99
116
|
restorePanes(): Promise<void>;
|
|
100
117
|
};
|
|
101
|
-
export declare function createUi<State extends object>({ name, claude, router, report, announce, mod }: UiOptions<State>): UiArea<State>;
|
|
118
|
+
export declare function createUi<State extends object>({ name, claude, router, report, announce, mod, borrowed, nextDraw }: UiOptions<State>): UiArea<State>;
|
|
102
119
|
//# sourceMappingURL=ui.d.ts.map
|
package/runtime/ui.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ui.d.ts","sourceRoot":"","sources":["../src/runtime/ui.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"ui.d.ts","sourceRoot":"","sources":["../src/runtime/ui.ts"],"names":[],"mappings":"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"}
|
package/runtime/ui.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { isObject } from '../records.js';
|
|
2
2
|
import { TurnEnd } from '../ui/areas.js';
|
|
3
|
-
import { Box, drawWith, elementData, Text } from '../ui/elements.js';
|
|
3
|
+
import { Box, drawWith, elementData, Markdown, Text } from '../ui/elements.js';
|
|
4
4
|
import { checkPane, checkPart, sizeKeys } from '../ui/panes.js';
|
|
5
5
|
import { componentOf, nameOf } from '../ui/styles.js';
|
|
6
6
|
import { messageOf } from '../utils/text.js';
|
|
@@ -11,7 +11,15 @@ export const partMethods = {
|
|
|
11
11
|
press: 'cmod:press',
|
|
12
12
|
shown: 'cmod:shown',
|
|
13
13
|
changed: 'cmod:partsChanged',
|
|
14
|
+
stylers: 'cmod:markdownStylers',
|
|
14
15
|
};
|
|
16
|
+
const unmeasuredColumns = 80;
|
|
17
|
+
export function viewportColumns(e) {
|
|
18
|
+
return e.viewport?.columns ?? unmeasuredColumns;
|
|
19
|
+
}
|
|
20
|
+
export function styledAt(e, columns = viewportColumns(e)) {
|
|
21
|
+
return { surface: e.surface, columns };
|
|
22
|
+
}
|
|
15
23
|
const bullet = '⏺';
|
|
16
24
|
function paneSize(pane, state) {
|
|
17
25
|
const size = {};
|
|
@@ -75,32 +83,39 @@ function drawPieces(pieces, place) {
|
|
|
75
83
|
return Box({ children: [Box({ minWidth: 2, children: Text({ color: 'text', children: bullet }) }), column(spaced)] });
|
|
76
84
|
return column([opening, Box({ paddingLeft: 2, children: column(rest) })]);
|
|
77
85
|
}
|
|
78
|
-
function merged(updates) {
|
|
86
|
+
export function merged(updates) {
|
|
79
87
|
const parts = updates.findLast((update) => update.parts !== undefined)?.parts;
|
|
80
88
|
const requests = updates.flatMap((update) => update.requests ?? []);
|
|
81
89
|
const isRedrawn = updates.some((update) => update.redraw === true);
|
|
82
90
|
return { ...(parts === undefined ? {} : { parts }), ...(isRedrawn ? { redraw: true } : {}), ...(requests.length === 0 ? {} : { requests }) };
|
|
83
91
|
}
|
|
84
92
|
const keptDrawInputs = 200;
|
|
85
|
-
export function createUi({ name, claude, router, report, announce, mod }) {
|
|
93
|
+
export function createUi({ name, claude, router, report, announce, mod, borrowed, nextDraw }) {
|
|
86
94
|
const panes = new Map();
|
|
87
95
|
const paneLogs = new Map();
|
|
88
96
|
const openPanes = new Set();
|
|
89
97
|
const paneStates = new Map();
|
|
90
98
|
const syncPanes = async () => {
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
if (open
|
|
95
|
-
openPanes.add(
|
|
96
|
-
|
|
99
|
+
const listed = new Map((await claude.ui.panes()).map((open) => [open.id, open]));
|
|
100
|
+
for (const id of panes.keys()) {
|
|
101
|
+
const open = listed.get(id);
|
|
102
|
+
if (open?.isPlaced === true)
|
|
103
|
+
openPanes.add(id);
|
|
104
|
+
else
|
|
105
|
+
openPanes.delete(id);
|
|
106
|
+
if (open === undefined)
|
|
107
|
+
paneStates.delete(id);
|
|
108
|
+
else
|
|
109
|
+
paneStates.set(id, { isShown: open.isShown, isFocused: open.isFocused });
|
|
97
110
|
}
|
|
98
111
|
};
|
|
99
|
-
const readPanes = () =>
|
|
112
|
+
const readPanes = () => syncPanes().catch((error) => claude.ui.log(`${name} keeps its panes' open, shown, and focused state from before: ${messageOf(error)}`, { to: 'debug' }));
|
|
100
113
|
const requestedSizes = new Map();
|
|
101
114
|
const styles = new Set();
|
|
102
115
|
const markdownRenders = new Map();
|
|
103
116
|
let read;
|
|
117
|
+
let stylers = [];
|
|
118
|
+
let stylersSeen = 0;
|
|
104
119
|
let isRouted = false;
|
|
105
120
|
let isResizeQueued = false;
|
|
106
121
|
const widgets = new Map();
|
|
@@ -110,17 +125,54 @@ export function createUi({ name, claude, router, report, announce, mod }) {
|
|
|
110
125
|
const draws = new Map();
|
|
111
126
|
const latestDraws = new Map();
|
|
112
127
|
const failedDraws = new Set();
|
|
113
|
-
let drawCount = 0;
|
|
114
128
|
let beforeStart = [];
|
|
115
129
|
let askedDepth = 0;
|
|
130
|
+
const askedCalls = new Set();
|
|
116
131
|
let unheldRequests = 0;
|
|
117
132
|
let collected;
|
|
118
133
|
let collecting = 0;
|
|
119
134
|
let queued;
|
|
120
135
|
const partList = () => ({
|
|
121
|
-
widgets: [...widgets.values()].map(({ id, title, areas: listed }) => ({ id, title, areas: listed })),
|
|
136
|
+
widgets: [...widgets.values()].map(({ id, title, areas: listed, place }) => ({ id, title, areas: listed, ...(place === undefined ? {} : { place }) })),
|
|
122
137
|
pages: [...pages.values()].map(({ init: { id, title }, place }) => ({ id, title, place })),
|
|
138
|
+
...(markdownRenders.size > 0 ? { stylesMarkdown: true } : {}),
|
|
123
139
|
});
|
|
140
|
+
const hear = (listed, isRestyled) => {
|
|
141
|
+
if (!Array.isArray(listed))
|
|
142
|
+
return;
|
|
143
|
+
const heard = listed.filter((styler) => typeof styler === 'string' && styler !== name);
|
|
144
|
+
if (!isRestyled && heard.join('\0') === stylers.join('\0'))
|
|
145
|
+
return;
|
|
146
|
+
stylers = heard;
|
|
147
|
+
stylersSeen += 1;
|
|
148
|
+
claude.ui.invalidate('ui.render');
|
|
149
|
+
};
|
|
150
|
+
const treeOf = (render, handlers) => {
|
|
151
|
+
const drawn = render();
|
|
152
|
+
return drawn === undefined ? null : elementData(drawn, handlers);
|
|
153
|
+
};
|
|
154
|
+
const isAnyDrawingChanged = () => {
|
|
155
|
+
for (const [key, inputs] of latestDraws) {
|
|
156
|
+
if (key === 'markdown')
|
|
157
|
+
continue;
|
|
158
|
+
for (const sent of inputs.values()) {
|
|
159
|
+
const handlers = [];
|
|
160
|
+
try {
|
|
161
|
+
if (JSON.stringify(treeOf(sent.render, handlers)) !== sent.tree)
|
|
162
|
+
return true;
|
|
163
|
+
}
|
|
164
|
+
catch (error) {
|
|
165
|
+
claude.ui.log(`${name}: the ${key} drawing threw, so the cmod plugin asks for it again: ${messageOf(error)}`, { to: 'debug' });
|
|
166
|
+
return true;
|
|
167
|
+
}
|
|
168
|
+
const latest = sent.draws.at(-1);
|
|
169
|
+
if (latest !== undefined && draws.has(latest))
|
|
170
|
+
draws.set(latest, { id: key, handlers });
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
return false;
|
|
174
|
+
};
|
|
175
|
+
const withNeededRedraw = ({ redraw, ...update }) => (redraw === true && isAnyDrawingChanged() ? { ...update, redraw } : update);
|
|
124
176
|
const send = (update) => {
|
|
125
177
|
if (collected !== undefined)
|
|
126
178
|
return void collected.push(update);
|
|
@@ -132,21 +184,33 @@ export function createUi({ name, claude, router, report, announce, mod }) {
|
|
|
132
184
|
const batch = [update];
|
|
133
185
|
if (!isAsked)
|
|
134
186
|
queued = batch;
|
|
135
|
-
const tell = () => {
|
|
187
|
+
const tell = async () => {
|
|
136
188
|
if (queued === batch)
|
|
137
189
|
queued = undefined;
|
|
138
|
-
const
|
|
190
|
+
const needed = withNeededRedraw(merged(batch));
|
|
191
|
+
if (Object.keys(needed).length === 0)
|
|
192
|
+
return;
|
|
193
|
+
const input = { ...needed, ...(isAsked ? { isAsked: true } : {}) };
|
|
139
194
|
return claude.cmod.call({ to: cmodPluginName, method: partMethods.changed, input }).then((answer) => {
|
|
140
195
|
if (isAsked && input.requests !== undefined && !(isObject(answer) && answer['isHeld'] === true))
|
|
141
196
|
unheldRequests += 1;
|
|
197
|
+
if (isObject(answer) && name !== cmodPluginName)
|
|
198
|
+
hear(answer['stylers'], false);
|
|
142
199
|
}, (error) => claude.ui.log(`${name}: the cmod plugin did not hear about its pages and widgets: ${messageOf(error)}`, { to: 'debug' }));
|
|
143
200
|
};
|
|
144
|
-
|
|
201
|
+
if (!isAsked)
|
|
202
|
+
return Promise.resolve().then(tell);
|
|
203
|
+
const told = tell().finally(() => askedCalls.delete(told));
|
|
204
|
+
askedCalls.add(told);
|
|
205
|
+
return told;
|
|
145
206
|
};
|
|
146
207
|
const asked = async (run) => {
|
|
147
208
|
askedDepth += 1;
|
|
148
209
|
try {
|
|
149
|
-
|
|
210
|
+
const value = await run();
|
|
211
|
+
while (askedCalls.size > 0)
|
|
212
|
+
await Promise.allSettled(askedCalls);
|
|
213
|
+
return value;
|
|
150
214
|
}
|
|
151
215
|
finally {
|
|
152
216
|
askedDepth -= 1;
|
|
@@ -163,7 +227,7 @@ export function createUi({ name, claude, router, report, announce, mod }) {
|
|
|
163
227
|
}
|
|
164
228
|
const mine = collected;
|
|
165
229
|
collected = collecting === 0 ? undefined : [];
|
|
166
|
-
return merged(mine);
|
|
230
|
+
return withNeededRedraw(merged(mine));
|
|
167
231
|
};
|
|
168
232
|
const logOnce = (what) => {
|
|
169
233
|
let hasLogged = false;
|
|
@@ -174,30 +238,49 @@ export function createUi({ name, claude, router, report, announce, mod }) {
|
|
|
174
238
|
};
|
|
175
239
|
};
|
|
176
240
|
const renderOf = (type) => markdownRenders.get(type);
|
|
177
|
-
const
|
|
241
|
+
const drawnBlock = (piece, at, drawClaudes, table) => {
|
|
242
|
+
if ('text' in piece)
|
|
243
|
+
return drawClaudes(piece.text);
|
|
244
|
+
const { render, props: block } = piece;
|
|
245
|
+
const draw = () => render.Component({ ...block, ...at, Default: ({ source = block.source }) => drawClaudes(source) });
|
|
246
|
+
try {
|
|
247
|
+
return table === undefined ? draw() : drawWith(table, draw);
|
|
248
|
+
}
|
|
249
|
+
catch (error) {
|
|
250
|
+
render.log(threw(error));
|
|
251
|
+
return drawClaudes(block.source);
|
|
252
|
+
}
|
|
253
|
+
};
|
|
254
|
+
const othersFrom = (table, at, from) => (props) => {
|
|
255
|
+
for (const [index, styler] of stylers.entries()) {
|
|
256
|
+
if (index < from)
|
|
257
|
+
continue;
|
|
258
|
+
const cached = `${stylersSeen}\u0000${at.surface}\u0000${at.columns}\u0000${props.text}`;
|
|
259
|
+
const drawn = drawWith(table, () => borrowed(styler, cached, { markdown: props.text, ...at }), othersFrom(table, at, index + 1));
|
|
260
|
+
if (drawn !== undefined)
|
|
261
|
+
return drawn;
|
|
262
|
+
}
|
|
263
|
+
return table.Markdown(props);
|
|
264
|
+
};
|
|
265
|
+
const markdownIn = (table, at) => {
|
|
178
266
|
const reader = read;
|
|
267
|
+
const others = othersFrom(table, at, 0);
|
|
179
268
|
if (reader === undefined)
|
|
180
|
-
return undefined;
|
|
269
|
+
return stylers.length === 0 ? undefined : others;
|
|
181
270
|
return (props) => {
|
|
182
271
|
const pieces = reader(props.text, renderOf);
|
|
183
272
|
if (pieces.every((piece) => 'text' in piece))
|
|
184
|
-
return
|
|
185
|
-
const
|
|
186
|
-
const drawings = pieces.map((piece) => {
|
|
187
|
-
if ('text' in piece)
|
|
188
|
-
return drawClaudes(piece.text);
|
|
189
|
-
const { render, props: block } = piece;
|
|
190
|
-
try {
|
|
191
|
-
return drawWith(table, () => render.Component({ ...block, Default: ({ source = block.source }) => drawClaudes(source) }));
|
|
192
|
-
}
|
|
193
|
-
catch (error) {
|
|
194
|
-
render.log(threw(error));
|
|
195
|
-
return drawClaudes(block.source);
|
|
196
|
-
}
|
|
197
|
-
});
|
|
273
|
+
return others(props);
|
|
274
|
+
const drawings = pieces.map((piece) => drawnBlock(piece, at, (text) => others({ ...props, text }), table));
|
|
198
275
|
return drawPieces(drawings.map((drawing) => ({ drawing, isClaudesRow: false })), 'pane');
|
|
199
276
|
};
|
|
200
277
|
};
|
|
278
|
+
const markdownDrawing = (text, at) => {
|
|
279
|
+
const pieces = read === undefined ? [] : read(text, renderOf);
|
|
280
|
+
if (pieces.every((piece) => 'text' in piece))
|
|
281
|
+
return Markdown({ text });
|
|
282
|
+
return drawPieces(pieces.map((piece) => ({ drawing: drawnBlock(piece, at, (source) => Markdown({ text: source })), isClaudesRow: false })), 'pane');
|
|
283
|
+
};
|
|
201
284
|
const routeMarkdown = (createReader) => {
|
|
202
285
|
if (read !== undefined)
|
|
203
286
|
return;
|
|
@@ -215,7 +298,7 @@ export function createUi({ name, claude, router, report, announce, mod }) {
|
|
|
215
298
|
if ('text' in piece)
|
|
216
299
|
return { drawing: await drawClaudes(piece.text, index === 0), isClaudesRow: true };
|
|
217
300
|
const { render, props: block } = piece;
|
|
218
|
-
const component = await drawComponent(table, (Default) => render.Component({ ...block, Default }), ({ source = block.source }, isClaudesRow) => drawClaudes(source, index === 0 && isClaudesRow));
|
|
301
|
+
const component = await drawComponent(table, (Default) => render.Component({ ...block, ...styledAt(e), id: e.requestId, Default }), ({ source = block.source }, isClaudesRow) => drawClaudes(source, index === 0 && isClaudesRow));
|
|
219
302
|
if (!('failure' in component))
|
|
220
303
|
return component;
|
|
221
304
|
render.log(component.failure);
|
|
@@ -260,10 +343,10 @@ export function createUi({ name, claude, router, report, announce, mod }) {
|
|
|
260
343
|
const { init } = added;
|
|
261
344
|
openPanes.add(init.id);
|
|
262
345
|
paneStates.set(init.id, { isShown: true, isFocused: e.props.isFocused });
|
|
263
|
-
readPanes();
|
|
346
|
+
void readPanes();
|
|
264
347
|
const table = claude.ui.resolve(e);
|
|
265
348
|
try {
|
|
266
|
-
return drawWith(table, () => init.render(mod(), { ...e.props, params: added.params }), markdownIn(table));
|
|
349
|
+
return drawWith(table, () => init.render(mod(), { ...e.props, surface: e.surface, params: added.params }), markdownIn(table, styledAt(e, e.props.bodyColumns)));
|
|
267
350
|
}
|
|
268
351
|
catch (error) {
|
|
269
352
|
paneLogs.get(init.id)?.(`threw: ${messageOf(error)}`);
|
|
@@ -281,8 +364,8 @@ export function createUi({ name, claude, router, report, announce, mod }) {
|
|
|
281
364
|
router.add('ui.close', async (e, next) => {
|
|
282
365
|
openPanes.delete(e.id);
|
|
283
366
|
paneStates.delete(e.id);
|
|
284
|
-
readPanes();
|
|
285
367
|
const closed = await next(e);
|
|
368
|
+
await readPanes();
|
|
286
369
|
const init = panes.get(e.id)?.init;
|
|
287
370
|
if (init?.onClose !== undefined)
|
|
288
371
|
await handle(init, 'onClose', () => init.onClose?.(mod(), e));
|
|
@@ -427,14 +510,15 @@ export function createUi({ name, claude, router, report, announce, mod }) {
|
|
|
427
510
|
const Component = (props) => render(mod(), props);
|
|
428
511
|
const stop = (subscription) => () => {
|
|
429
512
|
subscription?.remove();
|
|
430
|
-
if (markdown !== undefined)
|
|
431
|
-
|
|
513
|
+
if (markdown !== undefined && markdownRenders.delete(markdown.markdown))
|
|
514
|
+
void send({ parts: partList() });
|
|
432
515
|
styles.delete(feature);
|
|
433
516
|
claude.ui.invalidate('ui.render');
|
|
434
517
|
};
|
|
435
518
|
if (markdown !== undefined) {
|
|
436
519
|
markdownRenders.set(markdown.markdown, { Component, log: logOnce(`${nameOf(kind)} style`) });
|
|
437
520
|
routeMarkdown(markdown.createReader);
|
|
521
|
+
void send({ parts: partList() });
|
|
438
522
|
return { kind, remove: stop() };
|
|
439
523
|
}
|
|
440
524
|
const log = logOnce(`${nameOf(kind)} style`);
|
|
@@ -442,7 +526,7 @@ export function createUi({ name, claude, router, report, announce, mod }) {
|
|
|
442
526
|
if (e.component !== component)
|
|
443
527
|
return next(e);
|
|
444
528
|
const table = claude.ui.resolve(e);
|
|
445
|
-
const drawn = await drawComponent(table, (Default) => Component({ ...e.props, Default }), (given, isClaudesRow) => next({ ...e, props: pieceProps(e.props, given, isClaudesRow) }));
|
|
529
|
+
const drawn = await drawComponent(table, (Default) => Component({ ...e.props, ...styledAt(e), id: e.requestId, Default }), (given, isClaudesRow) => next({ ...e, props: pieceProps(e.props, given, isClaudesRow) }));
|
|
446
530
|
if ('failure' in drawn) {
|
|
447
531
|
log(drawn.failure);
|
|
448
532
|
return next(e);
|
|
@@ -455,48 +539,49 @@ export function createUi({ name, claude, router, report, announce, mod }) {
|
|
|
455
539
|
};
|
|
456
540
|
const forgetDraws = (key) => {
|
|
457
541
|
for (const kept of latestDraws.get(key)?.values() ?? [])
|
|
458
|
-
for (const draw of kept)
|
|
542
|
+
for (const draw of kept.draws)
|
|
459
543
|
draws.delete(draw);
|
|
460
544
|
latestDraws.delete(key);
|
|
461
545
|
};
|
|
462
546
|
const drawPart = (key, title, input, render) => {
|
|
463
547
|
try {
|
|
464
548
|
const pressed = [];
|
|
465
|
-
const
|
|
466
|
-
const tree = drawn === undefined ? null : elementData(drawn, pressed);
|
|
549
|
+
const tree = treeOf(render, pressed);
|
|
467
550
|
failedDraws.delete(key);
|
|
468
|
-
|
|
551
|
+
const number = nextDraw();
|
|
469
552
|
const inputs = latestDraws.get(key) ?? new Map();
|
|
470
553
|
latestDraws.set(key, inputs);
|
|
471
554
|
const drawnFor = JSON.stringify('turn' in input ? { ...input, turn: input.turn.prompt.id } : input);
|
|
472
|
-
const earlier = inputs.get(drawnFor) ?? [];
|
|
473
|
-
const kept = [...earlier,
|
|
555
|
+
const earlier = inputs.get(drawnFor)?.draws ?? [];
|
|
556
|
+
const kept = [...earlier, number].slice(-2);
|
|
474
557
|
for (const draw of earlier)
|
|
475
558
|
if (!kept.includes(draw))
|
|
476
559
|
draws.delete(draw);
|
|
477
560
|
inputs.delete(drawnFor);
|
|
478
|
-
inputs.set(drawnFor, kept);
|
|
561
|
+
inputs.set(drawnFor, { draws: kept, tree: JSON.stringify(tree), render });
|
|
479
562
|
const [oldest] = inputs;
|
|
480
563
|
if (inputs.size > keptDrawInputs && oldest !== undefined) {
|
|
481
|
-
for (const draw of oldest[1])
|
|
564
|
+
for (const draw of oldest[1].draws)
|
|
482
565
|
draws.delete(draw);
|
|
483
566
|
inputs.delete(oldest[0]);
|
|
484
567
|
}
|
|
485
|
-
draws.set(
|
|
486
|
-
return { draw:
|
|
568
|
+
draws.set(number, { id: key, handlers: pressed });
|
|
569
|
+
return { draw: number, tree };
|
|
487
570
|
}
|
|
488
571
|
catch (error) {
|
|
489
572
|
if (!failedDraws.has(key))
|
|
490
573
|
report({ id: key, message: `The ${title} could not draw`, error });
|
|
491
574
|
failedDraws.add(key);
|
|
492
|
-
|
|
575
|
+
throw error;
|
|
493
576
|
}
|
|
494
577
|
};
|
|
495
578
|
const draw = (input) => {
|
|
579
|
+
if ('markdown' in input)
|
|
580
|
+
return drawPart('markdown', 'markdown style', input, () => markdownDrawing(input.markdown, { surface: input.surface, columns: input.columns }));
|
|
496
581
|
if ('page' in input) {
|
|
497
582
|
const added = pages.get(input.page);
|
|
498
583
|
if (added === undefined)
|
|
499
|
-
|
|
584
|
+
throw new Error(`${name} has no ${input.page} page.`);
|
|
500
585
|
return drawPart(`page:${input.page}`, `${added.init.title} page`, input, () => added.init.render(mod(), { params: input.params, isFocused: input.isFocused, columns: input.columns }));
|
|
501
586
|
}
|
|
502
587
|
const widget = widgets.get(input.widget);
|
|
@@ -506,19 +591,25 @@ export function createUi({ name, claude, router, report, announce, mod }) {
|
|
|
506
591
|
const context = (input.area === TurnEnd && input.turn !== undefined ? { area: input.area, columns: input.columns, turn: input.turn } : { area: input.area, columns: input.columns });
|
|
507
592
|
return drawPart(`widget:${widget.id}`, `${widget.title} widget`, input, () => widget.render(mod(), context));
|
|
508
593
|
};
|
|
509
|
-
const press = async ({ draw: drawn, handler, args }) => {
|
|
594
|
+
const press = async ({ draw: drawn, handler, args }, caller) => {
|
|
510
595
|
const known = draws.get(drawn);
|
|
511
596
|
const run = known?.handlers[handler];
|
|
512
597
|
if (known === undefined || run === undefined)
|
|
513
598
|
throw new Error(`${name}: that button drew before the last redraw. Press the one it shows now.`);
|
|
514
|
-
|
|
599
|
+
if (caller !== cmodPluginName && known.id !== 'markdown')
|
|
600
|
+
throw new Error(`${name}: ${caller} pressed a button only the cmod plugin draws.`);
|
|
601
|
+
const pressed = async () => {
|
|
515
602
|
try {
|
|
516
603
|
await run(...args);
|
|
517
604
|
}
|
|
518
605
|
catch (error) {
|
|
519
606
|
report({ id: known.id, message: 'Its button failed', error });
|
|
520
607
|
}
|
|
521
|
-
}
|
|
608
|
+
};
|
|
609
|
+
if (caller === cmodPluginName)
|
|
610
|
+
return collect(pressed);
|
|
611
|
+
await pressed();
|
|
612
|
+
return null;
|
|
522
613
|
};
|
|
523
614
|
return {
|
|
524
615
|
panes: { add: addPane },
|
|
@@ -539,19 +630,28 @@ export function createUi({ name, claude, router, report, announce, mod }) {
|
|
|
539
630
|
await passOn();
|
|
540
631
|
return answer;
|
|
541
632
|
},
|
|
542
|
-
answer(method, input) {
|
|
633
|
+
answer(method, input, caller) {
|
|
634
|
+
const isMarkdown = method === partMethods.draw && isObject(input) && typeof input['markdown'] === 'string';
|
|
635
|
+
if (caller !== cmodPluginName && !isMarkdown && method !== partMethods.press)
|
|
636
|
+
return undefined;
|
|
543
637
|
if (method === partMethods.list)
|
|
544
638
|
return Promise.resolve({ value: partList() });
|
|
545
639
|
if (method === partMethods.draw)
|
|
546
|
-
return Promise.resolve({ value: draw(input) });
|
|
640
|
+
return Promise.resolve().then(() => ({ value: draw(input) }));
|
|
547
641
|
if (method === partMethods.press)
|
|
548
|
-
return press(input).then((value) => ({ value }));
|
|
642
|
+
return press(input, caller).then((value) => ({ value }));
|
|
549
643
|
if (method === partMethods.shown) {
|
|
550
644
|
shownPages = input;
|
|
551
645
|
return Promise.resolve({ value: null });
|
|
552
646
|
}
|
|
647
|
+
if (method === partMethods.stylers) {
|
|
648
|
+
hear(input, true);
|
|
649
|
+
return Promise.resolve({ value: null });
|
|
650
|
+
}
|
|
553
651
|
return undefined;
|
|
554
652
|
},
|
|
653
|
+
markdownIn,
|
|
654
|
+
restyled: (stylers) => hear(stylers, true),
|
|
555
655
|
started() {
|
|
556
656
|
const held = merged(beforeStart ?? []);
|
|
557
657
|
beforeStart = undefined;
|
package/runtime/watches.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"watches.d.ts","sourceRoot":"","sources":["../src/runtime/watches.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,WAAW,CAAA;AAE3C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAA;AAC5D,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AACzC,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,cAAc,CAAA;AAE3C,MAAM,MAAM,OAAO,GAAG;IAAE,GAAG,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,EAAE,QAAQ,EAAE,CAAC,MAAM,EAAE,UAAU,KAAK,OAAO,GAAG,YAAY,CAAA;CAAE,CAAA;
|
|
1
|
+
{"version":3,"file":"watches.d.ts","sourceRoot":"","sources":["../src/runtime/watches.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,WAAW,CAAA;AAE3C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAA;AAC5D,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AACzC,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,cAAc,CAAA;AAE3C,MAAM,MAAM,OAAO,GAAG;IAAE,GAAG,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,EAAE,QAAQ,EAAE,CAAC,MAAM,EAAE,UAAU,KAAK,OAAO,GAAG,YAAY,CAAA;CAAE,CAAA;AAUhH,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,GAAG,OAAO,CAyEzF"}
|
package/runtime/watches.js
CHANGED
|
@@ -1,12 +1,17 @@
|
|
|
1
1
|
import { ifMissing } from '../utils/paths.js';
|
|
2
2
|
const watchMs = 500;
|
|
3
|
+
const missingEvery = 4;
|
|
3
4
|
const watchedFiles = 2000;
|
|
4
5
|
export function createWatches(claude, report) {
|
|
5
6
|
const watches = new Set();
|
|
6
7
|
let polling;
|
|
7
8
|
let isPolling = false;
|
|
8
|
-
|
|
9
|
+
let ticks = 0;
|
|
10
|
+
const stampsOf = async (watch) => {
|
|
11
|
+
const { paths } = watch;
|
|
9
12
|
const stamps = new Map();
|
|
13
|
+
const missing = new Set();
|
|
14
|
+
const skipped = ticks % missingEvery === 0 ? new Set() : watch.missing;
|
|
10
15
|
const visit = async (path) => {
|
|
11
16
|
const stat = await claude.fs.stat(path).catch(ifMissing(undefined));
|
|
12
17
|
if (stat === undefined)
|
|
@@ -19,8 +24,16 @@ export function createWatches(claude, report) {
|
|
|
19
24
|
for (const entry of await claude.fs.list(path).catch(ifMissing([])))
|
|
20
25
|
await visit(`${path}/${entry.name}`);
|
|
21
26
|
};
|
|
22
|
-
for (const path of paths)
|
|
27
|
+
for (const path of paths) {
|
|
28
|
+
if (skipped.has(path)) {
|
|
29
|
+
missing.add(path);
|
|
30
|
+
continue;
|
|
31
|
+
}
|
|
23
32
|
await visit(path);
|
|
33
|
+
if (![...stamps.keys()].some((seen) => seen === path || seen.startsWith(`${path}/`)))
|
|
34
|
+
missing.add(path);
|
|
35
|
+
}
|
|
36
|
+
watch.missing = missing;
|
|
24
37
|
return stamps;
|
|
25
38
|
};
|
|
26
39
|
const stop = (watch) => {
|
|
@@ -30,7 +43,7 @@ export function createWatches(claude, report) {
|
|
|
30
43
|
polling?.cancel();
|
|
31
44
|
polling = undefined;
|
|
32
45
|
};
|
|
33
|
-
const stampsOrStop = (watch) => stampsOf(watch
|
|
46
|
+
const stampsOrStop = (watch) => stampsOf(watch).catch((error) => {
|
|
34
47
|
stop(watch);
|
|
35
48
|
report({ id: 'fs:onChange', message: 'Could not read the files fs.onChange watches', error });
|
|
36
49
|
return undefined;
|
|
@@ -39,6 +52,7 @@ export function createWatches(claude, report) {
|
|
|
39
52
|
if (isPolling)
|
|
40
53
|
return;
|
|
41
54
|
isPolling = true;
|
|
55
|
+
ticks += 1;
|
|
42
56
|
try {
|
|
43
57
|
for (const watch of watches) {
|
|
44
58
|
const now = await stampsOrStop(watch);
|
|
@@ -63,7 +77,7 @@ export function createWatches(claude, report) {
|
|
|
63
77
|
};
|
|
64
78
|
return {
|
|
65
79
|
add(paths, listener) {
|
|
66
|
-
const watch = { paths, listener, seen: undefined };
|
|
80
|
+
const watch = { paths, listener, seen: undefined, missing: new Set() };
|
|
67
81
|
watches.add(watch);
|
|
68
82
|
void stampsOrStop(watch).then((stamps) => void (watch.seen ??= stamps));
|
|
69
83
|
polling ??= claude.clock.every(watchMs, () => void poll());
|
package/runtime/widgets.d.ts
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
import type { ElementTable, RenderElement } from 'claude-code';
|
|
1
|
+
import type { ElementTable, MarkdownProps, RenderElement } from 'claude-code';
|
|
2
2
|
import type { TurnData } from '../session/conversation.js';
|
|
3
3
|
import { type Area } from '../ui/areas.js';
|
|
4
|
+
import type { StyledAt } from '../ui/styles.js';
|
|
4
5
|
import type { Claude } from './claude.js';
|
|
5
6
|
import type { DrawnParts } from './parts.js';
|
|
6
7
|
import type { Router } from './router.js';
|
|
7
|
-
import { type PartsUpdate } from './ui.js';
|
|
8
|
+
import { type PartsUpdate, type WidgetDeclaration } from './ui.js';
|
|
8
9
|
export type WidgetRow = {
|
|
9
10
|
readonly left: readonly string[];
|
|
10
11
|
readonly right: readonly string[];
|
|
@@ -18,7 +19,7 @@ export type PlacedWidget = {
|
|
|
18
19
|
readonly mod: string;
|
|
19
20
|
readonly title: string;
|
|
20
21
|
readonly areas: readonly Area[];
|
|
21
|
-
}
|
|
22
|
+
} & Pick<WidgetDeclaration, 'place'>;
|
|
22
23
|
export type Move = 'up' | 'down' | 'left' | 'right';
|
|
23
24
|
export declare const claudeHint = "claude/hint";
|
|
24
25
|
export declare const claudeModes = "claude/modes";
|
|
@@ -31,18 +32,19 @@ export type Widgets = {
|
|
|
31
32
|
reload(): Promise<void>;
|
|
32
33
|
recheck(): Promise<void>;
|
|
33
34
|
rows(area: Area, columns: number): RenderElement[];
|
|
34
|
-
draw(area: Area, table: ElementTable,
|
|
35
|
+
draw(area: Area, table: ElementTable, at: StyledAt, turn?: TurnData): Promise<RenderElement[]>;
|
|
35
36
|
};
|
|
36
37
|
export declare function layoutOf(value: unknown): WidgetLayout;
|
|
37
38
|
export declare function placedIn(layout: WidgetLayout, key: string): Area | undefined;
|
|
38
39
|
export declare function toggled(layout: WidgetLayout, key: string): WidgetLayout;
|
|
39
40
|
export declare function moved(layout: WidgetLayout, widget: PlacedWidget, move: Move): WidgetLayout;
|
|
40
|
-
export declare function serveWidgets({ claude, router, store, report, turnClosedBy, parts, }: {
|
|
41
|
+
export declare function serveWidgets({ claude, router, store, report, turnClosedBy, parts, markdownIn, }: {
|
|
41
42
|
readonly claude: Claude;
|
|
42
43
|
readonly router: Router;
|
|
43
44
|
readonly store: string;
|
|
44
45
|
readonly report: (id: string, message: string, error: unknown) => void;
|
|
45
46
|
readonly turnClosedBy: (rowId: string) => TurnData | undefined;
|
|
46
47
|
readonly parts: DrawnParts;
|
|
48
|
+
readonly markdownIn: (table: ElementTable, at: StyledAt) => ((props: MarkdownProps) => RenderElement) | undefined;
|
|
47
49
|
}): Widgets;
|
|
48
50
|
//# sourceMappingURL=widgets.d.ts.map
|
package/runtime/widgets.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"widgets.d.ts","sourceRoot":"","sources":["../src/runtime/widgets.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,aAAa,CAAA;
|
|
1
|
+
{"version":3,"file":"widgets.d.ts","sourceRoot":"","sources":["../src/runtime/widgets.ts"],"names":[],"mappings":"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"}
|