@cmodjs/core 0.1.8 → 0.1.10
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 +2 -2
- package/docs/hooks.md +62 -6
- package/docs/index.md +7 -4
- package/docs/install-steps.md +3 -3
- package/docs/jobs.md +5 -4
- package/docs/mod.md +57 -7
- package/docs/testing.md +25 -9
- package/docs/ui.md +134 -5
- package/jobs/check.js +2 -2
- package/jobs/context.d.ts.map +1 -1
- package/jobs/context.js +2 -0
- package/jobs/permissions/decide-permission.js +2 -2
- package/jobs/permissions/find-project-scope.d.ts +1 -1
- package/jobs/permissions/find-project-scope.d.ts.map +1 -1
- package/jobs/permissions/find-project-scope.js +9 -9
- package/jobs/permissions/match-target.d.ts.map +1 -1
- package/jobs/permissions/match-target.js +4 -3
- package/mod.d.ts +16 -6
- package/mod.d.ts.map +1 -1
- package/package.json +2 -1
- package/path.d.ts +2 -0
- package/path.d.ts.map +1 -0
- package/path.js +1 -0
- package/register.d.ts.map +1 -1
- package/register.js +8 -2
- package/runtime/claude.d.ts +4 -1
- package/runtime/claude.d.ts.map +1 -1
- package/runtime/hooks.d.ts +10 -2
- package/runtime/hooks.d.ts.map +1 -1
- package/runtime/hooks.js +56 -18
- package/runtime/lifecycle.d.ts.map +1 -1
- package/runtime/lifecycle.js +12 -2
- package/runtime/ui.d.ts.map +1 -1
- package/runtime/ui.js +42 -26
- package/shell.d.ts +2 -0
- package/shell.d.ts.map +1 -0
- package/shell.js +1 -0
- package/src/jobs/check.ts +2 -2
- package/src/jobs/context.ts +2 -0
- package/src/jobs/permissions/decide-permission.ts +2 -2
- package/src/jobs/permissions/find-project-scope.ts +11 -10
- package/src/jobs/permissions/match-target.ts +4 -3
- package/src/mod.ts +24 -4
- package/src/path.ts +1 -0
- package/src/register.ts +8 -2
- package/src/runtime/claude.ts +11 -1
- package/src/runtime/hooks.ts +62 -23
- package/src/runtime/lifecycle.ts +11 -4
- package/src/runtime/ui.ts +39 -26
- package/src/shell.ts +1 -0
- package/src/testing/fake-claude.ts +14 -5
- package/src/testing/fake-elements.ts +5 -7
- package/src/testing/fake-files.ts +5 -5
- package/src/testing.ts +83 -11
- package/src/ui/components.ts +70 -0
- package/src/ui/define-pane.ts +5 -1
- package/src/utils/call-effects.ts +12 -11
- package/src/utils/parse-shell.ts +28 -36
- package/src/utils/paths.ts +4 -19
- package/src/vendor.ts +1 -0
- package/testing/fake-claude.d.ts +5 -0
- package/testing/fake-claude.d.ts.map +1 -1
- package/testing/fake-claude.js +13 -3
- package/testing/fake-elements.d.ts +5 -8
- package/testing/fake-elements.d.ts.map +1 -1
- package/testing/fake-elements.js +6 -6
- package/testing/fake-files.js +5 -5
- package/testing.d.ts +4 -2
- package/testing.d.ts.map +1 -1
- package/testing.js +65 -9
- package/ui/components.d.ts +48 -0
- package/ui/components.d.ts.map +1 -0
- package/ui/components.js +56 -0
- package/ui/define-pane.d.ts +5 -1
- package/ui/define-pane.d.ts.map +1 -1
- package/utils/call-effects.d.ts.map +1 -1
- package/utils/call-effects.js +12 -11
- package/utils/parse-shell.d.ts +5 -9
- package/utils/parse-shell.d.ts.map +1 -1
- package/utils/parse-shell.js +5 -10
- package/utils/paths.d.ts +0 -3
- package/utils/paths.d.ts.map +1 -1
- package/utils/paths.js +3 -18
- package/vendor.d.ts +1 -0
- package/vendor.d.ts.map +1 -1
- package/vendor.js +209 -12
package/testing.js
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { storeFolder } from './records.js';
|
|
2
2
|
import { answerCall, notInstalled } from './runtime/dependencies.js';
|
|
3
|
+
import { toolInputOf } from './runtime/tool-calls.js';
|
|
3
4
|
import { createLifecycle } from './runtime/lifecycle.js';
|
|
4
5
|
import { fakeClaude } from './testing/fake-claude.js';
|
|
5
|
-
import { elements,
|
|
6
|
+
import { elements, findElement, rowsOf } from './testing/fake-elements.js';
|
|
6
7
|
import { fakeFiles } from './testing/fake-files.js';
|
|
7
8
|
const defaultColumns = 80;
|
|
8
9
|
const defaultRows = 24;
|
|
@@ -24,6 +25,13 @@ export function testMod(definition, options = {}) {
|
|
|
24
25
|
fake.claude.session.root = async () => projectRoot;
|
|
25
26
|
fake.claude.session.cwd = async () => cwd;
|
|
26
27
|
fake.fakes.cmod.call = fakeDependencies(options.dependencies ?? {});
|
|
28
|
+
const firedAgents = new Map();
|
|
29
|
+
const listAgents = fake.claude.agent.list;
|
|
30
|
+
fake.claude.agent.list = async () => {
|
|
31
|
+
if (fake.fakes.agent.list !== undefined || firedAgents.size === 0)
|
|
32
|
+
return listAgents();
|
|
33
|
+
return [...firedAgents].map(([id, type]) => ({ id, type, description: '', status: 'running' }));
|
|
34
|
+
};
|
|
27
35
|
Object.assign(fake.fakes.fs, fakeFiles(options.files ?? {}));
|
|
28
36
|
const starting = options.state;
|
|
29
37
|
const declared = Object.entries(definition.state ?? {});
|
|
@@ -55,10 +63,18 @@ export function testMod(definition, options = {}) {
|
|
|
55
63
|
}
|
|
56
64
|
const opened = fake.calls.findLast((call) => call.call === 'ui.open' && call.args[0].id === paneId)?.args[0];
|
|
57
65
|
const columns = opened?.columns ?? defaultColumns;
|
|
58
|
-
const
|
|
66
|
+
const isFocused = (await fake.claude.ui.panes()).some((open) => open.id === paneId && open.isFocused);
|
|
67
|
+
const props = { title: opened?.title ?? paneId, isFocused, bodyColumns: columns, placement: 'dock', scroll: { offset: 0, bodyRows: defaultRows }, view: {} };
|
|
59
68
|
const drawing = await route('ui.render', { surface: 'terminal', component: 'Pane', requestId: paneId, props }, elements.Box({}));
|
|
60
69
|
return { drawing, columns };
|
|
61
70
|
};
|
|
71
|
+
const drawnElement = async (paneId, type, key) => {
|
|
72
|
+
const props = findElement((await drawPane(paneId)).drawing, type, key);
|
|
73
|
+
if (props === undefined)
|
|
74
|
+
throw new Error(`The pane "${paneId}" of ${name} draws no ${type} with the ${type === 'Button' ? 'key or label' : 'key'} "${key}".`);
|
|
75
|
+
return props;
|
|
76
|
+
};
|
|
77
|
+
const eventIn = (paneId, key) => ({ plugin: name, element: key, component: 'Pane', requestId: paneId, surface: 'terminal' });
|
|
62
78
|
const drawSlot = async (component, props, requestId = `${component}_${(slotDraws += 1)}`) => {
|
|
63
79
|
await start();
|
|
64
80
|
const input = { surface: 'terminal', component, requestId, props };
|
|
@@ -78,9 +94,29 @@ export function testMod(definition, options = {}) {
|
|
|
78
94
|
const filled = { session_id: sessionId, transcript_path: '/test/transcript.jsonl', cwd, hook_event_name: event, ...toolUse, ...input };
|
|
79
95
|
if (event !== 'PreToolUse')
|
|
80
96
|
return route(`classic.${event}`, filled, below);
|
|
81
|
-
|
|
82
|
-
return route('classic.PreToolUse', { ...tool_input, tool: tool_name, tool_use_id }, below);
|
|
97
|
+
return firePreToolUse(filled, below);
|
|
83
98
|
});
|
|
99
|
+
const firePreToolUse = async ({ tool_name, tool_input, tool_use_id, agent_id, agent_type }, below) => {
|
|
100
|
+
await start();
|
|
101
|
+
if (agent_id !== undefined && agent_type !== undefined)
|
|
102
|
+
firedAgents.set(agent_id, agent_type);
|
|
103
|
+
const envelope = { ...tool_input, tool: tool_name, tool_use_id, ...(agent_id === undefined ? {} : { agentId: agent_id }) };
|
|
104
|
+
const asks = below?.deny === undefined ? { decision: 'ask' } : { decision: 'deny', reason: below.deny };
|
|
105
|
+
let reached = envelope;
|
|
106
|
+
let check = asks;
|
|
107
|
+
const answer = await lifecycle.route('tool.call', envelope, async (e) => {
|
|
108
|
+
reached = e;
|
|
109
|
+
check = await lifecycle.route('tool.check', { tool: e.tool, input: toolInputOf(e), tool_use_id: e.tool_use_id, ...(e.agentId === undefined ? {} : { agentId: e.agentId }) }, async () => asks);
|
|
110
|
+
return (check.decision === 'deny' ? { deny: check.reason ?? '' } : { result: '' });
|
|
111
|
+
});
|
|
112
|
+
const updatedInput = toolInputOf(reached);
|
|
113
|
+
const decided = check === asks ? {} : check.decision === 'allow' ? { allow: true } : check.decision === 'ask' ? { ask: check.reason ?? '' } : {};
|
|
114
|
+
return {
|
|
115
|
+
...(answer.deny === undefined ? decided : { deny: answer.deny }),
|
|
116
|
+
...(JSON.stringify(updatedInput) === JSON.stringify(tool_input) ? {} : { updatedInput }),
|
|
117
|
+
...(answer.context === undefined || answer.context.length === 0 ? {} : { additionalContext: [...answer.context] }),
|
|
118
|
+
};
|
|
119
|
+
};
|
|
84
120
|
return {
|
|
85
121
|
start,
|
|
86
122
|
fire,
|
|
@@ -114,11 +150,31 @@ export function testMod(definition, options = {}) {
|
|
|
114
150
|
throw new Error(`${name} has no tool ${toolName}. Add it in setup with mod.use(tool({ name: '${toolName}', … })).`);
|
|
115
151
|
return answer;
|
|
116
152
|
},
|
|
117
|
-
async press(paneId, key) {
|
|
118
|
-
const
|
|
119
|
-
if (
|
|
120
|
-
throw new Error(`The pane "${paneId}" of ${name}
|
|
121
|
-
|
|
153
|
+
async press(paneId, key, link) {
|
|
154
|
+
const props = await drawnElement(paneId, link === undefined ? 'Button' : 'Markdown', key);
|
|
155
|
+
if (link !== undefined && props['onLinkPress'] === undefined)
|
|
156
|
+
throw new Error(`The Markdown "${key}" in the pane "${paneId}" of ${name} has no onLinkPress, so Claude Code opens its links itself.`);
|
|
157
|
+
const pressed = { ...eventIn(paneId, String(props['key'])), ...(link === undefined ? {} : { link: { href: link } }) };
|
|
158
|
+
await lifecycle.route('ui.press', pressed, async (e) => {
|
|
159
|
+
if (e.link === undefined)
|
|
160
|
+
await props['onPress'](e);
|
|
161
|
+
else
|
|
162
|
+
await props['onLinkPress'](e.link, e);
|
|
163
|
+
return { element: e.element };
|
|
164
|
+
});
|
|
165
|
+
},
|
|
166
|
+
async input(paneId, key, text, kind = 'submit') {
|
|
167
|
+
const props = await drawnElement(paneId, 'Input', key);
|
|
168
|
+
const typed = { ...eventIn(paneId, key), kind, value: text };
|
|
169
|
+
await props[kind === 'submit' ? 'onSubmit' : 'onInput']?.(text, typed);
|
|
170
|
+
},
|
|
171
|
+
async select(paneId, key, value) {
|
|
172
|
+
const props = await drawnElement(paneId, 'Select', key);
|
|
173
|
+
const options = props['options'].map((option) => option.value);
|
|
174
|
+
if (!options.includes(value))
|
|
175
|
+
throw new Error(`The Select "${key}" in the pane "${paneId}" of ${name} has no option "${value}". Its options are ${options.map((option) => `"${option}"`).join(', ')}.`);
|
|
176
|
+
const picked = { ...eventIn(paneId, key), value };
|
|
177
|
+
await props['onSelect'](value, picked);
|
|
122
178
|
},
|
|
123
179
|
async moveTo(nextRoot, nextCwd = nextRoot) {
|
|
124
180
|
await start();
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import type { RenderChildren, RenderElement } from 'claude-code';
|
|
2
|
+
export type Tab = {
|
|
3
|
+
readonly key: string;
|
|
4
|
+
readonly label: string;
|
|
5
|
+
};
|
|
6
|
+
export declare function Tabs({ tabs, selected, onSelect, children }: {
|
|
7
|
+
readonly tabs: readonly Tab[];
|
|
8
|
+
readonly selected: string;
|
|
9
|
+
readonly onSelect: (key: string) => void;
|
|
10
|
+
readonly children?: RenderChildren;
|
|
11
|
+
}): RenderElement;
|
|
12
|
+
export declare function Split({ children }: {
|
|
13
|
+
readonly children: readonly RenderElement[];
|
|
14
|
+
}): RenderElement;
|
|
15
|
+
export declare function Panel({ title, children }: {
|
|
16
|
+
readonly title: string;
|
|
17
|
+
readonly children?: RenderChildren;
|
|
18
|
+
}): RenderElement;
|
|
19
|
+
export declare function Toggle({ label, checked, onChange }: {
|
|
20
|
+
readonly label: string;
|
|
21
|
+
readonly checked: boolean;
|
|
22
|
+
readonly onChange: (checked: boolean) => void;
|
|
23
|
+
}): RenderElement;
|
|
24
|
+
export declare function Tooltip({ text, children }: {
|
|
25
|
+
readonly text: string;
|
|
26
|
+
readonly children?: RenderChildren;
|
|
27
|
+
}): RenderElement;
|
|
28
|
+
export declare function Help({ text, isOpen, onOpenChange }: {
|
|
29
|
+
readonly text: string;
|
|
30
|
+
readonly isOpen: boolean;
|
|
31
|
+
readonly onOpenChange: (isOpen: boolean) => void;
|
|
32
|
+
}): RenderElement;
|
|
33
|
+
export declare function Dialog({ title, children, actions }: {
|
|
34
|
+
readonly title: string;
|
|
35
|
+
readonly children?: RenderChildren;
|
|
36
|
+
readonly actions: RenderChildren;
|
|
37
|
+
}): RenderElement;
|
|
38
|
+
export declare function Pagination({ page, pages, onPage }: {
|
|
39
|
+
readonly page: number;
|
|
40
|
+
readonly pages: number;
|
|
41
|
+
readonly onPage: (page: number) => void;
|
|
42
|
+
}): RenderElement;
|
|
43
|
+
export declare function ProgressBar({ done, total, width }: {
|
|
44
|
+
readonly done: number;
|
|
45
|
+
readonly total: number;
|
|
46
|
+
readonly width?: number;
|
|
47
|
+
}): RenderElement;
|
|
48
|
+
//# sourceMappingURL=components.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"components.d.ts","sourceRoot":"","sources":["../src/ui/components.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,aAAa,CAAA;AAGhE,MAAM,MAAM,GAAG,GAAG;IAAE,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAA;AAElE,wBAAgB,IAAI,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,EAAE;IAAE,QAAQ,CAAC,IAAI,EAAE,SAAS,GAAG,EAAE,CAAC;IAAC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,QAAQ,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;IAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,cAAc,CAAA;CAAE,GAAG,aAAa,CAQtN;AAED,wBAAgB,KAAK,CAAC,EAAE,QAAQ,EAAE,EAAE;IAAE,QAAQ,CAAC,QAAQ,EAAE,SAAS,aAAa,EAAE,CAAA;CAAE,GAAG,aAAa,CAGlG;AAED,wBAAgB,KAAK,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,EAAE;IAAE,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,cAAc,CAAA;CAAE,GAAG,aAAa,CAExH;AAED,wBAAgB,MAAM,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,EAAE;IAAE,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,QAAQ,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,CAAA;CAAE,GAAG,aAAa,CAExK;AAED,wBAAgB,OAAO,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE;IAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,cAAc,CAAA;CAAE,GAAG,aAAa,CAExH;AAED,wBAAgB,IAAI,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,YAAY,EAAE,EAAE;IAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,YAAY,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,IAAI,CAAA;CAAE,GAAG,aAAa,CAEzK;AAED,wBAAgB,MAAM,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,EAAE;IAAE,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,cAAc,CAAC;IAAC,QAAQ,CAAC,OAAO,EAAE,cAAc,CAAA;CAAE,GAAG,aAAa,CAEpK;AAED,wBAAgB,UAAU,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE;IAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAA;CAAE,GAAG,aAAa,CAS7J;AAED,wBAAgB,WAAW,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,KAAU,EAAE,EAAE;IAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,aAAa,CAGlJ"}
|
package/ui/components.js
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { Box, Button, Text } from './elements.js';
|
|
2
|
+
export function Tabs({ tabs, selected, onSelect, children }) {
|
|
3
|
+
const row = tabs.map((tab, index) => {
|
|
4
|
+
const hotkey = index < 9 ? `${index + 1}` : undefined;
|
|
5
|
+
return tab.key === selected
|
|
6
|
+
? Text({ children: [...(hotkey === undefined ? [] : [Text({ color: 'claude', children: hotkey }), ': ']), Text({ bold: true, underline: true, children: tab.label })] })
|
|
7
|
+
: Button({ plain: true, dimColor: true, key: `tab:${tab.key}`, ...(hotkey === undefined ? {} : { hotkey }), label: tab.label, onPress: () => onSelect(tab.key) });
|
|
8
|
+
});
|
|
9
|
+
return Box({ flexDirection: 'column', gap: 1, children: [Box({ gap: 3, children: row }), children] });
|
|
10
|
+
}
|
|
11
|
+
export function Split({ children }) {
|
|
12
|
+
const width = `${Math.floor(100 / Math.max(children.length, 1))}%`;
|
|
13
|
+
return Box({ gap: 1, children: children.map((child) => Box({ width, children: child })) });
|
|
14
|
+
}
|
|
15
|
+
export function Panel({ title, children }) {
|
|
16
|
+
return Box({ flexDirection: 'column', flexGrow: 1, borderStyle: 'round', borderColor: 'subtle', paddingX: 1, children: [Text({ bold: true, children: title }), children] });
|
|
17
|
+
}
|
|
18
|
+
export function Toggle({ label, checked, onChange }) {
|
|
19
|
+
return Button({ plain: true, key: `toggle:${label}`, label: `${checked ? '[x]' : '[ ]'} ${label}`, onPress: () => onChange(!checked) });
|
|
20
|
+
}
|
|
21
|
+
export function Tooltip({ text, children }) {
|
|
22
|
+
return Box({ key: `tooltip:${text}`, children: [children, card(text, false)] });
|
|
23
|
+
}
|
|
24
|
+
export function Help({ text, isOpen, onOpenChange }) {
|
|
25
|
+
return Box({ key: `help:${text}`, children: [Button({ plain: true, key: `help-button:${text}`, label: '?', onPress: () => onOpenChange(!isOpen) }), card(text, isOpen)] });
|
|
26
|
+
}
|
|
27
|
+
export function Dialog({ title, children, actions }) {
|
|
28
|
+
return Box({ flexDirection: 'column', gap: 1, paddingX: 1, children: [Text({ bold: true, children: title }), children, Box({ gap: 2, children: actions })] });
|
|
29
|
+
}
|
|
30
|
+
export function Pagination({ page, pages, onPage }) {
|
|
31
|
+
return Box({
|
|
32
|
+
gap: 2,
|
|
33
|
+
children: [
|
|
34
|
+
page > 1 ? Button({ plain: true, hotkey: 'p', label: 'Previous', onPress: () => onPage(page - 1) }) : Text({ dimColor: true, children: 'p: Previous' }),
|
|
35
|
+
Text({ dimColor: true, children: `${page} of ${pages}` }),
|
|
36
|
+
page < pages ? Button({ plain: true, hotkey: 'n', label: 'Next', onPress: () => onPage(page + 1) }) : Text({ dimColor: true, children: 'n: Next' }),
|
|
37
|
+
],
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
export function ProgressBar({ done, total, width = 24 }) {
|
|
41
|
+
const filled = total > 0 ? Math.round(Math.min(done / total, 1) * width) : 0;
|
|
42
|
+
return Text({ children: [Text({ color: 'claude', children: '█'.repeat(filled) }), Text({ color: 'subtle', children: '░'.repeat(width - filled) }), ' ', Text({ dimColor: true, children: `${done}/${total}` })] });
|
|
43
|
+
}
|
|
44
|
+
const cardColumns = 36;
|
|
45
|
+
function card(text, isShown) {
|
|
46
|
+
return Box({
|
|
47
|
+
position: 'absolute',
|
|
48
|
+
bottom: 1,
|
|
49
|
+
left: 0,
|
|
50
|
+
width: Math.min(text.length + 2, cardColumns),
|
|
51
|
+
...(isShown ? {} : { display: 'none', hover: { display: 'flex' } }),
|
|
52
|
+
backgroundColor: 'text',
|
|
53
|
+
paddingX: 1,
|
|
54
|
+
children: Text({ color: 'inverseText', wrap: 'wrap', children: text }),
|
|
55
|
+
});
|
|
56
|
+
}
|
package/ui/define-pane.d.ts
CHANGED
|
@@ -1,11 +1,15 @@
|
|
|
1
|
-
import type { Frozen, RenderElement, RenderPropsOf } from 'claude-code';
|
|
1
|
+
import type { Frozen, PaneCloseInput, RenderElement, RenderPropsOf, UiScrollInput } from 'claude-code';
|
|
2
2
|
import type { Mod } from '../mod.js';
|
|
3
3
|
export type Pane<State extends object = Record<never, never>> = {
|
|
4
4
|
readonly id: string;
|
|
5
5
|
readonly title: string;
|
|
6
6
|
readonly columns?: number | ((state: State) => number | undefined);
|
|
7
7
|
readonly rows?: number | ((state: State) => number | undefined);
|
|
8
|
+
readonly closeOnEscape?: true;
|
|
9
|
+
readonly holdToasts?: true;
|
|
8
10
|
render(mod: Mod<State>, props: Frozen<RenderPropsOf['Pane']>): RenderElement;
|
|
11
|
+
onScroll?(mod: Mod<State>, e: Frozen<UiScrollInput>): void | Promise<void>;
|
|
12
|
+
onClose?(mod: Mod<State>, e: Frozen<PaneCloseInput>): void | Promise<void>;
|
|
9
13
|
};
|
|
10
14
|
export declare function definePane<State extends object = Record<never, never>>(pane: Pane<State>): Pane<State>;
|
|
11
15
|
//# sourceMappingURL=define-pane.d.ts.map
|
package/ui/define-pane.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"define-pane.d.ts","sourceRoot":"","sources":["../src/ui/define-pane.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,aAAa,CAAA;
|
|
1
|
+
{"version":3,"file":"define-pane.d.ts","sourceRoot":"","sources":["../src/ui/define-pane.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,cAAc,EAAE,aAAa,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,aAAa,CAAA;AACtG,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,WAAW,CAAA;AAEpC,MAAM,MAAM,IAAI,CAAC,KAAK,SAAS,MAAM,GAAG,MAAM,CAAC,KAAK,EAAE,KAAK,CAAC,IAAI;IAC9D,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAA;IACnB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;IACtB,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,CAAC,CAAC,KAAK,EAAE,KAAK,KAAK,MAAM,GAAG,SAAS,CAAC,CAAA;IAClE,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,CAAC,CAAC,KAAK,EAAE,KAAK,KAAK,MAAM,GAAG,SAAS,CAAC,CAAA;IAC/D,QAAQ,CAAC,aAAa,CAAC,EAAE,IAAI,CAAA;IAC7B,QAAQ,CAAC,UAAU,CAAC,EAAE,IAAI,CAAA;IAC1B,MAAM,CAAC,GAAG,EAAE,GAAG,CAAC,KAAK,CAAC,EAAE,KAAK,EAAE,MAAM,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC,GAAG,aAAa,CAAA;IAC5E,QAAQ,CAAC,CAAC,GAAG,EAAE,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,EAAE,MAAM,CAAC,aAAa,CAAC,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IAC1E,OAAO,CAAC,CAAC,GAAG,EAAE,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,EAAE,MAAM,CAAC,cAAc,CAAC,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;CAC3E,CAAA;AAMD,wBAAgB,UAAU,CAAC,KAAK,SAAS,MAAM,GAAG,MAAM,CAAC,KAAK,EAAE,KAAK,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,CAOtG"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"call-effects.d.ts","sourceRoot":"","sources":["../src/utils/call-effects.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"call-effects.d.ts","sourceRoot":"","sources":["../src/utils/call-effects.ts"],"names":[],"mappings":"AAAA,OAAO,EAAc,KAAK,YAAY,EAAE,MAAM,kBAAkB,CAAA;AAChE,OAAO,EAAc,KAAK,UAAU,EAAE,MAAM,YAAY,CAAA;AAGxD,MAAM,MAAM,OAAO,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,OAAO,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,CAAA;AAE5F,MAAM,MAAM,QAAQ,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,CAAA;AAC7E,MAAM,MAAM,WAAW,GAAG,QAAQ,GAAG;IAAE,QAAQ,EAAE,CAAC,MAAM,EAAE,GAAG,MAAM,EAAE,CAAC,EAAE,CAAC;IAAC,aAAa,EAAE,OAAO,CAAA;CAAE,CAAA;AAClG,MAAM,MAAM,QAAQ,GAAG,QAAQ,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAAC,eAAe,CAAC,EAAE,MAAM,CAAA;CAAE,CAAA;AAC9F,MAAM,MAAM,SAAS,GAAG,QAAQ,GAAG;IAAE,GAAG,EAAE,MAAM,CAAA;CAAE,CAAA;AAClD,MAAM,MAAM,QAAQ,GAAG,WAAW,GAAG,QAAQ,GAAG,SAAS,GAAG,QAAQ,CAAA;AAEpE,MAAM,MAAM,QAAQ,GAAG;IAAE,OAAO,CAAC,EAAE,MAAM,CAAC;IAAC,eAAe,CAAC,EAAE,MAAM,CAAA;CAAE,CAAA;AACrE,MAAM,MAAM,UAAU,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,CAAC,MAAM,OAAO,CAAC,QAAQ,CAAC,CAAC,GAAG,SAAS,CAAA;CAAE,CAAA;AAC1F,MAAM,MAAM,WAAW,GAAG;IACxB,KAAK,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,YAAY,EAAE,CAAC;QAAC,aAAa,EAAE,OAAO,CAAA;KAAE,GAAG,SAAS,CAAA;IACrF,KAAK,EAAE,UAAU,EAAE,CAAA;IACnB,MAAM,EAAE,UAAU,EAAE,CAAA;IACpB,IAAI,EAAE,MAAM,EAAE,CAAA;IACd,QAAQ,EAAE,MAAM,GAAG,SAAS,CAAA;CAC7B,CAAA;AAED,wBAAgB,WAAW,CAAC,GAAG,EAAE,OAAO,EAAE,SAAS,EAAE;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,UAAU,CAAA;CAAE,GAAG,WAAW,CAsC/G;AAED,wBAAgB,UAAU,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,SAAS,EAAE,EAAE,OAAO,GAAG,QAAQ,CAE1E"}
|
package/utils/call-effects.js
CHANGED
|
@@ -1,14 +1,15 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { expandHome
|
|
1
|
+
import { parseShell } from './parse-shell.js';
|
|
2
|
+
import { expandHome } from './paths.js';
|
|
3
|
+
import { resolve } from '../vendor.js';
|
|
3
4
|
export function callEffects(use, workspace) {
|
|
4
5
|
const { fs } = workspace;
|
|
5
|
-
const
|
|
6
|
-
const access = (path) => ({ path:
|
|
6
|
+
const absolute = (path, folder = workspace.cwd) => resolve(folder, expandHome(path, workspace.home));
|
|
7
|
+
const access = (path) => ({ path: absolute(path), contents: undefined });
|
|
7
8
|
const effects = { shell: undefined, reads: [], writes: [], urls: [], subagent: undefined };
|
|
8
9
|
if (use.tool === 'Bash') {
|
|
9
10
|
const line = textField(use, 'command');
|
|
10
|
-
const parsed =
|
|
11
|
-
const commands = parsed.commands.map(({ argv, folder }) => ({ argv, folder:
|
|
11
|
+
const parsed = parseShell(line);
|
|
12
|
+
const commands = parsed.commands.map(({ argv, folder }) => ({ argv, folder: absolute(folder) }));
|
|
12
13
|
effects.shell = { line, commands, isFullyParsed: parsed.isFullyParsed };
|
|
13
14
|
effects.reads = parsed.reads.map(access);
|
|
14
15
|
effects.writes = parsed.writes.map(access);
|
|
@@ -18,16 +19,16 @@ export function callEffects(use, workspace) {
|
|
|
18
19
|
effects.shell = { line: textField(use, 'command'), commands: [], isFullyParsed: false };
|
|
19
20
|
}
|
|
20
21
|
else if (use.tool === 'Edit') {
|
|
21
|
-
const path =
|
|
22
|
+
const path = absolute(textField(use, 'file_path'));
|
|
22
23
|
effects.writes = [{ path, contents: once(() => editedContents(use, path, fs)) }];
|
|
23
24
|
}
|
|
24
25
|
else if (use.tool === 'Write') {
|
|
25
|
-
const path =
|
|
26
|
+
const path = absolute(textField(use, 'file_path'));
|
|
26
27
|
const content = textField(use, 'content');
|
|
27
28
|
effects.writes = [{ path, contents: once(async () => contentsOf(content, await previousContentOf(path, fs))) }];
|
|
28
29
|
}
|
|
29
30
|
else if (use.tool === 'NotebookEdit') {
|
|
30
|
-
const path =
|
|
31
|
+
const path = absolute(textField(use, 'notebook_path'));
|
|
31
32
|
effects.writes = [{ path, contents: once(async () => contentsOf(undefined, await previousContentOf(path, fs))) }];
|
|
32
33
|
}
|
|
33
34
|
else if (use.tool === 'Read') {
|
|
@@ -37,8 +38,8 @@ export function callEffects(use, workspace) {
|
|
|
37
38
|
effects.reads = [access(optionalTextField(use, 'path') ?? '')];
|
|
38
39
|
}
|
|
39
40
|
else if (use.tool === 'Glob') {
|
|
40
|
-
const folder =
|
|
41
|
-
effects.reads = [{ path:
|
|
41
|
+
const folder = absolute(optionalTextField(use, 'path') ?? '');
|
|
42
|
+
effects.reads = [{ path: absolute(textField(use, 'pattern'), folder), contents: undefined }];
|
|
42
43
|
}
|
|
43
44
|
else if (use.tool === 'WebFetch') {
|
|
44
45
|
effects.urls = [textField(use, 'url')];
|
package/utils/parse-shell.d.ts
CHANGED
|
@@ -1,18 +1,14 @@
|
|
|
1
|
-
export type ParsedShell = {
|
|
2
|
-
commands: [string, ...string[]][];
|
|
3
|
-
writes: string[];
|
|
4
|
-
reads: string[];
|
|
5
|
-
fetches: string[];
|
|
6
|
-
isFullyParsed: boolean;
|
|
7
|
-
};
|
|
8
1
|
export type ShellCommand = {
|
|
9
2
|
argv: [string, ...string[]];
|
|
10
3
|
folder: string;
|
|
11
4
|
};
|
|
12
|
-
export type
|
|
5
|
+
export type ParsedShell = {
|
|
13
6
|
commands: ShellCommand[];
|
|
7
|
+
writes: string[];
|
|
8
|
+
reads: string[];
|
|
9
|
+
fetches: string[];
|
|
10
|
+
isFullyParsed: boolean;
|
|
14
11
|
};
|
|
15
12
|
export declare const dynamicPattern: RegExp;
|
|
16
13
|
export declare function parseShell(line: string): ParsedShell;
|
|
17
|
-
export declare function parseShellCommands(line: string): ParsedShellCommands;
|
|
18
14
|
//# sourceMappingURL=parse-shell.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"parse-shell.d.ts","sourceRoot":"","sources":["../src/utils/parse-shell.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"parse-shell.d.ts","sourceRoot":"","sources":["../src/utils/parse-shell.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,YAAY,GAAG;IAAE,IAAI,EAAE,CAAC,MAAM,EAAE,GAAG,MAAM,EAAE,CAAC,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAA;AAE1E,MAAM,MAAM,WAAW,GAAG;IACxB,QAAQ,EAAE,YAAY,EAAE,CAAA;IACxB,MAAM,EAAE,MAAM,EAAE,CAAA;IAChB,KAAK,EAAE,MAAM,EAAE,CAAA;IACf,OAAO,EAAE,MAAM,EAAE,CAAA;IACjB,aAAa,EAAE,OAAO,CAAA;CACvB,CAAA;AA2BD,eAAO,MAAM,cAAc,QAAS,CAAA;AAiKpC,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,WAAW,CAIpD"}
|
package/utils/parse-shell.js
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { parse } from '../vendor.js';
|
|
1
|
+
import { basename, parse } from '../vendor.js';
|
|
3
2
|
const markerPattern = /\u0001(\d+)\u0001/g;
|
|
4
3
|
const descriptorPattern = /[0-9]+(?=[<>])/y;
|
|
5
4
|
const assignmentPattern = /^[A-Za-z_][A-Za-z0-9_]*(\[[^\]]*\])?\+?=/;
|
|
@@ -163,10 +162,6 @@ const inlineCodeFlags = new Map([
|
|
|
163
162
|
['osascript', ['-e']],
|
|
164
163
|
]);
|
|
165
164
|
export function parseShell(line) {
|
|
166
|
-
const parsed = parseShellCommands(line);
|
|
167
|
-
return { ...parsed, commands: parsed.commands.map((command) => command.argv) };
|
|
168
|
-
}
|
|
169
|
-
export function parseShellCommands(line) {
|
|
170
165
|
const result = { commands: [], writes: [], reads: [], fetches: [], isFullyParsed: true };
|
|
171
166
|
parseLine(line, '', result);
|
|
172
167
|
return result;
|
|
@@ -533,7 +528,7 @@ function wordOf(token, markers, folder, result) {
|
|
|
533
528
|
return {
|
|
534
529
|
text: raw.replace(markerPattern, (_, index) => markers[Number(index)].raw),
|
|
535
530
|
isGlob: typeof token !== 'string',
|
|
536
|
-
isDynamic: /[$\u0001]/.test(
|
|
531
|
+
isDynamic: /[$\u0001]/.test(basename(raw)),
|
|
537
532
|
};
|
|
538
533
|
}
|
|
539
534
|
function finish(command, operator, folder, result) {
|
|
@@ -573,7 +568,7 @@ function addRedirect({ operator, target }, folder, result) {
|
|
|
573
568
|
function addCommand(first, args, folder, stdin, result) {
|
|
574
569
|
if (first.isDynamic || first.isGlob)
|
|
575
570
|
result.isFullyParsed = false;
|
|
576
|
-
const program =
|
|
571
|
+
const program = basename(first.text);
|
|
577
572
|
if (program === 'git')
|
|
578
573
|
addGit(first, args, folder, result);
|
|
579
574
|
else if (program === 'find')
|
|
@@ -734,7 +729,7 @@ function addCopy(program, args, folder, result) {
|
|
|
734
729
|
const target = options.findLast((option) => program.targetOptions?.includes(option.name) === true)?.value;
|
|
735
730
|
const only = operands[0];
|
|
736
731
|
if (program.linksHere === true && target === undefined && operands.length === 1 && only !== undefined) {
|
|
737
|
-
addPath(result, 'writes', { ...only, text:
|
|
732
|
+
addPath(result, 'writes', { ...only, text: basename(only.text) }, folder);
|
|
738
733
|
return;
|
|
739
734
|
}
|
|
740
735
|
const destination = target ?? operands.at(-1);
|
|
@@ -746,7 +741,7 @@ function addCopy(program, args, folder, result) {
|
|
|
746
741
|
if (program.sources !== undefined)
|
|
747
742
|
addPath(result, program.sources, source, folder);
|
|
748
743
|
if (isLocal(destination) && !source.isGlob && !destination.isGlob)
|
|
749
|
-
addPathText(result, 'writes', `${destination.text.replace(/\/+$/, '')}/${
|
|
744
|
+
addPathText(result, 'writes', `${destination.text.replace(/\/+$/, '')}/${basename(source.text)}`, folder);
|
|
750
745
|
}
|
|
751
746
|
if (isLocal(destination))
|
|
752
747
|
addPath(result, 'writes', destination, folder);
|
package/utils/paths.d.ts
CHANGED
|
@@ -7,9 +7,6 @@ export type FileSystem = {
|
|
|
7
7
|
exists: (path: string) => Promise<boolean>;
|
|
8
8
|
};
|
|
9
9
|
export declare function expandHome(path: string, home: string): string;
|
|
10
|
-
export declare function resolvePath(path: string, folder: string): string;
|
|
11
|
-
export declare function parentOf(path: string): string;
|
|
12
|
-
export declare function nameOf(path: string): string;
|
|
13
10
|
export declare function relativePath(base: string, path: string): string | undefined;
|
|
14
11
|
export declare function realPathOf(path: string, fs: FileSystem): Promise<string | undefined>;
|
|
15
12
|
//# sourceMappingURL=paths.d.ts.map
|
package/utils/paths.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"paths.d.ts","sourceRoot":"","sources":["../src/utils/paths.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"paths.d.ts","sourceRoot":"","sources":["../src/utils/paths.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,UAAU,GAAG;IACvB,IAAI,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAA;IACvC,IAAI,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC;QAAE,IAAI,EAAE,MAAM,GAAG,KAAK,GAAG,OAAO,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;IACtF,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAA;CAC3C,CAAA;AAED,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAG7D;AAED,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAI3E;AAED,wBAAsB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,UAAU,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAK1F"}
|
package/utils/paths.js
CHANGED
|
@@ -1,23 +1,8 @@
|
|
|
1
|
+
import { basename, dirname, resolve } from '../vendor.js';
|
|
1
2
|
export function expandHome(path, home) {
|
|
2
3
|
const prefix = /^(~|\$HOME)(?=\/|$)/.exec(path)?.[0];
|
|
3
4
|
return prefix === undefined ? path : `${home}${path.slice(prefix.length)}`;
|
|
4
5
|
}
|
|
5
|
-
export function resolvePath(path, folder) {
|
|
6
|
-
const parts = [];
|
|
7
|
-
for (const part of (path.startsWith('/') ? path : `${folder}/${path}`).split('/')) {
|
|
8
|
-
if (part === '..')
|
|
9
|
-
parts.pop();
|
|
10
|
-
else if (part !== '' && part !== '.')
|
|
11
|
-
parts.push(part);
|
|
12
|
-
}
|
|
13
|
-
return `/${parts.join('/')}`;
|
|
14
|
-
}
|
|
15
|
-
export function parentOf(path) {
|
|
16
|
-
return resolvePath('..', path);
|
|
17
|
-
}
|
|
18
|
-
export function nameOf(path) {
|
|
19
|
-
return path.slice(path.lastIndexOf('/') + 1);
|
|
20
|
-
}
|
|
21
6
|
export function relativePath(base, path) {
|
|
22
7
|
if (path === base)
|
|
23
8
|
return '';
|
|
@@ -28,6 +13,6 @@ export async function realPathOf(path, fs) {
|
|
|
28
13
|
const stat = await fs.stat(path).catch(() => undefined);
|
|
29
14
|
if (stat !== undefined || path === '/')
|
|
30
15
|
return stat?.realPath;
|
|
31
|
-
const folder = await realPathOf(
|
|
32
|
-
return folder === undefined ? undefined :
|
|
16
|
+
const folder = await realPathOf(dirname(path), fs);
|
|
17
|
+
return folder === undefined ? undefined : resolve(folder, basename(path));
|
|
33
18
|
}
|
package/vendor.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
export { Validator } from '@cfworker/json-schema';
|
|
2
|
+
export { basename, dirname, extname, isAbsolute, join, normalize, relative, resolve } from 'pathe';
|
|
2
3
|
export { default as picomatch } from 'picomatch/posix';
|
|
3
4
|
export { parse, quote, type GlobPattern, type ParseEntry } from 'shell-quote';
|
|
4
5
|
//# sourceMappingURL=vendor.d.ts.map
|
package/vendor.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"vendor.d.ts","sourceRoot":"","sources":["src/vendor.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAA;AACjD,OAAO,EAAE,OAAO,IAAI,SAAS,EAAE,MAAM,iBAAiB,CAAA;AACtD,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,WAAW,EAAE,KAAK,UAAU,EAAE,MAAM,aAAa,CAAA"}
|
|
1
|
+
{"version":3,"file":"vendor.d.ts","sourceRoot":"","sources":["src/vendor.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAA;AACjD,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,SAAS,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,OAAO,CAAA;AAClG,OAAO,EAAE,OAAO,IAAI,SAAS,EAAE,MAAM,iBAAiB,CAAA;AACtD,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,WAAW,EAAE,KAAK,UAAU,EAAE,MAAM,aAAa,CAAA"}
|