@mitsein-ai/cli 0.2.2 → 0.3.0

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/package.json CHANGED
@@ -46,5 +46,5 @@
46
46
  "typecheck": "tsc --noEmit"
47
47
  },
48
48
  "type": "module",
49
- "version": "0.2.2"
49
+ "version": "0.3.0"
50
50
  }
@@ -1,33 +1,42 @@
1
1
  import type { Command } from 'commander';
2
2
  import { ApiClient } from '../core/client.js';
3
+ import { runChat } from '../core/chat-run.js';
3
4
  import { resolveCredentials } from '../core/credentials.js';
4
5
  import { CliError, ExitCode, handleErrors } from '../core/errors.js';
5
6
  import { emit, setJsonMode } from '../core/output.js';
6
- import { waitForRun } from '../core/waiters.js';
7
7
  import { commaSet, httpTimeoutSec, readGlobals } from './command-opts.js';
8
8
 
9
+ type InvokeOpts = {
10
+ wait?: boolean;
11
+ stream?: boolean;
12
+ cancelOnInterrupt?: boolean;
13
+ filter?: string;
14
+ model?: string;
15
+ timeout?: string;
16
+ };
17
+
18
+ function effectiveTimeout(raw: string | undefined, fallback: number): number | null {
19
+ const v = Number.parseFloat(raw ?? String(fallback));
20
+ if (!Number.isFinite(v)) return fallback;
21
+ return v === 0 ? null : v;
22
+ }
23
+
9
24
  export function registerAgent(program: Command): void {
10
25
  const agent = program.command('agent').description('Agent operations');
11
26
 
12
27
  agent
13
28
  .command('invoke <thread_id> <prompt>')
14
- .description('Send a message, start the agent, optional wait/stream')
15
- .option('--wait', 'Block until run completes', false)
16
- .option('--stream', 'Stream run events', false)
17
- .option('--cancel-on-interrupt', 'Cancel run on Ctrl-C (reserved)', false)
18
- .option('--filter <types>', 'Comma-separated SSE event types')
29
+ .description('Send a message and run the agent (default: wait silently)')
30
+ .option('--wait', 'Block until run completes (default mode)', false)
31
+ .option('--stream', 'Stream events live to stdout', false)
32
+ .option('--cancel-on-interrupt', 'Cancel the run on Ctrl-C (default: detach)', false)
33
+ .option('--filter <types>', 'Comma-separated event types (text,tool_call,...)')
19
34
  .option('--model <name>', 'Model override')
20
- .option('--timeout <sec>', 'Wait/stream timeout (0 = no limit)', '120')
35
+ .option('--timeout <sec>', 'Stream timeout (0 = no limit)', '120')
21
36
  .action(
22
37
  handleErrors(async function agentInvokeAction(this: Command, threadId: string, prompt: string) {
23
38
  const g = readGlobals(this);
24
- const opts = this.opts() as {
25
- wait?: boolean;
26
- stream?: boolean;
27
- filter?: string;
28
- model?: string;
29
- timeout?: string;
30
- };
39
+ const opts = this.opts() as InvokeOpts;
31
40
  setJsonMode(Boolean(g.json));
32
41
 
33
42
  if (opts.wait && opts.stream) {
@@ -37,181 +46,154 @@ export function registerAgent(program: Command): void {
37
46
  const creds = resolveCredentials({
38
47
  token: g.token,
39
48
  endpoint: g.endpoint,
40
- profile: g.profile ?? 'e2e',
49
+ profile: g.profile ?? 'default',
41
50
  real: g.real,
42
51
  });
43
- const client = new ApiClient(creds, {
44
- debug: g.debug,
45
- timeoutSec: httpTimeoutSec(g),
46
- });
47
-
48
- const addResult = await client.post('/api/message/add', {
49
- thread_id: threadId,
50
- content: prompt,
51
- });
52
52
 
53
- const startData: Record<string, string> = {};
54
- if (opts.model) {
55
- startData.model_name = opts.model;
56
- }
57
- const startResult = (await client.postForm(`/api/thread/${threadId}/agent/start`, startData)) as {
58
- agent_run_id?: string;
59
- };
60
- const agentRunId = startResult.agent_run_id ?? '';
61
-
62
- if (!opts.wait && !opts.stream) {
63
- emit({
64
- message: addResult,
65
- agent_run_id: agentRunId,
66
- status: 'started',
67
- });
68
- return;
69
- }
70
-
71
- const rawT = opts.timeout ?? '120';
72
- const tNum = Number.parseFloat(rawT);
73
- const effectiveTimeout = Number.isFinite(tNum) && tNum === 0 ? null : Number.isFinite(tNum) ? tNum : 120;
74
-
75
- const result = await waitForRun({
53
+ const result = await runChat({
76
54
  endpoint: creds.endpoint,
77
55
  token: creds.token,
78
- agent_run_id: agentRunId,
79
- timeout: effectiveTimeout ?? undefined,
80
- stream_output: Boolean(opts.stream),
81
- json_mode: Boolean(g.json),
56
+ threadId,
57
+ content: [{ type: 'text', text: prompt }],
58
+ model: opts.model ?? null,
59
+ timeoutSec: effectiveTimeout(opts.timeout, 120),
82
60
  debug: g.debug,
83
- event_filter: commaSet(opts.filter),
61
+ streamOutput: Boolean(opts.stream),
62
+ jsonMode: Boolean(g.json),
63
+ eventFilter: commaSet(opts.filter),
64
+ cancelOnInterrupt: Boolean(opts.cancelOnInterrupt),
84
65
  });
85
66
 
86
- if (opts.wait && !opts.stream) {
87
- emit(result);
88
- }
89
- })
67
+ if (!opts.stream) emit(result);
68
+ }),
90
69
  );
91
70
 
92
- /* ── running sub-group (formerly top-level `run` command) ── */
71
+ /* ── agent running ─────────────────────────────────────────────────────── */
93
72
  const running = agent.command('running').description('Agent run management');
94
73
 
95
74
  running
96
- .command('list <thread_id>')
97
- .description('List agent runs for a thread')
75
+ .command('list')
76
+ .description('List all active agent runs for the current account')
98
77
  .action(
99
- handleErrors(async function runListAction(this: Command, threadId: string) {
78
+ handleErrors(async function runListAction(this: Command) {
100
79
  const g = readGlobals(this);
101
80
  setJsonMode(Boolean(g.json));
102
81
  const client = ApiClient.fromOptions({
103
82
  token: g.token,
104
83
  endpoint: g.endpoint,
105
- profile: g.profile ?? 'e2e',
84
+ profile: g.profile ?? 'default',
106
85
  real: g.real,
107
86
  timeoutSec: httpTimeoutSec(g),
108
87
  debug: g.debug,
109
88
  });
110
- const result = await client.post(`/api/thread/${threadId}/agent-runs`);
111
- emit(result);
112
- })
89
+ const result = (await client.get('/api/next/runs/active')) as {
90
+ runs?: unknown[];
91
+ } | null;
92
+ emit(result?.runs ?? result);
93
+ }),
113
94
  );
114
95
 
115
96
  running
116
- .command('status <run_id>')
117
- .description('Get agent run status')
97
+ .command('status <thread_id>')
98
+ .description('Get active-run status for a thread')
118
99
  .action(
119
- handleErrors(async function runStatusAction(this: Command, runId: string) {
100
+ handleErrors(async function runStatusAction(this: Command, threadId: string) {
120
101
  const g = readGlobals(this);
121
102
  setJsonMode(Boolean(g.json));
122
103
  const client = ApiClient.fromOptions({
123
104
  token: g.token,
124
105
  endpoint: g.endpoint,
125
- profile: g.profile ?? 'e2e',
106
+ profile: g.profile ?? 'default',
126
107
  real: g.real,
127
108
  timeoutSec: httpTimeoutSec(g),
128
109
  debug: g.debug,
129
110
  });
130
- const result = await client.post(`/api/agent-run/${runId}`);
131
- emit(result);
132
- })
111
+ const detail = (await client.get(`/api/next/threads/${threadId}`)) as {
112
+ active_run?: unknown;
113
+ } | null;
114
+ emit(detail?.active_run ?? { status: 'idle', last_event_id: null, error: null });
115
+ }),
133
116
  );
134
117
 
135
118
  running
136
- .command('tail <run_id>')
137
- .description('Stream agent run events (tail -f)')
119
+ .command('tail <thread_id>')
120
+ .description("Reconnect to a running agent's event stream (tail -f)")
138
121
  .option('--filter <types>', 'Comma-separated event types')
139
- .option('--timeout <sec>', 'Timeout (0 = no limit)', '120')
122
+ .option('--since <event_id>', 'Resume from this SSE event id')
123
+ .option('--timeout <sec>', 'Stream timeout (0 = no limit)', '120')
140
124
  .action(
141
- handleErrors(async function runTailAction(this: Command, runId: string) {
125
+ handleErrors(async function runTailAction(this: Command, threadId: string) {
142
126
  const g = readGlobals(this);
143
- const opts = this.opts() as { filter?: string; timeout?: string };
127
+ const opts = this.opts() as { filter?: string; since?: string; timeout?: string };
144
128
  setJsonMode(Boolean(g.json));
145
129
  const creds = resolveCredentials({
146
130
  token: g.token,
147
131
  endpoint: g.endpoint,
148
- profile: g.profile ?? 'e2e',
132
+ profile: g.profile ?? 'default',
149
133
  real: g.real,
150
134
  });
151
- const rawT = opts.timeout ?? '120';
152
- const tNum = Number.parseFloat(rawT);
153
- const effectiveTimeout = Number.isFinite(tNum) && tNum === 0 ? null : Number.isFinite(tNum) ? tNum : 120;
154
- await waitForRun({
135
+ await runChat({
155
136
  endpoint: creds.endpoint,
156
137
  token: creds.token,
157
- agent_run_id: runId,
158
- timeout: effectiveTimeout ?? undefined,
159
- stream_output: true,
160
- json_mode: Boolean(g.json),
138
+ threadId,
139
+ // no `content` → reconnect mode
140
+ lastEventId: opts.since ?? null,
141
+ timeoutSec: effectiveTimeout(opts.timeout, 120),
161
142
  debug: g.debug,
162
- event_filter: commaSet(opts.filter),
143
+ streamOutput: true,
144
+ jsonMode: Boolean(g.json),
145
+ eventFilter: commaSet(opts.filter),
163
146
  });
164
- })
147
+ }),
165
148
  );
166
149
 
167
150
  running
168
- .command('wait <run_id>')
169
- .description('Block until agent run completes')
170
- .option('--timeout <sec>', 'Timeout (0 = no limit)', '120')
151
+ .command('wait <thread_id>')
152
+ .description('Block until the active run for a thread completes')
153
+ .option('--since <event_id>', 'Resume from this SSE event id')
154
+ .option('--timeout <sec>', 'Wait timeout (0 = no limit)', '120')
171
155
  .action(
172
- handleErrors(async function runWaitAction(this: Command, runId: string) {
156
+ handleErrors(async function runWaitAction(this: Command, threadId: string) {
173
157
  const g = readGlobals(this);
174
- const opts = this.opts() as { timeout?: string };
158
+ const opts = this.opts() as { since?: string; timeout?: string };
175
159
  setJsonMode(Boolean(g.json));
176
160
  const creds = resolveCredentials({
177
161
  token: g.token,
178
162
  endpoint: g.endpoint,
179
- profile: g.profile ?? 'e2e',
163
+ profile: g.profile ?? 'default',
180
164
  real: g.real,
181
165
  });
182
- const rawT = opts.timeout ?? '120';
183
- const tNum = Number.parseFloat(rawT);
184
- const effectiveTimeout = Number.isFinite(tNum) && tNum === 0 ? null : Number.isFinite(tNum) ? tNum : 120;
185
- const result = await waitForRun({
166
+ const result = await runChat({
186
167
  endpoint: creds.endpoint,
187
168
  token: creds.token,
188
- agent_run_id: runId,
189
- timeout: effectiveTimeout ?? undefined,
190
- stream_output: false,
191
- json_mode: Boolean(g.json),
169
+ threadId,
170
+ lastEventId: opts.since ?? null,
171
+ timeoutSec: effectiveTimeout(opts.timeout, 120),
192
172
  debug: g.debug,
173
+ streamOutput: false,
174
+ jsonMode: Boolean(g.json),
193
175
  });
194
176
  emit(result);
195
- })
177
+ }),
196
178
  );
197
179
 
198
180
  running
199
- .command('cancel <run_id>')
200
- .description('Cancel a running agent')
181
+ .command('cancel <thread_id>')
182
+ .description("Cancel a thread's running agent")
201
183
  .action(
202
- handleErrors(async function runCancelAction(this: Command, runId: string) {
184
+ handleErrors(async function runCancelAction(this: Command, threadId: string) {
203
185
  const g = readGlobals(this);
204
186
  setJsonMode(Boolean(g.json));
205
187
  const client = ApiClient.fromOptions({
206
188
  token: g.token,
207
189
  endpoint: g.endpoint,
208
- profile: g.profile ?? 'e2e',
190
+ profile: g.profile ?? 'default',
209
191
  real: g.real,
210
192
  timeoutSec: httpTimeoutSec(g),
211
193
  debug: g.debug,
212
194
  });
213
- const result = await client.post(`/api/agent-run/${runId}/stop`);
195
+ const result = await client.post(`/api/next/chat/${threadId}/cancel`);
214
196
  emit(result);
215
- })
197
+ }),
216
198
  );
217
199
  }
@@ -232,7 +232,7 @@ export function registerApi(program: Command): void {
232
232
  const client = ApiClient.fromOptions({
233
233
  token: opts.token ?? g.token,
234
234
  endpoint: opts.endpoint ?? g.endpoint,
235
- profile: g.profile ?? 'e2e',
235
+ profile: g.profile ?? 'default',
236
236
  real: g.real,
237
237
  timeoutSec: effectiveTimeout,
238
238
  debug: Boolean(opts.debug ?? g.debug),
@@ -39,7 +39,7 @@ export function registerDev(parent: Command): void {
39
39
  const creds = resolveCredentials({
40
40
  token: g.token,
41
41
  endpoint: g.endpoint,
42
- profile: g.profile ?? 'e2e',
42
+ profile: g.profile ?? 'default',
43
43
  real: g.real,
44
44
  });
45
45
  emit(creds.token);
@@ -13,7 +13,7 @@ function makeClient(cmd: Command): ApiClient {
13
13
  return ApiClient.fromOptions({
14
14
  token: g.token,
15
15
  endpoint: g.endpoint,
16
- profile: g.profile ?? 'e2e',
16
+ profile: g.profile ?? 'default',
17
17
  real: g.real,
18
18
  timeoutSec: httpTimeoutSec(g),
19
19
  debug: g.debug,
@@ -20,18 +20,18 @@ export function registerProject(program: Command): void {
20
20
  const client = ApiClient.fromOptions({
21
21
  token: g.token,
22
22
  endpoint: g.endpoint,
23
- profile: g.profile ?? 'e2e',
23
+ profile: g.profile ?? 'default',
24
24
  real: g.real,
25
25
  timeoutSec: httpTimeoutSec(g),
26
26
  debug: g.debug,
27
27
  });
28
28
  const offset = Number.parseInt(String(opts.offset ?? '0'), 10);
29
29
  const limit = Number.parseInt(String(opts.limit ?? '20'), 10);
30
- const result = await client.post('/api/project/list', {
30
+ const result = (await client.post('/api/project/list', {
31
31
  offset: Number.isFinite(offset) ? offset : 0,
32
32
  limit: Number.isFinite(limit) ? limit : 20,
33
- });
34
- emit(result);
33
+ })) as { data?: unknown[] } | null;
34
+ emit(result?.data ?? result);
35
35
  })
36
36
  );
37
37
 
@@ -45,7 +45,7 @@ export function registerProject(program: Command): void {
45
45
  const client = ApiClient.fromOptions({
46
46
  token: g.token,
47
47
  endpoint: g.endpoint,
48
- profile: g.profile ?? 'e2e',
48
+ profile: g.profile ?? 'default',
49
49
  real: g.real,
50
50
  timeoutSec: httpTimeoutSec(g),
51
51
  debug: g.debug,
@@ -65,7 +65,7 @@ export function registerProject(program: Command): void {
65
65
  const client = ApiClient.fromOptions({
66
66
  token: g.token,
67
67
  endpoint: g.endpoint,
68
- profile: g.profile ?? 'e2e',
68
+ profile: g.profile ?? 'default',
69
69
  real: g.real,
70
70
  timeoutSec: httpTimeoutSec(g),
71
71
  debug: g.debug,
@@ -1,13 +1,24 @@
1
1
  import type { Command } from 'commander';
2
2
  import { ApiClient } from '../core/client.js';
3
- import { resolveCredentials } from '../core/credentials.js';
4
- import { CliError, ExitCode, handleErrors } from '../core/errors.js';
3
+ import { handleErrors } from '../core/errors.js';
5
4
  import { emit, setJsonMode } from '../core/output.js';
6
- import { waitForRun } from '../core/waiters.js';
7
- import { commaSet, httpTimeoutSec, readGlobals } from './command-opts.js';
5
+ import { httpTimeoutSec, readGlobals } from './command-opts.js';
6
+
7
+ function makeClient(cmd: Command): ApiClient {
8
+ const g = readGlobals(cmd);
9
+ setJsonMode(Boolean(g.json));
10
+ return ApiClient.fromOptions({
11
+ token: g.token,
12
+ endpoint: g.endpoint,
13
+ profile: g.profile ?? 'default',
14
+ real: g.real,
15
+ timeoutSec: httpTimeoutSec(g),
16
+ debug: g.debug,
17
+ });
18
+ }
8
19
 
9
20
  export function registerThread(program: Command): void {
10
- const thread = program.command('thread').description('Thread management and messaging');
21
+ const thread = program.command('thread').description('Thread management');
11
22
 
12
23
  thread
13
24
  .command('list')
@@ -16,24 +27,15 @@ export function registerThread(program: Command): void {
16
27
  .option('--limit <n>', 'Max results', '20')
17
28
  .action(
18
29
  handleErrors(async function threadListAction(this: Command) {
19
- const g = readGlobals(this);
20
- setJsonMode(Boolean(g.json));
21
- const client = ApiClient.fromOptions({
22
- token: g.token,
23
- endpoint: g.endpoint,
24
- profile: g.profile ?? 'e2e',
25
- real: g.real,
26
- timeoutSec: httpTimeoutSec(g),
27
- debug: g.debug,
28
- });
30
+ const client = makeClient(this);
29
31
  const offset = Number.parseInt(String(this.opts().offset ?? '0'), 10);
30
32
  const limit = Number.parseInt(String(this.opts().limit ?? '20'), 10);
31
- const result = await client.post('/api/thread/list', {
33
+ const result = (await client.get('/api/threads', {
32
34
  offset: Number.isFinite(offset) ? offset : 0,
33
35
  limit: Number.isFinite(limit) ? limit : 20,
34
- });
35
- emit(result);
36
- })
36
+ })) as { threads?: unknown[] } | null;
37
+ emit(result?.threads ?? result);
38
+ }),
37
39
  );
38
40
 
39
41
  thread
@@ -41,147 +43,68 @@ export function registerThread(program: Command): void {
41
43
  .description('Get thread details')
42
44
  .action(
43
45
  handleErrors(async function threadGetAction(this: Command, threadId: string) {
44
- const g = readGlobals(this);
45
- setJsonMode(Boolean(g.json));
46
- const client = ApiClient.fromOptions({
47
- token: g.token,
48
- endpoint: g.endpoint,
49
- profile: g.profile ?? 'e2e',
50
- real: g.real,
51
- timeoutSec: httpTimeoutSec(g),
52
- debug: g.debug,
53
- });
54
- const result = await client.post('/api/thread/get', { thread_id: threadId });
55
- emit(result);
56
- })
46
+ const client = makeClient(this);
47
+ const result = (await client.get(`/api/threads/${threadId}`)) as {
48
+ thread?: unknown;
49
+ } | null;
50
+ emit(result?.thread ?? result);
51
+ }),
57
52
  );
58
53
 
59
54
  thread
60
55
  .command('create')
61
56
  .description('Create a new thread')
62
- .option('--title <title>', 'Thread title', '')
57
+ .option('--name <name>', 'Thread name', '')
58
+ .option('--agent <id>', 'Agent id to bind to the thread')
63
59
  .action(
64
60
  handleErrors(async function threadCreateAction(this: Command) {
65
- const g = readGlobals(this);
66
- const { title } = this.opts() as { title?: string };
67
- setJsonMode(Boolean(g.json));
68
- const client = ApiClient.fromOptions({
69
- token: g.token,
70
- endpoint: g.endpoint,
71
- profile: g.profile ?? 'e2e',
72
- real: g.real,
73
- timeoutSec: httpTimeoutSec(g),
74
- debug: g.debug,
75
- });
76
- const result = await client.post('/api/threads', { title: title ?? '' });
61
+ const client = makeClient(this);
62
+ const opts = this.opts() as { name?: string; agent?: string };
63
+ const body: Record<string, unknown> = {};
64
+ if (opts.name) body.name = opts.name;
65
+ if (opts.agent) body.agent_id = opts.agent;
66
+ const result = await client.post('/api/next/threads', body);
77
67
  emit(result);
78
- })
68
+ }),
79
69
  );
80
70
 
81
71
  thread
82
- .command('history <thread_id>')
83
- .description('Show message history for a thread')
84
- .option('--limit <n>', 'Max messages', '50')
72
+ .command('rename <thread_id> <name>')
73
+ .description('Rename a thread')
85
74
  .action(
86
- handleErrors(async function threadHistoryAction(this: Command, threadId: string) {
87
- const g = readGlobals(this);
88
- const { limit: lim } = this.opts() as { limit?: string };
89
- setJsonMode(Boolean(g.json));
90
- const client = ApiClient.fromOptions({
91
- token: g.token,
92
- endpoint: g.endpoint,
93
- profile: g.profile ?? 'e2e',
94
- real: g.real,
95
- timeoutSec: httpTimeoutSec(g),
96
- debug: g.debug,
97
- });
98
- const limit = Number.parseInt(String(lim ?? '50'), 10);
99
- const result = await client.post('/api/message/list', {
100
- thread_id: threadId,
101
- limit: Number.isFinite(limit) ? limit : 50,
102
- });
75
+ handleErrors(async function threadRenameAction(this: Command, threadId: string, name: string) {
76
+ const client = makeClient(this);
77
+ const result = await client.patch(`/api/next/threads/${threadId}`, { name });
103
78
  emit(result);
104
- })
79
+ }),
105
80
  );
106
81
 
107
82
  thread
108
- .command('send <thread_id> <message>')
109
- .description('Send a message and start an agent run')
110
- .option('--wait', 'Block until run completes', false)
111
- .option('--stream', 'Stream run events', false)
112
- .option('--cancel-on-interrupt', 'Cancel run on Ctrl-C (reserved)', false)
113
- .option('--filter <types>', 'Comma-separated SSE event types')
114
- .option('--agent <name>', 'Agent name (reserved)', '')
115
- .option('--model <name>', 'Model override')
116
- .option('--timeout <sec>', 'Wait/stream timeout (0 = no limit)', '120')
83
+ .command('delete <thread_id>')
84
+ .description('Delete a thread')
117
85
  .action(
118
- handleErrors(async function threadSendAction(this: Command, threadId: string, message: string) {
119
- const g = readGlobals(this);
120
- const opts = this.opts() as {
121
- wait?: boolean;
122
- stream?: boolean;
123
- filter?: string;
124
- model?: string;
125
- timeout?: string;
126
- };
127
- setJsonMode(Boolean(g.json));
128
-
129
- if (opts.wait && opts.stream) {
130
- throw new CliError('--wait and --stream are mutually exclusive', ExitCode.USAGE_ERROR);
131
- }
132
-
133
- const creds = resolveCredentials({
134
- token: g.token,
135
- endpoint: g.endpoint,
136
- profile: g.profile ?? 'e2e',
137
- real: g.real,
138
- });
139
- const client = new ApiClient(creds, {
140
- debug: g.debug,
141
- timeoutSec: httpTimeoutSec(g),
142
- });
143
-
144
- const addResult = await client.post('/api/message/add', {
145
- thread_id: threadId,
146
- content: message,
147
- });
148
-
149
- const startData: Record<string, string> = {};
150
- if (opts.model) {
151
- startData.model_name = opts.model;
152
- }
153
- const startResult = (await client.postForm(`/api/thread/${threadId}/agent/start`, startData)) as {
154
- agent_run_id?: string;
155
- };
156
- const agentRunId = startResult.agent_run_id ?? '';
157
-
158
- if (!opts.wait && !opts.stream) {
159
- emit({
160
- message: addResult,
161
- agent_run_id: agentRunId,
162
- status: 'started',
163
- });
164
- return;
165
- }
166
-
167
- const rawT = opts.timeout ?? '120';
168
- const tNum = Number.parseFloat(rawT);
169
- const effectiveTimeout = Number.isFinite(tNum) && tNum === 0 ? null : Number.isFinite(tNum) ? tNum : 120;
170
-
171
- const result = await waitForRun({
172
- endpoint: creds.endpoint,
173
- token: creds.token,
174
- agent_run_id: agentRunId,
175
- timeout: effectiveTimeout ?? undefined,
176
- stream_output: Boolean(opts.stream),
177
- json_mode: Boolean(g.json),
178
- debug: g.debug,
179
- event_filter: commaSet(opts.filter),
180
- });
86
+ handleErrors(async function threadDeleteAction(this: Command, threadId: string) {
87
+ const client = makeClient(this);
88
+ const result = await client.delete(`/api/next/threads/${threadId}`);
89
+ emit(result);
90
+ }),
91
+ );
181
92
 
182
- if (opts.wait && !opts.stream) {
183
- emit(result);
184
- }
185
- })
93
+ thread
94
+ .command('history <thread_id>')
95
+ .description('Show message history for a thread')
96
+ .option('--limit <n>', 'Max messages', '50')
97
+ .action(
98
+ handleErrors(async function threadHistoryAction(this: Command, threadId: string) {
99
+ const client = makeClient(this);
100
+ const { limit: lim } = this.opts() as { limit?: string };
101
+ const limit = Number.parseInt(String(lim ?? '50'), 10);
102
+ const result = (await client.get(`/api/next/threads/${threadId}`)) as {
103
+ messages?: unknown[];
104
+ } | null;
105
+ const messages = Array.isArray(result?.messages) ? result!.messages : [];
106
+ const take = Number.isFinite(limit) && limit > 0 ? limit : 50;
107
+ emit(messages.slice(-take));
108
+ }),
186
109
  );
187
110
  }