@parallelworks/ui 0.19.0 → 0.19.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (217) hide show
  1. package/dist/{chunks/memoryStore-CC91S5LP.js → ai/adapter/memoryStore.js} +2 -2
  2. package/dist/ai/adapter/mock/index.js +2 -80
  3. package/dist/ai/adapter/mock/mockAdapter.js +81 -0
  4. package/dist/ai/adapter/openai/createOpenAIStream.js +33 -0
  5. package/dist/ai/adapter/openai/errors.js +37 -0
  6. package/dist/ai/adapter/openai/index.js +5 -333
  7. package/dist/ai/adapter/openai/openaiAdapter.js +54 -0
  8. package/dist/ai/adapter/openai/responses.js +108 -0
  9. package/dist/ai/adapter/openai/sse.js +112 -0
  10. package/dist/{chunks/types-Yy0NrerF.js → ai/adapter/types.js} +1 -1
  11. package/dist/ai/agent/classifier.js +12 -0
  12. package/dist/ai/agent/diff.js +223 -0
  13. package/dist/ai/agent/diffHighlight.js +101 -0
  14. package/dist/ai/agent/permissions.js +29 -0
  15. package/dist/ai/agent/toolfmt.js +383 -0
  16. package/dist/ai/agent/transcript.js +127 -0
  17. package/dist/ai/components/AllocationSelector.js +56 -0
  18. package/dist/ai/components/AttachmentManager.js +144 -0
  19. package/dist/ai/components/AttachmentUpload.js +179 -0
  20. package/dist/ai/components/BlockedGroupBanner.js +29 -0
  21. package/dist/ai/components/BranchNavigator.js +57 -0
  22. package/dist/ai/components/ChatEmptyState.js +171 -0
  23. package/dist/ai/components/ChatInput.js +265 -0
  24. package/dist/ai/components/ChatLayout.js +15 -0
  25. package/dist/ai/components/ChatMessage.js +338 -0
  26. package/dist/ai/components/ChatMessageList.js +301 -0
  27. package/dist/ai/components/ChatSidebar.js +345 -0
  28. package/dist/ai/components/ChatThread.js +198 -0
  29. package/dist/ai/components/ComposerChrome.js +50 -0
  30. package/dist/ai/components/ComposerFrame.js +33 -0
  31. package/dist/ai/components/DragOverlay.js +20 -0
  32. package/dist/ai/components/ModelSelector.js +343 -0
  33. package/dist/ai/components/ShareDialog.js +260 -0
  34. package/dist/ai/components/SlashMenu.js +91 -0
  35. package/dist/ai/components/agent/ActivityLine.js +151 -0
  36. package/dist/ai/components/agent/AgentMessageParts.js +721 -0
  37. package/dist/ai/components/agent/PermissionPicker.js +38 -0
  38. package/dist/ai/components/attachmentKeys.js +10 -0
  39. package/dist/ai/core/ChatProvider.js +848 -0
  40. package/dist/ai/core/KeyboardShortcutsProvider.js +9 -0
  41. package/dist/ai/core/chatReducer.js +223 -0
  42. package/dist/ai/core/config.js +45 -0
  43. package/dist/ai/core/events.js +4 -0
  44. package/dist/ai/core/exportConversation.js +42 -0
  45. package/dist/ai/core/greeting.js +38 -0
  46. package/dist/ai/core/parts.js +84 -0
  47. package/dist/ai/core/useDragDrop.js +36 -0
  48. package/dist/ai/core/useKeyboardShortcuts.js +77 -0
  49. package/dist/ai/core/useSSEStream.js +98 -0
  50. package/dist/ai/index.js +43 -6644
  51. package/dist/ai/strings.js +175 -0
  52. package/dist/ai/ui/Avatar.js +35 -0
  53. package/dist/ai/ui/Dropdown.js +110 -0
  54. package/dist/ai/ui/Markdown.js +79 -0
  55. package/dist/ai/ui/Notice.js +77 -0
  56. package/dist/ai/ui/codeBreaks.js +36 -0
  57. package/dist/ai/ui/prose.js +13 -0
  58. package/dist/ai/ui/sidebar.js +148 -0
  59. package/dist/ai/utils.js +23 -0
  60. package/dist/components/AddMenu.js +46 -0
  61. package/dist/components/Avatar.js +46 -0
  62. package/dist/{chunks/BareModal-BtRiQezg.js → components/BareModal.js} +1 -1
  63. package/dist/components/Breadcrumbs.js +83 -0
  64. package/dist/components/Button.js +83 -0
  65. package/dist/components/Callout.js +23 -0
  66. package/dist/components/Card.js +31 -0
  67. package/dist/components/CollapsiblePanel.js +77 -0
  68. package/dist/{chunks/ConfirmModal-aOR4O1QE.js → components/ConfirmModal.js} +4 -9
  69. package/dist/components/CopyToClipboard.js +81 -0
  70. package/dist/{chunks/Markdown-CM-FenNE.js → components/CreateModal.js} +9 -116
  71. package/dist/components/DescriptionList.js +42 -0
  72. package/dist/components/Dropdown.js +349 -0
  73. package/dist/components/EmptyState.js +27 -0
  74. package/dist/components/Filter.js +32 -0
  75. package/dist/components/FilterPill.js +13 -0
  76. package/dist/components/IconButton.js +34 -0
  77. package/dist/{chunks/Indicator-hBSIxOPK.js → components/Indicator.js} +1 -1
  78. package/dist/components/Input.js +88 -0
  79. package/dist/components/LetterBadge.js +13 -0
  80. package/dist/components/Listbox.js +123 -0
  81. package/dist/{chunks/Loader-BXoXTZGc.js → components/Loader.js} +1 -1
  82. package/dist/components/Markdown.js +15 -0
  83. package/dist/components/MultiSelect.js +171 -0
  84. package/dist/components/Overview.js +39 -0
  85. package/dist/components/PageHeader.js +194 -0
  86. package/dist/components/Pagination.js +35 -0
  87. package/dist/{chunks/Provider-CDYurraE.js → components/Provider.js} +1 -1
  88. package/dist/{chunks/RequiredMark-DfLdYbYZ.js → components/RequiredMark.js} +1 -1
  89. package/dist/components/SectionHeader.js +11 -0
  90. package/dist/components/SettingModeOption.js +30 -0
  91. package/dist/components/SettingRow.js +35 -0
  92. package/dist/components/SettingsCard.js +31 -0
  93. package/dist/components/SettingsGroup.js +17 -0
  94. package/dist/components/Sort.js +42 -0
  95. package/dist/components/StatusBadge.js +63 -0
  96. package/dist/components/SwitchToggle.js +59 -0
  97. package/dist/{chunks/SwitchToggleSmall-FcsaYSTs.js → components/SwitchToggleSmall.js} +1 -1
  98. package/dist/{chunks/Table-DU2MW8xz.js → components/Table.js} +3 -3
  99. package/dist/components/Toggle.js +20 -0
  100. package/dist/{chunks/Tooltip-K5HJr4_p.js → components/Tooltip.js} +2 -27
  101. package/dist/{chunks/StatusBadge-C1Blx_cW.js → components/dropdownUtils.js} +2 -63
  102. package/dist/{chunks/focus-D_iZJTW1.js → components/focus.js} +1 -1
  103. package/dist/components/ghostButton.js +7 -0
  104. package/dist/components/inputClasses.js +4 -0
  105. package/dist/components/keys.js +27 -0
  106. package/dist/components/relativeTime.js +32 -0
  107. package/dist/{chunks/useCssIsDark-DHr05dG2.js → components/useCssIsDark.js} +1 -1
  108. package/dist/{chunks/duration-BOv8Phl8.js → duration.js} +1 -1
  109. package/dist/editor/Editor.js +13 -0
  110. package/dist/editor/EditorField.js +53 -0
  111. package/dist/editor/FormCodePanel.js +173 -0
  112. package/dist/{chunks/Monaco-DJ8MW-Dq.js → editor/Monaco.js} +4 -2
  113. package/dist/editor/index.js +6 -1
  114. package/dist/editor/themes.js +91 -0
  115. package/dist/editor/workers.js +29 -0
  116. package/dist/editor/yaml.js +15 -0
  117. package/dist/file-explorer/FileExplorer.js +1402 -0
  118. package/dist/file-explorer/FileExplorerContext.js +370 -0
  119. package/dist/{chunks/CodePreviewEditor-YqQBz1YL.js → file-explorer/FilePreview/CodePreviewEditor.js} +3 -2
  120. package/dist/file-explorer/FilePreview/Inline.js +45 -0
  121. package/dist/file-explorer/FilePreview/StreamedBadge.js +16 -0
  122. package/dist/file-explorer/FilePreview/Viewer.js +526 -0
  123. package/dist/file-explorer/FilePreview/index.js +266 -0
  124. package/dist/file-explorer/FilePreview/parse.js +63 -0
  125. package/dist/file-explorer/FilePreview/previewCache.js +98 -0
  126. package/dist/file-explorer/FilePreview/previewType.js +151 -0
  127. package/dist/file-explorer/FilePreview/readCappedBytes.js +196 -0
  128. package/dist/file-explorer/FilePreview/useObjectBlobUrl.js +95 -0
  129. package/dist/file-explorer/FilePreview/useObjectText.js +109 -0
  130. package/dist/file-explorer/FilePreview/usePresignedUrl.js +73 -0
  131. package/dist/file-explorer/FileRow.js +165 -0
  132. package/dist/file-explorer/FileRowsWindow.js +92 -0
  133. package/dist/file-explorer/FileTable.js +172 -0
  134. package/dist/file-explorer/FileTableHeaders.js +49 -0
  135. package/dist/file-explorer/LoadMoreRow.js +46 -0
  136. package/dist/file-explorer/TreeView.js +376 -0
  137. package/dist/file-explorer/helpers.js +537 -0
  138. package/dist/file-explorer/index.js +7 -5671
  139. package/dist/file-explorer/lib/batch.js +39 -0
  140. package/dist/file-explorer/lib/errors.js +9 -0
  141. package/dist/file-explorer/lib/paging.js +124 -0
  142. package/dist/file-explorer/lib/utils.js +322 -0
  143. package/dist/file-explorer/toasts.js +400 -0
  144. package/dist/file-explorer/treeRows.js +73 -0
  145. package/dist/file-explorer/useNearEnd.js +27 -0
  146. package/dist/form/FieldWrapper.js +54 -0
  147. package/dist/form/Fields/BooleanField.js +51 -0
  148. package/dist/form/Fields/CheckboxGroupField.js +72 -0
  149. package/dist/form/Fields/ColorField.js +33 -0
  150. package/dist/form/Fields/DropdownField.js +49 -0
  151. package/dist/form/Fields/DurationField.js +130 -0
  152. package/dist/form/Fields/LabelField.js +19 -0
  153. package/dist/form/Fields/MultiDropdownField.js +40 -0
  154. package/dist/form/Fields/NumberField.js +51 -0
  155. package/dist/form/Fields/ObjectField.js +54 -0
  156. package/dist/form/Fields/RadioField.js +49 -0
  157. package/dist/form/Fields/RangeField.js +58 -0
  158. package/dist/form/Fields/ResourceOptionIcon.js +21 -0
  159. package/dist/form/Fields/StepField.js +6 -0
  160. package/dist/form/Fields/StringField.js +37 -0
  161. package/dist/form/Fields/TextAreaField.js +31 -0
  162. package/dist/form/Fields/durationValidity.js +11 -0
  163. package/dist/form/Form.js +643 -0
  164. package/dist/form/SpecialTypes/DropdownWrapper.js +30 -0
  165. package/dist/form/SpecialTypes/FormikCustomDropdown.js +122 -0
  166. package/dist/form/SpecialTypes/FormikCustomInput.js +111 -0
  167. package/dist/form/SpecialTypes/FormikMultiSelectDropdown.js +31 -0
  168. package/dist/form/SpecialTypes/FormikNumericInput.js +60 -0
  169. package/dist/form/Wizard/WizardContainer.js +138 -0
  170. package/dist/form/Wizard/WizardNavigation.js +92 -0
  171. package/dist/form/Wizard/WizardStepContent.js +35 -0
  172. package/dist/form/Wizard/WizardStepIndicator.js +108 -0
  173. package/dist/form/Wizard/useWizardState.js +118 -0
  174. package/dist/form/Wizard/utils.js +34 -0
  175. package/dist/form/fieldContext.js +26 -0
  176. package/dist/form/fieldRegistry.js +50 -0
  177. package/dist/form/index.js +17 -2321
  178. package/dist/{chunks/FieldWrapper-Cszwg-4B.js → form/lib.js} +2 -97
  179. package/dist/form/useParsedOpts.js +62 -0
  180. package/dist/form/usePrevious.js +11 -0
  181. package/dist/form/utils/checkShowIfObject.js +14 -0
  182. package/dist/form/utils/duration.js +69 -0
  183. package/dist/form/utils/getParentValue.js +23 -0
  184. package/dist/form/utils/getPlaceholder.js +9 -0
  185. package/dist/form/utils/getValueUsingPath.js +23 -0
  186. package/dist/form/utils/secondaryField.js +22 -0
  187. package/dist/graph/AnnotationBanner.js +141 -0
  188. package/dist/graph/Collapse.js +41 -0
  189. package/dist/graph/DependencyGraph.js +1398 -0
  190. package/dist/graph/JobSummary.js +104 -0
  191. package/dist/graph/MatrixGroup.js +107 -0
  192. package/dist/graph/Reveal.js +57 -0
  193. package/dist/graph/TreeView.js +711 -0
  194. package/dist/graph/index.js +1 -2519
  195. package/dist/graph/types.js +6 -0
  196. package/dist/index.js +46 -599
  197. package/dist/list/ActionToolbar.js +184 -0
  198. package/dist/list/HoverCard.js +73 -0
  199. package/dist/list/ListPage.js +145 -0
  200. package/dist/list/ListPager.js +59 -0
  201. package/dist/list/ListTable.js +163 -0
  202. package/dist/list/ListViewControls.js +372 -0
  203. package/dist/list/RowContextMenu.js +350 -0
  204. package/dist/list/UserHoverCard.js +117 -0
  205. package/dist/list/index.js +11 -2
  206. package/dist/list/listSearch.js +137 -0
  207. package/dist/list/listView.js +210 -0
  208. package/dist/list/textEntry.js +10 -0
  209. package/dist/{chunks/logviewer-BTKuQWzw.js → logviewer/LogViewer.js} +4 -82
  210. package/dist/logviewer/index.js +2 -1
  211. package/dist/logviewer/segments.js +80 -0
  212. package/package.json +1 -1
  213. package/dist/chunks/PageHeader-0kG_iypP.js +0 -692
  214. package/dist/chunks/SwitchToggle-DShNdcao.js +0 -758
  215. package/dist/chunks/editor-Dk1rbV75.js +0 -361
  216. package/dist/chunks/list-CJm875m7.js +0 -1418
  217. /package/dist/{chunks/MarkdownImpl-CyeTVvSt.js → components/MarkdownImpl.js} +0 -0
@@ -0,0 +1,108 @@
1
+ //#region src/ai/adapter/openai/responses.ts
2
+ function contentString(content) {
3
+ return typeof content === "string" ? content : "";
4
+ }
5
+ function buildResponsesRequestBody(model, messages) {
6
+ const input = [];
7
+ let attachmentIds;
8
+ for (const m of messages) switch (m.role) {
9
+ case "system":
10
+ input.push({
11
+ type: "message",
12
+ role: "system",
13
+ content: contentString(m.content)
14
+ });
15
+ break;
16
+ case "user":
17
+ if (m.attachment_ids?.length) attachmentIds = m.attachment_ids;
18
+ input.push({
19
+ type: "message",
20
+ role: "user",
21
+ content: contentString(m.content)
22
+ });
23
+ break;
24
+ case "assistant": {
25
+ const replayed = Array.isArray(m.responses_output) ? replayableOutput(m.responses_output) : [];
26
+ if (replayed.length > 0) {
27
+ for (const item of replayed) input.push(item);
28
+ break;
29
+ }
30
+ const text = contentString(m.content);
31
+ const toolCalls = m.tool_calls ?? [];
32
+ if (text || toolCalls.length === 0) input.push({
33
+ type: "message",
34
+ role: "assistant",
35
+ content: text
36
+ });
37
+ for (const tc of toolCalls) input.push({
38
+ type: "function_call",
39
+ call_id: tc.id ?? "",
40
+ name: tc.function.name,
41
+ arguments: tc.function.arguments
42
+ });
43
+ break;
44
+ }
45
+ case "tool": input.push({
46
+ type: "function_call_output",
47
+ call_id: m.tool_call_id ?? "",
48
+ output: contentString(m.content)
49
+ });
50
+ }
51
+ const body = {
52
+ model,
53
+ input,
54
+ stream: true,
55
+ store: false,
56
+ include: ["reasoning.encrypted_content"]
57
+ };
58
+ if (attachmentIds?.length) body["attachment_ids"] = attachmentIds;
59
+ return body;
60
+ }
61
+ var REPLAYABLE_ITEM_TYPES = /* @__PURE__ */ new Set([
62
+ "reasoning",
63
+ "message",
64
+ "function_call"
65
+ ]);
66
+ function replayableOutput(output) {
67
+ if (!output?.length) return [];
68
+ return output.filter((item) => {
69
+ if (typeof item !== "object" || item === null) return false;
70
+ const itemType = item.type;
71
+ return typeof itemType === "string" && REPLAYABLE_ITEM_TYPES.has(itemType);
72
+ });
73
+ }
74
+ function parseResponsesSSELine(line) {
75
+ if (!line.startsWith("data: ")) return null;
76
+ const data = line.slice(6);
77
+ if (data === "[DONE]" || data === "\"[DONE]\"") return null;
78
+ let event;
79
+ try {
80
+ event = JSON.parse(data);
81
+ } catch {
82
+ return null;
83
+ }
84
+ if (event.error) return { error: event.error.message || "Unknown error" };
85
+ const model = event.response?.model;
86
+ switch (event.type) {
87
+ case "pw.message_id": return event.messageId ? { messageId: event.messageId } : null;
88
+ case "response.output_text.delta":
89
+ case "response.refusal.delta": return typeof event.delta === "string" ? { content: event.delta } : null;
90
+ case "response.reasoning_summary_text.delta": return typeof event.delta === "string" ? { reasoningContent: event.delta } : null;
91
+ case "response.created": return model ? { model } : null;
92
+ case "response.completed": return {
93
+ ...model && { model },
94
+ finishReason: "stop",
95
+ responsesOutput: replayableOutput(event.response?.output)
96
+ };
97
+ case "response.incomplete": return {
98
+ ...model && { model },
99
+ finishReason: "length",
100
+ responsesOutput: replayableOutput(event.response?.output)
101
+ };
102
+ case "response.failed": return { error: event.response?.error?.message || "Response failed" };
103
+ case "error": return { error: event.message || "Stream error" };
104
+ default: return null;
105
+ }
106
+ }
107
+ //#endregion
108
+ export { buildResponsesRequestBody, parseResponsesSSELine };
@@ -0,0 +1,112 @@
1
+ //#region src/ai/adapter/openai/sse.ts
2
+ function parseSSELine(line) {
3
+ if (!line.startsWith("data: ")) return null;
4
+ const data = line.slice(6);
5
+ if (data === "[DONE]" || data === "\"[DONE]\"") return null;
6
+ try {
7
+ const parsed = JSON.parse(data);
8
+ if (parsed.error) return { error: parsed.error.message || "Unknown error" };
9
+ const chunk = parsed;
10
+ const choice = chunk.choices?.[0];
11
+ return {
12
+ id: chunk.id,
13
+ messageId: chunk.messageId,
14
+ content: choice?.delta?.content,
15
+ reasoningContent: choice?.delta?.reasoning_content,
16
+ toolCalls: choice?.delta?.tool_calls ?? void 0,
17
+ finishReason: choice?.finish_reason,
18
+ model: chunk.model
19
+ };
20
+ } catch {
21
+ return null;
22
+ }
23
+ }
24
+ /** Process an SSE stream from a ReadableStream reader */
25
+ async function processSSEStream(reader, onContent, onToolCall, onError, onReasoning, onMessageId, parseLine = parseSSELine) {
26
+ const decoder = new TextDecoder();
27
+ let assistantContent = "";
28
+ let assistantReasoning = "";
29
+ let assistantMessageId = "";
30
+ let finishReason = null;
31
+ let resolvedModel = null;
32
+ let responsesOutput = [];
33
+ const toolCallsMap = /* @__PURE__ */ new Map();
34
+ let lineBuffer = "";
35
+ while (true) {
36
+ const result = await reader.read();
37
+ if (result.done) break;
38
+ const chunk = decoder.decode(result.value, { stream: true });
39
+ const lines = (lineBuffer + chunk).split("\n");
40
+ lineBuffer = lines.pop() || "";
41
+ for (const line of lines) {
42
+ const parsed = parseLine(line);
43
+ if (parsed) {
44
+ if (parsed.error) {
45
+ onError?.(parsed.error);
46
+ throw new Error(parsed.error);
47
+ }
48
+ if (parsed.messageId && !assistantMessageId) {
49
+ assistantMessageId = parsed.messageId;
50
+ onMessageId?.(parsed.messageId);
51
+ } else if (parsed.id && !assistantMessageId) assistantMessageId = parsed.id;
52
+ if (parsed.model && !resolvedModel) resolvedModel = parsed.model;
53
+ if (parsed.content) {
54
+ assistantContent += parsed.content;
55
+ onContent(parsed.content);
56
+ }
57
+ if (parsed.reasoningContent) {
58
+ assistantReasoning += parsed.reasoningContent;
59
+ onReasoning?.(parsed.reasoningContent);
60
+ }
61
+ if (parsed.finishReason) finishReason = parsed.finishReason;
62
+ if (parsed.responsesOutput?.length) responsesOutput = parsed.responsesOutput;
63
+ if (parsed.toolCalls) for (const tc of parsed.toolCalls) {
64
+ if (tc.index === void 0) continue;
65
+ const existing = toolCallsMap.get(tc.index);
66
+ if (existing) {
67
+ if (tc.function?.arguments) existing.arguments += tc.function.arguments;
68
+ } else toolCallsMap.set(tc.index, {
69
+ id: tc.id || "",
70
+ type: tc.type || "function",
71
+ name: tc.function?.name || "",
72
+ arguments: tc.function?.arguments || ""
73
+ });
74
+ }
75
+ }
76
+ }
77
+ }
78
+ if (lineBuffer.trim()) {
79
+ const parsed = parseLine(lineBuffer);
80
+ if (parsed) {
81
+ if (parsed.content) {
82
+ assistantContent += parsed.content;
83
+ onContent(parsed.content);
84
+ }
85
+ if (parsed.reasoningContent) {
86
+ assistantReasoning += parsed.reasoningContent;
87
+ onReasoning?.(parsed.reasoningContent);
88
+ }
89
+ if (parsed.finishReason) finishReason = parsed.finishReason;
90
+ }
91
+ }
92
+ const toolCalls = Array.from(toolCallsMap.values()).map((tc) => ({
93
+ id: tc.id,
94
+ type: tc.type,
95
+ function: {
96
+ name: tc.name,
97
+ arguments: tc.arguments
98
+ }
99
+ }));
100
+ if (toolCalls.length > 0 && onToolCall) onToolCall(toolCalls);
101
+ return {
102
+ content: assistantContent,
103
+ messageId: assistantMessageId,
104
+ toolCalls,
105
+ finishReason,
106
+ model: resolvedModel,
107
+ reasoning: assistantReasoning,
108
+ responsesOutput
109
+ };
110
+ }
111
+ //#endregion
112
+ export { parseSSELine, processSSEStream };
@@ -8,4 +8,4 @@ var ChatAdapterError = class extends Error {
8
8
  }
9
9
  };
10
10
  //#endregion
11
- export { ChatAdapterError as t };
11
+ export { ChatAdapterError };
@@ -0,0 +1,12 @@
1
+ //#region src/ai/agent/classifier.ts
2
+ var COMPACTION_MARKER = "[Conversation summary from automatic compaction]";
3
+ function classifyPseudoUserMessage(role, content) {
4
+ if (role !== "user" || !content) return null;
5
+ const t = content.trimStart();
6
+ if (t.startsWith("<command-input>")) return "command-input";
7
+ if (t.startsWith("<shell-input>")) return "shell-input";
8
+ if (t.startsWith(COMPACTION_MARKER)) return "compaction";
9
+ return null;
10
+ }
11
+ //#endregion
12
+ export { classifyPseudoUserMessage };
@@ -0,0 +1,223 @@
1
+ import { sanitizeLabel } from "./toolfmt.js";
2
+ //#region src/ai/agent/diff.ts
3
+ var MAX_EDIT_DIFF_LINES = 100;
4
+ var MAX_WRITE_DIFF_LINES = 50;
5
+ function isEditDiffTool(name) {
6
+ return name === "EditFile" || name === "WriteFile";
7
+ }
8
+ function parseEditArgs(argsJSON) {
9
+ try {
10
+ const a = JSON.parse(argsJSON);
11
+ return a && typeof a === "object" ? a : null;
12
+ } catch {
13
+ return null;
14
+ }
15
+ }
16
+ function splitLines(s) {
17
+ const trimmed = s.endsWith("\n") ? s.slice(0, -1) : s;
18
+ return trimmed === "" ? [] : trimmed.split("\n");
19
+ }
20
+ function getOpCodes(a, b) {
21
+ const n = a.length;
22
+ const m = b.length;
23
+ const lcs = Array.from({ length: n + 1 }, () => new Array(m + 1).fill(0));
24
+ for (let i = n - 1; i >= 0; i--) {
25
+ const row = lcs[i];
26
+ const next = lcs[i + 1];
27
+ if (!row || !next) continue;
28
+ for (let j = m - 1; j >= 0; j--) row[j] = a[i] === b[j] ? (next[j + 1] ?? 0) + 1 : Math.max(next[j] ?? 0, row[j + 1] ?? 0);
29
+ }
30
+ const ops = [];
31
+ let i = 0;
32
+ let j = 0;
33
+ const push = (tag, i1, i2, j1, j2) => {
34
+ const last = ops[ops.length - 1];
35
+ if (last && last.tag === tag && last.i2 === i1 && last.j2 === j1) {
36
+ last.i2 = i2;
37
+ last.j2 = j2;
38
+ return;
39
+ }
40
+ ops.push({
41
+ tag,
42
+ i1,
43
+ i2,
44
+ j1,
45
+ j2
46
+ });
47
+ };
48
+ while (i < n && j < m) if (a[i] === b[j]) {
49
+ push("e", i, i + 1, j, j + 1);
50
+ i++;
51
+ j++;
52
+ } else if ((lcs[i + 1]?.[j] ?? 0) >= (lcs[i]?.[j + 1] ?? 0)) {
53
+ push("d", i, i + 1, j, j);
54
+ i++;
55
+ } else {
56
+ push("i", i, i, j, j + 1);
57
+ j++;
58
+ }
59
+ if (i < n) push("d", i, n, j, j);
60
+ if (j < m) push("i", i, i, j, m);
61
+ const merged = [];
62
+ for (const op of ops) {
63
+ const last = merged[merged.length - 1];
64
+ if (last && (last.tag === "d" && op.tag === "i" || last.tag === "i" && op.tag === "d")) {
65
+ merged[merged.length - 1] = {
66
+ tag: "r",
67
+ i1: Math.min(last.i1, op.i1),
68
+ i2: Math.max(last.i2, op.i2),
69
+ j1: Math.min(last.j1, op.j1),
70
+ j2: Math.max(last.j2, op.j2)
71
+ };
72
+ continue;
73
+ }
74
+ merged.push(op);
75
+ }
76
+ return merged;
77
+ }
78
+ function tokenizeWords(line) {
79
+ return line.match(/\w+|\s+|[^\w\s]+/g) ?? [];
80
+ }
81
+ function wordEmphasisRanges(oldLine, newLine) {
82
+ const a = tokenizeWords(oldLine);
83
+ const b = tokenizeWords(newLine);
84
+ if (a.length === 0 || b.length === 0) return null;
85
+ const ops = getOpCodes(a, b);
86
+ if (!ops.some((op) => op.tag === "e" && a.slice(op.i1, op.i2).some((t) => /\w/.test(t)))) return null;
87
+ const starts = [];
88
+ let pos = 0;
89
+ for (const t of b) {
90
+ starts.push(pos);
91
+ pos += t.length;
92
+ }
93
+ starts.push(pos);
94
+ const ranges = [];
95
+ for (const op of ops) {
96
+ if (op.tag !== "i" && op.tag !== "r") continue;
97
+ if (op.j1 >= op.j2) continue;
98
+ const start = starts[op.j1] ?? 0;
99
+ const end = starts[op.j2] ?? pos;
100
+ const last = ranges[ranges.length - 1];
101
+ if (last && last[1] === start) last[1] = end;
102
+ else ranges.push([start, end]);
103
+ }
104
+ return ranges.length > 0 ? ranges : null;
105
+ }
106
+ function lineDelta(oldLines, newLines) {
107
+ let added = 0;
108
+ let removed = 0;
109
+ for (const op of getOpCodes(oldLines, newLines)) {
110
+ if (op.tag === "d" || op.tag === "r") removed += op.i2 - op.i1;
111
+ if (op.tag === "i" || op.tag === "r") added += op.j2 - op.j1;
112
+ }
113
+ return [added, removed];
114
+ }
115
+ function computeEditDiff(oldString, newString, startLine = 0) {
116
+ const oldLines = splitLines(oldString);
117
+ const newLines = splitLines(newString);
118
+ const [added, removed] = lineDelta(oldLines, newLines);
119
+ const ops = getOpCodes(oldLines, newLines);
120
+ const numbered = startLine > 0;
121
+ const rows = [];
122
+ let truncated = false;
123
+ const push = (row) => {
124
+ if (rows.length >= 100) {
125
+ truncated = true;
126
+ return false;
127
+ }
128
+ rows.push(row);
129
+ return true;
130
+ };
131
+ outer: for (let k = 0; k < ops.length; k++) {
132
+ const op = ops[k];
133
+ if (!op) continue;
134
+ if (op.tag === "e") {
135
+ const len = op.i2 - op.i1;
136
+ const leading = k > 0 ? Math.min(3, len) : 0;
137
+ const trailing = k < ops.length - 1 ? Math.min(3, len) : 0;
138
+ const showAll = len <= leading + trailing;
139
+ const emit = (offset) => {
140
+ const oldNo = op.i1 + offset + 1;
141
+ const newNo = op.j1 + offset + 1;
142
+ return push({
143
+ kind: "ctx",
144
+ text: oldLines[op.i1 + offset] ?? "",
145
+ ...numbered ? {
146
+ oldNo: startLine + oldNo - 1,
147
+ newNo: startLine + newNo - 1
148
+ } : {}
149
+ });
150
+ };
151
+ if (showAll) {
152
+ for (let x = 0; x < len; x++) if (!emit(x)) break outer;
153
+ } else {
154
+ for (let x = 0; x < leading; x++) if (!emit(x)) break outer;
155
+ if (!push({
156
+ kind: "gap",
157
+ text: ""
158
+ })) break;
159
+ for (let x = len - trailing; x < len; x++) if (!emit(x)) break outer;
160
+ }
161
+ continue;
162
+ }
163
+ if (op.tag === "d" || op.tag === "r") {
164
+ for (let x = op.i1; x < op.i2; x++) if (!push({
165
+ kind: "del",
166
+ text: oldLines[x] ?? "",
167
+ ...numbered ? { oldNo: startLine + x } : {}
168
+ })) break outer;
169
+ }
170
+ if (op.tag === "i" || op.tag === "r") {
171
+ const paired = op.tag === "r" ? Math.min(op.i2 - op.i1, op.j2 - op.j1) : 0;
172
+ for (let x = op.j1; x < op.j2; x++) {
173
+ const k = x - op.j1;
174
+ const emphasis = k < paired ? wordEmphasisRanges(oldLines[op.i1 + k] ?? "", newLines[x] ?? "") : null;
175
+ if (!push({
176
+ kind: "add",
177
+ text: newLines[x] ?? "",
178
+ ...numbered ? { newNo: startLine + x } : {},
179
+ ...emphasis ? { emphasis } : {}
180
+ })) break outer;
181
+ }
182
+ }
183
+ }
184
+ return {
185
+ rows,
186
+ added,
187
+ removed,
188
+ truncated
189
+ };
190
+ }
191
+ function computeWriteRows(content) {
192
+ const lines = splitLines(content);
193
+ return {
194
+ rows: lines.slice(0, 50).map((text, i) => ({
195
+ kind: "ctx",
196
+ newNo: i + 1,
197
+ text
198
+ })),
199
+ total: lines.length,
200
+ truncated: lines.length > 50
201
+ };
202
+ }
203
+ function editSummary(toolName, argsJSON) {
204
+ const a = parseEditArgs(argsJSON);
205
+ if (!a) return "";
206
+ const count = (n) => `${n} ${n === 1 ? "line" : "lines"}`;
207
+ if (toolName === "EditFile") {
208
+ const [added, removed] = lineDelta(splitLines(a.old_string ?? ""), splitLines(a.new_string ?? ""));
209
+ if (added > 0 && removed > 0) return `Added ${count(added)}, removed ${count(removed)}`;
210
+ if (added > 0) return `Added ${count(added)}`;
211
+ if (removed > 0) return `Removed ${count(removed)}`;
212
+ return "";
213
+ }
214
+ if (toolName === "WriteFile") {
215
+ if (a.content === void 0) return "";
216
+ let s = `Wrote ${count(splitLines(a.content).length)}`;
217
+ if (a.path) s += ` to ${sanitizeLabel(a.path)}`;
218
+ return s;
219
+ }
220
+ return "";
221
+ }
222
+ //#endregion
223
+ export { MAX_EDIT_DIFF_LINES, MAX_WRITE_DIFF_LINES, computeEditDiff, computeWriteRows, editSummary, isEditDiffTool, lineDelta, parseEditArgs, wordEmphasisRanges };
@@ -0,0 +1,101 @@
1
+ //#region src/ai/agent/diffHighlight.ts
2
+ var EXT_LANG = {
3
+ ts: "typescript",
4
+ tsx: "tsx",
5
+ mts: "typescript",
6
+ cts: "typescript",
7
+ js: "javascript",
8
+ jsx: "jsx",
9
+ mjs: "javascript",
10
+ cjs: "javascript",
11
+ go: "go",
12
+ py: "python",
13
+ rb: "ruby",
14
+ rs: "rust",
15
+ java: "java",
16
+ c: "c",
17
+ h: "c",
18
+ cc: "cpp",
19
+ cpp: "cpp",
20
+ hpp: "cpp",
21
+ cs: "csharp",
22
+ php: "php",
23
+ swift: "swift",
24
+ kt: "kotlin",
25
+ scala: "scala",
26
+ sh: "shellscript",
27
+ bash: "shellscript",
28
+ zsh: "shellscript",
29
+ fish: "fish",
30
+ ps1: "powershell",
31
+ sql: "sql",
32
+ json: "json",
33
+ jsonc: "jsonc",
34
+ yaml: "yaml",
35
+ yml: "yaml",
36
+ toml: "toml",
37
+ xml: "xml",
38
+ html: "html",
39
+ css: "css",
40
+ scss: "scss",
41
+ less: "less",
42
+ md: "markdown",
43
+ mdx: "mdx",
44
+ vue: "vue",
45
+ svelte: "svelte",
46
+ tf: "terraform",
47
+ hcl: "hcl",
48
+ proto: "proto",
49
+ graphql: "graphql",
50
+ gql: "graphql",
51
+ dockerfile: "dockerfile",
52
+ lua: "lua",
53
+ r: "r",
54
+ pl: "perl",
55
+ ex: "elixir",
56
+ exs: "elixir",
57
+ zig: "zig"
58
+ };
59
+ function languageForPath(path) {
60
+ if (!path) return null;
61
+ const base = path.split("/").pop() ?? "";
62
+ if (base.toLowerCase() === "dockerfile") return "dockerfile";
63
+ const dot = base.lastIndexOf(".");
64
+ if (dot <= 0) return null;
65
+ return EXT_LANG[base.slice(dot + 1).toLowerCase()] ?? null;
66
+ }
67
+ var highlighters = /* @__PURE__ */ new Map();
68
+ function getHighlighter(lang) {
69
+ let p = highlighters.get(lang);
70
+ if (!p) {
71
+ p = (async () => {
72
+ const [{ createHighlighter }, { createJavaScriptRegexEngine }] = await Promise.all([import("shiki"), import("shiki/engine/javascript")]);
73
+ return await createHighlighter({
74
+ langs: [lang],
75
+ themes: ["github-light", "github-dark"],
76
+ engine: createJavaScriptRegexEngine({ forgiving: true })
77
+ });
78
+ })().catch(() => null);
79
+ highlighters.set(lang, p);
80
+ }
81
+ return p;
82
+ }
83
+ async function tokenizeDiffLines(lines, lang, isDark) {
84
+ const highlighter = await getHighlighter(lang);
85
+ if (!highlighter) return null;
86
+ try {
87
+ const tokens = highlighter.codeToTokensBase(lines.join("\n"), {
88
+ lang,
89
+ theme: isDark ? "github-dark" : "github-light"
90
+ });
91
+ if (tokens.length !== lines.length) return null;
92
+ return tokens.map((line) => line.map((t) => ({
93
+ content: t.content,
94
+ ...t.color ? { color: t.color } : {}
95
+ })));
96
+ } catch {
97
+ return null;
98
+ }
99
+ }
100
+ //#endregion
101
+ export { languageForPath, tokenizeDiffLines };
@@ -0,0 +1,29 @@
1
+ //#region src/ai/agent/permissions.ts
2
+ var REQUESTABLE_PERMISSION_MODES = [
3
+ "read-only",
4
+ "accept-edits",
5
+ "bypass-permissions"
6
+ ];
7
+ var NAMED_PERMISSION_MODES = [...REQUESTABLE_PERMISSION_MODES, "plan"];
8
+ var DEFAULT_PERMISSION_MODE = "accept-edits";
9
+ var PERMISSION_RANK = {
10
+ "read-only": 0,
11
+ plan: 1,
12
+ "accept-edits": 2,
13
+ "bypass-permissions": 3
14
+ };
15
+ function isNamedPermissionMode(mode) {
16
+ return NAMED_PERMISSION_MODES.some((m) => m === mode);
17
+ }
18
+ /** The daemon clamps a remote request to its owner's remoteMaxPermissionMode,
19
+ * so a menu offers only what that machine will honour. */
20
+ function permissionModesUpTo(ceiling) {
21
+ const max = isNamedPermissionMode(ceiling) ? PERMISSION_RANK[ceiling] : PERMISSION_RANK[DEFAULT_PERMISSION_MODE];
22
+ return REQUESTABLE_PERMISSION_MODES.filter((m) => PERMISSION_RANK[m] <= max);
23
+ }
24
+ function clampPermissionMode(mode, ceiling) {
25
+ const offered = permissionModesUpTo(ceiling);
26
+ return offered.includes(mode) ? mode : offered[offered.length - 1] ?? "read-only";
27
+ }
28
+ //#endregion
29
+ export { DEFAULT_PERMISSION_MODE, NAMED_PERMISSION_MODES, clampPermissionMode, isNamedPermissionMode, permissionModesUpTo };