@parallelworks/ui 0.18.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.
- package/README.md +86 -6
- package/dist/ai/adapter/memoryStore.d.ts +8 -0
- package/dist/ai/adapter/memoryStore.js +152 -0
- package/dist/ai/adapter/mock/index.d.ts +2 -0
- package/dist/ai/adapter/mock/index.js +3 -0
- package/dist/ai/adapter/mock/mockAdapter.d.ts +4 -0
- package/dist/ai/adapter/mock/mockAdapter.js +81 -0
- package/dist/ai/adapter/openai/createOpenAIStream.d.ts +9 -0
- package/dist/ai/adapter/openai/createOpenAIStream.js +33 -0
- package/dist/ai/adapter/openai/errors.d.ts +3 -0
- package/dist/ai/adapter/openai/errors.js +37 -0
- package/dist/ai/adapter/openai/index.d.ts +6 -0
- package/dist/ai/adapter/openai/index.js +6 -0
- package/dist/ai/adapter/openai/openaiAdapter.d.ts +9 -0
- package/dist/ai/adapter/openai/openaiAdapter.js +54 -0
- package/dist/ai/adapter/openai/responses.d.ts +4 -0
- package/dist/ai/adapter/openai/responses.js +108 -0
- package/dist/ai/adapter/openai/sse.d.ts +24 -0
- package/dist/ai/adapter/openai/sse.js +112 -0
- package/dist/ai/adapter/openai/wire.d.ts +40 -0
- package/dist/ai/adapter/types.d.ts +131 -0
- package/dist/ai/adapter/types.js +11 -0
- package/dist/ai/agent/classifier.d.ts +2 -0
- package/dist/ai/agent/classifier.js +12 -0
- package/dist/ai/agent/diff.d.ts +35 -0
- package/dist/ai/agent/diff.js +223 -0
- package/dist/ai/agent/diffHighlight.d.ts +6 -0
- package/dist/ai/agent/diffHighlight.js +101 -0
- package/dist/ai/agent/index.d.ts +6 -0
- package/dist/ai/agent/permissions.d.ts +11 -0
- package/dist/ai/agent/permissions.js +29 -0
- package/dist/ai/agent/toolfmt.d.ts +18 -0
- package/dist/ai/agent/toolfmt.js +383 -0
- package/dist/ai/agent/transcript.d.ts +38 -0
- package/dist/ai/agent/transcript.js +127 -0
- package/dist/ai/ai.css +325 -0
- package/dist/ai/components/AllocationSelector.d.ts +4 -0
- package/dist/ai/components/AllocationSelector.js +56 -0
- package/dist/ai/components/AttachmentManager.d.ts +1 -0
- package/dist/ai/components/AttachmentManager.js +144 -0
- package/dist/ai/components/AttachmentUpload.d.ts +24 -0
- package/dist/ai/components/AttachmentUpload.js +179 -0
- package/dist/ai/components/BlockedGroupBanner.d.ts +1 -0
- package/dist/ai/components/BlockedGroupBanner.js +29 -0
- package/dist/ai/components/BranchNavigator.d.ts +8 -0
- package/dist/ai/components/BranchNavigator.js +57 -0
- package/dist/ai/components/ChatEmptyState.d.ts +3 -0
- package/dist/ai/components/ChatEmptyState.js +171 -0
- package/dist/ai/components/ChatInput.d.ts +45 -0
- package/dist/ai/components/ChatInput.js +265 -0
- package/dist/ai/components/ChatLayout.d.ts +5 -0
- package/dist/ai/components/ChatLayout.js +15 -0
- package/dist/ai/components/ChatMessage.d.ts +24 -0
- package/dist/ai/components/ChatMessage.js +338 -0
- package/dist/ai/components/ChatMessageList.d.ts +35 -0
- package/dist/ai/components/ChatMessageList.js +301 -0
- package/dist/ai/components/ChatSidebar.d.ts +5 -0
- package/dist/ai/components/ChatSidebar.js +345 -0
- package/dist/ai/components/ChatThread.d.ts +3 -0
- package/dist/ai/components/ChatThread.js +198 -0
- package/dist/ai/components/ComposerChrome.d.ts +18 -0
- package/dist/ai/components/ComposerChrome.js +50 -0
- package/dist/ai/components/ComposerFrame.d.ts +16 -0
- package/dist/ai/components/ComposerFrame.js +33 -0
- package/dist/ai/components/DragOverlay.d.ts +5 -0
- package/dist/ai/components/DragOverlay.js +20 -0
- package/dist/ai/components/ModelSelector.d.ts +6 -0
- package/dist/ai/components/ModelSelector.js +343 -0
- package/dist/ai/components/ShareDialog.d.ts +11 -0
- package/dist/ai/components/ShareDialog.js +260 -0
- package/dist/ai/components/SlashMenu.d.ts +28 -0
- package/dist/ai/components/SlashMenu.js +91 -0
- package/dist/ai/components/agent/ActivityLine.d.ts +21 -0
- package/dist/ai/components/agent/ActivityLine.js +151 -0
- package/dist/ai/components/agent/AgentMessageParts.d.ts +54 -0
- package/dist/ai/components/agent/AgentMessageParts.js +721 -0
- package/dist/ai/components/agent/PermissionPicker.d.ts +11 -0
- package/dist/ai/components/agent/PermissionPicker.js +38 -0
- package/dist/ai/components/attachmentKeys.d.ts +4 -0
- package/dist/ai/components/attachmentKeys.js +10 -0
- package/dist/ai/core/ChatProvider.d.ts +66 -0
- package/dist/ai/core/ChatProvider.js +848 -0
- package/dist/ai/core/KeyboardShortcutsProvider.d.ts +5 -0
- package/dist/ai/core/KeyboardShortcutsProvider.js +9 -0
- package/dist/ai/core/chatReducer.d.ts +114 -0
- package/dist/ai/core/chatReducer.js +223 -0
- package/dist/ai/core/config.d.ts +47 -0
- package/dist/ai/core/config.js +45 -0
- package/dist/ai/core/events.d.ts +1 -0
- package/dist/ai/core/events.js +4 -0
- package/dist/ai/core/exportConversation.d.ts +4 -0
- package/dist/ai/core/exportConversation.js +42 -0
- package/dist/ai/core/greeting.d.ts +3 -0
- package/dist/ai/core/greeting.js +38 -0
- package/dist/ai/core/parts.d.ts +11 -0
- package/dist/ai/core/parts.js +84 -0
- package/dist/ai/core/useDragDrop.d.ts +14 -0
- package/dist/ai/core/useDragDrop.js +36 -0
- package/dist/ai/core/useKeyboardShortcuts.d.ts +12 -0
- package/dist/ai/core/useKeyboardShortcuts.js +77 -0
- package/dist/ai/core/useSSEStream.d.ts +34 -0
- package/dist/ai/core/useSSEStream.js +98 -0
- package/dist/ai/index.d.ts +40 -0
- package/dist/ai/index.js +44 -0
- package/dist/ai/strings.d.ts +167 -0
- package/dist/ai/strings.js +175 -0
- package/dist/ai/types.d.ts +236 -0
- package/dist/ai/ui/Avatar.d.ts +8 -0
- package/dist/ai/ui/Avatar.js +35 -0
- package/dist/ai/ui/Dropdown.d.ts +31 -0
- package/dist/ai/ui/Dropdown.js +110 -0
- package/dist/ai/ui/Markdown.d.ts +8 -0
- package/dist/ai/ui/Markdown.js +79 -0
- package/dist/ai/ui/Notice.d.ts +21 -0
- package/dist/ai/ui/Notice.js +77 -0
- package/dist/ai/ui/buttons.d.ts +1 -0
- package/dist/ai/ui/codeBreaks.d.ts +16 -0
- package/dist/ai/ui/codeBreaks.js +36 -0
- package/dist/ai/ui/prose.d.ts +1 -0
- package/dist/ai/ui/prose.js +13 -0
- package/dist/ai/ui/sidebar.d.ts +81 -0
- package/dist/ai/ui/sidebar.js +148 -0
- package/dist/ai/utils.d.ts +4 -0
- package/dist/ai/utils.js +23 -0
- package/dist/assets/{editor.worker-CuBRIwi-.js → editor.worker-BmHUIVG4.js} +194 -163
- package/dist/assets/{json.worker-8ytS02vz.js → json.worker-D8bJ92nw.js} +384 -338
- package/dist/assets/{yaml.worker-DJC-VUcv.js → yaml.worker-C4gyGAko.js} +15657 -13823
- package/dist/components/AddMenu.js +46 -0
- package/dist/components/Avatar.d.ts +1 -1
- package/dist/components/Avatar.js +46 -0
- package/dist/{chunks/BareModal-BtRiQezg.js → components/BareModal.js} +1 -1
- package/dist/components/Breadcrumbs.d.ts +1 -1
- package/dist/components/Breadcrumbs.js +83 -0
- package/dist/components/Button.js +83 -0
- package/dist/components/Callout.js +23 -0
- package/dist/components/Card.js +31 -0
- package/dist/components/CollapsiblePanel.js +77 -0
- package/dist/components/ConfirmModal.js +74 -0
- package/dist/components/CopyToClipboard.js +81 -0
- package/dist/{chunks/CreateModal-BY6DLmur.js → components/CreateModal.js} +10 -189
- package/dist/components/DescriptionList.js +42 -0
- package/dist/components/Dropdown.d.ts +1 -1
- package/dist/components/Dropdown.js +349 -0
- package/dist/components/EmptyState.d.ts +1 -1
- package/dist/components/EmptyState.js +27 -0
- package/dist/components/Filter.js +32 -0
- package/dist/components/FilterPill.js +13 -0
- package/dist/components/IconButton.js +34 -0
- package/dist/components/Indicator.d.ts +2 -2
- package/dist/{chunks/Indicator-hBSIxOPK.js → components/Indicator.js} +1 -1
- package/dist/components/Input.d.ts +1 -1
- package/dist/components/Input.js +88 -0
- package/dist/components/LetterBadge.d.ts +1 -1
- package/dist/components/LetterBadge.js +13 -0
- package/dist/components/Listbox.js +123 -0
- package/dist/{chunks/Loader-BXoXTZGc.js → components/Loader.js} +1 -1
- package/dist/components/Markdown.js +15 -0
- package/dist/components/MarkdownImpl.d.ts +1 -1
- package/dist/components/MultiSelect.js +171 -0
- package/dist/components/Overview.js +39 -0
- package/dist/components/PageHeader.js +194 -0
- package/dist/components/Pagination.js +35 -0
- package/dist/components/Provider.d.ts +16 -65
- package/dist/{chunks/Provider-Ghua9PkN.js → components/Provider.js} +54 -20
- package/dist/{chunks/RequiredMark-DfLdYbYZ.js → components/RequiredMark.js} +1 -1
- package/dist/components/SectionHeader.js +11 -0
- package/dist/components/SettingModeOption.js +30 -0
- package/dist/components/SettingRow.d.ts +1 -1
- package/dist/components/SettingRow.js +35 -0
- package/dist/components/SettingsCard.js +31 -0
- package/dist/components/SettingsGroup.d.ts +1 -1
- package/dist/components/SettingsGroup.js +17 -0
- package/dist/components/Sort.js +42 -0
- package/dist/components/StatusBadge.js +63 -0
- package/dist/components/SwitchToggle.js +59 -0
- package/dist/{chunks/SwitchToggleSmall-FcsaYSTs.js → components/SwitchToggleSmall.js} +1 -1
- package/dist/{chunks/Table-4OHjdKdO.js → components/Table.js} +7 -5
- package/dist/components/Toggle.js +20 -0
- package/dist/{chunks/Tooltip-Crxo_eU_.js → components/Tooltip.js} +6 -4
- package/dist/{chunks/StatusBadge-C1Blx_cW.js → components/dropdownUtils.js} +2 -63
- package/dist/components/focus.d.ts +2 -0
- package/dist/components/focus.js +7 -0
- package/dist/components/ghostButton.js +7 -0
- package/dist/components/inputClasses.js +4 -0
- package/dist/components/keys.d.ts +12 -0
- package/dist/components/keys.js +27 -0
- package/dist/components/relativeTime.js +32 -0
- package/dist/{chunks/useCssIsDark-DHr05dG2.js → components/useCssIsDark.js} +1 -1
- package/dist/duration.d.ts +3 -0
- package/dist/duration.js +17 -0
- package/dist/editor/Editor.js +13 -0
- package/dist/editor/EditorField.js +53 -0
- package/dist/editor/FormCodePanel.js +173 -0
- package/dist/editor/Monaco.d.ts +1 -20
- package/dist/editor/Monaco.js +112 -0
- package/dist/editor/index.d.ts +2 -1
- package/dist/editor/index.js +7 -2
- package/dist/editor/themes.js +91 -0
- package/dist/editor/workers.js +29 -0
- package/dist/editor/yaml.d.ts +5 -0
- package/dist/editor/yaml.js +15 -0
- package/dist/engine.d.ts +98 -0
- package/dist/file-explorer/FileExplorer.d.ts +11 -2
- package/dist/file-explorer/FileExplorer.js +1402 -0
- package/dist/file-explorer/FileExplorerContext.d.ts +1 -1
- package/dist/file-explorer/FileExplorerContext.js +370 -0
- package/dist/file-explorer/FilePreview/CodePreviewEditor.d.ts +1 -1
- package/dist/{chunks/CodePreviewEditor-4lx3kE-w.js → file-explorer/FilePreview/CodePreviewEditor.js} +3 -2
- package/dist/file-explorer/FilePreview/Inline.js +45 -0
- package/dist/file-explorer/FilePreview/StreamedBadge.js +16 -0
- package/dist/file-explorer/FilePreview/Viewer.js +526 -0
- package/dist/file-explorer/FilePreview/index.js +266 -0
- package/dist/file-explorer/FilePreview/parse.js +63 -0
- package/dist/file-explorer/FilePreview/previewCache.js +98 -0
- package/dist/file-explorer/FilePreview/previewType.d.ts +1 -1
- package/dist/file-explorer/FilePreview/previewType.js +151 -0
- package/dist/file-explorer/FilePreview/readCappedBytes.js +196 -0
- package/dist/file-explorer/FilePreview/useObjectBlobUrl.js +95 -0
- package/dist/file-explorer/FilePreview/useObjectText.js +109 -0
- package/dist/file-explorer/FilePreview/usePresignedUrl.js +73 -0
- package/dist/file-explorer/FileRow.d.ts +1 -1
- package/dist/file-explorer/FileRow.js +165 -0
- package/dist/file-explorer/FileRowsWindow.js +92 -0
- package/dist/file-explorer/FileTable.js +172 -0
- package/dist/file-explorer/FileTableHeaders.js +49 -0
- package/dist/file-explorer/LoadMoreRow.js +46 -0
- package/dist/file-explorer/TreeView.js +376 -0
- package/dist/file-explorer/helpers.d.ts +4 -4
- package/dist/file-explorer/helpers.js +537 -0
- package/dist/file-explorer/index.d.ts +3 -3
- package/dist/file-explorer/index.js +7 -5705
- package/dist/file-explorer/lib/batch.js +39 -0
- package/dist/file-explorer/lib/errors.js +9 -0
- package/dist/file-explorer/lib/paging.js +124 -0
- package/dist/file-explorer/lib/types.d.ts +6 -1
- package/dist/file-explorer/lib/utils.d.ts +1 -3
- package/dist/file-explorer/lib/utils.js +322 -0
- package/dist/file-explorer/toasts.js +400 -0
- package/dist/file-explorer/treeRows.js +73 -0
- package/dist/file-explorer/useNearEnd.d.ts +1 -1
- package/dist/file-explorer/useNearEnd.js +27 -0
- package/dist/form/FieldWrapper.d.ts +2 -2
- package/dist/form/FieldWrapper.js +54 -0
- package/dist/form/Fields/BooleanField.js +51 -0
- package/dist/form/Fields/CheckboxGroupField.js +72 -0
- package/dist/form/Fields/ColorField.js +33 -0
- package/dist/form/Fields/DropdownField.js +49 -0
- package/dist/form/Fields/DurationField.js +130 -0
- package/dist/form/Fields/LabelField.js +19 -0
- package/dist/form/Fields/MultiDropdownField.js +40 -0
- package/dist/form/Fields/NumberField.js +51 -0
- package/dist/form/Fields/ObjectField.js +54 -0
- package/dist/form/Fields/RadioField.js +49 -0
- package/dist/form/Fields/RangeField.js +58 -0
- package/dist/form/Fields/ResourceOptionIcon.d.ts +1 -1
- package/dist/form/Fields/ResourceOptionIcon.js +21 -0
- package/dist/form/Fields/StepField.js +6 -0
- package/dist/form/Fields/StringField.js +37 -0
- package/dist/form/Fields/TextAreaField.js +31 -0
- package/dist/form/Fields/durationValidity.js +11 -0
- package/dist/form/Form.d.ts +4 -21
- package/dist/form/Form.js +643 -0
- package/dist/form/SpecialTypes/DropdownWrapper.js +30 -0
- package/dist/form/SpecialTypes/FormikCustomDropdown.js +122 -0
- package/dist/form/SpecialTypes/FormikCustomInput.js +111 -0
- package/dist/form/SpecialTypes/FormikMultiSelectDropdown.js +31 -0
- package/dist/form/SpecialTypes/FormikNumericInput.js +60 -0
- package/dist/form/Wizard/WizardContainer.js +138 -0
- package/dist/form/Wizard/WizardNavigation.js +92 -0
- package/dist/form/Wizard/WizardStepContent.js +35 -0
- package/dist/form/Wizard/WizardStepIndicator.js +108 -0
- package/dist/form/Wizard/useWizardState.js +118 -0
- package/dist/form/Wizard/utils.js +34 -0
- package/dist/form/fieldContext.js +26 -0
- package/dist/form/fieldRegistry.js +50 -0
- package/dist/form/index.d.ts +11 -12
- package/dist/form/index.js +18 -2445
- package/dist/form/lib.d.ts +6 -1
- package/dist/{chunks/FieldWrapper-Bef01EWO.js → form/lib.js} +5 -104
- package/dist/form/types/fieldComponentTypes.d.ts +3 -2
- package/dist/form/types/fieldTypes.d.ts +6 -20
- package/dist/form/useParsedOpts.d.ts +1 -1
- package/dist/form/useParsedOpts.js +62 -0
- package/dist/form/usePrevious.js +11 -0
- package/dist/form/utils/checkShowIfObject.js +14 -0
- package/dist/form/utils/{slurmDuration.d.ts → duration.d.ts} +2 -2
- package/dist/form/utils/duration.js +69 -0
- package/dist/form/utils/getParentValue.js +23 -0
- package/dist/form/utils/getPlaceholder.js +9 -0
- package/dist/form/utils/getValueUsingPath.js +23 -0
- package/dist/form/utils/secondaryField.js +22 -0
- package/dist/graph/AnnotationBanner.js +141 -0
- package/dist/graph/Collapse.js +41 -0
- package/dist/{workflow/index.js → graph/DependencyGraph.js} +76 -1163
- package/dist/graph/JobSummary.js +104 -0
- package/dist/{workflow → graph}/MatrixGroup.d.ts +2 -2
- package/dist/graph/MatrixGroup.js +107 -0
- package/dist/graph/Reveal.js +57 -0
- package/dist/graph/TreeView.js +711 -0
- package/dist/{workflow → graph}/index.d.ts +1 -1
- package/dist/graph/index.js +2 -0
- package/dist/{workflow → graph}/types.d.ts +3 -3
- package/dist/graph/types.js +6 -0
- package/dist/icons.d.ts +20 -21
- package/dist/index.d.ts +38 -40
- package/dist/index.js +47 -599
- package/dist/list/ActionToolbar.js +184 -0
- package/dist/list/HoverCard.js +73 -0
- package/dist/list/ListPage.js +145 -0
- package/dist/list/ListPager.js +59 -0
- package/dist/list/ListTable.d.ts +1 -1
- package/dist/list/ListTable.js +163 -0
- package/dist/list/ListViewControls.d.ts +2 -2
- package/dist/list/ListViewControls.js +372 -0
- package/dist/list/RowContextMenu.js +350 -0
- package/dist/list/UserHoverCard.js +117 -0
- package/dist/list/index.d.ts +9 -9
- package/dist/list/index.js +11 -2
- package/dist/list/listSearch.js +137 -0
- package/dist/list/listView.js +210 -0
- package/dist/list/textEntry.js +10 -0
- package/dist/logviewer/LogViewer.d.ts +1 -1
- package/dist/logviewer/LogViewer.js +750 -0
- package/dist/logviewer/index.d.ts +1 -0
- package/dist/logviewer/index.js +3 -742
- package/dist/logviewer/segments.d.ts +9 -0
- package/dist/logviewer/segments.js +80 -0
- package/dist/styles/fonts.css +4 -4
- package/dist/styles/theme.css +6 -4
- package/dist/styles.css +1 -1
- package/dist/theme/index.js +2 -2
- package/package.json +38 -14
- package/LICENSE +0 -202
- package/dist/chunks/Monaco-C1POOdVv.js +0 -1046
- package/dist/chunks/PageHeader-l49p1nM9.js +0 -690
- package/dist/chunks/SwitchToggle-CHPP8uZQ.js +0 -755
- package/dist/chunks/editor-9_uVtUyy.js +0 -347
- package/dist/chunks/list-qrojZZNv.js +0 -1411
- package/dist/editor/usesGitlab.d.ts +0 -97
- package/dist/form/Fields/BucketReadOnlyField.d.ts +0 -7
- package/dist/form/types/workflow-schema.d.ts +0 -1145
- package/dist/form/utils/pwResolver.d.ts +0 -18
- package/dist/{chunks/MarkdownImpl-Bq4QhrtA.js → components/MarkdownImpl.js} +1 -1
- /package/dist/{workflow → graph}/AnnotationBanner.d.ts +0 -0
- /package/dist/{workflow → graph}/Collapse.d.ts +0 -0
- /package/dist/{workflow → graph}/DependencyGraph.d.ts +0 -0
- /package/dist/{workflow → graph}/JobSummary.d.ts +0 -0
- /package/dist/{workflow → graph}/Reveal.d.ts +0 -0
- /package/dist/{workflow → graph}/TreeView.d.ts +0 -0
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
declare const REQUESTABLE_PERMISSION_MODES: readonly ['read-only', 'accept-edits', 'bypass-permissions'];
|
|
2
|
+
export declare const NAMED_PERMISSION_MODES: readonly ["read-only", "accept-edits", "bypass-permissions", "plan"];
|
|
3
|
+
export type PermissionMode = (typeof REQUESTABLE_PERMISSION_MODES)[number];
|
|
4
|
+
export type NamedPermissionMode = (typeof NAMED_PERMISSION_MODES)[number];
|
|
5
|
+
export declare const DEFAULT_PERMISSION_MODE: PermissionMode;
|
|
6
|
+
export declare function isNamedPermissionMode(mode: string | undefined): mode is NamedPermissionMode;
|
|
7
|
+
/** The daemon clamps a remote request to its owner's remoteMaxPermissionMode,
|
|
8
|
+
* so a menu offers only what that machine will honour. */
|
|
9
|
+
export declare function permissionModesUpTo(ceiling: string | undefined): PermissionMode[];
|
|
10
|
+
export declare function clampPermissionMode(mode: PermissionMode, ceiling: string | undefined): PermissionMode;
|
|
11
|
+
export {};
|
|
@@ -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 };
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export interface ToolHeader {
|
|
2
|
+
label: string;
|
|
3
|
+
arg?: string;
|
|
4
|
+
}
|
|
5
|
+
export declare function toolHeaderFor(name: string): ToolHeader;
|
|
6
|
+
export declare function clip(s: string, max: number): string;
|
|
7
|
+
export declare function sanitizeLabel(s: string): string;
|
|
8
|
+
export declare function sanitizePanelText(s: string): string;
|
|
9
|
+
export declare function summarizeToolArgs(primary: string | undefined, argsJSON: string): string;
|
|
10
|
+
export declare function fullToolArgs(primary: string | undefined, argsJSON: string): string;
|
|
11
|
+
export declare function plural(n: number, noun: string): string;
|
|
12
|
+
export declare function resultFailed(name: string, result: string): boolean;
|
|
13
|
+
export declare function bashExitCode(body: string): [string, number, boolean];
|
|
14
|
+
export declare function toolSummary(name: string, args: string, result: string, isError: boolean, editSummaryFn?: (toolName: string, argsJSON: string) => string): string;
|
|
15
|
+
export declare function isGroupableTool(name: string): boolean;
|
|
16
|
+
export declare function rollupSentence(names: string[]): string;
|
|
17
|
+
export declare const AGENT_COLOR_NAMES: readonly ['blue', 'green', 'yellow', 'purple', 'cyan', 'orange', 'pink', 'red'];
|
|
18
|
+
export declare function agentColorHex(name: string | undefined): string | null;
|
|
@@ -0,0 +1,383 @@
|
|
|
1
|
+
//#region src/ai/agent/toolfmt.ts
|
|
2
|
+
var TOOL_HEADERS = {
|
|
3
|
+
Bash: {
|
|
4
|
+
label: "Bash",
|
|
5
|
+
arg: "command"
|
|
6
|
+
},
|
|
7
|
+
ReadFile: {
|
|
8
|
+
label: "Read",
|
|
9
|
+
arg: "path"
|
|
10
|
+
},
|
|
11
|
+
WriteFile: {
|
|
12
|
+
label: "Write",
|
|
13
|
+
arg: "path"
|
|
14
|
+
},
|
|
15
|
+
EditFile: {
|
|
16
|
+
label: "Update",
|
|
17
|
+
arg: "path"
|
|
18
|
+
},
|
|
19
|
+
GlobSearch: {
|
|
20
|
+
label: "Glob",
|
|
21
|
+
arg: "pattern"
|
|
22
|
+
},
|
|
23
|
+
GrepSearch: {
|
|
24
|
+
label: "Grep",
|
|
25
|
+
arg: "pattern"
|
|
26
|
+
},
|
|
27
|
+
WebFetch: {
|
|
28
|
+
label: "WebFetch",
|
|
29
|
+
arg: "url"
|
|
30
|
+
},
|
|
31
|
+
Task: {
|
|
32
|
+
label: "Task",
|
|
33
|
+
arg: "description"
|
|
34
|
+
},
|
|
35
|
+
Skill: {
|
|
36
|
+
label: "Skill",
|
|
37
|
+
arg: "name"
|
|
38
|
+
},
|
|
39
|
+
SendMessage: {
|
|
40
|
+
label: "SendMessage",
|
|
41
|
+
arg: "to"
|
|
42
|
+
},
|
|
43
|
+
AskUserQuestion: {
|
|
44
|
+
label: "AskUserQuestion",
|
|
45
|
+
arg: "question"
|
|
46
|
+
},
|
|
47
|
+
TodoWrite: { label: "TodoWrite" }
|
|
48
|
+
};
|
|
49
|
+
function toolHeaderFor(name) {
|
|
50
|
+
return TOOL_HEADERS[name] ?? { label: name };
|
|
51
|
+
}
|
|
52
|
+
function clip(s, max) {
|
|
53
|
+
const r = [...s];
|
|
54
|
+
if (r.length <= max) return s;
|
|
55
|
+
if (max <= 3) return r.slice(0, max).join("");
|
|
56
|
+
return r.slice(0, max - 3).join("") + "...";
|
|
57
|
+
}
|
|
58
|
+
function sanitizeLabel(s) {
|
|
59
|
+
let out = "";
|
|
60
|
+
for (const ch of s) {
|
|
61
|
+
const c = ch.codePointAt(0) ?? 0;
|
|
62
|
+
if (ch === "\n" || ch === " ") out += " ";
|
|
63
|
+
else if (c < 32 || c === 127) {} else out += ch;
|
|
64
|
+
}
|
|
65
|
+
return out;
|
|
66
|
+
}
|
|
67
|
+
function sanitizePanelText(s) {
|
|
68
|
+
let out = "";
|
|
69
|
+
for (const ch of s) {
|
|
70
|
+
const c = ch.codePointAt(0) ?? 0;
|
|
71
|
+
if (ch === " ") out += " ";
|
|
72
|
+
else if (ch === "\n") out += ch;
|
|
73
|
+
else if (c < 32 || c === 127) {} else out += ch;
|
|
74
|
+
}
|
|
75
|
+
return out;
|
|
76
|
+
}
|
|
77
|
+
var SALIENT_ARG_ORDER = [
|
|
78
|
+
"command",
|
|
79
|
+
"pattern",
|
|
80
|
+
"path",
|
|
81
|
+
"file_path",
|
|
82
|
+
"glob",
|
|
83
|
+
"url",
|
|
84
|
+
"query",
|
|
85
|
+
"output_mode",
|
|
86
|
+
"question",
|
|
87
|
+
"header"
|
|
88
|
+
];
|
|
89
|
+
var ELIDED_ARGS = /* @__PURE__ */ new Set([
|
|
90
|
+
"content",
|
|
91
|
+
"new_string",
|
|
92
|
+
"old_string",
|
|
93
|
+
"edits",
|
|
94
|
+
"options"
|
|
95
|
+
]);
|
|
96
|
+
function clipArg(s, style) {
|
|
97
|
+
const flat = s.replaceAll("\n", " ");
|
|
98
|
+
if (style.valueClip <= 0) return flat;
|
|
99
|
+
return clip(flat, style.valueClip);
|
|
100
|
+
}
|
|
101
|
+
function displayArg(v, style) {
|
|
102
|
+
return sanitizeLabel(clipArg((typeof v === "string" ? v : JSON.stringify(v)) ?? "", style));
|
|
103
|
+
}
|
|
104
|
+
function formatToolArgs(primary, argsJSON, style) {
|
|
105
|
+
let m;
|
|
106
|
+
try {
|
|
107
|
+
m = JSON.parse(argsJSON);
|
|
108
|
+
} catch {
|
|
109
|
+
return "";
|
|
110
|
+
}
|
|
111
|
+
if (!m || typeof m !== "object" || Object.keys(m).length === 0) return "";
|
|
112
|
+
const seen = /* @__PURE__ */ new Set();
|
|
113
|
+
const parts = [];
|
|
114
|
+
const add = (k) => {
|
|
115
|
+
if (!(k in m) || seen.has(k)) return;
|
|
116
|
+
seen.add(k);
|
|
117
|
+
const v = m[k];
|
|
118
|
+
const rendered = typeof v === "string" ? `${k}: "${clipArg(sanitizeLabel(v), style)}"` : `${k}: ${displayArg(v, style)}`;
|
|
119
|
+
parts.push(rendered);
|
|
120
|
+
};
|
|
121
|
+
if (primary && primary in m) {
|
|
122
|
+
seen.add(primary);
|
|
123
|
+
parts.push(displayArg(m[primary], style));
|
|
124
|
+
}
|
|
125
|
+
for (const k of SALIENT_ARG_ORDER) add(k);
|
|
126
|
+
const rest = Object.keys(m).filter((k) => !ELIDED_ARGS.has(k) && !seen.has(k)).sort();
|
|
127
|
+
for (const k of rest) add(k);
|
|
128
|
+
const joined = parts.join(", ");
|
|
129
|
+
if (style.totalClip <= 0) return joined;
|
|
130
|
+
return clip(joined, style.totalClip);
|
|
131
|
+
}
|
|
132
|
+
function summarizeToolArgs(primary, argsJSON) {
|
|
133
|
+
return formatToolArgs(primary, argsJSON, {
|
|
134
|
+
valueClip: 50,
|
|
135
|
+
totalClip: 100
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
function fullToolArgs(primary, argsJSON) {
|
|
139
|
+
return formatToolArgs(primary, argsJSON, {
|
|
140
|
+
valueClip: 0,
|
|
141
|
+
totalClip: 0
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
function plural(n, noun) {
|
|
145
|
+
return `${n} ${pluralNoun(n, noun)}`;
|
|
146
|
+
}
|
|
147
|
+
function pluralNoun(n, noun) {
|
|
148
|
+
if (n === 1) return noun;
|
|
149
|
+
if (/(?:s|x|ch|sh)$/.test(noun)) return `${noun}es`;
|
|
150
|
+
return `${noun}s`;
|
|
151
|
+
}
|
|
152
|
+
var TOOL_OUTPUT_TRUNCATION_MARKER = "\n\n... output truncated to ";
|
|
153
|
+
function trimToolOutputNotice(body) {
|
|
154
|
+
const i = body.lastIndexOf(TOOL_OUTPUT_TRUNCATION_MARKER);
|
|
155
|
+
if (i >= 0) return [body.slice(0, i).replace(/\n+$/, ""), true];
|
|
156
|
+
return [body, false];
|
|
157
|
+
}
|
|
158
|
+
function summarizeToolResult(result) {
|
|
159
|
+
const trimmed = result.replace(/\n+$/, "");
|
|
160
|
+
if (trimmed.trim() === "") return "(no output)";
|
|
161
|
+
const lines = trimmed.split("\n");
|
|
162
|
+
const first = clip((lines[0] ?? "").trim(), 100);
|
|
163
|
+
if (lines.length > 1) return `${first} (+${lines.length - 1} lines)`;
|
|
164
|
+
return first;
|
|
165
|
+
}
|
|
166
|
+
function isErrorResult(text) {
|
|
167
|
+
return text.trim().startsWith("Error:");
|
|
168
|
+
}
|
|
169
|
+
var RIPGREP_ERROR_PREFIX = "ripgrep error (exit ";
|
|
170
|
+
function resultFailed(name, result) {
|
|
171
|
+
const body = result.trim();
|
|
172
|
+
switch (name) {
|
|
173
|
+
case "Bash":
|
|
174
|
+
if (bashExitCode(body)[2]) return true;
|
|
175
|
+
return isErrorResult(body) && !body.includes("\n");
|
|
176
|
+
case "WebFetch": return webFetchFailed(body);
|
|
177
|
+
case "GrepSearch": return body.startsWith(RIPGREP_ERROR_PREFIX) || isErrorResult(body);
|
|
178
|
+
default: return isErrorResult(body);
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
function webFetchFailed(body) {
|
|
182
|
+
if (body.startsWith("Error ")) return true;
|
|
183
|
+
const m = body.match(/^HTTP (\d+)/);
|
|
184
|
+
if (m) return Number(m[1]) >= 400;
|
|
185
|
+
return false;
|
|
186
|
+
}
|
|
187
|
+
function trailingNote(body) {
|
|
188
|
+
const i = body.lastIndexOf("\n");
|
|
189
|
+
const last = body.slice(i + 1);
|
|
190
|
+
if (last.startsWith("... (")) return [body.slice(0, Math.max(i, 0)), last];
|
|
191
|
+
return [body, ""];
|
|
192
|
+
}
|
|
193
|
+
function contentLines(body) {
|
|
194
|
+
const [rest, note] = trailingNote(body);
|
|
195
|
+
if (rest === "") return [[], note];
|
|
196
|
+
return [rest.split("\n"), note];
|
|
197
|
+
}
|
|
198
|
+
function readFileSummary(body) {
|
|
199
|
+
if (body === "(empty file)") return "Empty file";
|
|
200
|
+
if (body.startsWith("Read image ")) return "Read image";
|
|
201
|
+
const [lines, note] = contentLines(body);
|
|
202
|
+
let more = 0;
|
|
203
|
+
const m = note.match(/^\.\.\. \(truncated, (\d+) more lines\)/);
|
|
204
|
+
if (m) more = Number(m[1]);
|
|
205
|
+
if (more > 0) return `Read ${plural(lines.length, "line")} (${more} more)`;
|
|
206
|
+
return `Read ${plural(lines.length, "line")}`;
|
|
207
|
+
}
|
|
208
|
+
var GREP_CONTENT_PATH = /^(.+?):\d+:/;
|
|
209
|
+
function grepMatchPath(line, lineNums) {
|
|
210
|
+
if (!lineNums) {
|
|
211
|
+
const i = line.indexOf(":");
|
|
212
|
+
return i >= 0 ? line.slice(0, i) : null;
|
|
213
|
+
}
|
|
214
|
+
const m = GREP_CONTENT_PATH.exec(line);
|
|
215
|
+
return m ? m[1] ?? null : null;
|
|
216
|
+
}
|
|
217
|
+
function grepSearchSummary(argsJSON, body) {
|
|
218
|
+
if (body === "No matches found." || body === "No results after applying offset.") return "No matches";
|
|
219
|
+
if (body.startsWith(RIPGREP_ERROR_PREFIX)) return summarizeToolResult(body);
|
|
220
|
+
const [lines, note] = contentLines(body);
|
|
221
|
+
let outputMode = "";
|
|
222
|
+
let lineNums = true;
|
|
223
|
+
try {
|
|
224
|
+
const a = JSON.parse(argsJSON);
|
|
225
|
+
outputMode = a.output_mode ?? "";
|
|
226
|
+
if (typeof a.n === "boolean") lineNums = a.n;
|
|
227
|
+
} catch {}
|
|
228
|
+
let s;
|
|
229
|
+
if (outputMode === "content") {
|
|
230
|
+
const files = /* @__PURE__ */ new Set();
|
|
231
|
+
let matches = 0;
|
|
232
|
+
for (const l of lines) {
|
|
233
|
+
const path = grepMatchPath(l, lineNums);
|
|
234
|
+
if (path === null) continue;
|
|
235
|
+
matches++;
|
|
236
|
+
files.add(path);
|
|
237
|
+
}
|
|
238
|
+
s = `Found ${plural(matches, "match")} in ${plural(files.size, "file")}`;
|
|
239
|
+
} else if (outputMode === "count") {
|
|
240
|
+
let total = 0;
|
|
241
|
+
for (const l of lines) {
|
|
242
|
+
const i = l.lastIndexOf(":");
|
|
243
|
+
const tail = i >= 0 ? l.slice(i + 1) : l;
|
|
244
|
+
const n = Number.parseInt(tail, 10);
|
|
245
|
+
if (!Number.isNaN(n)) total += n;
|
|
246
|
+
}
|
|
247
|
+
s = `Found ${plural(total, "match")} in ${plural(lines.length, "file")}`;
|
|
248
|
+
} else s = `Found ${plural(lines.length, "file")}`;
|
|
249
|
+
if (note !== "") s += " (truncated)";
|
|
250
|
+
return s;
|
|
251
|
+
}
|
|
252
|
+
function globSearchSummary(body) {
|
|
253
|
+
if (body === "No files matched the pattern.") return "No files matched";
|
|
254
|
+
const [lines, note] = contentLines(body);
|
|
255
|
+
let s = `Found ${plural(lines.length, "file")}`;
|
|
256
|
+
if (note !== "") s += " (truncated)";
|
|
257
|
+
return s;
|
|
258
|
+
}
|
|
259
|
+
function bashExitCode(body) {
|
|
260
|
+
let i = body.lastIndexOf("\nExit code: ");
|
|
261
|
+
if (i < 0) {
|
|
262
|
+
if (!body.startsWith("Exit code: ")) return [
|
|
263
|
+
body,
|
|
264
|
+
0,
|
|
265
|
+
false
|
|
266
|
+
];
|
|
267
|
+
i = 0;
|
|
268
|
+
}
|
|
269
|
+
const m = body.slice(i).replace(/^\n/, "").match(/^Exit code: (\d+)/);
|
|
270
|
+
const code = m ? Number(m[1]) : 0;
|
|
271
|
+
return [
|
|
272
|
+
body.slice(0, i).replace(/\n+$/, ""),
|
|
273
|
+
code,
|
|
274
|
+
true
|
|
275
|
+
];
|
|
276
|
+
}
|
|
277
|
+
function bashSummary(body) {
|
|
278
|
+
if (body === "(no output)") return "(no output)";
|
|
279
|
+
const [out, code, ok] = bashExitCode(body);
|
|
280
|
+
if (!ok) return summarizeToolResult(body);
|
|
281
|
+
if (out === "") return `Exit ${code}`;
|
|
282
|
+
return `Exit ${code} · ${plural(out.split("\n").length, "line")}`;
|
|
283
|
+
}
|
|
284
|
+
function webFetchSummary(body) {
|
|
285
|
+
const m = body.match(/^HTTP (\d+)/);
|
|
286
|
+
if (!m) return summarizeToolResult(body);
|
|
287
|
+
const status = Number(m[1]);
|
|
288
|
+
const sep = body.indexOf("\n\n");
|
|
289
|
+
if (sep < 0) return clip(body.split("\n")[0] ?? "", 100);
|
|
290
|
+
return `HTTP ${status} · ${plural(body.slice(sep + 2).split("\n").length, "line")}`;
|
|
291
|
+
}
|
|
292
|
+
function toolSummary(name, args, result, isError, editSummaryFn) {
|
|
293
|
+
const [body, spilled] = trimToolOutputNotice(result.replace(/\n+$/, ""));
|
|
294
|
+
if (isError || body.trim() === "" || isErrorResult(body)) return summarizeToolResult(result);
|
|
295
|
+
let s;
|
|
296
|
+
switch (name) {
|
|
297
|
+
case "EditFile":
|
|
298
|
+
case "WriteFile": {
|
|
299
|
+
const e = editSummaryFn?.(name, args) ?? "";
|
|
300
|
+
return e !== "" ? e : summarizeToolResult(result);
|
|
301
|
+
}
|
|
302
|
+
case "ReadFile":
|
|
303
|
+
s = readFileSummary(body);
|
|
304
|
+
break;
|
|
305
|
+
case "GrepSearch":
|
|
306
|
+
s = grepSearchSummary(args, body);
|
|
307
|
+
break;
|
|
308
|
+
case "GlobSearch":
|
|
309
|
+
s = globSearchSummary(body);
|
|
310
|
+
break;
|
|
311
|
+
case "Bash":
|
|
312
|
+
s = bashSummary(body);
|
|
313
|
+
break;
|
|
314
|
+
case "WebFetch":
|
|
315
|
+
s = webFetchSummary(body);
|
|
316
|
+
break;
|
|
317
|
+
default: return summarizeToolResult(result);
|
|
318
|
+
}
|
|
319
|
+
if (spilled) s += " (output truncated)";
|
|
320
|
+
return s;
|
|
321
|
+
}
|
|
322
|
+
var ROLLUP_CATEGORIES = [
|
|
323
|
+
[(n) => n === "GrepSearch" || n === "GlobSearch", (n) => `searched for ${plural(n, "pattern")}`],
|
|
324
|
+
[(n) => n === "ReadFile", (n) => `read ${plural(n, "file")}`],
|
|
325
|
+
[(n) => n === "Bash", (n) => `ran ${plural(n, "shell command")}`],
|
|
326
|
+
[(n) => n === "WebFetch", (n) => `fetched ${plural(n, "URL")}`],
|
|
327
|
+
[(n) => n === "Skill", (n) => `loaded ${plural(n, "skill")}`],
|
|
328
|
+
[(n) => n === "SendMessage", (n) => `sent ${plural(n, "message")}`],
|
|
329
|
+
[(n) => n.startsWith("mcp__"), (n) => `called ${plural(n, "MCP tool")}`],
|
|
330
|
+
[() => true, (n) => `ran ${plural(n, "tool")}`]
|
|
331
|
+
];
|
|
332
|
+
var NON_GROUPABLE_TOOLS = /* @__PURE__ */ new Set([
|
|
333
|
+
"EditFile",
|
|
334
|
+
"WriteFile",
|
|
335
|
+
"TodoWrite",
|
|
336
|
+
"Task"
|
|
337
|
+
]);
|
|
338
|
+
function isGroupableTool(name) {
|
|
339
|
+
return !NON_GROUPABLE_TOOLS.has(name);
|
|
340
|
+
}
|
|
341
|
+
function rollupSentence(names) {
|
|
342
|
+
const counts = ROLLUP_CATEGORIES.map(() => 0);
|
|
343
|
+
for (const name of names) for (let i = 0; i < ROLLUP_CATEGORIES.length; i++) if (ROLLUP_CATEGORIES[i]?.[0](name)) {
|
|
344
|
+
counts[i] = (counts[i] ?? 0) + 1;
|
|
345
|
+
break;
|
|
346
|
+
}
|
|
347
|
+
const parts = [];
|
|
348
|
+
for (let i = 0; i < counts.length; i++) {
|
|
349
|
+
const n = counts[i] ?? 0;
|
|
350
|
+
if (n > 0) {
|
|
351
|
+
const cat = ROLLUP_CATEGORIES[i];
|
|
352
|
+
if (cat) parts.push(cat[1](n));
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
if (parts.length === 0) return "";
|
|
356
|
+
const s = parts.join(", ");
|
|
357
|
+
return s.charAt(0).toUpperCase() + s.slice(1);
|
|
358
|
+
}
|
|
359
|
+
var AGENT_COLOR_NAMES = [
|
|
360
|
+
"blue",
|
|
361
|
+
"green",
|
|
362
|
+
"yellow",
|
|
363
|
+
"purple",
|
|
364
|
+
"cyan",
|
|
365
|
+
"orange",
|
|
366
|
+
"pink",
|
|
367
|
+
"red"
|
|
368
|
+
];
|
|
369
|
+
var AGENT_COLOR_HEX = {
|
|
370
|
+
red: "#ef4444",
|
|
371
|
+
blue: "#3b82f6",
|
|
372
|
+
green: "#22c55e",
|
|
373
|
+
yellow: "#eab308",
|
|
374
|
+
purple: "#a855f7",
|
|
375
|
+
orange: "#f97316",
|
|
376
|
+
pink: "#ec4899",
|
|
377
|
+
cyan: "#06b6d4"
|
|
378
|
+
};
|
|
379
|
+
function agentColorHex(name) {
|
|
380
|
+
return name ? AGENT_COLOR_HEX[name] ?? null : null;
|
|
381
|
+
}
|
|
382
|
+
//#endregion
|
|
383
|
+
export { AGENT_COLOR_NAMES, agentColorHex, bashExitCode, clip, fullToolArgs, isGroupableTool, plural, resultFailed, rollupSentence, sanitizeLabel, sanitizePanelText, summarizeToolArgs, toolHeaderFor, toolSummary };
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
export declare function hiddenTranscriptTool(name: string): boolean;
|
|
2
|
+
export declare function askQuestionFromArgs(argsJSON: string): string;
|
|
3
|
+
export declare function planFromArgs(argsJSON: string): string;
|
|
4
|
+
/** A Task call's display label the way the tool itself picks it: the
|
|
5
|
+
* description, else the clipped prompt, plus its custom agent type. */
|
|
6
|
+
export declare function taskCallFromArgs(argsJSON: string): {
|
|
7
|
+
description: string;
|
|
8
|
+
agentType: string;
|
|
9
|
+
};
|
|
10
|
+
/** The built-in "default" type is the same general-purpose agent an untyped
|
|
11
|
+
* Task spawns, so naming it would only add noise. */
|
|
12
|
+
export declare function agentTypeLabel(t: string): string;
|
|
13
|
+
/** The first line when the model wrote it as a heading ("# Title" or
|
|
14
|
+
* "**Title**"), the way reasoning summaries open, so a folded thought says
|
|
15
|
+
* what it was about. Prose gets no label of its own. */
|
|
16
|
+
export declare function thinkingHeading(raw: string): string;
|
|
17
|
+
/** How a turn cut short reads, whether replayed or watched live. */
|
|
18
|
+
export declare const INTERRUPTED_NOTICE: string;
|
|
19
|
+
/** The line the daemon files as the assistant's when a turn is cut short;
|
|
20
|
+
* it is a status, not something the model said. */
|
|
21
|
+
export declare function interruptionNotice(text: string): string | null;
|
|
22
|
+
export declare function firstNonEmptyLine(text: string, max: number): string;
|
|
23
|
+
export interface SubagentNotice {
|
|
24
|
+
id: string;
|
|
25
|
+
description: string;
|
|
26
|
+
preview: string;
|
|
27
|
+
/** The report itself, without the closing line addressed to the model. */
|
|
28
|
+
body: string;
|
|
29
|
+
interim: boolean;
|
|
30
|
+
/** The interrupted form is written for the model alone; the child's own
|
|
31
|
+
* block already reads interrupted, so no line is drawn for it. */
|
|
32
|
+
silent: boolean;
|
|
33
|
+
}
|
|
34
|
+
/** Reads a "[Background subagent <id> (<desc>) completed]" header; null for
|
|
35
|
+
* any other notice, which keeps its full text. */
|
|
36
|
+
export declare function parseSubagentNotice(text: string): SubagentNotice | null;
|
|
37
|
+
/** The line that marks a child's report entering the main conversation. */
|
|
38
|
+
export declare function subagentDeliveryLine(n: SubagentNotice): string;
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
import { clip, sanitizeLabel } from "./toolfmt.js";
|
|
2
|
+
//#region src/ai/agent/transcript.ts
|
|
3
|
+
var HIDDEN_TRANSCRIPT_TOOLS = /* @__PURE__ */ new Set([
|
|
4
|
+
"AskUserQuestion",
|
|
5
|
+
"TodoWrite",
|
|
6
|
+
"ExitPlanMode"
|
|
7
|
+
]);
|
|
8
|
+
function hiddenTranscriptTool(name) {
|
|
9
|
+
return HIDDEN_TRANSCRIPT_TOOLS.has(name);
|
|
10
|
+
}
|
|
11
|
+
function parseArgs(argsJSON) {
|
|
12
|
+
try {
|
|
13
|
+
const parsed = JSON.parse(argsJSON);
|
|
14
|
+
return parsed && typeof parsed === "object" ? parsed : {};
|
|
15
|
+
} catch {
|
|
16
|
+
return {};
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
function str(v) {
|
|
20
|
+
return typeof v === "string" ? v : "";
|
|
21
|
+
}
|
|
22
|
+
function askQuestionFromArgs(argsJSON) {
|
|
23
|
+
return str(parseArgs(argsJSON)["question"]);
|
|
24
|
+
}
|
|
25
|
+
function planFromArgs(argsJSON) {
|
|
26
|
+
return str(parseArgs(argsJSON)["plan"]);
|
|
27
|
+
}
|
|
28
|
+
/** A Task call's display label the way the tool itself picks it: the
|
|
29
|
+
* description, else the clipped prompt, plus its custom agent type. */
|
|
30
|
+
function taskCallFromArgs(argsJSON) {
|
|
31
|
+
const a = parseArgs(argsJSON);
|
|
32
|
+
const description = str(a["description"]) || clip(str(a["prompt"]), 40);
|
|
33
|
+
return {
|
|
34
|
+
description: sanitizeLabel(description),
|
|
35
|
+
agentType: agentTypeLabel(str(a["subagent_type"]))
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
/** The built-in "default" type is the same general-purpose agent an untyped
|
|
39
|
+
* Task spawns, so naming it would only add noise. */
|
|
40
|
+
function agentTypeLabel(t) {
|
|
41
|
+
return t === "default" ? "" : sanitizeLabel(t);
|
|
42
|
+
}
|
|
43
|
+
/** The first line when the model wrote it as a heading ("# Title" or
|
|
44
|
+
* "**Title**"), the way reasoning summaries open, so a folded thought says
|
|
45
|
+
* what it was about. Prose gets no label of its own. */
|
|
46
|
+
function thinkingHeading(raw) {
|
|
47
|
+
const first = raw.trim().split("\n")[0]?.trim() ?? "";
|
|
48
|
+
let line;
|
|
49
|
+
if (first.startsWith("#")) line = first.replace(/^#+/, "").trim();
|
|
50
|
+
else if (first.length > 4 && first.startsWith("**") && first.endsWith("**")) line = first.slice(2, -2).trim();
|
|
51
|
+
else return "";
|
|
52
|
+
return clip(sanitizeLabel(line), 60);
|
|
53
|
+
}
|
|
54
|
+
var INTERRUPTED_MARKER = "[Request interrupted by the user.]";
|
|
55
|
+
/** How a turn cut short reads, whether replayed or watched live. */
|
|
56
|
+
var INTERRUPTED_NOTICE = INTERRUPTED_MARKER.slice(1, -1);
|
|
57
|
+
/** The line the daemon files as the assistant's when a turn is cut short;
|
|
58
|
+
* it is a status, not something the model said. */
|
|
59
|
+
function interruptionNotice(text) {
|
|
60
|
+
return text.trim() === INTERRUPTED_MARKER ? INTERRUPTED_NOTICE : null;
|
|
61
|
+
}
|
|
62
|
+
function firstNonEmptyLine(text, max) {
|
|
63
|
+
for (const line of text.split("\n")) {
|
|
64
|
+
const s = line.trim();
|
|
65
|
+
if (s !== "") return clip(s, max);
|
|
66
|
+
}
|
|
67
|
+
return "";
|
|
68
|
+
}
|
|
69
|
+
var SUBAGENT_NOTICE_HEADS = /* @__PURE__ */ new Set(["Background subagent", "Message from subagent"]);
|
|
70
|
+
/** Reads a "[Background subagent <id> (<desc>) completed]" header; null for
|
|
71
|
+
* any other notice, which keeps its full text. */
|
|
72
|
+
function parseSubagentNotice(text) {
|
|
73
|
+
const trimmed = text.trim();
|
|
74
|
+
const nl = trimmed.indexOf("\n");
|
|
75
|
+
let head = nl === -1 ? trimmed : trimmed.slice(0, nl);
|
|
76
|
+
let body = nl === -1 ? "" : trimmed.slice(nl + 1);
|
|
77
|
+
if (!head.startsWith("[") || !head.endsWith("]")) return null;
|
|
78
|
+
head = head.slice(1, -1);
|
|
79
|
+
let shell = false;
|
|
80
|
+
let kind;
|
|
81
|
+
let rest;
|
|
82
|
+
const sub = head.indexOf(" subagent ");
|
|
83
|
+
if (sub !== -1 && SUBAGENT_NOTICE_HEADS.has(`${head.slice(0, sub)} subagent`)) {
|
|
84
|
+
kind = head.slice(0, sub);
|
|
85
|
+
rest = head.slice(sub + 10);
|
|
86
|
+
} else {
|
|
87
|
+
const cmd = head.indexOf(" command ");
|
|
88
|
+
if (cmd === -1 || head.slice(0, cmd) !== "Background") return null;
|
|
89
|
+
kind = "Background";
|
|
90
|
+
rest = head.slice(cmd + 9);
|
|
91
|
+
shell = true;
|
|
92
|
+
}
|
|
93
|
+
const open = rest.indexOf(" (");
|
|
94
|
+
if (open === -1) return null;
|
|
95
|
+
const id = rest.slice(0, open);
|
|
96
|
+
rest = rest.slice(open + 2);
|
|
97
|
+
const end = rest.lastIndexOf(")");
|
|
98
|
+
if (end === -1) return null;
|
|
99
|
+
const tail = rest.slice(end + 1);
|
|
100
|
+
const notice = {
|
|
101
|
+
id,
|
|
102
|
+
description: rest.slice(0, end),
|
|
103
|
+
interim: kind === "Message from",
|
|
104
|
+
silent: tail.includes("was interrupted"),
|
|
105
|
+
preview: "",
|
|
106
|
+
body: ""
|
|
107
|
+
};
|
|
108
|
+
if (shell) {
|
|
109
|
+
notice.preview = tail.trim();
|
|
110
|
+
return notice;
|
|
111
|
+
}
|
|
112
|
+
const lines = body.split("\n");
|
|
113
|
+
const last = lines[lines.length - 1] ?? "";
|
|
114
|
+
if (lines.length > 0 && last.trim().startsWith("(pass ")) body = lines.slice(0, -1).join("\n");
|
|
115
|
+
notice.body = body.trim();
|
|
116
|
+
notice.preview = firstNonEmptyLine(body, 70);
|
|
117
|
+
return notice;
|
|
118
|
+
}
|
|
119
|
+
/** The line that marks a child's report entering the main conversation. */
|
|
120
|
+
function subagentDeliveryLine(n) {
|
|
121
|
+
const name = n.description ? `${n.id} (${n.description})` : n.id;
|
|
122
|
+
let label = n.interim ? `↳ message from ${name}` : `↳ ${name} reported back`;
|
|
123
|
+
if (n.preview) label += `: ${sanitizeLabel(n.preview)}`;
|
|
124
|
+
return label;
|
|
125
|
+
}
|
|
126
|
+
//#endregion
|
|
127
|
+
export { INTERRUPTED_NOTICE, agentTypeLabel, askQuestionFromArgs, firstNonEmptyLine, hiddenTranscriptTool, interruptionNotice, parseSubagentNotice, planFromArgs, subagentDeliveryLine, taskCallFromArgs, thinkingHeading };
|