@exreve/exk 1.0.49 → 1.0.51
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/agentSession.js +63 -14
- package/dist/ttc-cli.tar.gz +0 -0
- package/package.json +2 -2
package/dist/agentSession.js
CHANGED
|
@@ -88,20 +88,59 @@ const CACHED_CLAUDE_PATH = (() => {
|
|
|
88
88
|
// Promisify symlink for async use
|
|
89
89
|
const symlinkAsync = promisify(fsSymlink);
|
|
90
90
|
// Helper function to extract tool name from result structure
|
|
91
|
+
/**
|
|
92
|
+
* Detect tool name from the shape of tool_use_result.
|
|
93
|
+
*
|
|
94
|
+
* Uses discriminating keys from the SDK's own type definitions
|
|
95
|
+
* (sdk-tools.d.ts: BashOutput, GrepOutput, GlobOutput, FileReadOutput,
|
|
96
|
+
* FileEditOutput, FileWriteOutput, TodoWriteOutput, etc.)
|
|
97
|
+
*/
|
|
91
98
|
function extractToolName(toolResult) {
|
|
92
|
-
if (toolResult
|
|
93
|
-
return
|
|
94
|
-
|
|
99
|
+
if (!toolResult || typeof toolResult !== 'object')
|
|
100
|
+
return 'unknown';
|
|
101
|
+
// ── Read (FileReadOutput): {type: 'text'|'image'|'notebook'|'pdf'|'parts'|'file_unchanged', file: {...}}
|
|
102
|
+
if (toolResult.file && typeof toolResult.file === 'object'
|
|
103
|
+
&& ['text', 'image', 'notebook', 'pdf', 'parts', 'file_unchanged'].includes(toolResult.type)) {
|
|
95
104
|
return 'Read';
|
|
96
|
-
if (toolResult.file_path || toolResult.filePath) {
|
|
97
|
-
// Has old_string/new_string → Edit; has content/create → Write; else Read
|
|
98
|
-
if (toolResult.old_string !== undefined && toolResult.new_string !== undefined)
|
|
99
|
-
return 'Edit';
|
|
100
|
-
return (toolResult.content !== undefined || toolResult.type === 'create') ? 'Write' : 'Read';
|
|
101
105
|
}
|
|
102
|
-
|
|
106
|
+
// ── Edit (FileEditOutput): {filePath, oldString, newString, structuredPatch}
|
|
107
|
+
if (toolResult.filePath && toolResult.oldString !== undefined && toolResult.newString !== undefined
|
|
108
|
+
&& Array.isArray(toolResult.structuredPatch)) {
|
|
109
|
+
return 'Edit';
|
|
110
|
+
}
|
|
111
|
+
// ── Write (FileWriteOutput): {type: 'create'|'update', filePath, content, structuredPatch}
|
|
112
|
+
if (toolResult.filePath && (toolResult.type === 'create' || toolResult.type === 'update')
|
|
113
|
+
&& toolResult.content !== undefined) {
|
|
114
|
+
return 'Write';
|
|
115
|
+
}
|
|
116
|
+
// ── Grep (GrepOutput): {mode, numFiles, filenames, content?, numLines?}
|
|
117
|
+
if (typeof toolResult.numFiles === 'number' && Array.isArray(toolResult.filenames)
|
|
118
|
+
&& toolResult.mode !== undefined) {
|
|
119
|
+
return 'Grep';
|
|
120
|
+
}
|
|
121
|
+
// ── Glob (GlobOutput): {durationMs, numFiles, filenames, truncated}
|
|
122
|
+
if (typeof toolResult.numFiles === 'number' && Array.isArray(toolResult.filenames)
|
|
123
|
+
&& typeof toolResult.durationMs === 'number' && toolResult.truncated !== undefined) {
|
|
124
|
+
return 'Glob';
|
|
125
|
+
}
|
|
126
|
+
// ── TodoWrite (TodoWriteOutput): {oldTodos, newTodos}
|
|
127
|
+
if (Array.isArray(toolResult.oldTodos) && Array.isArray(toolResult.newTodos)) {
|
|
128
|
+
return 'TodoWrite';
|
|
129
|
+
}
|
|
130
|
+
// ── Bash (BashOutput): {stdout, stderr, interrupted, ...}
|
|
131
|
+
if (toolResult.stdout !== undefined || toolResult.stderr !== undefined) {
|
|
103
132
|
return 'Bash';
|
|
104
|
-
|
|
133
|
+
}
|
|
134
|
+
// ── WebSearch (WebSearchOutput): {query, results}
|
|
135
|
+
if (typeof toolResult.query === 'string' && Array.isArray(toolResult.results)) {
|
|
136
|
+
return 'WebSearch';
|
|
137
|
+
}
|
|
138
|
+
// ── WebFetch (WebFetchOutput): {url, result, code, bytes}
|
|
139
|
+
if (typeof toolResult.url === 'string' && typeof toolResult.result === 'string'
|
|
140
|
+
&& typeof toolResult.code === 'number') {
|
|
141
|
+
return 'WebFetch';
|
|
142
|
+
}
|
|
143
|
+
// ── send_file (custom MCP tool): content is JSON with _type marker
|
|
105
144
|
if (toolResult.content && typeof toolResult.content === 'string' && toolResult.type === 'text') {
|
|
106
145
|
try {
|
|
107
146
|
const parsed = JSON.parse(toolResult.content);
|
|
@@ -112,6 +151,10 @@ function extractToolName(toolResult) {
|
|
|
112
151
|
// SDK 0.2.x: content-only results from nested tool calls (no stdout/stderr wrapper)
|
|
113
152
|
return 'Bash';
|
|
114
153
|
}
|
|
154
|
+
// ── Agent/Task output: {agentId, content, status}
|
|
155
|
+
if (toolResult.agentId && Array.isArray(toolResult.content) && toolResult.status) {
|
|
156
|
+
return 'Task';
|
|
157
|
+
}
|
|
115
158
|
return 'unknown';
|
|
116
159
|
}
|
|
117
160
|
// Look up tool name from the most recent assistant message's tool_use blocks by tool_use_id
|
|
@@ -122,7 +165,12 @@ function lookupToolNameFromHistory(messages, toolUseId) {
|
|
|
122
165
|
const msg = messages[i];
|
|
123
166
|
if (msg.role !== 'assistant')
|
|
124
167
|
continue;
|
|
125
|
-
|
|
168
|
+
// msg.content is the SDK message object: {role: 'assistant', content: [{type: 'text',...}, {type: 'tool_use',...}]}
|
|
169
|
+
let content = typeof msg.content === 'string' ? null : msg.content;
|
|
170
|
+
// Unwrap nested content: {content: [...]} → [...]
|
|
171
|
+
if (content && !Array.isArray(content) && Array.isArray(content.content)) {
|
|
172
|
+
content = content.content;
|
|
173
|
+
}
|
|
126
174
|
if (!Array.isArray(content))
|
|
127
175
|
continue;
|
|
128
176
|
const toolUse = content.find((c) => c.type === 'tool_use' && c.id === toolUseId);
|
|
@@ -1042,10 +1090,11 @@ export class AgentSessionManager {
|
|
|
1042
1090
|
}
|
|
1043
1091
|
}
|
|
1044
1092
|
if (toolResult) {
|
|
1093
|
+
// History lookup is authoritative: the assistant's tool_use block names the tool.
|
|
1094
|
+
// Heuristic detection can't distinguish Bash/Grep/Glob/etc (all have {stdout,stderr}).
|
|
1095
|
+
const historyName = lookupToolNameFromHistory(session.messages, toolUseId);
|
|
1045
1096
|
const detectedName = extractToolName(toolResult);
|
|
1046
|
-
const resolvedName =
|
|
1047
|
-
? detectedName
|
|
1048
|
-
: (lookupToolNameFromHistory(session.messages, toolUseId) || detectedName);
|
|
1097
|
+
const resolvedName = historyName || detectedName;
|
|
1049
1098
|
onOutput({
|
|
1050
1099
|
type: 'tool_result',
|
|
1051
1100
|
data: toolResult,
|
package/dist/ttc-cli.tar.gz
CHANGED
|
Binary file
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@exreve/exk",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.51",
|
|
4
4
|
"description": "exk - Control Claude CLI with voice and programmable interfaces",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -61,4 +61,4 @@
|
|
|
61
61
|
"engines": {
|
|
62
62
|
"node": ">=20.0.0"
|
|
63
63
|
}
|
|
64
|
-
}
|
|
64
|
+
}
|