opencode-miniterm 1.0.1 → 1.0.3

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.
@@ -1,5 +1,6 @@
1
1
  import { describe, expect, it, vi } from "bun:test";
2
2
  import { type State } from "../src";
3
+ import * as ansi from "../src/ansi";
3
4
  import { render, wrapText } from "../src/render";
4
5
 
5
6
  describe("render", () => {
@@ -61,7 +62,7 @@ describe("render", () => {
61
62
  const calls = write.mock.calls.map((c) => c[0]);
62
63
  expect(calls.some((c) => c.includes("\u001B[2A"))).toBe(true);
63
64
  const outputCall = calls.find((c) => c.includes("i've done it"));
64
- expect(outputCall).toContain("💬");
65
+ expect(outputCall).toContain(`${ansi.WHITE_BACKGROUND}${ansi.BOLD_BLACK}*${ansi.RESET}`);
65
66
  });
66
67
  });
67
68
 
@@ -76,8 +77,9 @@ describe("render", () => {
76
77
  render(state);
77
78
 
78
79
  const output = write.mock.calls.map((c) => c[0]).join("");
79
- expect(output).toContain("💭");
80
- expect(output).toContain("分析问题");
80
+ expect(output).toContain(
81
+ `${ansi.BOLD_BRIGHT_BLACK}~${ansi.RESET} ${ansi.BRIGHT_BLACK}分析问题${ansi.RESET}`,
82
+ );
81
83
  });
82
84
 
83
85
  it("should only show thinking indicator for last thinking part", () => {
@@ -93,9 +95,10 @@ describe("render", () => {
93
95
  render(state);
94
96
 
95
97
  const output = write.mock.calls.map((c) => c[0]).join("");
96
- expect(output).toContain("💭");
97
- expect(output).toContain("second");
98
- expect(output).not.toMatch(/first.*Thinking/);
98
+ expect(output).toContain(
99
+ `${ansi.BOLD_BRIGHT_BLACK}~${ansi.RESET} ${ansi.BRIGHT_BLACK}second${ansi.RESET}`,
100
+ );
101
+ expect(output).not.toContain("first");
99
102
  });
100
103
 
101
104
  it("should skip parts with empty text", () => {
@@ -134,23 +137,24 @@ describe("render", () => {
134
137
  render(state);
135
138
 
136
139
  const output = write.mock.calls.map((c) => c[0]).join("");
137
- expect(output).toContain("💬");
138
- expect(output).toContain("Hello world");
140
+ expect(output).toContain(
141
+ `${ansi.WHITE_BACKGROUND}${ansi.BOLD_BLACK}*${ansi.RESET} Hello world`,
142
+ );
139
143
  });
140
144
  });
141
145
 
142
146
  describe("tool parts", () => {
143
- it("should render tool part without indicator", () => {
147
+ it("should render tool part with indicator", () => {
144
148
  const write = vi.fn();
145
149
  const state = createMockState({
146
- accumulatedResponse: [{ key: "xxx", title: "tool", text: "🔧 bash: ls -la" }],
150
+ accumulatedResponse: [{ key: "xxx", title: "tool", text: "bash: ls -la" }],
147
151
  write,
148
152
  });
149
153
 
150
154
  render(state);
151
155
 
152
156
  const output = write.mock.calls.map((c) => c[0]).join("");
153
- expect(output).toContain("🔧 bash: ls -la");
157
+ expect(output).toContain("bash: ls -la");
154
158
  });
155
159
  });
156
160
 
@@ -238,7 +242,7 @@ describe("render", () => {
238
242
  const state = createMockState({
239
243
  accumulatedResponse: [
240
244
  { key: "xxx", title: "thinking", text: "分析中" },
241
- { key: "xxx", title: "tool", text: "🔧 bash: npm test" },
245
+ { key: "xxx", title: "tool", text: "bash: npm test" },
242
246
  { key: "xxx", title: "response", text: "Test results: 5 passed" },
243
247
  ],
244
248
  write,
@@ -247,10 +251,11 @@ describe("render", () => {
247
251
  render(state);
248
252
 
249
253
  const output = write.mock.calls.map((c) => c[0]).join("");
250
- expect(output).not.toContain("💭");
251
- expect(output).not.toContain("🔧 bash: npm test");
252
- expect(output).toContain("💬");
253
- expect(output).toContain("Test results: 5 passed");
254
+ expect(output).not.toContain(`分析中`);
255
+ expect(output).toContain(`bash: npm test`);
256
+ expect(output).toContain(
257
+ `${ansi.WHITE_BACKGROUND}${ansi.BOLD_BLACK}*${ansi.RESET} Test results: 5 passed`,
258
+ );
254
259
  });
255
260
  });
256
261
  });
@@ -259,115 +264,123 @@ describe("wrapText", () => {
259
264
  describe("basic wrapping", () => {
260
265
  it("should return single line for text shorter than width", () => {
261
266
  const result = wrapText("hello", 20);
262
- expect(result).toEqual(["hello"]);
267
+ expect(result).toEqual([" hello"]);
263
268
  });
264
269
 
265
270
  it("should wrap text longer than width", () => {
266
271
  const result = wrapText("hello world this is a long text", 10);
267
- expect(result).toEqual(["hello", "world this", "is a long", "text"]);
272
+ expect(result).toEqual([" hello", " world", " this is", " a long", " text"]);
268
273
  });
269
274
 
270
275
  it("should handle text exactly at width", () => {
271
276
  const result = wrapText("1234567890", 10);
272
- expect(result).toEqual(["1234567890"]);
277
+ expect(result).toEqual([" 1234567890"]);
273
278
  });
274
279
 
275
280
  it("should break long word that exceeds width", () => {
276
281
  const result = wrapText("12345678901", 10);
277
- expect(result).toEqual(["1234567890", "1"]);
282
+ expect(result).toEqual([" ", " 12345678", " 901"]);
278
283
  });
279
284
  });
280
285
 
281
286
  describe("multiple lines", () => {
282
287
  it("should preserve existing newlines", () => {
283
288
  const result = wrapText("line1\nline2\nline3", 20);
284
- expect(result).toEqual(["line1", "line2", "line3"]);
289
+ expect(result).toEqual([" line1", " line2", " line3"]);
285
290
  });
286
291
 
287
292
  it("should wrap lines that are too long", () => {
288
293
  const result = wrapText("very long line1\nshort\nvery long line2", 10);
289
- expect(result).toEqual(["very long", "line1", "short", "very long", "line2"]);
294
+ expect(result).toEqual([
295
+ " very",
296
+ " long",
297
+ " line1",
298
+ " short",
299
+ " very",
300
+ " long",
301
+ " line2",
302
+ ]);
290
303
  });
291
304
 
292
305
  it("should handle empty lines", () => {
293
306
  const result = wrapText("line1\n\nline3", 20);
294
- expect(result).toEqual(["line1", "", "line3"]);
307
+ expect(result).toEqual([" line1", " ", " line3"]);
295
308
  });
296
309
  });
297
310
 
298
311
  describe("ANSI codes", () => {
299
312
  it("should preserve ANSI codes in output", () => {
300
313
  const result = wrapText("\x1b[31mred\x1b[0m text", 20);
301
- expect(result).toEqual(["\x1b[31mred\x1b[0m text"]);
314
+ expect(result).toEqual([" \x1b[31mred\x1b[0m text"]);
302
315
  });
303
316
 
304
317
  it("should not count ANSI codes toward visible width", () => {
305
318
  const result = wrapText("\x1b[31mred\x1b[0m text", 8);
306
- expect(result).toEqual(["\x1b[31mred\x1b[0m text"]);
319
+ expect(result).toEqual([" \x1b[31mred\x1b[0m", " text"]);
307
320
  });
308
321
 
309
322
  it("should handle multiple ANSI codes", () => {
310
323
  const result = wrapText("\x1b[31m\x1b[1mbold red\x1b[0m\x1b[32m green\x1b[0m", 10);
311
- expect(result).toEqual(["\x1b[31m\x1b[1mbold red\x1b[0m\x1b[32m", "green\x1b[0m"]);
324
+ expect(result).toEqual([" \x1b[31m\x1b[1mbold red\x1b[0m\x1b[32m", " green\x1b[0m"]);
312
325
  });
313
326
 
314
327
  it("should handle ANSI codes at wrap boundary", () => {
315
328
  const result = wrapText("12345\x1b[31m67890\x1b[0m", 10);
316
- expect(result).toEqual(["12345\x1b[31m67890\x1b[0m"]);
329
+ expect(result).toEqual([" 12345\x1b[31m67890\x1b[0m"]);
317
330
  });
318
331
  });
319
332
 
320
333
  describe("edge cases", () => {
321
334
  it("should handle empty string", () => {
322
335
  const result = wrapText("", 20);
323
- expect(result).toEqual([""]);
336
+ expect(result).toEqual([" "]);
324
337
  });
325
338
 
326
339
  it("should handle single character", () => {
327
340
  const result = wrapText("a", 20);
328
- expect(result).toEqual(["a"]);
341
+ expect(result).toEqual([" a"]);
329
342
  });
330
343
 
331
344
  it("should handle width of 1", () => {
332
345
  const result = wrapText("a b c", 1);
333
- expect(result).toEqual(["a", "b", "c"]);
346
+ expect(result).toEqual([" a", " b", " c"]);
334
347
  });
335
348
 
336
349
  it("should handle carriage return characters", () => {
337
350
  const result = wrapText("hello\r\nworld", 20);
338
- expect(result).toEqual(["hello", "world"]);
351
+ expect(result).toEqual([" hello", " world"]);
339
352
  });
340
353
 
341
354
  it("should handle trailing newline", () => {
342
355
  const result = wrapText("hello\n", 20);
343
- expect(result).toEqual(["hello"]);
356
+ expect(result).toEqual([" hello"]);
344
357
  });
345
358
 
346
359
  it("should handle multiple trailing newlines", () => {
347
360
  const result = wrapText("hello\n\n", 20);
348
- expect(result).toEqual(["hello", ""]);
361
+ expect(result).toEqual([" hello", " "]);
349
362
  });
350
363
 
351
364
  it("should handle leading newline", () => {
352
365
  const result = wrapText("\nhello", 20);
353
- expect(result).toEqual(["", "hello"]);
366
+ expect(result).toEqual([" ", " hello"]);
354
367
  });
355
368
  });
356
369
 
357
370
  describe("real-world scenarios", () => {
358
- it("should wrap thinking output with emoji", () => {
371
+ it("should wrap thinking output with indicator", () => {
359
372
  const result = wrapText(
360
- "💭 Let me analyze this problem step by step to find the best solution",
361
- 40,
373
+ "Let me analyze this problem step by step to find the best solution",
374
+ 36,
362
375
  );
363
376
  expect(result.length).toBeGreaterThan(1);
364
- expect(result[0]).toBe("💭 Let me analyze this problem step by");
377
+ expect(result[0]).toBe(" Let me analyze this problem step");
365
378
  });
366
379
 
367
- it("should wrap response output with emoji", () => {
380
+ it("should wrap response output with indicator", () => {
368
381
  const result = wrapText(
369
- "💬 Here is the solution:\nWe need to implement the fix by updating the wrapText function",
370
- 30,
382
+ "Here is the solution:\nWe need to implement the fix by updating the wrapText function",
383
+ 26,
371
384
  );
372
385
  expect(result.length).toBeGreaterThan(1);
373
386
  });
@@ -1,33 +0,0 @@
1
- import type { OpencodeClient } from "@opencode-ai/sdk";
2
- import type { State } from "../index";
3
- import type { Command } from "../types";
4
-
5
- let command: Command = {
6
- name: "/kill",
7
- description: "Abort a session (e.g. `/kill ses_123`)",
8
- run,
9
- running: false,
10
- };
11
-
12
- export default command;
13
-
14
- async function run(client: OpencodeClient, _state: State, input?: string): Promise<void> {
15
- if (!input) {
16
- console.log("Usage: /kill <session_id>");
17
- console.log();
18
- return;
19
- }
20
-
21
- const result = await client.session.abort({
22
- path: { id: input },
23
- });
24
-
25
- if (result.error) {
26
- throw new Error(
27
- `Failed to abort session (${result.response.status}): ${JSON.stringify(result.error)}`,
28
- );
29
- }
30
-
31
- console.log(`Session aborted successfully.`);
32
- console.log();
33
- }