@vibe-forge/client 0.10.1 → 0.11.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 (133) hide show
  1. package/dist/assets/{arc-C1rWFTer.js → arc-CSepokz3.js} +1 -1
  2. package/dist/assets/{blockDiagram-c4efeb88-DlZ9x70F.js → blockDiagram-c4efeb88-D0ARcoNf.js} +1 -1
  3. package/dist/assets/{c4Diagram-c83219d4-BKKxi__y.js → c4Diagram-c83219d4-BysYF9kP.js} +1 -1
  4. package/dist/assets/channel-CeKPk6Nd.js +1 -0
  5. package/dist/assets/{classDiagram-beda092f-CVGPySZq.js → classDiagram-beda092f-BG1GhIOL.js} +1 -1
  6. package/dist/assets/{classDiagram-v2-2358418a-7kp8GVVj.js → classDiagram-v2-2358418a-Dd08uGSH.js} +1 -1
  7. package/dist/assets/clone-CrkD2PuD.js +1 -0
  8. package/dist/assets/{createText-1719965b-Dykv8kT9.js → createText-1719965b-CigPEIEn.js} +1 -1
  9. package/dist/assets/{cssMode-B59COYVW.js → cssMode-MjflyEfm.js} +1 -1
  10. package/dist/assets/{edges-96097737-CkZ1ZBro.js → edges-96097737-DuTBJJRv.js} +1 -1
  11. package/dist/assets/{erDiagram-0228fc6a-281ADcRp.js → erDiagram-0228fc6a-Cp1bL7Y7.js} +1 -1
  12. package/dist/assets/{flowDb-c6c81e3f-BQjX_flP.js → flowDb-c6c81e3f-BfKbhiq5.js} +1 -1
  13. package/dist/assets/{flowDiagram-50d868cf-DMHZTjES.js → flowDiagram-50d868cf-m7gGc3PK.js} +1 -1
  14. package/dist/assets/flowDiagram-v2-4f6560a1-4ZU4bdp1.js +1 -0
  15. package/dist/assets/{flowchart-elk-definition-6af322e1-CI3yz4z8.js → flowchart-elk-definition-6af322e1-EVeTDRRK.js} +1 -1
  16. package/dist/assets/{freemarker2-DWnWjibn.js → freemarker2-Bb3-QAIN.js} +1 -1
  17. package/dist/assets/{ganttDiagram-a2739b55-B3IING9L.js → ganttDiagram-a2739b55-DslB2U0R.js} +1 -1
  18. package/dist/assets/{gitGraphDiagram-82fe8481-CnArIr_T.js → gitGraphDiagram-82fe8481-C-KFWMXL.js} +1 -1
  19. package/dist/assets/{graph-BZ1F0Yve.js → graph-CukaUc0o.js} +1 -1
  20. package/dist/assets/{handlebars-C1QH9qTz.js → handlebars-C4le-2Y6.js} +1 -1
  21. package/dist/assets/{html-D1NkqHjC.js → html-CjNiRs5S.js} +1 -1
  22. package/dist/assets/{htmlMode-DAZCE_rA.js → htmlMode-B73_3-We.js} +1 -1
  23. package/dist/assets/{index-5325376f-Da9zSHjA.js → index-5325376f-CVISZFPw.js} +1 -1
  24. package/dist/assets/{index-C0vjF3D0.js → index-BZosmb5_.js} +336 -336
  25. package/dist/assets/index-C1oh0w9H.css +32 -0
  26. package/dist/assets/{infoDiagram-8eee0895-DYbFvRM7.js → infoDiagram-8eee0895-DoirLE1K.js} +1 -1
  27. package/dist/assets/{javascript-CoMjGRHa.js → javascript-BDjnqJFP.js} +1 -1
  28. package/dist/assets/{journeyDiagram-c64418c1-Boebox0b.js → journeyDiagram-c64418c1-Ckn-p2CM.js} +1 -1
  29. package/dist/assets/{jsonMode-D__gAvuz.js → jsonMode-C-ftOc5j.js} +1 -1
  30. package/dist/assets/{layout-CTcHNbHp.js → layout-Z7yUG7hB.js} +1 -1
  31. package/dist/assets/{line-4AwinCz2.js → line-DPG_cfAy.js} +1 -1
  32. package/dist/assets/{linear-CeSMLzJW.js → linear--GSeVfMi.js} +1 -1
  33. package/dist/assets/{liquid-DZF6egdE.js → liquid-COiLZ9py.js} +1 -1
  34. package/dist/assets/{lspLanguageFeatures-6K4lv5S2.js → lspLanguageFeatures-DGmhryFq.js} +1 -1
  35. package/dist/assets/{mdx-Cnt4ka6w.js → mdx-BpL87Gej.js} +1 -1
  36. package/dist/assets/{mermaid.core-B0yG5s4D.js → mermaid.core-Cg1CCDo6.js} +4 -4
  37. package/dist/assets/{mindmap-definition-8da855dc-KJEvXMKj.js → mindmap-definition-8da855dc-CKDof1lD.js} +1 -1
  38. package/dist/assets/{pieDiagram-a8764435-17nFAXPJ.js → pieDiagram-a8764435-DwvCaZVE.js} +1 -1
  39. package/dist/assets/{python-DA3TtjDv.js → python-63dBmWV_.js} +1 -1
  40. package/dist/assets/{quadrantDiagram-1e28029f-Dt4vubi-.js → quadrantDiagram-1e28029f-CkzYBQpy.js} +1 -1
  41. package/dist/assets/{razor-CWDJgvX_.js → razor-C50tBqEZ.js} +1 -1
  42. package/dist/assets/{requirementDiagram-08caed73-H6aDyDK-.js → requirementDiagram-08caed73-Brgdjqf4.js} +1 -1
  43. package/dist/assets/{sankeyDiagram-a04cb91d-DxsVtbjI.js → sankeyDiagram-a04cb91d-CGkYexrs.js} +1 -1
  44. package/dist/assets/{sequenceDiagram-c5b8d532-BHa148XJ.js → sequenceDiagram-c5b8d532-D0wE-_J8.js} +1 -1
  45. package/dist/assets/{stateDiagram-1ecb1508-DgwBm8LO.js → stateDiagram-1ecb1508-BYb3NCXZ.js} +1 -1
  46. package/dist/assets/{stateDiagram-v2-c2b004d7-BK7IQLVc.js → stateDiagram-v2-c2b004d7-DrPqi4Pt.js} +1 -1
  47. package/dist/assets/{styles-b4e223ce-DzW27Bc-.js → styles-b4e223ce-DD66TIO4.js} +1 -1
  48. package/dist/assets/{styles-ca3715f6-Dex2GiLT.js → styles-ca3715f6-iy02LHIV.js} +1 -1
  49. package/dist/assets/{styles-d45a18b0-B6fGtDKS.js → styles-d45a18b0-BgqAgJyW.js} +1 -1
  50. package/dist/assets/{svgDrawCommon-b86b1483-B4HYgfV5.js → svgDrawCommon-b86b1483-CDq7ugnw.js} +1 -1
  51. package/dist/assets/{timeline-definition-faaaa080--QSbWb25.js → timeline-definition-faaaa080-DzcLLjK0.js} +1 -1
  52. package/dist/assets/{tsMode-ZM7ocZCH.js → tsMode-BFRFI4ct.js} +1 -1
  53. package/dist/assets/{typescript-CKWDmBCc.js → typescript-CBZQRAPv.js} +1 -1
  54. package/dist/assets/{xml-DuEUAzPi.js → xml-BpWm6upt.js} +1 -1
  55. package/dist/assets/{xychartDiagram-f5964ef8-D09Zkv2K.js → xychartDiagram-f5964ef8-zBN8FmLQ.js} +1 -1
  56. package/dist/assets/{yaml-DL7QPRYk.js → yaml-CqbJPiIP.js} +1 -1
  57. package/dist/index.html +2 -2
  58. package/package.json +10 -10
  59. package/src/api/git.ts +78 -0
  60. package/src/api.ts +24 -0
  61. package/src/components/chat/ChatHeader.tsx +4 -0
  62. package/src/components/chat/ChatHistoryView.tsx +22 -13
  63. package/src/components/chat/git-controls/BranchSwitcherDropdown.tsx +157 -0
  64. package/src/components/chat/git-controls/ChatGitControls.scss +616 -0
  65. package/src/components/chat/git-controls/ChatGitControls.tsx +151 -0
  66. package/src/components/chat/git-controls/GitCommitModal.tsx +199 -0
  67. package/src/components/chat/git-controls/GitCommitModalParts.tsx +151 -0
  68. package/src/components/chat/git-controls/GitOperationsDropdown.tsx +123 -0
  69. package/src/components/chat/git-controls/GitPushModal.tsx +106 -0
  70. package/src/components/chat/git-controls/GitWorktreeDropdown.tsx +68 -0
  71. package/src/components/chat/git-controls/git-branch-utils.ts +88 -0
  72. package/src/components/chat/git-controls/git-commit-utils.ts +79 -0
  73. package/src/components/chat/git-controls/git-mutation-utils.ts +69 -0
  74. package/src/components/chat/git-controls/git-operation-utils.ts +98 -0
  75. package/src/components/chat/git-controls/git-worktree-utils.ts +49 -0
  76. package/src/components/chat/git-controls/use-chat-git-commit.ts +185 -0
  77. package/src/components/chat/git-controls/use-chat-git-controls.ts +200 -0
  78. package/src/components/chat/git-controls/use-chat-git-push-state.ts +19 -0
  79. package/src/components/chat/git-controls/use-chat-git-worktrees.ts +39 -0
  80. package/src/components/chat/messages/MessageStatusNotice.scss +163 -0
  81. package/src/components/chat/messages/MessageStatusNotice.tsx +48 -0
  82. package/src/components/chat/messages/build-chat-history-status-notices.ts +138 -0
  83. package/src/components/chat/sender/@components/sender-body/SenderBody.tsx +0 -24
  84. package/src/components/chat/sender/@core/build-sender-controller-result.ts +0 -6
  85. package/src/components/chat/sender/@hooks/use-sender-controller.ts +0 -2
  86. package/src/components/chat/sender/@types/sender-props.ts +0 -3
  87. package/src/components/chat/sender/Sender.scss +0 -58
  88. package/src/components/chat/sender/Sender.tsx +0 -2
  89. package/src/components/chat/tools/DefaultTool.tsx +84 -208
  90. package/src/components/chat/tools/adapter-claude/ClaudeEditDiff.tsx +30 -0
  91. package/src/components/chat/tools/adapter-claude/GenericClaudeTool.scss +128 -0
  92. package/src/components/chat/tools/adapter-claude/GenericClaudeTool.tsx +119 -0
  93. package/src/components/chat/tools/adapter-claude/claude-tool-edit-builders.ts +109 -0
  94. package/src/components/chat/tools/adapter-claude/claude-tool-field-sections.tsx +83 -0
  95. package/src/components/chat/tools/adapter-claude/claude-tool-operation-builders.ts +135 -0
  96. package/src/components/chat/tools/adapter-claude/claude-tool-presentation.ts +61 -0
  97. package/src/components/chat/tools/adapter-claude/claude-tool-shared.ts +185 -0
  98. package/src/components/chat/tools/adapter-claude/claude-tool-summary.ts +76 -0
  99. package/src/components/chat/tools/adapter-claude/claude-tool-system-builders.ts +125 -0
  100. package/src/components/chat/tools/adapter-claude/claude-tool-task-builders.ts +148 -0
  101. package/src/components/chat/tools/adapter-claude/index.ts +24 -15
  102. package/src/components/chat/tools/core/ToolCallBox.scss +362 -36
  103. package/src/components/chat/tools/core/ToolCallBox.tsx +35 -13
  104. package/src/components/chat/tools/core/ToolDiffViewer.scss +138 -0
  105. package/src/components/chat/tools/core/ToolDiffViewer.tsx +180 -0
  106. package/src/components/chat/tools/core/ToolGroup.scss +52 -74
  107. package/src/components/chat/tools/core/ToolGroup.tsx +25 -40
  108. package/src/components/chat/tools/core/ToolRenderer.tsx +3 -3
  109. package/src/components/chat/tools/core/ToolResultContent.tsx +66 -0
  110. package/src/components/chat/tools/core/ToolSummaryHeader.tsx +67 -0
  111. package/src/components/chat/tools/core/generic-tool-presentation.ts +661 -0
  112. package/src/components/chat/tools/core/tool-content-presence.ts +57 -0
  113. package/src/components/chat/tools/core/tool-display.ts +203 -0
  114. package/src/components/chat/tools/core/tool-field-sections.tsx +132 -0
  115. package/src/components/chat/tools/core/tool-result-content-utils.ts +171 -0
  116. package/src/components/chat/tools/core/tool-summary.ts +206 -0
  117. package/src/components/chat/tools/plugin-chrome-devtools/ChromeDevtoolsTool.tsx +59 -53
  118. package/src/components/chat/tools/task/GetTaskInfoTool.tsx +26 -9
  119. package/src/components/chat/tools/task/ListTasksTool.tsx +22 -9
  120. package/src/components/chat/tools/task/StartTasksTool.tsx +22 -9
  121. package/src/hooks/chat/interaction-state.ts +29 -9
  122. package/src/hooks/chat/session-view-cache.ts +80 -0
  123. package/src/hooks/chat/use-chat-scroll.ts +2 -2
  124. package/src/hooks/chat/use-chat-session-messages.ts +139 -39
  125. package/src/hooks/chat/use-chat-session.ts +2 -2
  126. package/src/resources/locales/en.json +149 -0
  127. package/src/resources/locales/zh.json +149 -0
  128. package/src/routes/ChatRoute.tsx +24 -27
  129. package/src/utils/strip-ansi.ts +26 -0
  130. package/dist/assets/channel-F1aqMANO.js +0 -1
  131. package/dist/assets/clone-B-GCuXNo.js +0 -1
  132. package/dist/assets/flowDiagram-v2-4f6560a1-C5FzdVl1.js +0 -1
  133. package/dist/assets/index-vzEbM21t.css +0 -32
@@ -0,0 +1,185 @@
1
+ export type ClaudeToolFieldFormat = 'inline' | 'text' | 'code' | 'list' | 'json' | 'questions'
2
+
3
+ export interface ClaudeToolQuestionOption {
4
+ label: string
5
+ description?: string
6
+ }
7
+
8
+ export interface ClaudeToolQuestion {
9
+ header?: string
10
+ question: string
11
+ options: ClaudeToolQuestionOption[]
12
+ multiSelect: boolean
13
+ }
14
+
15
+ export interface ClaudeToolField {
16
+ labelKey: string
17
+ fallbackLabel: string
18
+ format: ClaudeToolFieldFormat
19
+ value: unknown
20
+ lang?: string
21
+ }
22
+
23
+ export interface ClaudeToolPresentation {
24
+ baseName: string
25
+ titleKey: string
26
+ fallbackTitle: string
27
+ icon: string
28
+ primary?: string
29
+ fields: ClaudeToolField[]
30
+ }
31
+
32
+ export const CLAUDE_TOOL_META: Record<string, Pick<ClaudeToolPresentation, 'titleKey' | 'fallbackTitle' | 'icon'>> = {
33
+ AskUserQuestion: { titleKey: 'chat.tools.askUserQuestion', fallbackTitle: 'Ask User Question', icon: 'help' },
34
+ Bash: { titleKey: 'chat.tools.bash', fallbackTitle: 'Bash', icon: 'terminal' },
35
+ Edit: { titleKey: 'chat.tools.editTool', fallbackTitle: 'Edit File', icon: 'edit' },
36
+ EnterPlanMode: { titleKey: 'chat.tools.enterPlanMode', fallbackTitle: 'Enter Plan Mode', icon: 'rule_settings' },
37
+ ExitPlanMode: { titleKey: 'chat.tools.exitPlanMode', fallbackTitle: 'Exit Plan Mode', icon: 'exit_to_app' },
38
+ Glob: { titleKey: 'chat.tools.globTool', fallbackTitle: 'Glob', icon: 'search' },
39
+ Grep: { titleKey: 'chat.tools.grepTool', fallbackTitle: 'Grep', icon: 'find_in_page' },
40
+ LS: { titleKey: 'chat.tools.lsTool', fallbackTitle: 'List Directory', icon: 'folder_open' },
41
+ NotebookEdit: { titleKey: 'chat.tools.notebookEdit', fallbackTitle: 'Notebook Edit', icon: 'edit_note' },
42
+ Read: { titleKey: 'chat.tools.read', fallbackTitle: 'Read File', icon: 'visibility' },
43
+ Skill: { titleKey: 'chat.tools.skill', fallbackTitle: 'Skill', icon: 'auto_awesome' },
44
+ Task: { titleKey: 'chat.tools.claudeTask', fallbackTitle: 'Claude Task', icon: 'smart_toy' },
45
+ TaskCreate: { titleKey: 'chat.tools.taskCreate', fallbackTitle: 'Create Task', icon: 'add_task' },
46
+ TaskGet: { titleKey: 'chat.tools.taskGet', fallbackTitle: 'Get Task', icon: 'info' },
47
+ TaskList: { titleKey: 'chat.tools.taskList', fallbackTitle: 'List Tasks', icon: 'list_alt' },
48
+ TaskUpdate: { titleKey: 'chat.tools.taskUpdate', fallbackTitle: 'Update Task', icon: 'edit_calendar' },
49
+ TodoWrite: { titleKey: 'chat.tools.todo', fallbackTitle: 'Task Planning', icon: 'task_alt' },
50
+ WebFetch: { titleKey: 'chat.tools.webFetch', fallbackTitle: 'Web Fetch', icon: 'language' },
51
+ WebSearch: { titleKey: 'chat.tools.webSearch', fallbackTitle: 'Web Search', icon: 'travel_explore' },
52
+ Write: { titleKey: 'chat.tools.write', fallbackTitle: 'Write File', icon: 'edit_note' }
53
+ }
54
+
55
+ export const isRecord = (value: unknown): value is Record<string, unknown> => (
56
+ value != null && typeof value === 'object' && !Array.isArray(value)
57
+ )
58
+
59
+ export const asString = (value: unknown) => (
60
+ typeof value === 'string' && value.trim() !== '' ? value : undefined
61
+ )
62
+
63
+ export const asNumber = (value: unknown) => (
64
+ typeof value === 'number' && Number.isFinite(value) ? value : undefined
65
+ )
66
+
67
+ export const asBoolean = (value: unknown) => (
68
+ typeof value === 'boolean' ? value : undefined
69
+ )
70
+
71
+ export const asStringArray = (value: unknown) => {
72
+ if (!Array.isArray(value)) {
73
+ return undefined
74
+ }
75
+
76
+ const items = value
77
+ .filter(item => typeof item === 'string' && item.trim() !== '')
78
+ .map(item => item.trim())
79
+ return items.length > 0 ? items : undefined
80
+ }
81
+
82
+ export const pushField = (
83
+ fields: ClaudeToolField[],
84
+ usedKeys: Set<string>,
85
+ key: string,
86
+ field: Omit<ClaudeToolField, 'value'> & { value: unknown }
87
+ ) => {
88
+ const { value } = field
89
+ if (value == null || value === '') {
90
+ return
91
+ }
92
+ if (Array.isArray(value) && value.length === 0) {
93
+ return
94
+ }
95
+ if (isRecord(value) && Object.keys(value).length === 0) {
96
+ return
97
+ }
98
+
99
+ usedKeys.add(key)
100
+ fields.push(field)
101
+ }
102
+
103
+ export const toQuestionList = (value: unknown): ClaudeToolQuestion[] | undefined => {
104
+ if (!Array.isArray(value)) {
105
+ return undefined
106
+ }
107
+
108
+ const questions: ClaudeToolQuestion[] = []
109
+ for (const item of value) {
110
+ if (!isRecord(item)) {
111
+ continue
112
+ }
113
+
114
+ const question = asString(item.question)
115
+ if (question == null) {
116
+ continue
117
+ }
118
+
119
+ const options: ClaudeToolQuestionOption[] = []
120
+ if (Array.isArray(item.options)) {
121
+ for (const option of item.options) {
122
+ if (!isRecord(option)) {
123
+ continue
124
+ }
125
+
126
+ const label = asString(option.label)
127
+ if (label == null) {
128
+ continue
129
+ }
130
+
131
+ options.push({
132
+ label,
133
+ description: asString(option.description)
134
+ })
135
+ }
136
+ }
137
+
138
+ questions.push({
139
+ header: asString(item.header),
140
+ question,
141
+ options,
142
+ multiSelect: item.multiSelect === true
143
+ })
144
+ }
145
+
146
+ return questions.length > 0 ? questions : undefined
147
+ }
148
+
149
+ export const getDescriptionTitle = (value: string | undefined) => (
150
+ value != null && value !== '' ? value.split('\n')[0]?.trim() || value : undefined
151
+ )
152
+
153
+ export const addDetailsField = (
154
+ fields: ClaudeToolField[],
155
+ record: Record<string, unknown> | null,
156
+ usedKeys: Set<string>
157
+ ) => {
158
+ if (record == null) {
159
+ return
160
+ }
161
+
162
+ const details = Object.fromEntries(
163
+ Object.entries(record).filter(([key, value]) => {
164
+ if (usedKeys.has(key) || value == null) {
165
+ return false
166
+ }
167
+ if (typeof value === 'string') {
168
+ return value.trim() !== ''
169
+ }
170
+ if (Array.isArray(value)) {
171
+ return value.length > 0
172
+ }
173
+ return !isRecord(value) || Object.keys(value).length > 0
174
+ })
175
+ )
176
+
177
+ if (Object.keys(details).length > 0) {
178
+ fields.push({
179
+ labelKey: 'chat.tools.fields.details',
180
+ fallbackLabel: 'Details',
181
+ format: 'json',
182
+ value: details
183
+ })
184
+ }
185
+ }
@@ -0,0 +1,76 @@
1
+ import { buildClaudeToolPresentation, getClaudeToolBaseName } from './claude-tool-presentation'
2
+ import { isRecord, toQuestionList } from './claude-tool-shared'
3
+ import { getFileInfo } from './utils'
4
+
5
+ type Translate = (key: string, options?: Record<string, unknown>) => string
6
+
7
+ const getRecord = (input: unknown) => (isRecord(input) ? input : null)
8
+
9
+ const joinSummary = (title: string, primary?: string) => (
10
+ primary != null && primary !== '' ? `${title} ${primary}` : title
11
+ )
12
+
13
+ export function getClaudeToolSummaryText(name: string, input: unknown, t: Translate) {
14
+ const baseName = getClaudeToolBaseName(name)
15
+ const record = getRecord(input)
16
+
17
+ if (baseName === 'Bash') {
18
+ const description = [record?.description, record?.reason, record?.thought]
19
+ .find(value => typeof value === 'string' && value.trim() !== '')
20
+ const command = typeof record?.command === 'string' ? record.command : ''
21
+ const commandLine = command.split('\n')[0]?.trim()
22
+ return typeof description === 'string' && description.trim() !== ''
23
+ ? description.trim()
24
+ : joinSummary(t('chat.tools.bash', { defaultValue: 'Bash' }), commandLine)
25
+ }
26
+
27
+ if (baseName === 'Read' || baseName === 'Write' || baseName === 'Edit') {
28
+ const pathValue = typeof record?.file_path === 'string' ? getFileInfo(record.file_path).filePath : undefined
29
+ const titleKey = baseName === 'Read'
30
+ ? 'chat.tools.read'
31
+ : baseName === 'Write'
32
+ ? 'chat.tools.write'
33
+ : 'chat.tools.editTool'
34
+ const fallback = baseName === 'Read' ? 'Read File' : baseName === 'Write' ? 'Write File' : 'Edit File'
35
+ return joinSummary(t(titleKey, { defaultValue: fallback }), pathValue)
36
+ }
37
+
38
+ if (baseName === 'NotebookEdit') {
39
+ const notebookPath = typeof record?.notebook_path === 'string'
40
+ ? getFileInfo(record.notebook_path).filePath
41
+ : undefined
42
+ return joinSummary(t('chat.tools.notebookEdit', { defaultValue: 'Notebook Edit' }), notebookPath)
43
+ }
44
+
45
+ if (baseName === 'LS') {
46
+ const pathValue = typeof record?.path === 'string' && record.path !== '' ? record.path : 'current directory'
47
+ return joinSummary(t('chat.tools.lsTool', { defaultValue: 'List Directory' }), pathValue)
48
+ }
49
+
50
+ if (baseName === 'Glob') {
51
+ const pattern = typeof record?.pattern === 'string' && record.pattern !== '' ? record.pattern : '*'
52
+ return joinSummary(t('chat.tools.globTool', { defaultValue: 'Glob' }), pattern)
53
+ }
54
+
55
+ if (baseName === 'Grep') {
56
+ const pattern = typeof record?.pattern === 'string' ? record.pattern : undefined
57
+ return joinSummary(t('chat.tools.grepTool', { defaultValue: 'Grep' }), pattern)
58
+ }
59
+
60
+ if (baseName === 'TodoWrite') {
61
+ const count = Array.isArray(record?.todos) ? record.todos.length : 0
62
+ return joinSummary(t('chat.tools.todo', { defaultValue: 'Task Planning' }), count > 0 ? `${count}` : undefined)
63
+ }
64
+
65
+ if (baseName === 'AskUserQuestion') {
66
+ const firstQuestion = toQuestionList(record?.questions)?.[0]
67
+ return joinSummary(
68
+ t('chat.tools.askUserQuestion', { defaultValue: 'Ask User Question' }),
69
+ firstQuestion?.header ?? firstQuestion?.question
70
+ )
71
+ }
72
+
73
+ const presentation = buildClaudeToolPresentation(name, input)
74
+ const title = t(presentation.titleKey, { defaultValue: presentation.fallbackTitle })
75
+ return joinSummary(title, presentation.primary)
76
+ }
@@ -0,0 +1,125 @@
1
+ import { asBoolean, asString, asStringArray, pushField, toQuestionList } from './claude-tool-shared'
2
+ import type { ClaudeToolField } from './claude-tool-shared'
3
+
4
+ interface BuilderParams {
5
+ baseName: string
6
+ record: Record<string, unknown> | null
7
+ fields: ClaudeToolField[]
8
+ usedKeys: Set<string>
9
+ }
10
+
11
+ export function buildClaudeSystemToolPresentation(params: BuilderParams) {
12
+ const { baseName, record, fields, usedKeys } = params
13
+
14
+ if (baseName === 'WebFetch') {
15
+ pushField(fields, usedKeys, 'prompt', {
16
+ labelKey: 'chat.tools.fields.prompt',
17
+ fallbackLabel: 'Prompt',
18
+ format: 'text',
19
+ value: asString(record?.prompt)
20
+ })
21
+ usedKeys.add('url')
22
+ return { handled: true, primary: asString(record?.url) }
23
+ }
24
+
25
+ if (baseName === 'WebSearch') {
26
+ pushField(fields, usedKeys, 'allowed_domains', {
27
+ labelKey: 'chat.tools.fields.allowedDomains',
28
+ fallbackLabel: 'Allowed Domains',
29
+ format: 'list',
30
+ value: asStringArray(record?.allowed_domains)
31
+ })
32
+ pushField(fields, usedKeys, 'blocked_domains', {
33
+ labelKey: 'chat.tools.fields.blockedDomains',
34
+ fallbackLabel: 'Blocked Domains',
35
+ format: 'list',
36
+ value: asStringArray(record?.blocked_domains)
37
+ })
38
+ usedKeys.add('query')
39
+ return { handled: true, primary: asString(record?.query) }
40
+ }
41
+
42
+ if (baseName === 'AskUserQuestion') {
43
+ const questions = toQuestionList(record?.questions)
44
+
45
+ pushField(fields, usedKeys, 'questions', {
46
+ labelKey: 'chat.tools.fields.questions',
47
+ fallbackLabel: 'Questions',
48
+ format: 'questions',
49
+ value: questions
50
+ })
51
+ pushField(fields, usedKeys, 'answers', {
52
+ labelKey: 'chat.tools.fields.answers',
53
+ fallbackLabel: 'Answers',
54
+ format: 'json',
55
+ value: record?.answers != null && typeof record.answers === 'object' ? record.answers : undefined
56
+ })
57
+ pushField(fields, usedKeys, 'metadata', {
58
+ labelKey: 'chat.tools.fields.metadata',
59
+ fallbackLabel: 'Metadata',
60
+ format: 'json',
61
+ value: record?.metadata != null && typeof record.metadata === 'object' ? record.metadata : undefined
62
+ })
63
+ return { handled: true, primary: questions?.[0]?.header ?? questions?.[0]?.question }
64
+ }
65
+
66
+ if (baseName === 'Skill') {
67
+ pushField(fields, usedKeys, 'args', {
68
+ labelKey: 'chat.tools.fields.args',
69
+ fallbackLabel: 'Args',
70
+ format: 'text',
71
+ value: asString(record?.args)
72
+ })
73
+ usedKeys.add('skill')
74
+ return { handled: true, primary: asString(record?.skill) }
75
+ }
76
+
77
+ if (baseName === 'EnterPlanMode') {
78
+ return { handled: true }
79
+ }
80
+
81
+ if (baseName !== 'ExitPlanMode') {
82
+ return { handled: false }
83
+ }
84
+
85
+ pushField(fields, usedKeys, 'pushToRemote', {
86
+ labelKey: 'chat.tools.fields.pushToRemote',
87
+ fallbackLabel: 'Push To Remote',
88
+ format: 'inline',
89
+ value: asBoolean(record?.pushToRemote) != null ? String(record?.pushToRemote) : undefined
90
+ })
91
+ pushField(fields, usedKeys, 'remoteSessionId', {
92
+ labelKey: 'chat.tools.fields.remoteSession',
93
+ fallbackLabel: 'Remote Session',
94
+ format: 'inline',
95
+ value: asString(record?.remoteSessionId)
96
+ })
97
+ pushField(fields, usedKeys, 'remoteSessionUrl', {
98
+ labelKey: 'chat.tools.fields.remoteSessionUrl',
99
+ fallbackLabel: 'Remote Session URL',
100
+ format: 'text',
101
+ value: asString(record?.remoteSessionUrl)
102
+ })
103
+ pushField(fields, usedKeys, 'allowedPrompts', {
104
+ labelKey: 'chat.tools.fields.allowedPrompts',
105
+ fallbackLabel: 'Allowed Prompts',
106
+ format: 'list',
107
+ value: Array.isArray(record?.allowedPrompts)
108
+ ? record.allowedPrompts.flatMap((item) => {
109
+ if (item == null || typeof item !== 'object') {
110
+ return []
111
+ }
112
+ const data = item as Record<string, unknown>
113
+ const tool = asString(data.tool)
114
+ const prompt = asString(data.prompt)
115
+ return prompt != null ? [`${tool ?? 'Tool'}: ${prompt}`] : []
116
+ })
117
+ : undefined
118
+ })
119
+ usedKeys.add('remoteSessionTitle')
120
+
121
+ return {
122
+ handled: true,
123
+ primary: asString(record?.remoteSessionTitle) ?? asString(record?.remoteSessionId)
124
+ }
125
+ }
@@ -0,0 +1,148 @@
1
+ import { asBoolean, asNumber, asString, asStringArray, getDescriptionTitle, pushField } from './claude-tool-shared'
2
+ import type { ClaudeToolField } from './claude-tool-shared'
3
+
4
+ interface BuilderParams {
5
+ baseName: string
6
+ record: Record<string, unknown> | null
7
+ fields: ClaudeToolField[]
8
+ usedKeys: Set<string>
9
+ }
10
+
11
+ export function buildClaudeTaskToolPresentation(params: BuilderParams) {
12
+ const { baseName, record, fields, usedKeys } = params
13
+
14
+ if (baseName === 'Task') {
15
+ const description = asString(record?.description)
16
+
17
+ pushField(fields, usedKeys, 'description', {
18
+ labelKey: 'chat.tools.fields.description',
19
+ fallbackLabel: 'Description',
20
+ format: 'text',
21
+ value: description
22
+ })
23
+ pushField(fields, usedKeys, 'prompt', {
24
+ labelKey: 'chat.tools.fields.prompt',
25
+ fallbackLabel: 'Prompt',
26
+ format: 'text',
27
+ value: asString(record?.prompt)
28
+ })
29
+ pushField(fields, usedKeys, 'subagent_type', {
30
+ labelKey: 'chat.tools.fields.subagentType',
31
+ fallbackLabel: 'Subagent Type',
32
+ format: 'inline',
33
+ value: asString(record?.subagent_type)
34
+ })
35
+ pushField(fields, usedKeys, 'model', {
36
+ labelKey: 'chat.tools.fields.model',
37
+ fallbackLabel: 'Model',
38
+ format: 'inline',
39
+ value: asString(record?.model)
40
+ })
41
+ pushField(fields, usedKeys, 'resume', {
42
+ labelKey: 'chat.tools.fields.resume',
43
+ fallbackLabel: 'Resume',
44
+ format: 'inline',
45
+ value: asString(record?.resume)
46
+ })
47
+ pushField(fields, usedKeys, 'run_in_background', {
48
+ labelKey: 'chat.tools.fields.runInBackground',
49
+ fallbackLabel: 'Run In Background',
50
+ format: 'inline',
51
+ value: asBoolean(record?.run_in_background) != null ? String(record?.run_in_background) : undefined
52
+ })
53
+ pushField(fields, usedKeys, 'max_turns', {
54
+ labelKey: 'chat.tools.fields.maxTurns',
55
+ fallbackLabel: 'Max Turns',
56
+ format: 'inline',
57
+ value: asNumber(record?.max_turns)
58
+ })
59
+ return { handled: true, primary: getDescriptionTitle(description) ?? asString(record?.subagent_type) }
60
+ }
61
+
62
+ if (baseName === 'TaskCreate') {
63
+ pushField(fields, usedKeys, 'description', {
64
+ labelKey: 'chat.tools.fields.description',
65
+ fallbackLabel: 'Description',
66
+ format: 'text',
67
+ value: asString(record?.description)
68
+ })
69
+ pushField(fields, usedKeys, 'activeForm', {
70
+ labelKey: 'chat.tools.fields.activeForm',
71
+ fallbackLabel: 'Active Form',
72
+ format: 'text',
73
+ value: asString(record?.activeForm)
74
+ })
75
+ pushField(fields, usedKeys, 'metadata', {
76
+ labelKey: 'chat.tools.fields.metadata',
77
+ fallbackLabel: 'Metadata',
78
+ format: 'json',
79
+ value: record?.metadata != null && typeof record.metadata === 'object' ? record.metadata : undefined
80
+ })
81
+ usedKeys.add('subject')
82
+ return { handled: true, primary: asString(record?.subject) }
83
+ }
84
+
85
+ if (baseName === 'TaskGet') {
86
+ usedKeys.add('taskId')
87
+ return { handled: true, primary: asString(record?.taskId) }
88
+ }
89
+
90
+ if (baseName === 'TaskUpdate') {
91
+ pushField(fields, usedKeys, 'subject', {
92
+ labelKey: 'chat.tools.fields.subject',
93
+ fallbackLabel: 'Subject',
94
+ format: 'text',
95
+ value: asString(record?.subject)
96
+ })
97
+ pushField(fields, usedKeys, 'description', {
98
+ labelKey: 'chat.tools.fields.description',
99
+ fallbackLabel: 'Description',
100
+ format: 'text',
101
+ value: asString(record?.description)
102
+ })
103
+ pushField(fields, usedKeys, 'activeForm', {
104
+ labelKey: 'chat.tools.fields.activeForm',
105
+ fallbackLabel: 'Active Form',
106
+ format: 'text',
107
+ value: asString(record?.activeForm)
108
+ })
109
+ pushField(fields, usedKeys, 'status', {
110
+ labelKey: 'chat.tools.fields.status',
111
+ fallbackLabel: 'Status',
112
+ format: 'inline',
113
+ value: asString(record?.status)
114
+ })
115
+ pushField(fields, usedKeys, 'owner', {
116
+ labelKey: 'chat.tools.fields.owner',
117
+ fallbackLabel: 'Owner',
118
+ format: 'inline',
119
+ value: asString(record?.owner)
120
+ })
121
+ pushField(fields, usedKeys, 'addBlocks', {
122
+ labelKey: 'chat.tools.fields.addBlocks',
123
+ fallbackLabel: 'Add Blocks',
124
+ format: 'list',
125
+ value: asStringArray(record?.addBlocks)
126
+ })
127
+ pushField(fields, usedKeys, 'addBlockedBy', {
128
+ labelKey: 'chat.tools.fields.addBlockedBy',
129
+ fallbackLabel: 'Add Blocked By',
130
+ format: 'list',
131
+ value: asStringArray(record?.addBlockedBy)
132
+ })
133
+ pushField(fields, usedKeys, 'metadata', {
134
+ labelKey: 'chat.tools.fields.metadata',
135
+ fallbackLabel: 'Metadata',
136
+ format: 'json',
137
+ value: record?.metadata != null && typeof record.metadata === 'object' ? record.metadata : undefined
138
+ })
139
+ usedKeys.add('taskId')
140
+ return { handled: true, primary: asString(record?.taskId) }
141
+ }
142
+
143
+ if (baseName === 'TaskList') {
144
+ return { handled: true }
145
+ }
146
+
147
+ return { handled: false }
148
+ }
@@ -1,22 +1,31 @@
1
1
  import type {} from '@vibe-forge/adapter-claude-code/schema'
2
2
 
3
3
  import { defineToolRenders } from '../defineToolRender'
4
- import { BashTool } from './BashTool'
5
- import { GlobTool } from './GlobTool'
6
- import { GrepTool } from './GrepTool'
7
- import { LsTool } from './LSTool'
8
- import { ReadTool } from './ReadTool'
9
- import { TodoTool } from './TodoTool'
10
- import { WriteTool } from './WriteTool'
4
+ import { GenericClaudeTool } from './GenericClaudeTool'
5
+ export { buildClaudeToolPresentation, getClaudeToolBaseName, isClaudeToolName } from './claude-tool-presentation'
6
+ export { getClaudeToolSummaryText } from './claude-tool-summary'
11
7
 
12
8
  export const adapterClaudeToolRenders = defineToolRenders({
13
- Bash: BashTool,
14
- LS: LsTool,
15
- Glob: GlobTool,
16
- Grep: GrepTool,
17
- Read: ReadTool,
18
- Write: WriteTool,
19
- TodoWrite: TodoTool
9
+ AskUserQuestion: GenericClaudeTool,
10
+ Bash: GenericClaudeTool,
11
+ Edit: GenericClaudeTool,
12
+ EnterPlanMode: GenericClaudeTool,
13
+ ExitPlanMode: GenericClaudeTool,
14
+ LS: GenericClaudeTool,
15
+ Glob: GenericClaudeTool,
16
+ Grep: GenericClaudeTool,
17
+ NotebookEdit: GenericClaudeTool,
18
+ Read: GenericClaudeTool,
19
+ Skill: GenericClaudeTool,
20
+ Task: GenericClaudeTool,
21
+ TaskCreate: GenericClaudeTool,
22
+ TaskGet: GenericClaudeTool,
23
+ TaskList: GenericClaudeTool,
24
+ TaskUpdate: GenericClaudeTool,
25
+ WebFetch: GenericClaudeTool,
26
+ WebSearch: GenericClaudeTool,
27
+ Write: GenericClaudeTool,
28
+ TodoWrite: GenericClaudeTool
20
29
  }, { namespace: 'adapter:claude-code:' })
21
30
 
22
- export { BashTool, GlobTool, GrepTool, LsTool, ReadTool, TodoTool, WriteTool }
31
+ export { GenericClaudeTool }