@exreve/exk 1.0.48 → 1.0.50
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 +59 -40
- package/dist/ttc-cli.tar.gz +0 -0
- package/package.json +2 -2
package/dist/agentSession.js
CHANGED
|
@@ -99,6 +99,12 @@ function extractToolName(toolResult) {
|
|
|
99
99
|
return 'Edit';
|
|
100
100
|
return (toolResult.content !== undefined || toolResult.type === 'create') ? 'Write' : 'Read';
|
|
101
101
|
}
|
|
102
|
+
// Grep: {mode, numFiles, filenames, content, numLines}
|
|
103
|
+
if (toolResult.numFiles !== undefined && toolResult.filenames !== undefined && toolResult.mode !== undefined)
|
|
104
|
+
return 'Grep';
|
|
105
|
+
// Glob: {type, pattern, files}
|
|
106
|
+
if (toolResult.files !== undefined && toolResult.pattern !== undefined && !toolResult.stdout)
|
|
107
|
+
return 'Glob';
|
|
102
108
|
if (toolResult.stdout !== undefined || toolResult.stderr !== undefined)
|
|
103
109
|
return 'Bash';
|
|
104
110
|
// send_file tool: content is JSON with _type marker — detect before Bash fallback
|
|
@@ -122,7 +128,12 @@ function lookupToolNameFromHistory(messages, toolUseId) {
|
|
|
122
128
|
const msg = messages[i];
|
|
123
129
|
if (msg.role !== 'assistant')
|
|
124
130
|
continue;
|
|
125
|
-
|
|
131
|
+
// msg.content is the SDK message object: {role: 'assistant', content: [{type: 'text',...}, {type: 'tool_use',...}]}
|
|
132
|
+
let content = typeof msg.content === 'string' ? null : msg.content;
|
|
133
|
+
// Unwrap nested content: {content: [...]} → [...]
|
|
134
|
+
if (content && !Array.isArray(content) && Array.isArray(content.content)) {
|
|
135
|
+
content = content.content;
|
|
136
|
+
}
|
|
126
137
|
if (!Array.isArray(content))
|
|
127
138
|
continue;
|
|
128
139
|
const toolUse = content.find((c) => c.type === 'tool_use' && c.id === toolUseId);
|
|
@@ -960,10 +971,14 @@ export class AgentSessionManager {
|
|
|
960
971
|
}
|
|
961
972
|
else if (message.type === 'user') {
|
|
962
973
|
const msg = message;
|
|
963
|
-
// SDK
|
|
964
|
-
//
|
|
965
|
-
//
|
|
966
|
-
//
|
|
974
|
+
// SDK sends tool results with TWO data sources:
|
|
975
|
+
// message.content[0] — {type:'tool_result', tool_use_id:'...', content: <raw text>}
|
|
976
|
+
// msg.tool_use_result — structured object with {stdout,stderr} for Bash,
|
|
977
|
+
// {type,file} for Read, or [{type:'text',text:'...'}] for MCP tools
|
|
978
|
+
//
|
|
979
|
+
// The tool_use_id lives ONLY in message.content[].tool_use_id.
|
|
980
|
+
// The structured result lives in tool_use_result for built-in tools.
|
|
981
|
+
// For MCP tools, tool_use_result is a content-block array we need to parse.
|
|
967
982
|
let toolResult = null;
|
|
968
983
|
let toolUseId = msg.parent_tool_use_id;
|
|
969
984
|
// STEP 1: Always extract tool_use_id from message.content (authoritative source)
|
|
@@ -974,8 +989,41 @@ export class AgentSessionManager {
|
|
|
974
989
|
toolUseId = toolResultBlock.tool_use_id;
|
|
975
990
|
}
|
|
976
991
|
}
|
|
977
|
-
// STEP 2:
|
|
978
|
-
|
|
992
|
+
// STEP 2: Use tool_use_result as the primary data source.
|
|
993
|
+
// For built-in tools (Bash, Read, Edit, Write, Glob, Grep) it's a structured
|
|
994
|
+
// object like {stdout, stderr} or {type:'text', file:{...}} — use directly.
|
|
995
|
+
// For MCP tools it's a content-block array [{type:'text', text:'...'}] — parse text.
|
|
996
|
+
if (msg.tool_use_result) {
|
|
997
|
+
const raw = msg.tool_use_result;
|
|
998
|
+
if (Array.isArray(raw)) {
|
|
999
|
+
// MCP tool result: [{type:'text', text:'...'}] — extract and parse
|
|
1000
|
+
const textParts = raw
|
|
1001
|
+
.filter((c) => c.type === 'text')
|
|
1002
|
+
.map((c) => c.text);
|
|
1003
|
+
const rawContent = textParts.join('\n');
|
|
1004
|
+
try {
|
|
1005
|
+
toolResult = JSON.parse(rawContent);
|
|
1006
|
+
}
|
|
1007
|
+
catch {
|
|
1008
|
+
toolResult = { content: rawContent, type: 'text' };
|
|
1009
|
+
}
|
|
1010
|
+
}
|
|
1011
|
+
else if (typeof raw === 'object' && raw !== null) {
|
|
1012
|
+
// Built-in tool result: {stdout, stderr, ...} or {type, file, ...} — use directly
|
|
1013
|
+
toolResult = raw;
|
|
1014
|
+
}
|
|
1015
|
+
else if (typeof raw === 'string') {
|
|
1016
|
+
try {
|
|
1017
|
+
toolResult = JSON.parse(raw);
|
|
1018
|
+
}
|
|
1019
|
+
catch {
|
|
1020
|
+
toolResult = { content: raw, type: 'text' };
|
|
1021
|
+
}
|
|
1022
|
+
}
|
|
1023
|
+
}
|
|
1024
|
+
// STEP 3: Fallback to parsing message.content if tool_use_result wasn't available
|
|
1025
|
+
// (e.g. subagent calls where tool_use_result may be absent)
|
|
1026
|
+
if (!toolResult && Array.isArray(msg.message?.content)) {
|
|
979
1027
|
const contentBlocks = msg.message.content;
|
|
980
1028
|
const toolResultBlock = contentBlocks.find((c) => c.type === 'tool_result');
|
|
981
1029
|
if (toolResultBlock) {
|
|
@@ -988,7 +1036,6 @@ export class AgentSessionManager {
|
|
|
988
1036
|
}
|
|
989
1037
|
}
|
|
990
1038
|
else if (Array.isArray(toolResultBlock.content)) {
|
|
991
|
-
// Extract text from content blocks and try to parse as JSON
|
|
992
1039
|
const textParts = toolResultBlock.content
|
|
993
1040
|
.filter((c) => c.type === 'text')
|
|
994
1041
|
.map((c) => c.text);
|
|
@@ -1005,40 +1052,12 @@ export class AgentSessionManager {
|
|
|
1005
1052
|
}
|
|
1006
1053
|
}
|
|
1007
1054
|
}
|
|
1008
|
-
// STEP 3: Fallback to top-level tool_use_result if message.content didn't yield a result
|
|
1009
|
-
// (present in SDK 0.1.x and some 0.2.x messages). Parse the raw content blocks.
|
|
1010
|
-
if (!toolResult && msg.tool_use_result) {
|
|
1011
|
-
const raw = msg.tool_use_result;
|
|
1012
|
-
if (Array.isArray(raw)) {
|
|
1013
|
-
// tool_use_result is [{type:"text", text:"..."}] — extract and parse text
|
|
1014
|
-
const textParts = raw
|
|
1015
|
-
.filter((c) => c.type === 'text')
|
|
1016
|
-
.map((c) => c.text);
|
|
1017
|
-
const rawContent = textParts.join('\n');
|
|
1018
|
-
try {
|
|
1019
|
-
toolResult = JSON.parse(rawContent);
|
|
1020
|
-
}
|
|
1021
|
-
catch {
|
|
1022
|
-
toolResult = { content: rawContent, type: 'text' };
|
|
1023
|
-
}
|
|
1024
|
-
}
|
|
1025
|
-
else if (typeof raw === 'string') {
|
|
1026
|
-
try {
|
|
1027
|
-
toolResult = JSON.parse(raw);
|
|
1028
|
-
}
|
|
1029
|
-
catch {
|
|
1030
|
-
toolResult = { content: raw, type: 'text' };
|
|
1031
|
-
}
|
|
1032
|
-
}
|
|
1033
|
-
else {
|
|
1034
|
-
toolResult = raw;
|
|
1035
|
-
}
|
|
1036
|
-
}
|
|
1037
1055
|
if (toolResult) {
|
|
1056
|
+
// History lookup is authoritative: the assistant's tool_use block names the tool.
|
|
1057
|
+
// Heuristic detection can't distinguish Bash/Grep/Glob/etc (all have {stdout,stderr}).
|
|
1058
|
+
const historyName = lookupToolNameFromHistory(session.messages, toolUseId);
|
|
1038
1059
|
const detectedName = extractToolName(toolResult);
|
|
1039
|
-
const resolvedName =
|
|
1040
|
-
? detectedName
|
|
1041
|
-
: (lookupToolNameFromHistory(session.messages, toolUseId) || detectedName);
|
|
1060
|
+
const resolvedName = historyName || detectedName;
|
|
1042
1061
|
onOutput({
|
|
1043
1062
|
type: 'tool_result',
|
|
1044
1063
|
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.50",
|
|
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
|
+
}
|