wave-code 1.0.5 → 1.0.7
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/components/AgentsManager.d.ts +7 -0
- package/dist/components/AgentsManager.js +109 -0
- package/dist/components/ConfirmationSelector.js +17 -3
- package/dist/components/InputBox.js +7 -21
- package/dist/components/LoginCommand.js +31 -2
- package/dist/components/MarketplaceAddForm.js +16 -2
- package/dist/constants/commands.js +6 -0
- package/dist/contexts/useChat.d.ts +2 -1
- package/dist/contexts/useChat.js +96 -21
- package/dist/hooks/useInputManager.d.ts +2 -0
- package/dist/hooks/useInputManager.js +8 -0
- package/dist/managers/inputHandlers.js +3 -0
- package/dist/managers/inputReducer.d.ts +4 -0
- package/dist/managers/inputReducer.js +8 -0
- package/dist/reducers/agentsManagerReducer.d.ts +26 -0
- package/dist/reducers/agentsManagerReducer.js +54 -0
- package/dist/stdio/agentBridge.d.ts +4 -0
- package/dist/stdio/agentBridge.js +45 -10
- package/dist/stdio/protocol.d.ts +1 -1
- package/dist/utils/rewindCheckpoints.d.ts +2 -2
- package/dist/utils/rewindCheckpoints.js +4 -2
- package/dist/utils/usageSummary.d.ts +0 -4
- package/dist/utils/usageSummary.js +1 -34
- package/package.json +2 -2
- package/src/components/AgentsManager.tsx +290 -0
- package/src/components/ConfirmationSelector.tsx +18 -3
- package/src/components/InputBox.tsx +54 -45
- package/src/components/LoginCommand.tsx +35 -2
- package/src/components/MarketplaceAddForm.tsx +17 -2
- package/src/constants/commands.ts +6 -0
- package/src/contexts/useChat.tsx +159 -72
- package/src/hooks/useInputManager.ts +8 -0
- package/src/managers/inputHandlers.ts +2 -0
- package/src/managers/inputReducer.ts +10 -0
- package/src/reducers/agentsManagerReducer.ts +91 -0
- package/src/stdio/agentBridge.ts +55 -9
- package/src/stdio/protocol.ts +2 -0
- package/src/utils/rewindCheckpoints.ts +3 -2
- package/src/utils/usageSummary.ts +2 -46
|
@@ -111,6 +111,7 @@ export interface InputState {
|
|
|
111
111
|
imageIdCounter: number;
|
|
112
112
|
showBackgroundTaskManager: boolean;
|
|
113
113
|
showMcpManager: boolean;
|
|
114
|
+
showAgentsManager: boolean;
|
|
114
115
|
showRewindManager: boolean;
|
|
115
116
|
showHelp: boolean;
|
|
116
117
|
showStatusCommand: boolean;
|
|
@@ -187,6 +188,9 @@ export type InputAction = {
|
|
|
187
188
|
} | {
|
|
188
189
|
type: "SET_SHOW_MCP_MANAGER";
|
|
189
190
|
payload: boolean;
|
|
191
|
+
} | {
|
|
192
|
+
type: "SET_SHOW_AGENTS_MANAGER";
|
|
193
|
+
payload: boolean;
|
|
190
194
|
} | {
|
|
191
195
|
type: "SET_SHOW_REWIND_MANAGER";
|
|
192
196
|
payload: boolean;
|
|
@@ -26,6 +26,7 @@ export const initialState = {
|
|
|
26
26
|
imageIdCounter: 1,
|
|
27
27
|
showBackgroundTaskManager: false,
|
|
28
28
|
showMcpManager: false,
|
|
29
|
+
showAgentsManager: false,
|
|
29
30
|
showRewindManager: false,
|
|
30
31
|
showHelp: false,
|
|
31
32
|
showStatusCommand: false,
|
|
@@ -347,6 +348,12 @@ export function inputReducer(state, action) {
|
|
|
347
348
|
showMcpManager: action.payload,
|
|
348
349
|
selectorJustUsed: !action.payload ? true : state.selectorJustUsed,
|
|
349
350
|
};
|
|
351
|
+
case "SET_SHOW_AGENTS_MANAGER":
|
|
352
|
+
return {
|
|
353
|
+
...state,
|
|
354
|
+
showAgentsManager: action.payload,
|
|
355
|
+
selectorJustUsed: !action.payload ? true : state.selectorJustUsed,
|
|
356
|
+
};
|
|
350
357
|
case "SET_SHOW_REWIND_MANAGER":
|
|
351
358
|
return {
|
|
352
359
|
...state,
|
|
@@ -695,6 +702,7 @@ export function inputReducer(state, action) {
|
|
|
695
702
|
}
|
|
696
703
|
if (!(state.showBackgroundTaskManager ||
|
|
697
704
|
state.showMcpManager ||
|
|
705
|
+
state.showAgentsManager ||
|
|
698
706
|
state.showRewindManager ||
|
|
699
707
|
state.showHelp ||
|
|
700
708
|
state.showStatusCommand ||
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { Key } from "ink";
|
|
2
|
+
export type PendingEffect = {
|
|
3
|
+
type: "CANCEL";
|
|
4
|
+
};
|
|
5
|
+
export interface AgentsManagerState {
|
|
6
|
+
selectedIndex: number;
|
|
7
|
+
viewMode: "list" | "detail";
|
|
8
|
+
pendingEffect: PendingEffect | null;
|
|
9
|
+
}
|
|
10
|
+
export type AgentsManagerAction = {
|
|
11
|
+
type: "MOVE_UP";
|
|
12
|
+
} | {
|
|
13
|
+
type: "MOVE_DOWN";
|
|
14
|
+
itemCount: number;
|
|
15
|
+
} | {
|
|
16
|
+
type: "SET_VIEW_MODE";
|
|
17
|
+
viewMode: "list" | "detail";
|
|
18
|
+
} | {
|
|
19
|
+
type: "HANDLE_KEY";
|
|
20
|
+
input: string;
|
|
21
|
+
key: Key;
|
|
22
|
+
itemCount: number;
|
|
23
|
+
} | {
|
|
24
|
+
type: "CLEAR_PENDING_EFFECT";
|
|
25
|
+
};
|
|
26
|
+
export declare function agentsManagerReducer(state: AgentsManagerState, action: AgentsManagerAction): AgentsManagerState;
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
export function agentsManagerReducer(state, action) {
|
|
2
|
+
switch (action.type) {
|
|
3
|
+
case "MOVE_UP":
|
|
4
|
+
return {
|
|
5
|
+
...state,
|
|
6
|
+
selectedIndex: Math.max(0, state.selectedIndex - 1),
|
|
7
|
+
};
|
|
8
|
+
case "MOVE_DOWN":
|
|
9
|
+
return {
|
|
10
|
+
...state,
|
|
11
|
+
selectedIndex: Math.min(Math.max(0, action.itemCount - 1), state.selectedIndex + 1),
|
|
12
|
+
};
|
|
13
|
+
case "SET_VIEW_MODE":
|
|
14
|
+
return { ...state, viewMode: action.viewMode };
|
|
15
|
+
case "HANDLE_KEY": {
|
|
16
|
+
const { key, itemCount } = action;
|
|
17
|
+
if (key.return) {
|
|
18
|
+
if (state.viewMode === "list") {
|
|
19
|
+
return { ...state, viewMode: "detail" };
|
|
20
|
+
}
|
|
21
|
+
// Aligned with Claude Code AgentDetail: Enter returns to the list.
|
|
22
|
+
return { ...state, viewMode: "list" };
|
|
23
|
+
}
|
|
24
|
+
if (key.escape) {
|
|
25
|
+
if (state.viewMode === "detail") {
|
|
26
|
+
return { ...state, viewMode: "list" };
|
|
27
|
+
}
|
|
28
|
+
return { ...state, pendingEffect: { type: "CANCEL" } };
|
|
29
|
+
}
|
|
30
|
+
// Detail view does not respond to arrow keys (aligned with CC
|
|
31
|
+
// AgentDetail, which only Esc/Enter back to the list).
|
|
32
|
+
if (state.viewMode === "detail") {
|
|
33
|
+
return state;
|
|
34
|
+
}
|
|
35
|
+
if (key.upArrow) {
|
|
36
|
+
return {
|
|
37
|
+
...state,
|
|
38
|
+
selectedIndex: Math.max(0, state.selectedIndex - 1),
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
if (key.downArrow) {
|
|
42
|
+
return {
|
|
43
|
+
...state,
|
|
44
|
+
selectedIndex: Math.min(Math.max(0, itemCount - 1), state.selectedIndex + 1),
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
return state;
|
|
48
|
+
}
|
|
49
|
+
case "CLEAR_PENDING_EFFECT":
|
|
50
|
+
return { ...state, pendingEffect: null };
|
|
51
|
+
default:
|
|
52
|
+
return state;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
@@ -56,6 +56,8 @@ export declare class AgentBridge {
|
|
|
56
56
|
private removeWorktreeSession;
|
|
57
57
|
private getSessionInfo;
|
|
58
58
|
private updateConfig;
|
|
59
|
+
private getConfiguredModels;
|
|
60
|
+
private setModel;
|
|
59
61
|
private sendMessage;
|
|
60
62
|
private bang;
|
|
61
63
|
private askBtw;
|
|
@@ -71,6 +73,7 @@ export declare class AgentBridge {
|
|
|
71
73
|
private compact;
|
|
72
74
|
private getBackgroundTaskOutput;
|
|
73
75
|
private stopBackgroundTask;
|
|
76
|
+
private backgroundCurrentTask;
|
|
74
77
|
private getWorkflowRuns;
|
|
75
78
|
private stopWorkflowRun;
|
|
76
79
|
private setPermissionMode;
|
|
@@ -79,6 +82,7 @@ export declare class AgentBridge {
|
|
|
79
82
|
private connectMcpServer;
|
|
80
83
|
private disconnectMcpServer;
|
|
81
84
|
private getSlashCommands;
|
|
85
|
+
private getSubagentConfigurations;
|
|
82
86
|
private searchFiles;
|
|
83
87
|
/**
|
|
84
88
|
* Writes an uploaded file (from the desktop/webview "+上传文件" flow) into the
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
* - Implement the canUseTool permission flow over the stdio protocol
|
|
15
15
|
* - Handle config updates by destroying and recreating the Agent
|
|
16
16
|
*/
|
|
17
|
-
import { Agent, listSessions, searchFiles, generateRandomName, getDefaultRemoteBranch, getMessageContent, PromptHistoryManager, AuthService, PluginCore, validateWorktreeRemovalPath, } from "wave-agent-sdk";
|
|
17
|
+
import { Agent, listSessions, searchFiles, generateRandomName, getDefaultRemoteBranch, getMessageContent, PromptHistoryManager, AuthService, PluginCore, validateWorktreeRemovalPath, loadUserConfigEnv, } from "wave-agent-sdk";
|
|
18
18
|
import { INVALID_PARAMS as PROTOCOL_INVALID_PARAMS, INTERNAL_ERROR as PROTOCOL_INTERNAL_ERROR, METHOD_NOT_FOUND as PROTOCOL_METHOD_NOT_FOUND, } from "./protocol.js";
|
|
19
19
|
import { execFileSync } from "node:child_process";
|
|
20
20
|
import { mkdirSync, existsSync, writeFileSync } from "node:fs";
|
|
@@ -32,6 +32,15 @@ export class AgentBridge {
|
|
|
32
32
|
this.pendingPermissions = new Map();
|
|
33
33
|
this.permissionCounter = 0;
|
|
34
34
|
this.emit = options.emit;
|
|
35
|
+
// Mirror the user-level settings env WAVE_SERVER_URL into process.env
|
|
36
|
+
// before any agent initializes. getAuthStatus (webviewReady →
|
|
37
|
+
// pushInitialState) can run before the first agent, and AuthService falls
|
|
38
|
+
// back to the default URL otherwise — refreshing a custom-domain token
|
|
39
|
+
// against the wrong host 401s into a logged-out state.
|
|
40
|
+
const userEnv = loadUserConfigEnv();
|
|
41
|
+
if (userEnv.WAVE_SERVER_URL) {
|
|
42
|
+
process.env.WAVE_SERVER_URL = userEnv.WAVE_SERVER_URL;
|
|
43
|
+
}
|
|
35
44
|
}
|
|
36
45
|
// ── Public API ────────────────────────────────────────────────
|
|
37
46
|
async handleRequest(method, params, sessionId) {
|
|
@@ -52,6 +61,10 @@ export class AgentBridge {
|
|
|
52
61
|
return this.listPendingPermissions();
|
|
53
62
|
case "updateConfig":
|
|
54
63
|
return this.updateConfig(p, sessionId);
|
|
64
|
+
case "getConfiguredModels":
|
|
65
|
+
return this.getConfiguredModels(sessionId);
|
|
66
|
+
case "setModel":
|
|
67
|
+
return this.setModel(p.model, sessionId);
|
|
55
68
|
// ── Messages ──
|
|
56
69
|
case "sendMessage":
|
|
57
70
|
return this.sendMessage(p, sessionId);
|
|
@@ -92,6 +105,8 @@ export class AgentBridge {
|
|
|
92
105
|
// ── Commands ──
|
|
93
106
|
case "getSlashCommands":
|
|
94
107
|
return this.getSlashCommands(sessionId);
|
|
108
|
+
case "getSubagentConfigurations":
|
|
109
|
+
return this.getSubagentConfigurations(sessionId);
|
|
95
110
|
// ── File / History (global — no session required) ──
|
|
96
111
|
case "searchFiles":
|
|
97
112
|
return this.searchFiles(p, sessionId);
|
|
@@ -140,6 +155,8 @@ export class AgentBridge {
|
|
|
140
155
|
return this.getBackgroundTaskOutput(p.taskId, sessionId);
|
|
141
156
|
case "stopBackgroundTask":
|
|
142
157
|
return this.stopBackgroundTask(p.taskId, sessionId);
|
|
158
|
+
case "backgroundCurrentTask":
|
|
159
|
+
return this.backgroundCurrentTask(sessionId);
|
|
143
160
|
case "getWorkflowRuns":
|
|
144
161
|
return this.getWorkflowRuns(sessionId);
|
|
145
162
|
case "stopWorkflowRun":
|
|
@@ -428,6 +445,22 @@ export class AgentBridge {
|
|
|
428
445
|
});
|
|
429
446
|
return { sessionId: agent.sessionId };
|
|
430
447
|
}
|
|
448
|
+
getConfiguredModels(sessionId) {
|
|
449
|
+
const entry = this.requireSession(sessionId);
|
|
450
|
+
return {
|
|
451
|
+
models: entry.agent.getConfiguredModels(),
|
|
452
|
+
currentModel: entry.agent.getModelConfig().model,
|
|
453
|
+
};
|
|
454
|
+
}
|
|
455
|
+
async setModel(model, sessionId) {
|
|
456
|
+
const entry = this.requireSession(sessionId);
|
|
457
|
+
entry.agent.setModel(model);
|
|
458
|
+
// Keep storedConfig in sync: updateConfig recreates the agent from
|
|
459
|
+
// storedConfig, so without this a later config save would revert the
|
|
460
|
+
// model chosen here.
|
|
461
|
+
entry.storedConfig = { ...entry.storedConfig, model };
|
|
462
|
+
return null;
|
|
463
|
+
}
|
|
431
464
|
// ── Messages ──────────────────────────────────────────────────
|
|
432
465
|
async sendMessage(params, sessionId) {
|
|
433
466
|
const entry = this.requireSession(sessionId);
|
|
@@ -539,6 +572,11 @@ export class AgentBridge {
|
|
|
539
572
|
const success = entry.agent.stopBackgroundTask(taskId);
|
|
540
573
|
return { success };
|
|
541
574
|
}
|
|
575
|
+
async backgroundCurrentTask(sessionId) {
|
|
576
|
+
const entry = this.requireSession(sessionId);
|
|
577
|
+
await entry.agent.backgroundCurrentTask();
|
|
578
|
+
return null;
|
|
579
|
+
}
|
|
542
580
|
async getWorkflowRuns(sessionId) {
|
|
543
581
|
const entry = this.requireSession(sessionId);
|
|
544
582
|
const runs = await entry.agent.getWorkflowRuns();
|
|
@@ -585,6 +623,10 @@ export class AgentBridge {
|
|
|
585
623
|
const entry = this.requireSession(sessionId);
|
|
586
624
|
return { commands: entry.agent.getSlashCommands() };
|
|
587
625
|
}
|
|
626
|
+
getSubagentConfigurations(sessionId) {
|
|
627
|
+
const entry = this.requireSession(sessionId);
|
|
628
|
+
return { configurations: entry.agent.getSubagentConfigurations() };
|
|
629
|
+
}
|
|
588
630
|
// ── File / History (global) ───────────────────────────────────
|
|
589
631
|
async searchFiles(params, sessionId) {
|
|
590
632
|
const files = await searchFiles(params.query, {
|
|
@@ -659,13 +701,6 @@ export class AgentBridge {
|
|
|
659
701
|
// ── Auth (global) ────────────────────────────────────────────
|
|
660
702
|
async getAuthStatus() {
|
|
661
703
|
const authService = AuthService.getInstance();
|
|
662
|
-
// A stale-but-refreshable token still means "logged in" — the daemon may
|
|
663
|
-
// have started with an expired access token (hourly expiry) and only
|
|
664
|
-
// refreshes lazily on the first API call. Without this proactive refresh a
|
|
665
|
-
// fresh client querying right after daemon start gets a false
|
|
666
|
-
// isAuthenticated and e.g. the desktop welcome page keeps showing the
|
|
667
|
-
// login button for an authenticated host. Mirrors the refresh that
|
|
668
|
-
// createAuthAwareFetch does before every real request.
|
|
669
704
|
await authService.checkAndRefreshTokenIfNeeded();
|
|
670
705
|
return {
|
|
671
706
|
isAuthenticated: authService.isSSOAuthenticated(),
|
|
@@ -861,8 +896,8 @@ export class AgentBridge {
|
|
|
861
896
|
onUpdateBangMessage: (command, output, messageId) => {
|
|
862
897
|
this.emit("bangMessageUpdated", { command, output, messageId }, ctx.registeredSessionId);
|
|
863
898
|
},
|
|
864
|
-
onCompleteBangMessage: (command, exitCode, messageId) => {
|
|
865
|
-
this.emit("bangMessageCompleted", { command, exitCode, messageId }, ctx.registeredSessionId);
|
|
899
|
+
onCompleteBangMessage: (command, exitCode, messageId, output) => {
|
|
900
|
+
this.emit("bangMessageCompleted", { command, exitCode, messageId, output }, ctx.registeredSessionId);
|
|
866
901
|
},
|
|
867
902
|
onNotificationMessageAdded: (params) => {
|
|
868
903
|
const msg = ctx.agent?.messages.find((m) => m.role === "user" &&
|
package/dist/stdio/protocol.d.ts
CHANGED
|
@@ -34,7 +34,7 @@ export declare const INVALID_REQUEST = -32600;
|
|
|
34
34
|
export declare const METHOD_NOT_FOUND = -32601;
|
|
35
35
|
export declare const INVALID_PARAMS = -32602;
|
|
36
36
|
export declare const INTERNAL_ERROR = -32603;
|
|
37
|
-
export type RequestMethod = "initialize" | "destroy" | "restoreSession" | "listSessions" | "getSessionInfo" | "sendMessage" | "bang" | "askBtw" | "abortMessage" | "clearMessages" | "rewindToMessage" | "listRewindCheckpoints" | "deleteQueuedMessage" | "updateQueuedMessage" | "deleteQueuedMessageById" | "getMessages" | "getFullMessageThread" | "setPermissionMode" | "getPermissionMode" | "getMcpServers" | "connectMcpServer" | "disconnectMcpServer" | "getSlashCommands" | "searchFiles" | "writeArtifactFile" | "getPromptHistory" | "searchPromptHistory" | "updateConfig" | "listPendingPermissions" | "getAuthStatus" | "login" | "logout" | "listPlugins" | "installPlugin" | "uninstallPlugin" | "enablePlugin" | "disablePlugin" | "updatePlugin" | "listMarketplaces" | "addMarketplace" | "removeMarketplace" | "updateMarketplace" | "compact" | "getBackgroundTaskOutput" | "stopBackgroundTask" | "getWorkflowRuns" | "stopWorkflowRun" | "listGitBranches" | "createWorktree" | "removeWorktree";
|
|
37
|
+
export type RequestMethod = "initialize" | "destroy" | "restoreSession" | "listSessions" | "getSessionInfo" | "sendMessage" | "bang" | "askBtw" | "abortMessage" | "clearMessages" | "rewindToMessage" | "listRewindCheckpoints" | "deleteQueuedMessage" | "updateQueuedMessage" | "deleteQueuedMessageById" | "getMessages" | "getFullMessageThread" | "setPermissionMode" | "getPermissionMode" | "getMcpServers" | "connectMcpServer" | "disconnectMcpServer" | "getSlashCommands" | "searchFiles" | "writeArtifactFile" | "getPromptHistory" | "searchPromptHistory" | "updateConfig" | "getConfiguredModels" | "setModel" | "listPendingPermissions" | "getAuthStatus" | "login" | "logout" | "listPlugins" | "installPlugin" | "uninstallPlugin" | "enablePlugin" | "disablePlugin" | "updatePlugin" | "listMarketplaces" | "addMarketplace" | "removeMarketplace" | "updateMarketplace" | "compact" | "getBackgroundTaskOutput" | "stopBackgroundTask" | "getWorkflowRuns" | "stopWorkflowRun" | "listGitBranches" | "createWorktree" | "removeWorktree";
|
|
38
38
|
export type ClientNotificationMethod = "permissionResponse";
|
|
39
39
|
export type ServerNotificationMethod = "userMessageAdded" | "assistantMessageAdded" | "assistantContentUpdated" | "assistantReasoningUpdated" | "toolBlockUpdated" | "errorBlockAdded" | "loadingChange" | "commandRunningChange" | "queuedMessagesChange" | "tasksChange" | "sessionIdChange" | "permissionModeChange" | "mcpServersChange" | "workdirChange" | "bangMessageAdded" | "bangMessageUpdated" | "bangMessageCompleted" | "notificationMessageAdded" | "permissionRequest" | "authUrl" | "compactBlockAdded" | "compactionStateChange" | "backgroundTasksChange" | "btwContent";
|
|
40
40
|
export declare function isRequest(msg: unknown): msg is JsonRpcRequest;
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import type { Message } from "wave-agent-sdk";
|
|
2
2
|
/**
|
|
3
3
|
* 判断一条 user 消息能否作为 /rewind 检查点。
|
|
4
|
-
* 后台任务通知(task_notification
|
|
5
|
-
*
|
|
4
|
+
* 后台任务通知(task_notification)、hook 注入的消息(source: "hook")
|
|
5
|
+
* 与 bang 命令消息都是系统生成、用户不可见的,不能作为回滚点。
|
|
6
6
|
* CLI 交互式选择器与 stdio listRewindCheckpoints 共用此判定,避免两处漂移。
|
|
7
7
|
*/
|
|
8
8
|
export declare function isUserCheckpointMessage(m: Message): boolean;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* 判断一条 user 消息能否作为 /rewind 检查点。
|
|
3
|
-
* 后台任务通知(task_notification
|
|
4
|
-
*
|
|
3
|
+
* 后台任务通知(task_notification)、hook 注入的消息(source: "hook")
|
|
4
|
+
* 与 bang 命令消息都是系统生成、用户不可见的,不能作为回滚点。
|
|
5
5
|
* CLI 交互式选择器与 stdio listRewindCheckpoints 共用此判定,避免两处漂移。
|
|
6
6
|
*/
|
|
7
7
|
export function isUserCheckpointMessage(m) {
|
|
@@ -11,5 +11,7 @@ export function isUserCheckpointMessage(m) {
|
|
|
11
11
|
return false;
|
|
12
12
|
if (m.blocks.some((b) => b.type === "text" && b.source === "hook"))
|
|
13
13
|
return false;
|
|
14
|
+
if (m.blocks.some((b) => b.type === "bang"))
|
|
15
|
+
return false;
|
|
14
16
|
return true;
|
|
15
17
|
}
|
|
@@ -13,10 +13,6 @@ export interface TokenSummary {
|
|
|
13
13
|
};
|
|
14
14
|
cache_read_input_tokens?: number;
|
|
15
15
|
cache_creation_input_tokens?: number;
|
|
16
|
-
cache_creation?: {
|
|
17
|
-
ephemeral_5m_input_tokens: number;
|
|
18
|
-
ephemeral_1h_input_tokens: number;
|
|
19
|
-
};
|
|
20
16
|
}
|
|
21
17
|
/**
|
|
22
18
|
* Calculate token usage summary by model from usage array
|
|
@@ -34,20 +34,6 @@ export function calculateTokenSummary(usages) {
|
|
|
34
34
|
(summary.cache_creation_input_tokens || 0) +
|
|
35
35
|
usage.cache_creation_input_tokens;
|
|
36
36
|
}
|
|
37
|
-
if (usage.cache_creation &&
|
|
38
|
-
(usage.cache_creation.ephemeral_5m_input_tokens > 0 ||
|
|
39
|
-
usage.cache_creation.ephemeral_1h_input_tokens > 0)) {
|
|
40
|
-
if (!summary.cache_creation) {
|
|
41
|
-
summary.cache_creation = {
|
|
42
|
-
ephemeral_5m_input_tokens: 0,
|
|
43
|
-
ephemeral_1h_input_tokens: 0,
|
|
44
|
-
};
|
|
45
|
-
}
|
|
46
|
-
summary.cache_creation.ephemeral_5m_input_tokens +=
|
|
47
|
-
usage.cache_creation.ephemeral_5m_input_tokens || 0;
|
|
48
|
-
summary.cache_creation.ephemeral_1h_input_tokens +=
|
|
49
|
-
usage.cache_creation.ephemeral_1h_input_tokens || 0;
|
|
50
|
-
}
|
|
51
37
|
// Track operation types
|
|
52
38
|
if (usage.operation_type === "agent") {
|
|
53
39
|
summary.operations.agent_calls += 1;
|
|
@@ -86,8 +72,6 @@ export function displayUsageSummary(usages, sessionFilePath) {
|
|
|
86
72
|
let totalCompactions = 0;
|
|
87
73
|
let totalCacheRead = 0;
|
|
88
74
|
let totalCacheCreation = 0;
|
|
89
|
-
let totalCache5m = 0;
|
|
90
|
-
let totalCache1h = 0;
|
|
91
75
|
let hasCacheData = false;
|
|
92
76
|
for (const [, summary] of Object.entries(summaries)) {
|
|
93
77
|
console.log(`Model: ${summary.model}`);
|
|
@@ -96,8 +80,7 @@ export function displayUsageSummary(usages, sessionFilePath) {
|
|
|
96
80
|
console.log(` Total tokens: ${summary.total_tokens.toLocaleString()}`);
|
|
97
81
|
// Display cache information if available
|
|
98
82
|
if (summary.cache_read_input_tokens ||
|
|
99
|
-
summary.cache_creation_input_tokens
|
|
100
|
-
summary.cache_creation) {
|
|
83
|
+
summary.cache_creation_input_tokens) {
|
|
101
84
|
hasCacheData = true;
|
|
102
85
|
console.log(" Cache Usage:");
|
|
103
86
|
if (summary.cache_read_input_tokens &&
|
|
@@ -110,16 +93,6 @@ export function displayUsageSummary(usages, sessionFilePath) {
|
|
|
110
93
|
console.log(` Created cache: ${summary.cache_creation_input_tokens.toLocaleString()} tokens`);
|
|
111
94
|
totalCacheCreation += summary.cache_creation_input_tokens;
|
|
112
95
|
}
|
|
113
|
-
if (summary.cache_creation) {
|
|
114
|
-
if (summary.cache_creation.ephemeral_5m_input_tokens > 0) {
|
|
115
|
-
console.log(` 5m cache: ${summary.cache_creation.ephemeral_5m_input_tokens.toLocaleString()} tokens`);
|
|
116
|
-
totalCache5m += summary.cache_creation.ephemeral_5m_input_tokens;
|
|
117
|
-
}
|
|
118
|
-
if (summary.cache_creation.ephemeral_1h_input_tokens > 0) {
|
|
119
|
-
console.log(` 1h cache: ${summary.cache_creation.ephemeral_1h_input_tokens.toLocaleString()} tokens`);
|
|
120
|
-
totalCache1h += summary.cache_creation.ephemeral_1h_input_tokens;
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
96
|
}
|
|
124
97
|
console.log(` Operations: ${summary.operations.agent_calls} agent calls, ${summary.operations.compactions} compactions`);
|
|
125
98
|
console.log();
|
|
@@ -142,12 +115,6 @@ export function displayUsageSummary(usages, sessionFilePath) {
|
|
|
142
115
|
if (totalCacheCreation > 0) {
|
|
143
116
|
console.log(` Created cache: ${totalCacheCreation.toLocaleString()} tokens`);
|
|
144
117
|
}
|
|
145
|
-
if (totalCache5m > 0) {
|
|
146
|
-
console.log(` 5m cache: ${totalCache5m.toLocaleString()} tokens`);
|
|
147
|
-
}
|
|
148
|
-
if (totalCache1h > 0) {
|
|
149
|
-
console.log(` 1h cache: ${totalCache1h.toLocaleString()} tokens`);
|
|
150
|
-
}
|
|
151
118
|
}
|
|
152
119
|
console.log(` Operations: ${totalAgentCalls} agent calls, ${totalCompactions} compactions`);
|
|
153
120
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "wave-code",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.7",
|
|
4
4
|
"description": "CLI-based code assistant powered by AI, built with React and Ink",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -43,7 +43,7 @@
|
|
|
43
43
|
"wrap-ansi": "^10.0.0",
|
|
44
44
|
"yargs": "^17.7.2",
|
|
45
45
|
"zod": "^3.23.8",
|
|
46
|
-
"wave-agent-sdk": "1.0.
|
|
46
|
+
"wave-agent-sdk": "1.0.7"
|
|
47
47
|
},
|
|
48
48
|
"devDependencies": {
|
|
49
49
|
"@types/react": "^19.1.8",
|