@heysalad/cheri-cli 1.2.1 → 1.3.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/CHANGELOG.md +76 -0
- package/README.md +53 -13
- package/package.json +2 -2
- package/src/commands/agent.js +84 -4
- package/src/commands/login.js +10 -0
- package/src/lib/api-client.js +38 -0
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,82 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to Cheri CLI will be documented in this file.
|
|
4
4
|
|
|
5
|
+
## [1.3.1] - 2026-02-17
|
|
6
|
+
|
|
7
|
+
### 🐛 Bug Fixes
|
|
8
|
+
|
|
9
|
+
#### Permission System
|
|
10
|
+
- **Fixed spinner blocking approval prompts**: Approval prompts now appear BEFORE spinners start, preventing terminal blocking
|
|
11
|
+
- **Added upfront permission request**: Tasks with write operations now ask for permissions at the start
|
|
12
|
+
- **Better user experience**: Users can approve entire session with [a]lways option
|
|
13
|
+
|
|
14
|
+
#### How It Works
|
|
15
|
+
1. Agent analyzes task for write operations (build, create, modify, etc.)
|
|
16
|
+
2. Shows upfront permission request: `[Y]es, [n]o, [a]lways`
|
|
17
|
+
3. If approved, proceeds with task
|
|
18
|
+
4. Individual risky operations still prompt for confirmation (unless 'always' was chosen)
|
|
19
|
+
|
|
20
|
+
#### Changes
|
|
21
|
+
- Moved approval logic before `ToolPanel` creation to avoid spinner blocking input
|
|
22
|
+
- Added `requestUpfrontPermissions()` function to analyze and request batch permissions
|
|
23
|
+
- Added `skipApproval` parameter to `executeTool()` to avoid double prompting
|
|
24
|
+
- Improved permission flow for better UX
|
|
25
|
+
|
|
26
|
+
---
|
|
27
|
+
|
|
28
|
+
## [1.3.0] - 2026-02-17
|
|
29
|
+
|
|
30
|
+
### 🎯 Major Feature - Token-Tracked Sessions with Predictable Costs
|
|
31
|
+
|
|
32
|
+
#### Durable Objects Backend
|
|
33
|
+
- **Automatic Workspace Creation**: Workspaces are automatically initialized on login
|
|
34
|
+
- **Session Management**: Each chat is tracked as a separate session with token limits
|
|
35
|
+
- **Token Tracking**: Real-time tracking of input and output tokens
|
|
36
|
+
- **Cost Calculation**: Automatic cost estimation based on AWS Bedrock pricing
|
|
37
|
+
- Claude Sonnet 4: $3/M input, $15/M output
|
|
38
|
+
- Max ~$9 per 1M token session
|
|
39
|
+
- **Auto-Compaction**: Sessions automatically compact at 90% of 1M token limit
|
|
40
|
+
- **Force Compaction**: Sessions force compact at 100% to maintain limits
|
|
41
|
+
|
|
42
|
+
#### New Cloud Tools
|
|
43
|
+
- `get_workspace_stats` - View monthly token usage, limits, and costs
|
|
44
|
+
- `list_sessions` - List all chat sessions with token tracking
|
|
45
|
+
- `get_session_cost` - Get detailed cost breakdown for a specific session
|
|
46
|
+
|
|
47
|
+
#### Backend Architecture
|
|
48
|
+
- **WorkspaceDO**: One Durable Object per user managing all sessions
|
|
49
|
+
- **SessionDO**: One Durable Object per chat tracking messages and tokens
|
|
50
|
+
- **Persistent State**: Automatic state management with Cloudflare Durable Objects
|
|
51
|
+
- **Scalable**: Handles unlimited users with per-user isolation
|
|
52
|
+
|
|
53
|
+
#### API Enhancements
|
|
54
|
+
- `POST /api/workspace/init` - Initialize user workspace
|
|
55
|
+
- `POST /api/workspace/session/create` - Create new tracked session
|
|
56
|
+
- `GET /api/workspace/sessions` - List recent sessions
|
|
57
|
+
- `GET /api/workspace/session/:id` - Get specific session details
|
|
58
|
+
- `GET /api/workspace/stats` - Get workspace statistics
|
|
59
|
+
- `POST /api/session/:id/message` - Add message with token tracking
|
|
60
|
+
- `GET /api/session/:id/cost` - Get session cost estimate
|
|
61
|
+
- `POST /api/session/:id/compact` - Manual session compaction
|
|
62
|
+
|
|
63
|
+
### ✨ Improved
|
|
64
|
+
- **Login Flow**: Now automatically initializes workspace with token tracking
|
|
65
|
+
- **Cost Visibility**: Users can see token usage and costs at any time
|
|
66
|
+
- **Predictable Billing**: 1M token limit per chat ensures known maximum costs
|
|
67
|
+
|
|
68
|
+
### 📚 Documentation
|
|
69
|
+
- Added `ARCHITECTURE_PLAN.md` with complete system design
|
|
70
|
+
- Added `DURABLE_OBJECTS_STARTER.ts` with implementation reference
|
|
71
|
+
- Added `wrangler.toml` for Cloudflare Workers configuration
|
|
72
|
+
|
|
73
|
+
### 🔧 Technical Details
|
|
74
|
+
- Integrated Durable Objects into existing Cloudflare Workers backend
|
|
75
|
+
- Added TypeScript interfaces for Workspace and Session types
|
|
76
|
+
- Implemented token estimation based on character count (~4 chars/token)
|
|
77
|
+
- Added pricing constants for multiple AI models (Claude, Nova)
|
|
78
|
+
|
|
79
|
+
---
|
|
80
|
+
|
|
5
81
|
## [1.1.0] - 2026-02-17
|
|
6
82
|
|
|
7
83
|
### ✨ Added - Beautiful UI & Animations
|
package/README.md
CHANGED
|
@@ -2,7 +2,12 @@
|
|
|
2
2
|
|
|
3
3
|
CLI for [Cheri](https://cheri.heysalad.app) — the AI-powered cloud IDE that never forgets.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
**Features:**
|
|
6
|
+
- 🤖 AI-powered coding agent with tool execution
|
|
7
|
+
- 📊 Token-tracked sessions with predictable costs
|
|
8
|
+
- ☁️ Cloud workspace management
|
|
9
|
+
- 💾 Persistent memory system
|
|
10
|
+
- 🔧 Automatic workspace initialization
|
|
6
11
|
|
|
7
12
|
## Install
|
|
8
13
|
|
|
@@ -15,14 +20,14 @@ Requires Node.js 18+.
|
|
|
15
20
|
## Quick Start
|
|
16
21
|
|
|
17
22
|
```bash
|
|
18
|
-
# Authenticate with your Cheri account
|
|
23
|
+
# Authenticate with your Cheri account (auto-initializes workspace)
|
|
19
24
|
cheri login
|
|
20
25
|
|
|
21
|
-
#
|
|
22
|
-
cheri
|
|
26
|
+
# Start coding with AI agent
|
|
27
|
+
cheri agent "create a todo list app"
|
|
23
28
|
|
|
24
|
-
# Check
|
|
25
|
-
cheri
|
|
29
|
+
# Check token usage and costs
|
|
30
|
+
cheri stats
|
|
26
31
|
|
|
27
32
|
# View API usage and rate limits
|
|
28
33
|
cheri usage
|
|
@@ -30,19 +35,40 @@ cheri usage
|
|
|
30
35
|
|
|
31
36
|
## Commands
|
|
32
37
|
|
|
38
|
+
### AI Agent
|
|
33
39
|
| Command | Description |
|
|
34
40
|
|---|---|
|
|
35
|
-
| `cheri
|
|
41
|
+
| `cheri agent <task>` | Start AI coding agent for a task |
|
|
42
|
+
| `cheri agent -i` | Interactive agent mode |
|
|
43
|
+
| `cheri agent -r <session-id>` | Resume a previous session |
|
|
44
|
+
|
|
45
|
+
### Account & Authentication
|
|
46
|
+
| Command | Description |
|
|
47
|
+
|---|---|
|
|
48
|
+
| `cheri login` | Authenticate with GitHub (auto-initializes workspace) |
|
|
36
49
|
| `cheri status` | Show account and workspace status |
|
|
37
50
|
| `cheri usage` | Show API usage and rate limit status |
|
|
51
|
+
| `cheri stats` | Show token usage statistics and costs |
|
|
52
|
+
|
|
53
|
+
### Workspaces
|
|
54
|
+
| Command | Description |
|
|
55
|
+
|---|---|
|
|
38
56
|
| `cheri workspace launch <repo>` | Launch a new cloud workspace |
|
|
39
57
|
| `cheri workspace list` | List all workspaces |
|
|
40
58
|
| `cheri workspace stop <id>` | Stop a running workspace |
|
|
41
59
|
| `cheri workspace status <id>` | Get workspace status |
|
|
60
|
+
|
|
61
|
+
### Memory
|
|
62
|
+
| Command | Description |
|
|
63
|
+
|---|---|
|
|
42
64
|
| `cheri memory show` | Show current memory entries |
|
|
43
65
|
| `cheri memory add <text>` | Add a memory entry |
|
|
44
66
|
| `cheri memory clear` | Clear all memory |
|
|
45
67
|
| `cheri memory export` | Export memory to JSON |
|
|
68
|
+
|
|
69
|
+
### Configuration
|
|
70
|
+
| Command | Description |
|
|
71
|
+
|---|---|
|
|
46
72
|
| `cheri config list` | Show all configuration |
|
|
47
73
|
| `cheri config get <key>` | Get a config value |
|
|
48
74
|
| `cheri config set <key> <value>` | Set a config value |
|
|
@@ -60,6 +86,26 @@ $ cheri
|
|
|
60
86
|
🍒 cheri > exit
|
|
61
87
|
```
|
|
62
88
|
|
|
89
|
+
## Token Limits & Costs
|
|
90
|
+
|
|
91
|
+
### Per Session (Chat)
|
|
92
|
+
- **Max Tokens**: 1,000,000 tokens per chat
|
|
93
|
+
- **Auto-Compact**: Triggers at 900K tokens (90%)
|
|
94
|
+
- **Force Compact**: Triggers at 1M tokens (100%)
|
|
95
|
+
|
|
96
|
+
### Monthly Limits
|
|
97
|
+
| Plan | Sessions | Tokens/Month | Max Cost/Month |
|
|
98
|
+
|---|---|---|---|
|
|
99
|
+
| Free | 10 | 10M tokens | ~$90 |
|
|
100
|
+
| Pro | 100 | 100M tokens | ~$900 |
|
|
101
|
+
|
|
102
|
+
### Pricing (AWS Bedrock Claude Sonnet 4)
|
|
103
|
+
- **Input**: $3.00 per 1M tokens
|
|
104
|
+
- **Output**: $15.00 per 1M tokens
|
|
105
|
+
- **Max per chat**: ~$9.00 (at 1M tokens, 50/50 split)
|
|
106
|
+
|
|
107
|
+
Use `cheri stats` to check your current token usage and costs.
|
|
108
|
+
|
|
63
109
|
## Rate Limits
|
|
64
110
|
|
|
65
111
|
| Plan | Limit |
|
|
@@ -77,12 +123,6 @@ Config is stored in `~/.cheri/`. Set the API URL if self-hosting:
|
|
|
77
123
|
cheri config set apiUrl https://your-instance.example.com
|
|
78
124
|
```
|
|
79
125
|
|
|
80
|
-
## Links
|
|
81
|
-
|
|
82
|
-
- [Cheri Cloud IDE](https://cheri.heysalad.app)
|
|
83
|
-
- [Dashboard](https://cheri.heysalad.app/dashboard)
|
|
84
|
-
- [GitHub](https://github.com/chilu18/cloud-ide)
|
|
85
|
-
|
|
86
126
|
## 🔗 Links
|
|
87
127
|
|
|
88
128
|
- **Homepage**: [cheri.heysalad.app](https://cheri.heysalad.app)
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@heysalad/cheri-cli",
|
|
3
|
-
"version": "1.
|
|
4
|
-
"description": "Cheri CLI - AI-powered cloud IDE by HeySalad®.
|
|
3
|
+
"version": "1.3.1",
|
|
4
|
+
"description": "Cheri CLI - AI-powered cloud IDE by HeySalad®. With token-tracked sessions, predictable AI costs, and automatic workspace management.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
7
7
|
"cheri": "./bin/cheri.js"
|
package/src/commands/agent.js
CHANGED
|
@@ -50,6 +50,9 @@ const CLOUD_TOOLS = [
|
|
|
50
50
|
{ name: "get_usage", description: "Get the user's API usage and rate limit statistics", parameters: { type: "object", properties: {}, required: [] } },
|
|
51
51
|
{ name: "get_config", description: "Get a configuration value by key (dot notation supported)", parameters: { type: "object", properties: { key: { type: "string", description: "Config key, e.g. 'ai.provider'" } }, required: ["key"] } },
|
|
52
52
|
{ name: "set_config", description: "Set a configuration value", parameters: { type: "object", properties: { key: { type: "string", description: "Config key" }, value: { type: "string", description: "Value to set" } }, required: ["key", "value"] } },
|
|
53
|
+
{ name: "get_workspace_stats", description: "Get token usage statistics for your workspace (monthly usage, limits, costs)", parameters: { type: "object", properties: {}, required: [] } },
|
|
54
|
+
{ name: "list_sessions", description: "List recent chat sessions with token tracking", parameters: { type: "object", properties: {}, required: [] } },
|
|
55
|
+
{ name: "get_session_cost", description: "Get detailed token usage and cost estimate for a specific session", parameters: { type: "object", properties: { sessionId: { type: "string", description: "Session ID to query" } }, required: ["sessionId"] } },
|
|
53
56
|
];
|
|
54
57
|
|
|
55
58
|
// ── Agent meta-tools ────────────────────────────────────────────────────────
|
|
@@ -99,6 +102,9 @@ async function executeCloudTool(name, args) {
|
|
|
99
102
|
setConfigValue(args.key, args.value);
|
|
100
103
|
return { key: args.key, value: args.value, status: "updated" };
|
|
101
104
|
}
|
|
105
|
+
case "get_workspace_stats": return await apiClient.getWorkspaceStats();
|
|
106
|
+
case "list_sessions": return await apiClient.listSessions();
|
|
107
|
+
case "get_session_cost": return await apiClient.getSessionCost(args.sessionId);
|
|
102
108
|
default: return { error: `Unknown cloud tool: ${name}` };
|
|
103
109
|
}
|
|
104
110
|
} catch (err) {
|
|
@@ -175,7 +181,7 @@ async function executeLocalToolEnhanced(name, args) {
|
|
|
175
181
|
// ── Main tool execution with approval + hooks + permissions ───────────────────
|
|
176
182
|
let sessionAutoApprove = false;
|
|
177
183
|
|
|
178
|
-
async function executeTool(name, args, orchestrator, allTools, parseSSE, mcpManager) {
|
|
184
|
+
async function executeTool(name, args, orchestrator, allTools, parseSSE, mcpManager, skipApproval = false) {
|
|
179
185
|
// Permission rules check
|
|
180
186
|
const permission = checkPermission(name, args);
|
|
181
187
|
if (permission === "deny") return { error: `Tool ${name} is denied by permission rules` };
|
|
@@ -206,7 +212,9 @@ async function executeTool(name, args, orchestrator, allTools, parseSSE, mcpMana
|
|
|
206
212
|
}
|
|
207
213
|
|
|
208
214
|
// Local tools — enhanced approval system
|
|
209
|
-
|
|
215
|
+
// Note: For tools executed via executeOne in agent loop, approval is handled
|
|
216
|
+
// BEFORE spinner creation to avoid blocking terminal. This is a fallback.
|
|
217
|
+
if (!sessionAutoApprove && !skipApproval) {
|
|
210
218
|
const decision = shouldApprove(name, args);
|
|
211
219
|
if (decision === "deny") return { error: "Denied by approval policy" };
|
|
212
220
|
if (decision === "ask" || decision === "suggest") {
|
|
@@ -280,6 +288,51 @@ async function* parseSSEStream(response) {
|
|
|
280
288
|
}
|
|
281
289
|
}
|
|
282
290
|
|
|
291
|
+
// ── Upfront permission request ────────────────────────────────────────────────
|
|
292
|
+
async function requestUpfrontPermissions(userRequest) {
|
|
293
|
+
const approvalMode = getApprovalMode();
|
|
294
|
+
|
|
295
|
+
// Skip if in auto mode or already auto-approved this session
|
|
296
|
+
if (approvalMode === "auto" || sessionAutoApprove) {
|
|
297
|
+
return true;
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
// Check if request likely involves write operations
|
|
301
|
+
const writeKeywords = ['build', 'create', 'make', 'write', 'add', 'implement', 'generate', 'fix', 'update', 'modify', 'delete', 'install', 'setup'];
|
|
302
|
+
const hasWriteIntent = writeKeywords.some(kw => userRequest.toLowerCase().includes(kw));
|
|
303
|
+
|
|
304
|
+
if (!hasWriteIntent) {
|
|
305
|
+
return true; // No write operations expected, proceed
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
// Show upfront permission request
|
|
309
|
+
console.log("");
|
|
310
|
+
log.info("This task may require file modifications and command execution.");
|
|
311
|
+
console.log("");
|
|
312
|
+
|
|
313
|
+
return new Promise((resolve) => {
|
|
314
|
+
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
315
|
+
rl.question(
|
|
316
|
+
chalk.yellow(` Grant permissions for this session? ${chalk.dim("[Y]es, [n]o, [a]lways")} `),
|
|
317
|
+
(answer) => {
|
|
318
|
+
rl.close();
|
|
319
|
+
const a = answer.trim().toLowerCase();
|
|
320
|
+
if (a === "a" || a === "always") {
|
|
321
|
+
sessionAutoApprove = true;
|
|
322
|
+
log.success("Auto-approve enabled for this session");
|
|
323
|
+
resolve(true);
|
|
324
|
+
} else if (a === "n" || a === "no") {
|
|
325
|
+
log.warn("Permissions denied");
|
|
326
|
+
resolve(false);
|
|
327
|
+
} else {
|
|
328
|
+
log.success("Permissions granted - will ask before risky operations");
|
|
329
|
+
resolve(true);
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
);
|
|
333
|
+
});
|
|
334
|
+
}
|
|
335
|
+
|
|
283
336
|
// ── Active session state ──────────────────────────────────────────────────────
|
|
284
337
|
let currentSession = null;
|
|
285
338
|
|
|
@@ -291,6 +344,13 @@ export async function runAgent(userRequest, options = {}) {
|
|
|
291
344
|
const memoryContext = getMemoryContext();
|
|
292
345
|
const skillContext = getSkillContext(plugins.skills, userRequest);
|
|
293
346
|
|
|
347
|
+
// Request upfront permissions if needed
|
|
348
|
+
const hasPermission = await requestUpfrontPermissions(userRequest);
|
|
349
|
+
if (!hasPermission) {
|
|
350
|
+
log.error("Task cancelled - permissions denied");
|
|
351
|
+
return;
|
|
352
|
+
}
|
|
353
|
+
|
|
294
354
|
// Create provider (defaults to Cheri cloud which uses AWS Bedrock)
|
|
295
355
|
const providerName = getConfigValue("agent.provider") || getConfigValue("ai.provider") || "cheri";
|
|
296
356
|
let provider;
|
|
@@ -561,7 +621,26 @@ export async function runAgent(userRequest, options = {}) {
|
|
|
561
621
|
const isMcp = mcpManager.isMcpTool(tc.name);
|
|
562
622
|
const isLocal = !CLOUD_TOOL_NAMES.has(tc.name) && !AGENT_TOOL_NAMES.has(tc.name) && !isMcp;
|
|
563
623
|
|
|
564
|
-
//
|
|
624
|
+
// Check if approval is needed BEFORE creating spinner
|
|
625
|
+
let needsApproval = false;
|
|
626
|
+
if (isLocal && !sessionAutoApprove) {
|
|
627
|
+
const decision = shouldApprove(tc.name, input);
|
|
628
|
+
if (decision === "ask" || decision === "suggest") {
|
|
629
|
+
needsApproval = true;
|
|
630
|
+
|
|
631
|
+
// Get approval WITHOUT spinner running
|
|
632
|
+
const approved = await promptApproval(tc.name, input, decision);
|
|
633
|
+
if (approved === "auto") {
|
|
634
|
+
sessionAutoApprove = true;
|
|
635
|
+
} else if (!approved) {
|
|
636
|
+
return { id: tc.id, result: { error: "User denied execution" } };
|
|
637
|
+
}
|
|
638
|
+
} else if (decision === "deny") {
|
|
639
|
+
return { id: tc.id, result: { error: "Denied by approval policy" } };
|
|
640
|
+
}
|
|
641
|
+
}
|
|
642
|
+
|
|
643
|
+
// Create animated panel for this tool execution (AFTER approval)
|
|
565
644
|
const panel = new ToolPanel(tc.name, input);
|
|
566
645
|
|
|
567
646
|
// Command safety label for run_command
|
|
@@ -571,7 +650,8 @@ export async function runAgent(userRequest, options = {}) {
|
|
|
571
650
|
panel.update(`running ${safetyLabel}`);
|
|
572
651
|
}
|
|
573
652
|
|
|
574
|
-
|
|
653
|
+
// Skip approval in executeTool since we already handled it above
|
|
654
|
+
const result = await executeTool(tc.name, input, orchestrator, ALL_TOOLS, parseSSEStream, mcpManager, needsApproval);
|
|
575
655
|
|
|
576
656
|
// Determine result message based on tool type
|
|
577
657
|
let resultMsg = '';
|
package/src/commands/login.js
CHANGED
|
@@ -63,6 +63,16 @@ export async function loginFlow() {
|
|
|
63
63
|
log.blank();
|
|
64
64
|
log.success(`Logged in as ${chalk.cyan(me.ghLogin || me.userId)}`);
|
|
65
65
|
log.keyValue("Plan", me.plan === "pro" ? chalk.green("Pro") : "Free");
|
|
66
|
+
|
|
67
|
+
// Initialize workspace for token tracking
|
|
68
|
+
try {
|
|
69
|
+
await apiClient.initWorkspace();
|
|
70
|
+
log.dim("✓ Workspace initialized with token tracking");
|
|
71
|
+
} catch (workspaceErr) {
|
|
72
|
+
// Workspace init is non-critical, just log it
|
|
73
|
+
log.dim(`⚠ Workspace init skipped: ${workspaceErr.message}`);
|
|
74
|
+
}
|
|
75
|
+
|
|
66
76
|
log.blank();
|
|
67
77
|
log.tip("Using Cheri cloud service (AWS Bedrock). Run 'cheri agent' to start coding!");
|
|
68
78
|
} catch (err) {
|
package/src/lib/api-client.js
CHANGED
|
@@ -128,4 +128,42 @@ export const apiClient = {
|
|
|
128
128
|
async getModels() {
|
|
129
129
|
return request("/api/chat/models");
|
|
130
130
|
},
|
|
131
|
+
|
|
132
|
+
// Token-Tracked Workspaces & Sessions
|
|
133
|
+
async initWorkspace() {
|
|
134
|
+
return request("/api/workspace/init", { method: "POST" });
|
|
135
|
+
},
|
|
136
|
+
|
|
137
|
+
async createSession() {
|
|
138
|
+
return request("/api/workspace/session/create", { method: "POST" });
|
|
139
|
+
},
|
|
140
|
+
|
|
141
|
+
async listSessions() {
|
|
142
|
+
return request("/api/workspace/sessions");
|
|
143
|
+
},
|
|
144
|
+
|
|
145
|
+
async getSession(sessionId) {
|
|
146
|
+
return request(`/api/workspace/session/${encodeURIComponent(sessionId)}`);
|
|
147
|
+
},
|
|
148
|
+
|
|
149
|
+
async getWorkspaceStats() {
|
|
150
|
+
return request("/api/workspace/stats");
|
|
151
|
+
},
|
|
152
|
+
|
|
153
|
+
async addSessionMessage(sessionId, role, content, tokens = null) {
|
|
154
|
+
return request(`/api/session/${encodeURIComponent(sessionId)}/message`, {
|
|
155
|
+
method: "POST",
|
|
156
|
+
body: JSON.stringify({ role, content, tokens }),
|
|
157
|
+
});
|
|
158
|
+
},
|
|
159
|
+
|
|
160
|
+
async getSessionCost(sessionId) {
|
|
161
|
+
return request(`/api/session/${encodeURIComponent(sessionId)}/cost`);
|
|
162
|
+
},
|
|
163
|
+
|
|
164
|
+
async compactSession(sessionId) {
|
|
165
|
+
return request(`/api/session/${encodeURIComponent(sessionId)}/compact`, {
|
|
166
|
+
method: "POST",
|
|
167
|
+
});
|
|
168
|
+
},
|
|
131
169
|
};
|