@agimon-ai/po-ui 0.0.0-alpha.73 → 0.0.0-alpha.75
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/dist/extensions/native.mjs +493 -0
- package/dist/extensions/native.mjs.map +1 -0
- package/dist/extensions/web.mjs +38 -17
- package/dist/extensions/web.mjs.map +1 -1
- package/package.json +40 -13
|
@@ -0,0 +1,493 @@
|
|
|
1
|
+
import { defineNativePlugin, defineToolRenderer } from "@agimon-ai/po-core/native";
|
|
2
|
+
import { View } from "react-native-unistyles/components/native/View";
|
|
3
|
+
import { Text } from "react-native-unistyles/components/native/Text";
|
|
4
|
+
import { MessageItem, MessageItemBody, MessageItemHeader, MessageItemStatus, SyntaxLine, ToolPathLink, fontOf, toolTone, useSyntaxLines } from "@agimon-ai/po-native-components";
|
|
5
|
+
import { StyleSheet } from "react-native-unistyles";
|
|
6
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
7
|
+
/** Pi's default output cap, the size its truncation warning names when details omit one. */
|
|
8
|
+
const DEFAULT_MAX_BYTES = 51200;
|
|
9
|
+
const KIBIBYTE = 1024;
|
|
10
|
+
function compactDetails(values) {
|
|
11
|
+
return values.filter((value) => value !== void 0 && value.length > 0);
|
|
12
|
+
}
|
|
13
|
+
function optionalCount(value, unit) {
|
|
14
|
+
return typeof value === "number" && Number.isFinite(value) ? `${value} ${unit}` : void 0;
|
|
15
|
+
}
|
|
16
|
+
function pathOrDot(value) {
|
|
17
|
+
return typeof value === "string" && value.length > 0 ? value : ".";
|
|
18
|
+
}
|
|
19
|
+
/** Pi's size formatter, so the web warning names the same figure the TUI does. */
|
|
20
|
+
function formatSize(bytes) {
|
|
21
|
+
if (bytes < KIBIBYTE) return `${bytes}B`;
|
|
22
|
+
if (bytes < KIBIBYTE * KIBIBYTE) return `${(bytes / KIBIBYTE).toFixed(1)}KB`;
|
|
23
|
+
return `${(bytes / (KIBIBYTE * KIBIBYTE)).toFixed(1)}MB`;
|
|
24
|
+
}
|
|
25
|
+
/** What the write call shows: the path, the content size, and a numbered preview of the file. */
|
|
26
|
+
function writeCallView(args, expanded) {
|
|
27
|
+
const content = typeof args.content === "string" ? args.content : "";
|
|
28
|
+
const path = typeof args.path === "string" ? args.path : "";
|
|
29
|
+
const size = `${content.length.toLocaleString("en-US")} chars`;
|
|
30
|
+
if (content.length === 0) return {
|
|
31
|
+
path,
|
|
32
|
+
size,
|
|
33
|
+
preview: [],
|
|
34
|
+
hidden: 0,
|
|
35
|
+
gutter: 1
|
|
36
|
+
};
|
|
37
|
+
const lines = content.replaceAll(" ", " ").replaceAll("\r\n", "\n").split("\n");
|
|
38
|
+
while (lines.at(-1) === "") lines.pop();
|
|
39
|
+
const visible = expanded ? lines : lines.slice(0, 10);
|
|
40
|
+
return {
|
|
41
|
+
path,
|
|
42
|
+
size,
|
|
43
|
+
preview: visible.map((text, index) => ({
|
|
44
|
+
number: index + 1,
|
|
45
|
+
text
|
|
46
|
+
})),
|
|
47
|
+
hidden: lines.length - visible.length,
|
|
48
|
+
gutter: String(visible.length).length
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
/** `pattern · path · N results`, as the find call heading lists them. */
|
|
52
|
+
function findCallView(args) {
|
|
53
|
+
return {
|
|
54
|
+
primary: typeof args.pattern === "string" ? args.pattern : "",
|
|
55
|
+
details: compactDetails([pathOrDot(args.path), optionalCount(args.limit, "results")])
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
/** `path · N entries`, as the ls call heading lists them. */
|
|
59
|
+
function lsCallView(args) {
|
|
60
|
+
return {
|
|
61
|
+
primary: pathOrDot(args.path),
|
|
62
|
+
details: compactDetails([optionalCount(args.limit, "entries")])
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
/** The result's text, from its blocks when the view exists and from the joined output otherwise. */
|
|
66
|
+
/**
|
|
67
|
+
* A listing line split into the name a reader scans for and the folder it sits
|
|
68
|
+
* in, so the name can lead and the folder recede. `ls` lines have no folder;
|
|
69
|
+
* a trailing `/` marks a directory and stays on its name.
|
|
70
|
+
*/
|
|
71
|
+
function listingEntry(line) {
|
|
72
|
+
const slash = line.replace(/\/$/, "").lastIndexOf("/");
|
|
73
|
+
return slash < 0 ? {
|
|
74
|
+
name: line,
|
|
75
|
+
folder: ""
|
|
76
|
+
} : {
|
|
77
|
+
name: line.slice(slash + 1),
|
|
78
|
+
folder: line.slice(0, slash)
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
function resultText(result, output) {
|
|
82
|
+
if (result === null) return output;
|
|
83
|
+
return result.content.flatMap((block) => {
|
|
84
|
+
const record = typeof block === "object" && block !== null ? block : {};
|
|
85
|
+
return record.type === "text" && typeof record.text === "string" ? [record.text] : [];
|
|
86
|
+
}).join("\n");
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* A find or ls listing the way Pi's own renderer shows it: the lines,
|
|
90
|
+
* collapsed to twenty, and the limit warning its details carry. `limitKey`
|
|
91
|
+
* names the per-tool counter (resultLimitReached, entryLimitReached).
|
|
92
|
+
*/
|
|
93
|
+
function listResultView(result, output, expanded, limitKey, limitUnit) {
|
|
94
|
+
const text = resultText(result, output).trim();
|
|
95
|
+
const all = text.length === 0 ? [] : text.split("\n");
|
|
96
|
+
const lines = expanded ? all : all.slice(0, 20);
|
|
97
|
+
const details = typeof result?.details === "object" && result.details !== null ? result.details : {};
|
|
98
|
+
const limit = details[limitKey];
|
|
99
|
+
const truncation = typeof details.truncation === "object" && details.truncation !== null ? details.truncation : void 0;
|
|
100
|
+
const warnings = [];
|
|
101
|
+
if (typeof limit === "number" && limit > 0) warnings.push(`${limit} ${limitUnit} limit`);
|
|
102
|
+
if (truncation?.truncated === true) warnings.push(`${formatSize(typeof truncation.maxBytes === "number" ? truncation.maxBytes : DEFAULT_MAX_BYTES)} limit`);
|
|
103
|
+
return {
|
|
104
|
+
lines,
|
|
105
|
+
hidden: all.length - lines.length,
|
|
106
|
+
truncated: warnings.length > 0 ? `[Truncated: ${warnings.join(", ")}]` : void 0
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
//#endregion
|
|
110
|
+
//#region src/extensions/workspaces/sessions/(frontend)/tool/_components/ListingBody.native.tsx
|
|
111
|
+
/**
|
|
112
|
+
* The body shared by find and ls on native, as the web's ListingBody: Pi's
|
|
113
|
+
* listing lines, collapsed to twenty until the item expands, with the limit
|
|
114
|
+
* warning its details carry. One row per line: the name leads in full ink, its
|
|
115
|
+
* folder follows dimmed and truncates from the front, so the nearest folder
|
|
116
|
+
* stays readable on a phone.
|
|
117
|
+
*/
|
|
118
|
+
function ListingBody({ tool, limitKey, limitUnit, expanded, props }) {
|
|
119
|
+
const { result, output, running, isError } = props;
|
|
120
|
+
if (isError) return /* @__PURE__ */ jsx(MessageItemBody, {
|
|
121
|
+
testID: `tool-result-${tool}`,
|
|
122
|
+
children: /* @__PURE__ */ jsx(Text, {
|
|
123
|
+
selectable: true,
|
|
124
|
+
style: [styles$3.sans, styles$3.error],
|
|
125
|
+
children: resultText(result, output)
|
|
126
|
+
})
|
|
127
|
+
});
|
|
128
|
+
if (result === null) return running ? /* @__PURE__ */ jsx(MessageItemBody, {
|
|
129
|
+
testID: `tool-result-${tool}`,
|
|
130
|
+
children: /* @__PURE__ */ jsx(MessageItemStatus, {
|
|
131
|
+
tone: "running",
|
|
132
|
+
children: "running"
|
|
133
|
+
})
|
|
134
|
+
}) : null;
|
|
135
|
+
const view = listResultView(result, output, expanded, limitKey, limitUnit);
|
|
136
|
+
if (view.lines.length === 0 && view.truncated === void 0) return null;
|
|
137
|
+
return /* @__PURE__ */ jsxs(MessageItemBody, {
|
|
138
|
+
testID: `tool-result-${tool}`,
|
|
139
|
+
children: [
|
|
140
|
+
view.lines.map((line, index) => {
|
|
141
|
+
const entry = listingEntry(line);
|
|
142
|
+
return /* @__PURE__ */ jsxs(View, {
|
|
143
|
+
style: styles$3.row,
|
|
144
|
+
accessibilityLabel: line,
|
|
145
|
+
children: [/* @__PURE__ */ jsx(Text, {
|
|
146
|
+
numberOfLines: 1,
|
|
147
|
+
selectable: true,
|
|
148
|
+
style: [styles$3.mono, styles$3.name],
|
|
149
|
+
children: entry.name
|
|
150
|
+
}), entry.folder.length > 0 ? /* @__PURE__ */ jsx(Text, {
|
|
151
|
+
numberOfLines: 1,
|
|
152
|
+
ellipsizeMode: "head",
|
|
153
|
+
style: [styles$3.mono, styles$3.folder],
|
|
154
|
+
children: entry.folder
|
|
155
|
+
}) : null]
|
|
156
|
+
}, `${String(index)}-${line}`);
|
|
157
|
+
}),
|
|
158
|
+
view.hidden > 0 ? /* @__PURE__ */ jsxs(MessageItemStatus, {
|
|
159
|
+
expands: true,
|
|
160
|
+
children: [view.hidden, " more lines"]
|
|
161
|
+
}) : null,
|
|
162
|
+
view.truncated !== void 0 ? /* @__PURE__ */ jsx(Text, {
|
|
163
|
+
style: [styles$3.mono, styles$3.warning],
|
|
164
|
+
children: view.truncated
|
|
165
|
+
}) : null
|
|
166
|
+
]
|
|
167
|
+
});
|
|
168
|
+
}
|
|
169
|
+
const styles$3 = StyleSheet.create((theme) => ({
|
|
170
|
+
sans: {
|
|
171
|
+
fontFamily: fontOf(theme.fontFamily.sans),
|
|
172
|
+
fontSize: theme.fontSize.base,
|
|
173
|
+
lineHeight: theme.lineHeight.base,
|
|
174
|
+
uni__dependencies: [0]
|
|
175
|
+
},
|
|
176
|
+
mono: {
|
|
177
|
+
fontFamily: fontOf(theme.fontFamily.mono),
|
|
178
|
+
fontSize: theme.fontSize.sm,
|
|
179
|
+
lineHeight: theme.lineHeightRelaxed.sm,
|
|
180
|
+
uni__dependencies: [0]
|
|
181
|
+
},
|
|
182
|
+
row: {
|
|
183
|
+
flexDirection: "row",
|
|
184
|
+
alignItems: "baseline",
|
|
185
|
+
gap: theme.spacing(2),
|
|
186
|
+
minWidth: 0,
|
|
187
|
+
uni__dependencies: [0]
|
|
188
|
+
},
|
|
189
|
+
name: {
|
|
190
|
+
flexShrink: 0,
|
|
191
|
+
maxWidth: "100%",
|
|
192
|
+
color: theme.colors.text,
|
|
193
|
+
uni__dependencies: [0]
|
|
194
|
+
},
|
|
195
|
+
folder: {
|
|
196
|
+
flexShrink: 1,
|
|
197
|
+
minWidth: 0,
|
|
198
|
+
color: theme.colors.dim,
|
|
199
|
+
uni__dependencies: [0]
|
|
200
|
+
},
|
|
201
|
+
warning: {
|
|
202
|
+
color: theme.colors.yellow,
|
|
203
|
+
uni__dependencies: [0]
|
|
204
|
+
},
|
|
205
|
+
error: {
|
|
206
|
+
color: theme.colors.red,
|
|
207
|
+
uni__dependencies: [0]
|
|
208
|
+
}
|
|
209
|
+
}));
|
|
210
|
+
//#endregion
|
|
211
|
+
//#region src/extensions/workspaces/sessions/(frontend)/tool/_components/FindToolMessage.native.tsx
|
|
212
|
+
const LIMIT_KEY$1 = "resultLimitReached";
|
|
213
|
+
const LIMIT_UNIT$1 = "results";
|
|
214
|
+
/** The find tool's timeline item on native, as the web's: `pattern · path · N results` over Pi's listing lines. */
|
|
215
|
+
function FindToolMessage(props) {
|
|
216
|
+
const view = findCallView(props.args);
|
|
217
|
+
return /* @__PURE__ */ jsx(MessageItem, {
|
|
218
|
+
tone: toolTone({
|
|
219
|
+
running: props.running,
|
|
220
|
+
isError: props.isError
|
|
221
|
+
}),
|
|
222
|
+
expandable: true,
|
|
223
|
+
children: ({ expanded }) => /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(MessageItemHeader, {
|
|
224
|
+
title: "find",
|
|
225
|
+
children: /* @__PURE__ */ jsxs(View, {
|
|
226
|
+
testID: "tool-call-find",
|
|
227
|
+
style: styles$2.summary,
|
|
228
|
+
children: [/* @__PURE__ */ jsx(Text, {
|
|
229
|
+
numberOfLines: 1,
|
|
230
|
+
style: [styles$2.sans, styles$2.primary],
|
|
231
|
+
children: view.primary
|
|
232
|
+
}), view.details.length > 0 ? /* @__PURE__ */ jsxs(Text, {
|
|
233
|
+
numberOfLines: 1,
|
|
234
|
+
ellipsizeMode: "middle",
|
|
235
|
+
style: [styles$2.sans, styles$2.detail],
|
|
236
|
+
children: ["· ", view.details.join(" · ")]
|
|
237
|
+
}) : null]
|
|
238
|
+
})
|
|
239
|
+
}), expanded ? /* @__PURE__ */ jsx(ListingBody, {
|
|
240
|
+
tool: "find",
|
|
241
|
+
limitKey: LIMIT_KEY$1,
|
|
242
|
+
limitUnit: LIMIT_UNIT$1,
|
|
243
|
+
expanded: true,
|
|
244
|
+
props
|
|
245
|
+
}) : null] })
|
|
246
|
+
});
|
|
247
|
+
}
|
|
248
|
+
const styles$2 = StyleSheet.create((theme) => ({
|
|
249
|
+
summary: {
|
|
250
|
+
flex: 1,
|
|
251
|
+
flexDirection: "row",
|
|
252
|
+
alignItems: "center",
|
|
253
|
+
gap: theme.spacing(2),
|
|
254
|
+
minWidth: 0,
|
|
255
|
+
uni__dependencies: [0]
|
|
256
|
+
},
|
|
257
|
+
sans: {
|
|
258
|
+
fontFamily: fontOf(theme.fontFamily.sans),
|
|
259
|
+
fontSize: theme.fontSize.base,
|
|
260
|
+
lineHeight: theme.lineHeight.base,
|
|
261
|
+
uni__dependencies: [0]
|
|
262
|
+
},
|
|
263
|
+
primary: {
|
|
264
|
+
flexShrink: 0,
|
|
265
|
+
maxWidth: "60%",
|
|
266
|
+
color: theme.colors.text,
|
|
267
|
+
uni__dependencies: [0]
|
|
268
|
+
},
|
|
269
|
+
detail: {
|
|
270
|
+
flexShrink: 1,
|
|
271
|
+
color: theme.colors.faint,
|
|
272
|
+
uni__dependencies: [0]
|
|
273
|
+
}
|
|
274
|
+
}));
|
|
275
|
+
//#endregion
|
|
276
|
+
//#region src/extensions/workspaces/sessions/(frontend)/tool/find.native.tsx
|
|
277
|
+
var find_native_default = defineToolRenderer({ message: FindToolMessage });
|
|
278
|
+
//#endregion
|
|
279
|
+
//#region src/extensions/workspaces/sessions/(frontend)/tool/_components/LsToolMessage.native.tsx
|
|
280
|
+
const LIMIT_KEY = "entryLimitReached";
|
|
281
|
+
const LIMIT_UNIT = "entries";
|
|
282
|
+
/** The ls tool's timeline item on native, as the web's: `path · N entries` over Pi's listing lines. */
|
|
283
|
+
function LsToolMessage(props) {
|
|
284
|
+
const view = lsCallView(props.args);
|
|
285
|
+
return /* @__PURE__ */ jsx(MessageItem, {
|
|
286
|
+
tone: toolTone({
|
|
287
|
+
running: props.running,
|
|
288
|
+
isError: props.isError
|
|
289
|
+
}),
|
|
290
|
+
expandable: true,
|
|
291
|
+
children: ({ expanded }) => /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(MessageItemHeader, {
|
|
292
|
+
title: "ls",
|
|
293
|
+
children: /* @__PURE__ */ jsxs(View, {
|
|
294
|
+
testID: "tool-call-ls",
|
|
295
|
+
style: styles$1.summary,
|
|
296
|
+
children: [/* @__PURE__ */ jsx(Text, {
|
|
297
|
+
numberOfLines: 1,
|
|
298
|
+
style: [styles$1.sans, styles$1.primary],
|
|
299
|
+
children: view.primary
|
|
300
|
+
}), view.details.length > 0 ? /* @__PURE__ */ jsxs(Text, {
|
|
301
|
+
numberOfLines: 1,
|
|
302
|
+
style: [styles$1.sans, styles$1.detail],
|
|
303
|
+
children: ["· ", view.details.join(" · ")]
|
|
304
|
+
}) : null]
|
|
305
|
+
})
|
|
306
|
+
}), expanded ? /* @__PURE__ */ jsx(ListingBody, {
|
|
307
|
+
tool: "ls",
|
|
308
|
+
limitKey: LIMIT_KEY,
|
|
309
|
+
limitUnit: LIMIT_UNIT,
|
|
310
|
+
expanded: true,
|
|
311
|
+
props
|
|
312
|
+
}) : null] })
|
|
313
|
+
});
|
|
314
|
+
}
|
|
315
|
+
const styles$1 = StyleSheet.create((theme) => ({
|
|
316
|
+
summary: {
|
|
317
|
+
flex: 1,
|
|
318
|
+
flexDirection: "row",
|
|
319
|
+
alignItems: "center",
|
|
320
|
+
gap: theme.spacing(2),
|
|
321
|
+
minWidth: 0,
|
|
322
|
+
uni__dependencies: [0]
|
|
323
|
+
},
|
|
324
|
+
sans: {
|
|
325
|
+
fontFamily: fontOf(theme.fontFamily.sans),
|
|
326
|
+
fontSize: theme.fontSize.base,
|
|
327
|
+
lineHeight: theme.lineHeight.base,
|
|
328
|
+
uni__dependencies: [0]
|
|
329
|
+
},
|
|
330
|
+
primary: {
|
|
331
|
+
flexShrink: 1,
|
|
332
|
+
color: theme.colors.text,
|
|
333
|
+
uni__dependencies: [0]
|
|
334
|
+
},
|
|
335
|
+
detail: {
|
|
336
|
+
flexShrink: 0,
|
|
337
|
+
color: theme.colors.faint,
|
|
338
|
+
uni__dependencies: [0]
|
|
339
|
+
}
|
|
340
|
+
}));
|
|
341
|
+
//#endregion
|
|
342
|
+
//#region src/extensions/workspaces/sessions/(frontend)/tool/ls.native.tsx
|
|
343
|
+
var ls_native_default = defineToolRenderer({ message: LsToolMessage });
|
|
344
|
+
//#endregion
|
|
345
|
+
//#region src/extensions/workspaces/sessions/(frontend)/tool/_components/WriteToolMessage.native.tsx
|
|
346
|
+
/** The numbered preview, coloured as the file it is about to become, as the web's WritePreview. */
|
|
347
|
+
function WritePreview({ view, path }) {
|
|
348
|
+
const spans = useSyntaxLines(view.preview.map((line) => line.text).join("\n"), { path });
|
|
349
|
+
return /* @__PURE__ */ jsx(View, { children: view.preview.map((line, index) => /* @__PURE__ */ jsxs(View, {
|
|
350
|
+
style: styles.row,
|
|
351
|
+
children: [/* @__PURE__ */ jsx(Text, {
|
|
352
|
+
style: [styles.mono, styles.gutter],
|
|
353
|
+
children: String(line.number).padStart(view.gutter)
|
|
354
|
+
}), /* @__PURE__ */ jsx(SyntaxLine, {
|
|
355
|
+
selectable: true,
|
|
356
|
+
spans: spans?.[index],
|
|
357
|
+
text: line.text,
|
|
358
|
+
style: [styles.mono, styles.content]
|
|
359
|
+
})]
|
|
360
|
+
}, line.number)) });
|
|
361
|
+
}
|
|
362
|
+
/**
|
|
363
|
+
* The write tool's timeline item on native, as the web's WriteToolMessage:
|
|
364
|
+
* `path · N chars` in the header and, expanded, the numbered file content.
|
|
365
|
+
* A failure shows the tool's message in red instead.
|
|
366
|
+
*/
|
|
367
|
+
function WriteToolMessage({ args, result, output, running, isError, fileTabFor, openTransientTab }) {
|
|
368
|
+
const collapsed = writeCallView(args, false);
|
|
369
|
+
const tab = fileTabFor(collapsed.path);
|
|
370
|
+
return /* @__PURE__ */ jsx(MessageItem, {
|
|
371
|
+
tone: toolTone({
|
|
372
|
+
running,
|
|
373
|
+
isError
|
|
374
|
+
}),
|
|
375
|
+
expandable: true,
|
|
376
|
+
children: ({ expanded }) => {
|
|
377
|
+
const view = expanded ? writeCallView(args, true) : collapsed;
|
|
378
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(MessageItemHeader, {
|
|
379
|
+
title: "write",
|
|
380
|
+
children: /* @__PURE__ */ jsxs(View, {
|
|
381
|
+
testID: "tool-call-write",
|
|
382
|
+
style: styles.summary,
|
|
383
|
+
children: [/* @__PURE__ */ jsx(ToolPathLink, {
|
|
384
|
+
path: view.path,
|
|
385
|
+
...tab === void 0 ? {} : { onOpen: () => openTransientTab(tab) }
|
|
386
|
+
}), /* @__PURE__ */ jsxs(Text, {
|
|
387
|
+
numberOfLines: 1,
|
|
388
|
+
style: [styles.sans, styles.detail],
|
|
389
|
+
children: ["· ", view.size]
|
|
390
|
+
})]
|
|
391
|
+
})
|
|
392
|
+
}), !expanded ? null : isError ? /* @__PURE__ */ jsx(MessageItemBody, {
|
|
393
|
+
testID: "tool-result-write",
|
|
394
|
+
children: /* @__PURE__ */ jsx(Text, {
|
|
395
|
+
selectable: true,
|
|
396
|
+
style: [styles.sans, styles.error],
|
|
397
|
+
children: resultText(result, output)
|
|
398
|
+
})
|
|
399
|
+
}) : view.preview.length === 0 ? running ? /* @__PURE__ */ jsx(MessageItemBody, {
|
|
400
|
+
testID: "tool-result-write",
|
|
401
|
+
children: /* @__PURE__ */ jsx(MessageItemStatus, {
|
|
402
|
+
tone: "running",
|
|
403
|
+
children: "running"
|
|
404
|
+
})
|
|
405
|
+
}) : null : /* @__PURE__ */ jsxs(MessageItemBody, {
|
|
406
|
+
testID: "tool-result-write",
|
|
407
|
+
children: [
|
|
408
|
+
/* @__PURE__ */ jsx(WritePreview, {
|
|
409
|
+
view,
|
|
410
|
+
path: view.path
|
|
411
|
+
}),
|
|
412
|
+
view.hidden > 0 ? /* @__PURE__ */ jsxs(MessageItemStatus, {
|
|
413
|
+
expands: true,
|
|
414
|
+
children: [view.hidden, " more lines"]
|
|
415
|
+
}) : null,
|
|
416
|
+
running ? /* @__PURE__ */ jsx(MessageItemStatus, {
|
|
417
|
+
tone: "running",
|
|
418
|
+
children: "running"
|
|
419
|
+
}) : null
|
|
420
|
+
]
|
|
421
|
+
})] });
|
|
422
|
+
}
|
|
423
|
+
});
|
|
424
|
+
}
|
|
425
|
+
const styles = StyleSheet.create((theme) => ({
|
|
426
|
+
summary: {
|
|
427
|
+
flex: 1,
|
|
428
|
+
flexDirection: "row",
|
|
429
|
+
alignItems: "center",
|
|
430
|
+
gap: theme.spacing(2),
|
|
431
|
+
minWidth: 0,
|
|
432
|
+
uni__dependencies: [0]
|
|
433
|
+
},
|
|
434
|
+
sans: {
|
|
435
|
+
fontFamily: fontOf(theme.fontFamily.sans),
|
|
436
|
+
fontSize: theme.fontSize.base,
|
|
437
|
+
lineHeight: theme.lineHeight.base,
|
|
438
|
+
uni__dependencies: [0]
|
|
439
|
+
},
|
|
440
|
+
detail: {
|
|
441
|
+
flexShrink: 0,
|
|
442
|
+
color: theme.colors.faint,
|
|
443
|
+
uni__dependencies: [0]
|
|
444
|
+
},
|
|
445
|
+
error: {
|
|
446
|
+
color: theme.colors.red,
|
|
447
|
+
uni__dependencies: [0]
|
|
448
|
+
},
|
|
449
|
+
row: {
|
|
450
|
+
flexDirection: "row",
|
|
451
|
+
gap: theme.spacing(2),
|
|
452
|
+
uni__dependencies: [0]
|
|
453
|
+
},
|
|
454
|
+
mono: {
|
|
455
|
+
fontFamily: fontOf(theme.fontFamily.mono),
|
|
456
|
+
fontSize: theme.fontSize.sm,
|
|
457
|
+
lineHeight: theme.lineHeightRelaxed.sm,
|
|
458
|
+
uni__dependencies: [0]
|
|
459
|
+
},
|
|
460
|
+
gutter: {
|
|
461
|
+
color: theme.colors.faint,
|
|
462
|
+
uni__dependencies: [0]
|
|
463
|
+
},
|
|
464
|
+
content: {
|
|
465
|
+
flex: 1,
|
|
466
|
+
minWidth: 0,
|
|
467
|
+
color: theme.colors.text,
|
|
468
|
+
uni__dependencies: [0]
|
|
469
|
+
}
|
|
470
|
+
}));
|
|
471
|
+
//#endregion
|
|
472
|
+
//#region src/extensions/workspaces/sessions/(frontend)/tool/write.native.tsx
|
|
473
|
+
var write_native_default = defineToolRenderer({ message: WriteToolMessage });
|
|
474
|
+
//#endregion
|
|
475
|
+
//#region generated/native.ts
|
|
476
|
+
const via = (identity, value) => value === void 0 ? void 0 : {
|
|
477
|
+
...identity,
|
|
478
|
+
...value
|
|
479
|
+
};
|
|
480
|
+
const nativePlugin = defineNativePlugin({
|
|
481
|
+
id: "builtin-tools",
|
|
482
|
+
session: { get toolRenderers() {
|
|
483
|
+
return [
|
|
484
|
+
via({ tools: ["find"] }, find_native_default),
|
|
485
|
+
via({ tools: ["ls"] }, ls_native_default),
|
|
486
|
+
via({ tools: ["write"] }, write_native_default)
|
|
487
|
+
];
|
|
488
|
+
} }
|
|
489
|
+
});
|
|
490
|
+
//#endregion
|
|
491
|
+
export { nativePlugin };
|
|
492
|
+
|
|
493
|
+
//# sourceMappingURL=native.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"native.mjs","names":["ToolMessageRenderProps","fontOf","MessageItemBody","MessageItemStatus","PoNativeTheme","StyleSheet","listingEntry","listResultView","resultText","ListingBody","tool","limitKey","limitUnit","expanded","props","result","output","running","isError","styles","sans","error","view","lines","length","truncated","undefined","map","line","index","entry","String","row","mono","name","folder","hidden","warning","create","theme","fontFamily","fontSize","base","lineHeight","uni__dependencies","sm","lineHeightRelaxed","flexDirection","alignItems","gap","spacing","minWidth","flexShrink","maxWidth","color","colors","text","dim","yellow","red","styles","ToolMessageRenderProps","fontOf","MessageItem","MessageItemHeader","toolTone","PoNativeTheme","StyleSheet","findCallView","ListingBody","LIMIT_KEY","LIMIT_UNIT","FindToolMessage","props","view","args","running","isError","expanded","styles","summary","sans","primary","details","length","detail","join","create","theme","flex","flexDirection","alignItems","gap","spacing","minWidth","uni__dependencies","fontFamily","fontSize","base","lineHeight","flexShrink","maxWidth","color","colors","text","faint","LIMIT_KEY","LIMIT_UNIT","styles","ToolMessageRenderProps","fontOf","MessageItem","MessageItemHeader","toolTone","PoNativeTheme","StyleSheet","lsCallView","ListingBody","LIMIT_KEY","LIMIT_UNIT","LsToolMessage","props","view","args","running","isError","expanded","styles","summary","sans","primary","details","length","detail","join","create","theme","flex","flexDirection","alignItems","gap","spacing","minWidth","uni__dependencies","fontFamily","fontSize","base","lineHeight","flexShrink","color","colors","text","faint","styles","ToolMessageRenderProps","fontOf","MessageItem","MessageItemBody","MessageItemHeader","MessageItemStatus","SyntaxLine","ToolPathLink","toolTone","useSyntaxLines","PoNativeTheme","StyleSheet","resultText","WriteCallView","writeCallView","WritePreview","view","path","spans","preview","map","line","text","join","index","number","styles","row","mono","gutter","String","padStart","content","WriteToolMessage","args","result","output","running","isError","fileTabFor","openTransientTab","collapsed","tab","expanded","summary","undefined","onOpen","sans","detail","size","error","length","hidden","create","theme","flex","flexDirection","alignItems","gap","spacing","minWidth","uni__dependencies","fontFamily","fontSize","base","lineHeight","flexShrink","color","colors","faint","red","sm","lineHeightRelaxed","toolFind","toolLs","toolWrite"],"sources":["../../src/extensions/workspaces/sessions/(frontend)/tool/_lib/builtinToolView.ts","../../src/extensions/workspaces/sessions/(frontend)/tool/_components/ListingBody.native.tsx","../../src/extensions/workspaces/sessions/(frontend)/tool/_components/FindToolMessage.native.tsx","../../src/extensions/workspaces/sessions/(frontend)/tool/find.native.tsx","../../src/extensions/workspaces/sessions/(frontend)/tool/_components/LsToolMessage.native.tsx","../../src/extensions/workspaces/sessions/(frontend)/tool/ls.native.tsx","../../src/extensions/workspaces/sessions/(frontend)/tool/_components/WriteToolMessage.native.tsx","../../src/extensions/workspaces/sessions/(frontend)/tool/write.native.tsx","../../generated/native.ts"],"sourcesContent":["import type { ToolResultView } from '@agimon-ai/po-core/web';\n\n/** The TUI's collapsed budgets: ten preview lines for a write, twenty for a listing. */\nexport const WRITE_COLLAPSED_LINES = 10;\nexport const LIST_COLLAPSED_LINES = 20;\n/** Pi's default output cap, the size its truncation warning names when details omit one. */\nconst DEFAULT_MAX_BYTES = 50 * 1024;\nconst KIBIBYTE = 1024;\n\nexport interface NumberedLine {\n readonly number: number;\n readonly text: string;\n}\n\nexport interface WriteCallView {\n readonly path: string;\n /** `N chars`, the size the TUI's call heading shows. */\n readonly size: string;\n readonly preview: readonly NumberedLine[];\n readonly hidden: number;\n /** Widest shown line number, in characters. */\n readonly gutter: number;\n}\n\nexport interface SearchCallView {\n readonly primary: string;\n readonly details: readonly string[];\n}\n\nexport interface ListResultView {\n readonly lines: readonly string[];\n readonly hidden: number;\n /** Pi's `[Truncated: ...]` warning, when the listing hit a limit. */\n readonly truncated: string | undefined;\n}\n\nfunction compactDetails(values: ReadonlyArray<string | undefined>): string[] {\n return values.filter((value): value is string => value !== undefined && value.length > 0);\n}\n\nfunction optionalCount(value: unknown, unit: string): string | undefined {\n return typeof value === 'number' && Number.isFinite(value) ? `${value} ${unit}` : undefined;\n}\n\nfunction pathOrDot(value: unknown): string {\n return typeof value === 'string' && value.length > 0 ? value : '.';\n}\n\n/** Pi's size formatter, so the web warning names the same figure the TUI does. */\nexport function formatSize(bytes: number): string {\n if (bytes < KIBIBYTE) return `${bytes}B`;\n if (bytes < KIBIBYTE * KIBIBYTE) return `${(bytes / KIBIBYTE).toFixed(1)}KB`;\n return `${(bytes / (KIBIBYTE * KIBIBYTE)).toFixed(1)}MB`;\n}\n\n/** What the write call shows: the path, the content size, and a numbered preview of the file. */\nexport function writeCallView(args: Readonly<Record<string, unknown>>, expanded: boolean): WriteCallView {\n const content = typeof args.content === 'string' ? args.content : '';\n const path = typeof args.path === 'string' ? args.path : '';\n const size = `${content.length.toLocaleString('en-US')} chars`;\n if (content.length === 0) return { path, size, preview: [], hidden: 0, gutter: 1 };\n const lines = content.replaceAll('\\t', ' ').replaceAll('\\r\\n', '\\n').split('\\n');\n while (lines.at(-1) === '') lines.pop();\n const visible = expanded ? lines : lines.slice(0, WRITE_COLLAPSED_LINES);\n const preview = visible.map((text, index) => ({ number: index + 1, text }));\n return { path, size, preview, hidden: lines.length - visible.length, gutter: String(visible.length).length };\n}\n\n/** `pattern · path · N results`, as the find call heading lists them. */\nexport function findCallView(args: Readonly<Record<string, unknown>>): SearchCallView {\n return {\n primary: typeof args.pattern === 'string' ? args.pattern : '',\n details: compactDetails([pathOrDot(args.path), optionalCount(args.limit, 'results')]),\n };\n}\n\n/** `path · N entries`, as the ls call heading lists them. */\nexport function lsCallView(args: Readonly<Record<string, unknown>>): SearchCallView {\n return { primary: pathOrDot(args.path), details: compactDetails([optionalCount(args.limit, 'entries')]) };\n}\n\n/** The result's text, from its blocks when the view exists and from the joined output otherwise. */\n/**\n * A listing line split into the name a reader scans for and the folder it sits\n * in, so the name can lead and the folder recede. `ls` lines have no folder;\n * a trailing `/` marks a directory and stays on its name.\n */\nexport function listingEntry(line: string): { name: string; folder: string } {\n const slash = line.replace(/\\/$/, '').lastIndexOf('/');\n return slash < 0 ? { name: line, folder: '' } : { name: line.slice(slash + 1), folder: line.slice(0, slash) };\n}\n\nexport function resultText(result: ToolResultView | null, output: string): string {\n if (result === null) return output;\n return result.content\n .flatMap((block) => {\n const record = typeof block === 'object' && block !== null ? (block as { type?: unknown; text?: unknown }) : {};\n return record.type === 'text' && typeof record.text === 'string' ? [record.text] : [];\n })\n .join('\\n');\n}\n\n/**\n * A find or ls listing the way Pi's own renderer shows it: the lines,\n * collapsed to twenty, and the limit warning its details carry. `limitKey`\n * names the per-tool counter (resultLimitReached, entryLimitReached).\n */\nexport function listResultView(\n result: ToolResultView | null,\n output: string,\n expanded: boolean,\n limitKey: string,\n limitUnit: string,\n): ListResultView {\n const text = resultText(result, output).trim();\n const all = text.length === 0 ? [] : text.split('\\n');\n const lines = expanded ? all : all.slice(0, LIST_COLLAPSED_LINES);\n const details =\n typeof result?.details === 'object' && result.details !== null ? (result.details as Record<string, unknown>) : {};\n const limit = details[limitKey];\n const truncation =\n typeof details.truncation === 'object' && details.truncation !== null\n ? (details.truncation as Record<string, unknown>)\n : undefined;\n const warnings: string[] = [];\n if (typeof limit === 'number' && limit > 0) warnings.push(`${limit} ${limitUnit} limit`);\n if (truncation?.truncated === true) {\n warnings.push(\n `${formatSize(typeof truncation.maxBytes === 'number' ? truncation.maxBytes : DEFAULT_MAX_BYTES)} limit`,\n );\n }\n return {\n lines,\n hidden: all.length - lines.length,\n truncated: warnings.length > 0 ? `[Truncated: ${warnings.join(', ')}]` : undefined,\n };\n}\n","import type { ToolMessageRenderProps } from '@agimon-ai/po-core/native';\nimport { fontOf, MessageItemBody, MessageItemStatus } from '@agimon-ai/po-native-components';\nimport type { PoNativeTheme } from '@agimon-ai/po-web-components/nativeTheme';\nimport { Text, View } from 'react-native';\nimport { StyleSheet } from 'react-native-unistyles';\n\nimport { listingEntry, listResultView, resultText } from '../_lib/builtinToolView';\n\n/**\n * The body shared by find and ls on native, as the web's ListingBody: Pi's\n * listing lines, collapsed to twenty until the item expands, with the limit\n * warning its details carry. One row per line: the name leads in full ink, its\n * folder follows dimmed and truncates from the front, so the nearest folder\n * stays readable on a phone.\n */\nexport function ListingBody({\n tool,\n limitKey,\n limitUnit,\n expanded,\n props,\n}: {\n tool: string;\n limitKey: string;\n limitUnit: string;\n expanded: boolean;\n props: ToolMessageRenderProps;\n}) {\n const { result, output, running, isError } = props;\n if (isError) {\n return (\n <MessageItemBody testID={`tool-result-${tool}`}>\n <Text selectable style={[styles.sans, styles.error]}>\n {resultText(result, output)}\n </Text>\n </MessageItemBody>\n );\n }\n if (result === null) {\n return running ? (\n <MessageItemBody testID={`tool-result-${tool}`}>\n <MessageItemStatus tone=\"running\">running</MessageItemStatus>\n </MessageItemBody>\n ) : null;\n }\n const view = listResultView(result, output, expanded, limitKey, limitUnit);\n if (view.lines.length === 0 && view.truncated === undefined) return null;\n return (\n <MessageItemBody testID={`tool-result-${tool}`}>\n {view.lines.map((line, index) => {\n const entry = listingEntry(line);\n return (\n <View key={`${String(index)}-${line}`} style={styles.row} accessibilityLabel={line}>\n <Text numberOfLines={1} selectable style={[styles.mono, styles.name]}>\n {entry.name}\n </Text>\n {entry.folder.length > 0 ? (\n <Text numberOfLines={1} ellipsizeMode=\"head\" style={[styles.mono, styles.folder]}>\n {entry.folder}\n </Text>\n ) : null}\n </View>\n );\n })}\n {view.hidden > 0 ? <MessageItemStatus expands>{view.hidden} more lines</MessageItemStatus> : null}\n {view.truncated !== undefined ? <Text style={[styles.mono, styles.warning]}>{view.truncated}</Text> : null}\n </MessageItemBody>\n );\n}\n\nconst styles = StyleSheet.create((theme: PoNativeTheme) => ({\n sans: {\n fontFamily: fontOf(theme.fontFamily.sans),\n fontSize: theme.fontSize.base,\n lineHeight: theme.lineHeight.base,\n },\n mono: {\n fontFamily: fontOf(theme.fontFamily.mono),\n fontSize: theme.fontSize.sm,\n lineHeight: theme.lineHeightRelaxed.sm,\n },\n row: { flexDirection: 'row', alignItems: 'baseline', gap: theme.spacing(2), minWidth: 0 },\n name: { flexShrink: 0, maxWidth: '100%', color: theme.colors.text },\n folder: { flexShrink: 1, minWidth: 0, color: theme.colors.dim },\n warning: { color: theme.colors.yellow },\n error: { color: theme.colors.red },\n}));\n","import type { ToolMessageRenderProps } from '@agimon-ai/po-core/native';\nimport { fontOf, MessageItem, MessageItemHeader, toolTone } from '@agimon-ai/po-native-components';\nimport type { PoNativeTheme } from '@agimon-ai/po-web-components/nativeTheme';\nimport { Text, View } from 'react-native';\nimport { StyleSheet } from 'react-native-unistyles';\n\nimport { findCallView } from '../_lib/builtinToolView';\nimport { ListingBody } from './ListingBody.native';\n\nconst LIMIT_KEY = 'resultLimitReached';\nconst LIMIT_UNIT = 'results';\n\n/** The find tool's timeline item on native, as the web's: `pattern · path · N results` over Pi's listing lines. */\nexport function FindToolMessage(props: ToolMessageRenderProps) {\n const view = findCallView(props.args);\n return (\n <MessageItem tone={toolTone({ running: props.running, isError: props.isError })} expandable>\n {({ expanded }) => (\n <>\n <MessageItemHeader title=\"find\">\n <View testID=\"tool-call-find\" style={styles.summary}>\n <Text numberOfLines={1} style={[styles.sans, styles.primary]}>\n {view.primary}\n </Text>\n {view.details.length > 0 ? (\n <Text numberOfLines={1} ellipsizeMode=\"middle\" style={[styles.sans, styles.detail]}>\n · {view.details.join(' · ')}\n </Text>\n ) : null}\n </View>\n </MessageItemHeader>\n {expanded ? (\n <ListingBody tool=\"find\" limitKey={LIMIT_KEY} limitUnit={LIMIT_UNIT} expanded props={props} />\n ) : null}\n </>\n )}\n </MessageItem>\n );\n}\n\nconst styles = StyleSheet.create((theme: PoNativeTheme) => ({\n summary: { flex: 1, flexDirection: 'row', alignItems: 'center', gap: theme.spacing(2), minWidth: 0 },\n sans: {\n fontFamily: fontOf(theme.fontFamily.sans),\n fontSize: theme.fontSize.base,\n lineHeight: theme.lineHeight.base,\n },\n // The pattern is what was asked, so it stays whole up to most of a phone row; the path\n // and count yield first, cut in the middle so the count at the end survives.\n primary: { flexShrink: 0, maxWidth: '60%', color: theme.colors.text },\n detail: { flexShrink: 1, color: theme.colors.faint },\n}));\n","import { defineToolRenderer } from '@agimon-ai/po-core/native';\n\nimport { FindToolMessage } from './_components/FindToolMessage.native';\n\nexport default defineToolRenderer({ message: FindToolMessage });\n","import type { ToolMessageRenderProps } from '@agimon-ai/po-core/native';\nimport { fontOf, MessageItem, MessageItemHeader, toolTone } from '@agimon-ai/po-native-components';\nimport type { PoNativeTheme } from '@agimon-ai/po-web-components/nativeTheme';\nimport { Text, View } from 'react-native';\nimport { StyleSheet } from 'react-native-unistyles';\n\nimport { lsCallView } from '../_lib/builtinToolView';\nimport { ListingBody } from './ListingBody.native';\n\nconst LIMIT_KEY = 'entryLimitReached';\nconst LIMIT_UNIT = 'entries';\n\n/** The ls tool's timeline item on native, as the web's: `path · N entries` over Pi's listing lines. */\nexport function LsToolMessage(props: ToolMessageRenderProps) {\n const view = lsCallView(props.args);\n return (\n <MessageItem tone={toolTone({ running: props.running, isError: props.isError })} expandable>\n {({ expanded }) => (\n <>\n <MessageItemHeader title=\"ls\">\n <View testID=\"tool-call-ls\" style={styles.summary}>\n <Text numberOfLines={1} style={[styles.sans, styles.primary]}>\n {view.primary}\n </Text>\n {view.details.length > 0 ? (\n <Text numberOfLines={1} style={[styles.sans, styles.detail]}>\n · {view.details.join(' · ')}\n </Text>\n ) : null}\n </View>\n </MessageItemHeader>\n {expanded ? (\n <ListingBody tool=\"ls\" limitKey={LIMIT_KEY} limitUnit={LIMIT_UNIT} expanded props={props} />\n ) : null}\n </>\n )}\n </MessageItem>\n );\n}\n\nconst styles = StyleSheet.create((theme: PoNativeTheme) => ({\n summary: { flex: 1, flexDirection: 'row', alignItems: 'center', gap: theme.spacing(2), minWidth: 0 },\n sans: {\n fontFamily: fontOf(theme.fontFamily.sans),\n fontSize: theme.fontSize.base,\n lineHeight: theme.lineHeight.base,\n },\n primary: { flexShrink: 1, color: theme.colors.text },\n detail: { flexShrink: 0, color: theme.colors.faint },\n}));\n","import { defineToolRenderer } from '@agimon-ai/po-core/native';\n\nimport { LsToolMessage } from './_components/LsToolMessage.native';\n\nexport default defineToolRenderer({ message: LsToolMessage });\n","import type { ToolMessageRenderProps } from '@agimon-ai/po-core/native';\nimport {\n fontOf,\n MessageItem,\n MessageItemBody,\n MessageItemHeader,\n MessageItemStatus,\n SyntaxLine,\n ToolPathLink,\n toolTone,\n useSyntaxLines,\n} from '@agimon-ai/po-native-components';\nimport type { PoNativeTheme } from '@agimon-ai/po-web-components/nativeTheme';\nimport { Text, View } from 'react-native';\nimport { StyleSheet } from 'react-native-unistyles';\n\nimport { resultText, type WriteCallView, writeCallView } from '../_lib/builtinToolView';\n\n/** The numbered preview, coloured as the file it is about to become, as the web's WritePreview. */\nfunction WritePreview({ view, path }: { view: WriteCallView; path: string }) {\n const spans = useSyntaxLines(view.preview.map((line) => line.text).join('\\n'), { path });\n return (\n <View>\n {view.preview.map((line, index) => (\n <View key={line.number} style={styles.row}>\n <Text style={[styles.mono, styles.gutter]}>{String(line.number).padStart(view.gutter)}</Text>\n <SyntaxLine selectable spans={spans?.[index]} text={line.text} style={[styles.mono, styles.content]} />\n </View>\n ))}\n </View>\n );\n}\n\n/**\n * The write tool's timeline item on native, as the web's WriteToolMessage:\n * `path · N chars` in the header and, expanded, the numbered file content.\n * A failure shows the tool's message in red instead.\n */\nexport function WriteToolMessage({\n args,\n result,\n output,\n running,\n isError,\n fileTabFor,\n openTransientTab,\n}: ToolMessageRenderProps) {\n const collapsed = writeCallView(args, false);\n const tab = fileTabFor(collapsed.path);\n return (\n <MessageItem tone={toolTone({ running, isError })} expandable>\n {({ expanded }) => {\n const view = expanded ? writeCallView(args, true) : collapsed;\n return (\n <>\n <MessageItemHeader title=\"write\">\n <View testID=\"tool-call-write\" style={styles.summary}>\n <ToolPathLink\n path={view.path}\n {...(tab === undefined ? {} : { onOpen: () => openTransientTab(tab) })}\n />\n <Text numberOfLines={1} style={[styles.sans, styles.detail]}>\n · {view.size}\n </Text>\n </View>\n </MessageItemHeader>\n {!expanded ? null : isError ? (\n <MessageItemBody testID=\"tool-result-write\">\n <Text selectable style={[styles.sans, styles.error]}>\n {resultText(result, output)}\n </Text>\n </MessageItemBody>\n ) : view.preview.length === 0 ? (\n running ? (\n <MessageItemBody testID=\"tool-result-write\">\n <MessageItemStatus tone=\"running\">running</MessageItemStatus>\n </MessageItemBody>\n ) : null\n ) : (\n <MessageItemBody testID=\"tool-result-write\">\n <WritePreview view={view} path={view.path} />\n {view.hidden > 0 ? <MessageItemStatus expands>{view.hidden} more lines</MessageItemStatus> : null}\n {running ? <MessageItemStatus tone=\"running\">running</MessageItemStatus> : null}\n </MessageItemBody>\n )}\n </>\n );\n }}\n </MessageItem>\n );\n}\n\nconst styles = StyleSheet.create((theme: PoNativeTheme) => ({\n summary: { flex: 1, flexDirection: 'row', alignItems: 'center', gap: theme.spacing(2), minWidth: 0 },\n sans: {\n fontFamily: fontOf(theme.fontFamily.sans),\n fontSize: theme.fontSize.base,\n lineHeight: theme.lineHeight.base,\n },\n detail: { flexShrink: 0, color: theme.colors.faint },\n error: { color: theme.colors.red },\n row: { flexDirection: 'row', gap: theme.spacing(2) },\n mono: {\n fontFamily: fontOf(theme.fontFamily.mono),\n fontSize: theme.fontSize.sm,\n lineHeight: theme.lineHeightRelaxed.sm,\n },\n gutter: { color: theme.colors.faint },\n content: { flex: 1, minWidth: 0, color: theme.colors.text },\n}));\n","import { defineToolRenderer } from '@agimon-ai/po-core/native';\n\nimport { WriteToolMessage } from './_components/WriteToolMessage.native';\n\nexport default defineToolRenderer({ message: WriteToolMessage });\n","// Generated by @agimon-ai/po-build. Do not edit by hand.\nimport { defineNativePlugin, type WebPluginContributions } from '@agimon-ai/po-core/native';\n\nimport toolFind from '../src/extensions/workspaces/sessions/(frontend)/tool/find.native';\nimport toolLs from '../src/extensions/workspaces/sessions/(frontend)/tool/ls.native';\nimport toolWrite from '../src/extensions/workspaces/sessions/(frontend)/tool/write.native';\n\nconst via = <T>(identity: Record<string, unknown>, value: unknown): T =>\n (value === undefined ? undefined : { ...identity, ...(value as object) }) as T;\n\nexport const nativePlugin = defineNativePlugin({\n id: 'builtin-tools',\n session: {\n get toolRenderers(): WebPluginContributions['toolRenderers'] { return [via({ tools: ['find'] }, toolFind), via({ tools: ['ls'] }, toolLs), via({ tools: ['write'] }, toolWrite)]; },\n },\n});\n"],"mappings":"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"}
|
package/dist/extensions/web.mjs
CHANGED
|
@@ -60,6 +60,21 @@ function lsCallView(args) {
|
|
|
60
60
|
};
|
|
61
61
|
}
|
|
62
62
|
/** The result's text, from its blocks when the view exists and from the joined output otherwise. */
|
|
63
|
+
/**
|
|
64
|
+
* A listing line split into the name a reader scans for and the folder it sits
|
|
65
|
+
* in, so the name can lead and the folder recede. `ls` lines have no folder;
|
|
66
|
+
* a trailing `/` marks a directory and stays on its name.
|
|
67
|
+
*/
|
|
68
|
+
function listingEntry(line) {
|
|
69
|
+
const slash = line.replace(/\/$/, "").lastIndexOf("/");
|
|
70
|
+
return slash < 0 ? {
|
|
71
|
+
name: line,
|
|
72
|
+
folder: ""
|
|
73
|
+
} : {
|
|
74
|
+
name: line.slice(slash + 1),
|
|
75
|
+
folder: line.slice(0, slash)
|
|
76
|
+
};
|
|
77
|
+
}
|
|
63
78
|
function resultText(result, output) {
|
|
64
79
|
if (result === null) return output;
|
|
65
80
|
return result.content.flatMap((block) => {
|
|
@@ -92,20 +107,19 @@ function listResultView(result, output, expanded, limitKey, limitUnit) {
|
|
|
92
107
|
//#region src/extensions/workspaces/sessions/(frontend)/tool/_components/ListingBody.tsx
|
|
93
108
|
/**
|
|
94
109
|
* The body shared by find and ls: Pi's listing lines, collapsed to twenty
|
|
95
|
-
* until the item expands, with the limit warning its details carry.
|
|
110
|
+
* until the item expands, with the limit warning its details carry. Each line
|
|
111
|
+
* stays on one row: the name leads in full ink and never cuts, its folder
|
|
112
|
+
* follows dimmed and is the part that truncates.
|
|
96
113
|
*/
|
|
97
114
|
function ListingBody({ tool, limitKey, limitUnit, expanded, props }) {
|
|
98
115
|
const { result, output, running, isError } = props;
|
|
99
|
-
if (isError) return /* @__PURE__ */
|
|
116
|
+
if (isError) return /* @__PURE__ */ jsx(MessageItemBody, {
|
|
100
117
|
"data-testid": `tool-result-${tool}`,
|
|
101
118
|
className: "flex flex-col",
|
|
102
|
-
children:
|
|
103
|
-
tone: "error",
|
|
104
|
-
children: "failed"
|
|
105
|
-
}), /* @__PURE__ */ jsx("span", {
|
|
119
|
+
children: /* @__PURE__ */ jsx("span", {
|
|
106
120
|
className: "whitespace-pre-wrap break-words text-po-red",
|
|
107
121
|
children: resultText(result, output)
|
|
108
|
-
})
|
|
122
|
+
})
|
|
109
123
|
});
|
|
110
124
|
if (result === null) return running ? /* @__PURE__ */ jsx(MessageItemBody, {
|
|
111
125
|
"data-testid": `tool-result-${tool}`,
|
|
@@ -120,10 +134,20 @@ function ListingBody({ tool, limitKey, limitUnit, expanded, props }) {
|
|
|
120
134
|
"data-testid": `tool-result-${tool}`,
|
|
121
135
|
className: "flex flex-col font-mono",
|
|
122
136
|
children: [
|
|
123
|
-
view.lines.map((line, index) =>
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
137
|
+
view.lines.map((line, index) => {
|
|
138
|
+
const entry = listingEntry(line);
|
|
139
|
+
return /* @__PURE__ */ jsxs("span", {
|
|
140
|
+
title: line,
|
|
141
|
+
className: "flex min-w-0 items-baseline gap-2",
|
|
142
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
143
|
+
className: "max-w-full shrink-0 truncate text-po-text",
|
|
144
|
+
children: entry.name
|
|
145
|
+
}), entry.folder.length > 0 ? /* @__PURE__ */ jsx("span", {
|
|
146
|
+
className: "min-w-0 truncate text-po-dim",
|
|
147
|
+
children: entry.folder
|
|
148
|
+
}) : null]
|
|
149
|
+
}, `${String(index)}-${line}`);
|
|
150
|
+
}),
|
|
127
151
|
view.hidden > 0 ? /* @__PURE__ */ jsxs(MessageItemStatus, {
|
|
128
152
|
expands: true,
|
|
129
153
|
children: [view.hidden, " more lines"]
|
|
@@ -264,16 +288,13 @@ function WriteToolMessage({ args, result, output, running, isError, fileTabFor,
|
|
|
264
288
|
children: ["· ", view.size]
|
|
265
289
|
})]
|
|
266
290
|
})
|
|
267
|
-
}), !expanded ? null : isError ? /* @__PURE__ */
|
|
291
|
+
}), !expanded ? null : isError ? /* @__PURE__ */ jsx(MessageItemBody, {
|
|
268
292
|
"data-testid": "tool-result-write",
|
|
269
293
|
className: "flex flex-col",
|
|
270
|
-
children:
|
|
271
|
-
tone: "error",
|
|
272
|
-
children: "failed"
|
|
273
|
-
}), /* @__PURE__ */ jsx("span", {
|
|
294
|
+
children: /* @__PURE__ */ jsx("span", {
|
|
274
295
|
className: "whitespace-pre-wrap break-words text-po-red",
|
|
275
296
|
children: resultText(result, output)
|
|
276
|
-
})
|
|
297
|
+
})
|
|
277
298
|
}) : view.preview.length === 0 ? running ? /* @__PURE__ */ jsx(MessageItemBody, {
|
|
278
299
|
"data-testid": "tool-result-write",
|
|
279
300
|
children: /* @__PURE__ */ jsx(MessageItemStatus, {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"web.mjs","names":["LIMIT_KEY","LIMIT_UNIT","toolFind","toolLs","toolWrite"],"sources":["../../src/extensions/workspaces/sessions/(frontend)/tool/_lib/builtinToolView.ts","../../src/extensions/workspaces/sessions/(frontend)/tool/_components/ListingBody.tsx","../../src/extensions/workspaces/sessions/(frontend)/tool/_components/FindToolMessage.tsx","../../src/extensions/workspaces/sessions/(frontend)/tool/find.web.tsx","../../src/extensions/workspaces/sessions/(frontend)/tool/_components/LsToolMessage.tsx","../../src/extensions/workspaces/sessions/(frontend)/tool/ls.web.tsx","../../src/extensions/workspaces/sessions/(frontend)/tool/_components/WriteToolMessage.tsx","../../src/extensions/workspaces/sessions/(frontend)/tool/write.web.tsx","../../generated/web.ts"],"sourcesContent":["import type { ToolResultView } from '@agimon-ai/po-core/web';\n\n/** The TUI's collapsed budgets: ten preview lines for a write, twenty for a listing. */\nexport const WRITE_COLLAPSED_LINES = 10;\nexport const LIST_COLLAPSED_LINES = 20;\n/** Pi's default output cap, the size its truncation warning names when details omit one. */\nconst DEFAULT_MAX_BYTES = 50 * 1024;\nconst KIBIBYTE = 1024;\n\nexport interface NumberedLine {\n readonly number: number;\n readonly text: string;\n}\n\nexport interface WriteCallView {\n readonly path: string;\n /** `N chars`, the size the TUI's call heading shows. */\n readonly size: string;\n readonly preview: readonly NumberedLine[];\n readonly hidden: number;\n /** Widest shown line number, in characters. */\n readonly gutter: number;\n}\n\nexport interface SearchCallView {\n readonly primary: string;\n readonly details: readonly string[];\n}\n\nexport interface ListResultView {\n readonly lines: readonly string[];\n readonly hidden: number;\n /** Pi's `[Truncated: ...]` warning, when the listing hit a limit. */\n readonly truncated: string | undefined;\n}\n\nfunction compactDetails(values: ReadonlyArray<string | undefined>): string[] {\n return values.filter((value): value is string => value !== undefined && value.length > 0);\n}\n\nfunction optionalCount(value: unknown, unit: string): string | undefined {\n return typeof value === 'number' && Number.isFinite(value) ? `${value} ${unit}` : undefined;\n}\n\nfunction pathOrDot(value: unknown): string {\n return typeof value === 'string' && value.length > 0 ? value : '.';\n}\n\n/** Pi's size formatter, so the web warning names the same figure the TUI does. */\nexport function formatSize(bytes: number): string {\n if (bytes < KIBIBYTE) return `${bytes}B`;\n if (bytes < KIBIBYTE * KIBIBYTE) return `${(bytes / KIBIBYTE).toFixed(1)}KB`;\n return `${(bytes / (KIBIBYTE * KIBIBYTE)).toFixed(1)}MB`;\n}\n\n/** What the write call shows: the path, the content size, and a numbered preview of the file. */\nexport function writeCallView(args: Readonly<Record<string, unknown>>, expanded: boolean): WriteCallView {\n const content = typeof args.content === 'string' ? args.content : '';\n const path = typeof args.path === 'string' ? args.path : '';\n const size = `${content.length.toLocaleString('en-US')} chars`;\n if (content.length === 0) return { path, size, preview: [], hidden: 0, gutter: 1 };\n const lines = content.replaceAll('\\t', ' ').replaceAll('\\r\\n', '\\n').split('\\n');\n while (lines.at(-1) === '') lines.pop();\n const visible = expanded ? lines : lines.slice(0, WRITE_COLLAPSED_LINES);\n const preview = visible.map((text, index) => ({ number: index + 1, text }));\n return { path, size, preview, hidden: lines.length - visible.length, gutter: String(visible.length).length };\n}\n\n/** `pattern · path · N results`, as the find call heading lists them. */\nexport function findCallView(args: Readonly<Record<string, unknown>>): SearchCallView {\n return {\n primary: typeof args.pattern === 'string' ? args.pattern : '',\n details: compactDetails([pathOrDot(args.path), optionalCount(args.limit, 'results')]),\n };\n}\n\n/** `path · N entries`, as the ls call heading lists them. */\nexport function lsCallView(args: Readonly<Record<string, unknown>>): SearchCallView {\n return { primary: pathOrDot(args.path), details: compactDetails([optionalCount(args.limit, 'entries')]) };\n}\n\n/** The result's text, from its blocks when the view exists and from the joined output otherwise. */\nexport function resultText(result: ToolResultView | null, output: string): string {\n if (result === null) return output;\n return result.content\n .flatMap((block) => {\n const record = typeof block === 'object' && block !== null ? (block as { type?: unknown; text?: unknown }) : {};\n return record.type === 'text' && typeof record.text === 'string' ? [record.text] : [];\n })\n .join('\\n');\n}\n\n/**\n * A find or ls listing the way Pi's own renderer shows it: the lines,\n * collapsed to twenty, and the limit warning its details carry. `limitKey`\n * names the per-tool counter (resultLimitReached, entryLimitReached).\n */\nexport function listResultView(\n result: ToolResultView | null,\n output: string,\n expanded: boolean,\n limitKey: string,\n limitUnit: string,\n): ListResultView {\n const text = resultText(result, output).trim();\n const all = text.length === 0 ? [] : text.split('\\n');\n const lines = expanded ? all : all.slice(0, LIST_COLLAPSED_LINES);\n const details =\n typeof result?.details === 'object' && result.details !== null ? (result.details as Record<string, unknown>) : {};\n const limit = details[limitKey];\n const truncation =\n typeof details.truncation === 'object' && details.truncation !== null\n ? (details.truncation as Record<string, unknown>)\n : undefined;\n const warnings: string[] = [];\n if (typeof limit === 'number' && limit > 0) warnings.push(`${limit} ${limitUnit} limit`);\n if (truncation?.truncated === true) {\n warnings.push(\n `${formatSize(typeof truncation.maxBytes === 'number' ? truncation.maxBytes : DEFAULT_MAX_BYTES)} limit`,\n );\n }\n return {\n lines,\n hidden: all.length - lines.length,\n truncated: warnings.length > 0 ? `[Truncated: ${warnings.join(', ')}]` : undefined,\n };\n}\n","import type { ToolMessageRenderProps } from '@agimon-ai/po-core/web';\nimport { MessageItemBody, MessageItemStatus } from '@agimon-ai/po-web-components';\n\nimport { listResultView, resultText } from '../_lib/builtinToolView';\n\n/**\n * The body shared by find and ls: Pi's listing lines, collapsed to twenty\n * until the item expands, with the limit warning its details carry.\n */\nexport function ListingBody({\n tool,\n limitKey,\n limitUnit,\n expanded,\n props,\n}: {\n tool: string;\n limitKey: string;\n limitUnit: string;\n expanded: boolean;\n props: ToolMessageRenderProps;\n}) {\n const { result, output, running, isError } = props;\n if (isError) {\n return (\n <MessageItemBody data-testid={`tool-result-${tool}`} className=\"flex flex-col\">\n <MessageItemStatus tone=\"error\">failed</MessageItemStatus>\n <span className=\"whitespace-pre-wrap break-words text-po-red\">{resultText(result, output)}</span>\n </MessageItemBody>\n );\n }\n if (result === null) {\n return running ? (\n <MessageItemBody data-testid={`tool-result-${tool}`}>\n <MessageItemStatus tone=\"running\">running</MessageItemStatus>\n </MessageItemBody>\n ) : null;\n }\n const view = listResultView(result, output, expanded, limitKey, limitUnit);\n if (view.lines.length === 0 && view.truncated === undefined) return null;\n return (\n <MessageItemBody data-testid={`tool-result-${tool}`} className=\"flex flex-col font-mono\">\n {view.lines.map((line, index) => (\n <span key={`${String(index)}-${line}`} className=\"whitespace-pre-wrap break-words text-po-text\">\n {line}\n </span>\n ))}\n {view.hidden > 0 ? <MessageItemStatus expands>{view.hidden} more lines</MessageItemStatus> : null}\n {view.truncated !== undefined ? <span className=\"text-po-yellow\">{view.truncated}</span> : null}\n </MessageItemBody>\n );\n}\n\n/** Whether the listing hides lines while collapsed, so the item can offer its toggle. */\nexport function listingExpandable(props: ToolMessageRenderProps, limitKey: string, limitUnit: string): boolean {\n if (props.result === null || props.isError) return false;\n return listResultView(props.result, props.output, false, limitKey, limitUnit).hidden > 0;\n}\n","import type { ToolMessageRenderProps } from '@agimon-ai/po-core/web';\nimport { MessageItem, MessageItemHeader, toolTone } from '@agimon-ai/po-web-components';\n\nimport { findCallView } from '../_lib/builtinToolView';\nimport { ListingBody } from './ListingBody';\n\nconst LIMIT_KEY = 'resultLimitReached';\nconst LIMIT_UNIT = 'results';\n\n/** The find tool's timeline item: `pattern · path · N results` over Pi's listing lines. */\nexport function FindToolMessage(props: ToolMessageRenderProps) {\n const view = findCallView(props.args);\n return (\n <MessageItem tone={toolTone({ running: props.running, isError: props.isError })} expandable>\n {({ expanded }) => (\n <>\n <MessageItemHeader title=\"find\">\n <span data-testid=\"tool-call-find\" className=\"flex min-w-0 flex-1 items-center gap-2\">\n <span className=\"truncate text-po-text\">{view.primary}</span>\n {view.details.length > 0 ? (\n <span className=\"shrink-0 text-po-faint\">· {view.details.join(' · ')}</span>\n ) : null}\n </span>\n </MessageItemHeader>\n {expanded ? (\n <ListingBody tool=\"find\" limitKey={LIMIT_KEY} limitUnit={LIMIT_UNIT} expanded props={props} />\n ) : null}\n </>\n )}\n </MessageItem>\n );\n}\n","import { defineToolRenderer } from '@agimon-ai/po-core/web';\n\nimport { FindToolMessage } from './_components/FindToolMessage';\n\nexport default defineToolRenderer({ message: FindToolMessage });\n","import type { ToolMessageRenderProps } from '@agimon-ai/po-core/web';\nimport { MessageItem, MessageItemHeader, toolTone } from '@agimon-ai/po-web-components';\n\nimport { lsCallView } from '../_lib/builtinToolView';\nimport { ListingBody } from './ListingBody';\n\nconst LIMIT_KEY = 'entryLimitReached';\nconst LIMIT_UNIT = 'entries';\n\n/** The ls tool's timeline item: `path · N entries` over Pi's listing lines. */\nexport function LsToolMessage(props: ToolMessageRenderProps) {\n const view = lsCallView(props.args);\n return (\n <MessageItem tone={toolTone({ running: props.running, isError: props.isError })} expandable>\n {({ expanded }) => (\n <>\n <MessageItemHeader title=\"ls\">\n <span data-testid=\"tool-call-ls\" className=\"flex min-w-0 flex-1 items-center gap-2\">\n <span className=\"truncate text-po-text\">{view.primary}</span>\n {view.details.length > 0 ? (\n <span className=\"shrink-0 text-po-faint\">· {view.details.join(' · ')}</span>\n ) : null}\n </span>\n </MessageItemHeader>\n {expanded ? (\n <ListingBody tool=\"ls\" limitKey={LIMIT_KEY} limitUnit={LIMIT_UNIT} expanded props={props} />\n ) : null}\n </>\n )}\n </MessageItem>\n );\n}\n","import { defineToolRenderer } from '@agimon-ai/po-core/web';\n\nimport { LsToolMessage } from './_components/LsToolMessage';\n\nexport default defineToolRenderer({ message: LsToolMessage });\n","import type { ToolMessageRenderProps } from '@agimon-ai/po-core/web';\nimport {\n MessageItem,\n MessageItemBody,\n MessageItemHeader,\n MessageItemStatus,\n SyntaxLine,\n ToolPathLink,\n toolTone,\n useSyntaxLines,\n} from '@agimon-ai/po-web-components';\n\nimport { resultText, type WriteCallView, writeCallView } from '../_lib/builtinToolView';\n\n/**\n * The numbered preview, coloured as the file it is about to become.\n *\n * Its own component so the highlighting hook has somewhere to live: the body\n * around it is picked inside a render prop. The preview is a prefix of the\n * content, so it parses as the file it came from up to wherever it was cut.\n */\nfunction WritePreview({ view, path }: { view: WriteCallView; path: string }) {\n const spans = useSyntaxLines(view.preview.map((line) => line.text).join('\\n'), { path });\n return (\n <>\n {view.preview.map((line, index) => (\n <span key={line.number} className=\"flex gap-2\">\n <span className=\"shrink-0 text-right text-po-faint\" style={{ width: `${String(view.gutter)}ch` }}>\n {line.number}\n </span>\n <SyntaxLine\n spans={spans?.[index]}\n text={line.text}\n className=\"min-w-0 whitespace-pre-wrap break-words text-po-text\"\n />\n </span>\n ))}\n </>\n );\n}\n\n/**\n * The write tool's timeline item: `path · N chars` in the header. Pi's write\n * result is silent on success, so expanding shows the numbered file content.\n * A failure shows the tool's message in red instead.\n */\nexport function WriteToolMessage({\n args,\n result,\n output,\n running,\n isError,\n fileTabFor,\n openTransientTab,\n}: ToolMessageRenderProps) {\n const collapsed = writeCallView(args, false);\n // The header names a file the tool is writing, so the reader can open it\n // rather than hunt for it; nothing installed to show files leaves it as text.\n const tab = fileTabFor(collapsed.path);\n return (\n <MessageItem tone={toolTone({ running, isError })} expandable>\n {({ expanded }) => {\n const view = expanded ? writeCallView(args, true) : collapsed;\n return (\n <>\n <MessageItemHeader title=\"write\">\n <span data-testid=\"tool-call-write\" className=\"flex min-w-0 flex-1 items-center gap-2\">\n <ToolPathLink\n path={view.path}\n {...(tab === undefined ? {} : { onOpen: () => openTransientTab(tab) })}\n />\n <span className=\"shrink-0 text-po-faint\">· {view.size}</span>\n </span>\n </MessageItemHeader>\n {!expanded ? null : isError ? (\n <MessageItemBody data-testid=\"tool-result-write\" className=\"flex flex-col\">\n <MessageItemStatus tone=\"error\">failed</MessageItemStatus>\n <span className=\"whitespace-pre-wrap break-words text-po-red\">{resultText(result, output)}</span>\n </MessageItemBody>\n ) : view.preview.length === 0 ? (\n running ? (\n <MessageItemBody data-testid=\"tool-result-write\">\n <MessageItemStatus tone=\"running\">running</MessageItemStatus>\n </MessageItemBody>\n ) : null\n ) : (\n <MessageItemBody data-testid=\"tool-result-write\" className=\"flex flex-col font-mono\">\n <WritePreview view={view} path={view.path} />\n {view.hidden > 0 ? <MessageItemStatus expands>{view.hidden} more lines</MessageItemStatus> : null}\n {running ? <MessageItemStatus tone=\"running\">running</MessageItemStatus> : null}\n </MessageItemBody>\n )}\n </>\n );\n }}\n </MessageItem>\n );\n}\n","import { defineToolRenderer } from '@agimon-ai/po-core/web';\n\nimport { WriteToolMessage } from './_components/WriteToolMessage';\n\nexport default defineToolRenderer({ message: WriteToolMessage });\n","// Generated by @agimon-ai/po-build. Do not edit by hand.\nimport { defineWebPlugin, type WebPluginContributions } from '@agimon-ai/po-core/web';\n\nimport toolFind from '../src/extensions/workspaces/sessions/(frontend)/tool/find.web';\nimport toolLs from '../src/extensions/workspaces/sessions/(frontend)/tool/ls.web';\nimport toolWrite from '../src/extensions/workspaces/sessions/(frontend)/tool/write.web';\n\nconst via = <T>(identity: Record<string, unknown>, value: unknown): T =>\n (value === undefined ? undefined : { ...identity, ...(value as object) }) as T;\n\nexport const webPlugin = defineWebPlugin({\n id: 'builtin-tools',\n session: {\n get toolRenderers(): WebPluginContributions['toolRenderers'] { return [via({ tools: ['find'] }, toolFind), via({ tools: ['ls'] }, toolLs), via({ tools: ['write'] }, toolWrite)]; },\n },\n});\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"web.mjs","names":["LIMIT_KEY","LIMIT_UNIT","toolFind","toolLs","toolWrite"],"sources":["../../src/extensions/workspaces/sessions/(frontend)/tool/_lib/builtinToolView.ts","../../src/extensions/workspaces/sessions/(frontend)/tool/_components/ListingBody.tsx","../../src/extensions/workspaces/sessions/(frontend)/tool/_components/FindToolMessage.tsx","../../src/extensions/workspaces/sessions/(frontend)/tool/find.web.tsx","../../src/extensions/workspaces/sessions/(frontend)/tool/_components/LsToolMessage.tsx","../../src/extensions/workspaces/sessions/(frontend)/tool/ls.web.tsx","../../src/extensions/workspaces/sessions/(frontend)/tool/_components/WriteToolMessage.tsx","../../src/extensions/workspaces/sessions/(frontend)/tool/write.web.tsx","../../generated/web.ts"],"sourcesContent":["import type { ToolResultView } from '@agimon-ai/po-core/web';\n\n/** The TUI's collapsed budgets: ten preview lines for a write, twenty for a listing. */\nexport const WRITE_COLLAPSED_LINES = 10;\nexport const LIST_COLLAPSED_LINES = 20;\n/** Pi's default output cap, the size its truncation warning names when details omit one. */\nconst DEFAULT_MAX_BYTES = 50 * 1024;\nconst KIBIBYTE = 1024;\n\nexport interface NumberedLine {\n readonly number: number;\n readonly text: string;\n}\n\nexport interface WriteCallView {\n readonly path: string;\n /** `N chars`, the size the TUI's call heading shows. */\n readonly size: string;\n readonly preview: readonly NumberedLine[];\n readonly hidden: number;\n /** Widest shown line number, in characters. */\n readonly gutter: number;\n}\n\nexport interface SearchCallView {\n readonly primary: string;\n readonly details: readonly string[];\n}\n\nexport interface ListResultView {\n readonly lines: readonly string[];\n readonly hidden: number;\n /** Pi's `[Truncated: ...]` warning, when the listing hit a limit. */\n readonly truncated: string | undefined;\n}\n\nfunction compactDetails(values: ReadonlyArray<string | undefined>): string[] {\n return values.filter((value): value is string => value !== undefined && value.length > 0);\n}\n\nfunction optionalCount(value: unknown, unit: string): string | undefined {\n return typeof value === 'number' && Number.isFinite(value) ? `${value} ${unit}` : undefined;\n}\n\nfunction pathOrDot(value: unknown): string {\n return typeof value === 'string' && value.length > 0 ? value : '.';\n}\n\n/** Pi's size formatter, so the web warning names the same figure the TUI does. */\nexport function formatSize(bytes: number): string {\n if (bytes < KIBIBYTE) return `${bytes}B`;\n if (bytes < KIBIBYTE * KIBIBYTE) return `${(bytes / KIBIBYTE).toFixed(1)}KB`;\n return `${(bytes / (KIBIBYTE * KIBIBYTE)).toFixed(1)}MB`;\n}\n\n/** What the write call shows: the path, the content size, and a numbered preview of the file. */\nexport function writeCallView(args: Readonly<Record<string, unknown>>, expanded: boolean): WriteCallView {\n const content = typeof args.content === 'string' ? args.content : '';\n const path = typeof args.path === 'string' ? args.path : '';\n const size = `${content.length.toLocaleString('en-US')} chars`;\n if (content.length === 0) return { path, size, preview: [], hidden: 0, gutter: 1 };\n const lines = content.replaceAll('\\t', ' ').replaceAll('\\r\\n', '\\n').split('\\n');\n while (lines.at(-1) === '') lines.pop();\n const visible = expanded ? lines : lines.slice(0, WRITE_COLLAPSED_LINES);\n const preview = visible.map((text, index) => ({ number: index + 1, text }));\n return { path, size, preview, hidden: lines.length - visible.length, gutter: String(visible.length).length };\n}\n\n/** `pattern · path · N results`, as the find call heading lists them. */\nexport function findCallView(args: Readonly<Record<string, unknown>>): SearchCallView {\n return {\n primary: typeof args.pattern === 'string' ? args.pattern : '',\n details: compactDetails([pathOrDot(args.path), optionalCount(args.limit, 'results')]),\n };\n}\n\n/** `path · N entries`, as the ls call heading lists them. */\nexport function lsCallView(args: Readonly<Record<string, unknown>>): SearchCallView {\n return { primary: pathOrDot(args.path), details: compactDetails([optionalCount(args.limit, 'entries')]) };\n}\n\n/** The result's text, from its blocks when the view exists and from the joined output otherwise. */\n/**\n * A listing line split into the name a reader scans for and the folder it sits\n * in, so the name can lead and the folder recede. `ls` lines have no folder;\n * a trailing `/` marks a directory and stays on its name.\n */\nexport function listingEntry(line: string): { name: string; folder: string } {\n const slash = line.replace(/\\/$/, '').lastIndexOf('/');\n return slash < 0 ? { name: line, folder: '' } : { name: line.slice(slash + 1), folder: line.slice(0, slash) };\n}\n\nexport function resultText(result: ToolResultView | null, output: string): string {\n if (result === null) return output;\n return result.content\n .flatMap((block) => {\n const record = typeof block === 'object' && block !== null ? (block as { type?: unknown; text?: unknown }) : {};\n return record.type === 'text' && typeof record.text === 'string' ? [record.text] : [];\n })\n .join('\\n');\n}\n\n/**\n * A find or ls listing the way Pi's own renderer shows it: the lines,\n * collapsed to twenty, and the limit warning its details carry. `limitKey`\n * names the per-tool counter (resultLimitReached, entryLimitReached).\n */\nexport function listResultView(\n result: ToolResultView | null,\n output: string,\n expanded: boolean,\n limitKey: string,\n limitUnit: string,\n): ListResultView {\n const text = resultText(result, output).trim();\n const all = text.length === 0 ? [] : text.split('\\n');\n const lines = expanded ? all : all.slice(0, LIST_COLLAPSED_LINES);\n const details =\n typeof result?.details === 'object' && result.details !== null ? (result.details as Record<string, unknown>) : {};\n const limit = details[limitKey];\n const truncation =\n typeof details.truncation === 'object' && details.truncation !== null\n ? (details.truncation as Record<string, unknown>)\n : undefined;\n const warnings: string[] = [];\n if (typeof limit === 'number' && limit > 0) warnings.push(`${limit} ${limitUnit} limit`);\n if (truncation?.truncated === true) {\n warnings.push(\n `${formatSize(typeof truncation.maxBytes === 'number' ? truncation.maxBytes : DEFAULT_MAX_BYTES)} limit`,\n );\n }\n return {\n lines,\n hidden: all.length - lines.length,\n truncated: warnings.length > 0 ? `[Truncated: ${warnings.join(', ')}]` : undefined,\n };\n}\n","import type { ToolMessageRenderProps } from '@agimon-ai/po-core/web';\nimport { MessageItemBody, MessageItemStatus } from '@agimon-ai/po-web-components';\n\nimport { listingEntry, listResultView, resultText } from '../_lib/builtinToolView';\n\n/**\n * The body shared by find and ls: Pi's listing lines, collapsed to twenty\n * until the item expands, with the limit warning its details carry. Each line\n * stays on one row: the name leads in full ink and never cuts, its folder\n * follows dimmed and is the part that truncates.\n */\nexport function ListingBody({\n tool,\n limitKey,\n limitUnit,\n expanded,\n props,\n}: {\n tool: string;\n limitKey: string;\n limitUnit: string;\n expanded: boolean;\n props: ToolMessageRenderProps;\n}) {\n const { result, output, running, isError } = props;\n if (isError) {\n return (\n <MessageItemBody data-testid={`tool-result-${tool}`} className=\"flex flex-col\">\n <span className=\"whitespace-pre-wrap break-words text-po-red\">{resultText(result, output)}</span>\n </MessageItemBody>\n );\n }\n if (result === null) {\n return running ? (\n <MessageItemBody data-testid={`tool-result-${tool}`}>\n <MessageItemStatus tone=\"running\">running</MessageItemStatus>\n </MessageItemBody>\n ) : null;\n }\n const view = listResultView(result, output, expanded, limitKey, limitUnit);\n if (view.lines.length === 0 && view.truncated === undefined) return null;\n return (\n <MessageItemBody data-testid={`tool-result-${tool}`} className=\"flex flex-col font-mono\">\n {view.lines.map((line, index) => {\n const entry = listingEntry(line);\n return (\n <span key={`${String(index)}-${line}`} title={line} className=\"flex min-w-0 items-baseline gap-2\">\n <span className=\"max-w-full shrink-0 truncate text-po-text\">{entry.name}</span>\n {entry.folder.length > 0 ? <span className=\"min-w-0 truncate text-po-dim\">{entry.folder}</span> : null}\n </span>\n );\n })}\n {view.hidden > 0 ? <MessageItemStatus expands>{view.hidden} more lines</MessageItemStatus> : null}\n {view.truncated !== undefined ? <span className=\"text-po-yellow\">{view.truncated}</span> : null}\n </MessageItemBody>\n );\n}\n\n/** Whether the listing hides lines while collapsed, so the item can offer its toggle. */\nexport function listingExpandable(props: ToolMessageRenderProps, limitKey: string, limitUnit: string): boolean {\n if (props.result === null || props.isError) return false;\n return listResultView(props.result, props.output, false, limitKey, limitUnit).hidden > 0;\n}\n","import type { ToolMessageRenderProps } from '@agimon-ai/po-core/web';\nimport { MessageItem, MessageItemHeader, toolTone } from '@agimon-ai/po-web-components';\n\nimport { findCallView } from '../_lib/builtinToolView';\nimport { ListingBody } from './ListingBody';\n\nconst LIMIT_KEY = 'resultLimitReached';\nconst LIMIT_UNIT = 'results';\n\n/** The find tool's timeline item: `pattern · path · N results` over Pi's listing lines. */\nexport function FindToolMessage(props: ToolMessageRenderProps) {\n const view = findCallView(props.args);\n return (\n <MessageItem tone={toolTone({ running: props.running, isError: props.isError })} expandable>\n {({ expanded }) => (\n <>\n <MessageItemHeader title=\"find\">\n <span data-testid=\"tool-call-find\" className=\"flex min-w-0 flex-1 items-center gap-2\">\n <span className=\"truncate text-po-text\">{view.primary}</span>\n {view.details.length > 0 ? (\n <span className=\"shrink-0 text-po-faint\">· {view.details.join(' · ')}</span>\n ) : null}\n </span>\n </MessageItemHeader>\n {expanded ? (\n <ListingBody tool=\"find\" limitKey={LIMIT_KEY} limitUnit={LIMIT_UNIT} expanded props={props} />\n ) : null}\n </>\n )}\n </MessageItem>\n );\n}\n","import { defineToolRenderer } from '@agimon-ai/po-core/web';\n\nimport { FindToolMessage } from './_components/FindToolMessage';\n\nexport default defineToolRenderer({ message: FindToolMessage });\n","import type { ToolMessageRenderProps } from '@agimon-ai/po-core/web';\nimport { MessageItem, MessageItemHeader, toolTone } from '@agimon-ai/po-web-components';\n\nimport { lsCallView } from '../_lib/builtinToolView';\nimport { ListingBody } from './ListingBody';\n\nconst LIMIT_KEY = 'entryLimitReached';\nconst LIMIT_UNIT = 'entries';\n\n/** The ls tool's timeline item: `path · N entries` over Pi's listing lines. */\nexport function LsToolMessage(props: ToolMessageRenderProps) {\n const view = lsCallView(props.args);\n return (\n <MessageItem tone={toolTone({ running: props.running, isError: props.isError })} expandable>\n {({ expanded }) => (\n <>\n <MessageItemHeader title=\"ls\">\n <span data-testid=\"tool-call-ls\" className=\"flex min-w-0 flex-1 items-center gap-2\">\n <span className=\"truncate text-po-text\">{view.primary}</span>\n {view.details.length > 0 ? (\n <span className=\"shrink-0 text-po-faint\">· {view.details.join(' · ')}</span>\n ) : null}\n </span>\n </MessageItemHeader>\n {expanded ? (\n <ListingBody tool=\"ls\" limitKey={LIMIT_KEY} limitUnit={LIMIT_UNIT} expanded props={props} />\n ) : null}\n </>\n )}\n </MessageItem>\n );\n}\n","import { defineToolRenderer } from '@agimon-ai/po-core/web';\n\nimport { LsToolMessage } from './_components/LsToolMessage';\n\nexport default defineToolRenderer({ message: LsToolMessage });\n","import type { ToolMessageRenderProps } from '@agimon-ai/po-core/web';\nimport {\n MessageItem,\n MessageItemBody,\n MessageItemHeader,\n MessageItemStatus,\n SyntaxLine,\n ToolPathLink,\n toolTone,\n useSyntaxLines,\n} from '@agimon-ai/po-web-components';\n\nimport { resultText, type WriteCallView, writeCallView } from '../_lib/builtinToolView';\n\n/**\n * The numbered preview, coloured as the file it is about to become.\n *\n * Its own component so the highlighting hook has somewhere to live: the body\n * around it is picked inside a render prop. The preview is a prefix of the\n * content, so it parses as the file it came from up to wherever it was cut.\n */\nfunction WritePreview({ view, path }: { view: WriteCallView; path: string }) {\n const spans = useSyntaxLines(view.preview.map((line) => line.text).join('\\n'), { path });\n return (\n <>\n {view.preview.map((line, index) => (\n <span key={line.number} className=\"flex gap-2\">\n <span className=\"shrink-0 text-right text-po-faint\" style={{ width: `${String(view.gutter)}ch` }}>\n {line.number}\n </span>\n <SyntaxLine\n spans={spans?.[index]}\n text={line.text}\n className=\"min-w-0 whitespace-pre-wrap break-words text-po-text\"\n />\n </span>\n ))}\n </>\n );\n}\n\n/**\n * The write tool's timeline item: `path · N chars` in the header. Pi's write\n * result is silent on success, so expanding shows the numbered file content.\n * A failure shows the tool's message in red instead.\n */\nexport function WriteToolMessage({\n args,\n result,\n output,\n running,\n isError,\n fileTabFor,\n openTransientTab,\n}: ToolMessageRenderProps) {\n const collapsed = writeCallView(args, false);\n // The header names a file the tool is writing, so the reader can open it\n // rather than hunt for it; nothing installed to show files leaves it as text.\n const tab = fileTabFor(collapsed.path);\n return (\n <MessageItem tone={toolTone({ running, isError })} expandable>\n {({ expanded }) => {\n const view = expanded ? writeCallView(args, true) : collapsed;\n return (\n <>\n <MessageItemHeader title=\"write\">\n <span data-testid=\"tool-call-write\" className=\"flex min-w-0 flex-1 items-center gap-2\">\n <ToolPathLink\n path={view.path}\n {...(tab === undefined ? {} : { onOpen: () => openTransientTab(tab) })}\n />\n <span className=\"shrink-0 text-po-faint\">· {view.size}</span>\n </span>\n </MessageItemHeader>\n {!expanded ? null : isError ? (\n <MessageItemBody data-testid=\"tool-result-write\" className=\"flex flex-col\">\n <span className=\"whitespace-pre-wrap break-words text-po-red\">{resultText(result, output)}</span>\n </MessageItemBody>\n ) : view.preview.length === 0 ? (\n running ? (\n <MessageItemBody data-testid=\"tool-result-write\">\n <MessageItemStatus tone=\"running\">running</MessageItemStatus>\n </MessageItemBody>\n ) : null\n ) : (\n <MessageItemBody data-testid=\"tool-result-write\" className=\"flex flex-col font-mono\">\n <WritePreview view={view} path={view.path} />\n {view.hidden > 0 ? <MessageItemStatus expands>{view.hidden} more lines</MessageItemStatus> : null}\n {running ? <MessageItemStatus tone=\"running\">running</MessageItemStatus> : null}\n </MessageItemBody>\n )}\n </>\n );\n }}\n </MessageItem>\n );\n}\n","import { defineToolRenderer } from '@agimon-ai/po-core/web';\n\nimport { WriteToolMessage } from './_components/WriteToolMessage';\n\nexport default defineToolRenderer({ message: WriteToolMessage });\n","// Generated by @agimon-ai/po-build. Do not edit by hand.\nimport { defineWebPlugin, type WebPluginContributions } from '@agimon-ai/po-core/web';\n\nimport toolFind from '../src/extensions/workspaces/sessions/(frontend)/tool/find.web';\nimport toolLs from '../src/extensions/workspaces/sessions/(frontend)/tool/ls.web';\nimport toolWrite from '../src/extensions/workspaces/sessions/(frontend)/tool/write.web';\n\nconst via = <T>(identity: Record<string, unknown>, value: unknown): T =>\n (value === undefined ? undefined : { ...identity, ...(value as object) }) as T;\n\nexport const webPlugin = defineWebPlugin({\n id: 'builtin-tools',\n session: {\n get toolRenderers(): WebPluginContributions['toolRenderers'] { return [via({ tools: ['find'] }, toolFind), via({ tools: ['ls'] }, toolLs), via({ tools: ['write'] }, toolWrite)]; },\n },\n});\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agimon-ai/po-ui",
|
|
3
|
-
"version": "0.0.0-alpha.
|
|
3
|
+
"version": "0.0.0-alpha.75",
|
|
4
4
|
"description": "Leader-key menus, themes, and TUI components for Po and Pi extensions.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"ai",
|
|
@@ -50,6 +50,9 @@
|
|
|
50
50
|
"import": "./dist/extensionName.mjs",
|
|
51
51
|
"require": "./dist/extensionName.cjs"
|
|
52
52
|
},
|
|
53
|
+
"./extensions/native": {
|
|
54
|
+
"import": "./dist/extensions/native.mjs"
|
|
55
|
+
},
|
|
53
56
|
"./extensions/server": {
|
|
54
57
|
"types": "./dist/extensions/server.d.mts",
|
|
55
58
|
"import": "./dist/extensions/server.mjs",
|
|
@@ -110,17 +113,18 @@
|
|
|
110
113
|
"access": "public"
|
|
111
114
|
},
|
|
112
115
|
"dependencies": {
|
|
113
|
-
"@agimon-ai/po-core": "0.0.0-alpha.
|
|
114
|
-
"@agimon-ai/po-hashline": "0.0.0-alpha.
|
|
115
|
-
"@agimon-ai/po-minor-mode": "0.0.0-alpha.
|
|
116
|
-
"@agimon-ai/po-web-components": "0.0.0-alpha.
|
|
116
|
+
"@agimon-ai/po-core": "0.0.0-alpha.75",
|
|
117
|
+
"@agimon-ai/po-hashline": "0.0.0-alpha.75",
|
|
118
|
+
"@agimon-ai/po-minor-mode": "0.0.0-alpha.75",
|
|
119
|
+
"@agimon-ai/po-web-components": "0.0.0-alpha.75",
|
|
117
120
|
"@deepseek-ai/cordis": "4.0.5",
|
|
118
121
|
"yaml": "2.9.1"
|
|
119
122
|
},
|
|
120
123
|
"devDependencies": {
|
|
121
|
-
"@agimon-ai/po-build": "0.0.0-alpha.
|
|
122
|
-
"@agimon-ai/po-core": "0.0.0-alpha.
|
|
123
|
-
"@agimon-ai/po-
|
|
124
|
+
"@agimon-ai/po-build": "0.0.0-alpha.75",
|
|
125
|
+
"@agimon-ai/po-core": "0.0.0-alpha.75",
|
|
126
|
+
"@agimon-ai/po-native-components": "0.0.0-alpha.75",
|
|
127
|
+
"@agimon-ai/po-web-components": "0.0.0-alpha.75",
|
|
124
128
|
"@earendil-works/pi-coding-agent": "1.4.0",
|
|
125
129
|
"@tanstack/react-store": "0.11.2",
|
|
126
130
|
"@tanstack/store": "0.11.2",
|
|
@@ -129,20 +133,35 @@
|
|
|
129
133
|
"@vitest/coverage-v8": "5.0.4",
|
|
130
134
|
"react": "19.3.1",
|
|
131
135
|
"react-dom": "19.3.1",
|
|
136
|
+
"react-native": "0.88.0",
|
|
137
|
+
"react-native-unistyles": "3.5.3",
|
|
138
|
+
"react-native-web": "0.21.4",
|
|
132
139
|
"tsdown": "0.23.1",
|
|
133
140
|
"typescript": "7.0.2",
|
|
134
141
|
"vitest": "5.0.4"
|
|
135
142
|
},
|
|
136
143
|
"peerDependencies": {
|
|
137
|
-
"@agimon-ai/po-core": "0.0.0-alpha.
|
|
138
|
-
"@agimon-ai/po-
|
|
139
|
-
"@
|
|
144
|
+
"@agimon-ai/po-core": "0.0.0-alpha.75",
|
|
145
|
+
"@agimon-ai/po-native-components": "0.0.0-alpha.75",
|
|
146
|
+
"@agimon-ai/po-web-components": "0.0.0-alpha.75",
|
|
147
|
+
"@earendil-works/pi-coding-agent": "1.4.0",
|
|
148
|
+
"react-native": "0.88.0",
|
|
149
|
+
"react-native-unistyles": "^3.5.3"
|
|
140
150
|
},
|
|
141
151
|
"peerDependenciesMeta": {
|
|
152
|
+
"@agimon-ai/po-core": {
|
|
153
|
+
"optional": true
|
|
154
|
+
},
|
|
155
|
+
"@agimon-ai/po-native-components": {
|
|
156
|
+
"optional": true
|
|
157
|
+
},
|
|
142
158
|
"@agimon-ai/po-web-components": {
|
|
143
159
|
"optional": true
|
|
144
160
|
},
|
|
145
|
-
"
|
|
161
|
+
"react-native": {
|
|
162
|
+
"optional": true
|
|
163
|
+
},
|
|
164
|
+
"react-native-unistyles": {
|
|
146
165
|
"optional": true
|
|
147
166
|
}
|
|
148
167
|
},
|
|
@@ -165,6 +184,14 @@
|
|
|
165
184
|
]
|
|
166
185
|
}
|
|
167
186
|
},
|
|
187
|
+
"poNative": {
|
|
188
|
+
"pluginId": "builtin-tools",
|
|
189
|
+
"channels": [],
|
|
190
|
+
"client": "./dist/extensions/native.mjs",
|
|
191
|
+
"scopes": [
|
|
192
|
+
"session"
|
|
193
|
+
]
|
|
194
|
+
},
|
|
168
195
|
"poServer": {
|
|
169
196
|
"entry": "./generated/server.ts",
|
|
170
197
|
"dist": "./dist/extensions/server.mjs",
|
|
@@ -188,7 +215,7 @@
|
|
|
188
215
|
"build": "tsdown && tsdown --config tsdown.mcp.config.ts",
|
|
189
216
|
"build:mcp": "tsdown --config tsdown.mcp.config.ts",
|
|
190
217
|
"test": "vitest --run",
|
|
191
|
-
"typecheck": "tsrs --noEmit && tsrs --noEmit -p tsconfig.web.json && tsrs --noEmit -p tsconfig.mcp.json",
|
|
218
|
+
"typecheck": "tsrs --noEmit && tsrs --noEmit -p tsconfig.web.json && tsrs --noEmit -p tsconfig.native.json && tsrs --noEmit -p tsconfig.mcp.json",
|
|
192
219
|
"lint": "oxlint . && oxfmt . --check",
|
|
193
220
|
"fixcode": "oxlint . --fix && oxfmt ."
|
|
194
221
|
}
|