@hunterzhu/pulse-cli 0.1.5 → 0.1.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.
Files changed (36) hide show
  1. package/dist/bin.d.ts +1 -0
  2. package/dist/bin.js +128 -30
  3. package/dist/commands/interactive.d.ts +2 -1
  4. package/dist/commands/interactive.js +21 -2
  5. package/dist/commands/resume.js +4 -0
  6. package/dist/commands/run.js +4 -0
  7. package/dist/components/App.d.ts +2 -1
  8. package/dist/components/App.js +177 -37
  9. package/dist/components/ApprovalPrompt.d.ts +4 -1
  10. package/dist/components/ApprovalPrompt.js +20 -15
  11. package/dist/components/AskPrompt.d.ts +8 -0
  12. package/dist/components/AskPrompt.js +57 -0
  13. package/dist/components/AssistantMessage.js +2 -1
  14. package/dist/components/Header.js +2 -1
  15. package/dist/components/HelpView.js +3 -1
  16. package/dist/components/InputArea.d.ts +2 -1
  17. package/dist/components/InputArea.js +13 -3
  18. package/dist/components/MessageList.d.ts +2 -1
  19. package/dist/components/MessageList.js +4 -11
  20. package/dist/components/MessageViewport.d.ts +14 -0
  21. package/dist/components/MessageViewport.js +77 -0
  22. package/dist/components/SessionList.js +43 -13
  23. package/dist/components/StatusHud.d.ts +11 -0
  24. package/dist/components/StatusHud.js +12 -0
  25. package/dist/components/ToolCallCard.js +27 -2
  26. package/dist/components/UserMessage.js +1 -1
  27. package/dist/config.d.ts +39 -7
  28. package/dist/config.js +35 -8
  29. package/dist/hooks/useConversation.d.ts +2 -1
  30. package/dist/hooks/useConversation.js +12 -5
  31. package/dist/hooks/useRun.d.ts +8 -3
  32. package/dist/hooks/useRun.js +175 -18
  33. package/dist/hooks/useSlashCommands.d.ts +2 -0
  34. package/dist/hooks/useSlashCommands.js +2 -0
  35. package/dist/types.d.ts +23 -1
  36. package/package.json +2 -2
package/dist/config.js CHANGED
@@ -2,8 +2,16 @@ import { access, chmod, mkdir, readFile, writeFile } from 'node:fs/promises';
2
2
  import { homedir } from 'node:os';
3
3
  import { dirname, join, resolve } from 'node:path';
4
4
  export const defaultPulseConfig = {
5
- provider: { provider: 'mock', model: 'mock', apiKeyEnv: 'OPENAI_API_KEY' },
5
+ providers: {
6
+ mock: { provider: 'mock', name: 'Mock' },
7
+ },
8
+ models: {
9
+ mock: { displayName: 'mock', provider: 'mock', modelCode: 'mock', maxContextTokens: 32_000, maxOutputTokens: 4_096, reasoningEffort: 'medium' },
10
+ },
11
+ activeModel: 'mock',
6
12
  approvalMode: 'ask',
13
+ maxTurns: 32,
14
+ autoCompactPercent: 90,
7
15
  allowNetwork: false,
8
16
  };
9
17
  export function defaultPulseConfigPath() {
@@ -43,16 +51,34 @@ function asConfig(value) {
43
51
  return undefined;
44
52
  return value;
45
53
  }
46
- /** Workspace files must not escalate approval, network, or provider credentials. */
54
+ /** Workspace files must not escalate approval, network, provider credentials, or the system prompt. */
47
55
  export function sanitizeWorkspaceConfig(value) {
48
- const provider = value.provider === undefined ? undefined : {
49
- ...(value.provider.provider === undefined ? {} : { provider: value.provider.provider }),
50
- ...(value.provider.model === undefined ? {} : { model: value.provider.model }),
51
- };
56
+ const providers = value.providers === undefined ? undefined : Object.fromEntries(Object.entries(value.providers).flatMap(([name, profile]) => {
57
+ const safe = {
58
+ provider: profile.provider,
59
+ ...(profile.name === undefined ? {} : { name: profile.name }),
60
+ };
61
+ return Object.keys(safe).length ? [[name, safe]] : [];
62
+ }));
52
63
  return {
53
64
  ...(value.cwd === undefined ? {} : { cwd: value.cwd }),
54
65
  ...(value.dataDir === undefined ? {} : { dataDir: value.dataDir }),
55
- ...(provider === undefined || Object.keys(provider).length === 0 ? {} : { provider }),
66
+ ...(providers === undefined || Object.keys(providers).length === 0 ? {} : { providers }),
67
+ ...(value.activeModel === undefined ? {} : { activeModel: value.activeModel }),
68
+ ...(value.models === undefined ? {} : {
69
+ models: Object.fromEntries(Object.entries(value.models).flatMap(([name, model]) => {
70
+ if (!model.provider || !model.modelCode)
71
+ return [];
72
+ return [[name, {
73
+ provider: model.provider,
74
+ modelCode: model.modelCode,
75
+ displayName: model.displayName,
76
+ ...(model.maxContextTokens === undefined ? {} : { maxContextTokens: model.maxContextTokens }),
77
+ ...(model.maxOutputTokens === undefined ? {} : { maxOutputTokens: model.maxOutputTokens }),
78
+ ...(model.reasoningEffort === undefined ? {} : { reasoningEffort: model.reasoningEffort }),
79
+ }]];
80
+ })),
81
+ }),
56
82
  };
57
83
  }
58
84
  export function mergePulseConfigs(layers) {
@@ -62,7 +88,8 @@ export function mergePulseConfigs(layers) {
62
88
  merged = {
63
89
  ...merged,
64
90
  ...value,
65
- ...(merged.provider === undefined && value.provider === undefined ? {} : { provider: { ...merged.provider, ...value.provider } }),
91
+ ...(merged.providers === undefined && value.providers === undefined ? {} : { providers: { ...merged.providers, ...value.providers } }),
92
+ ...(merged.models === undefined && value.models === undefined ? {} : { models: { ...merged.models, ...value.models } }),
66
93
  };
67
94
  }
68
95
  return merged;
@@ -11,5 +11,6 @@ export declare function useConversation({ host, conversationId, }: {
11
11
  addAssistantMessage: (msg: DisplayMessage) => void;
12
12
  clearMessages: () => void;
13
13
  switchConversation: (id: string) => Promise<void>;
14
- newConversation: () => Promise<void>;
14
+ newConversation: () => Promise<ConversationHandle | null>;
15
+ createConversation: () => Promise<ConversationHandle | null>;
15
16
  };
@@ -36,9 +36,10 @@ export function useConversation({ host, conversationId, }) {
36
36
  }
37
37
  }
38
38
  else {
39
- const conv = await currentHost.createConversation();
40
- if (mounted && conv) {
41
- setConversation(conv);
39
+ // An interactive window starts without a persisted session. The
40
+ // first user message (or an explicit /new) creates one.
41
+ if (mounted) {
42
+ setConversation(null);
42
43
  setMessages([]);
43
44
  }
44
45
  }
@@ -89,19 +90,24 @@ export function useConversation({ host, conversationId, }) {
89
90
  setError(err instanceof Error ? err.message : String(err));
90
91
  }
91
92
  }, [host, loadMessages]);
92
- const newConversation = useCallback(async () => {
93
+ const createConversation = useCallback(async () => {
93
94
  if (!host)
94
- return;
95
+ return null;
95
96
  try {
96
97
  const conv = await host.createConversation();
97
98
  setConversation(conv);
98
99
  setMessages([]);
99
100
  setError(null);
101
+ return conv;
100
102
  }
101
103
  catch (err) {
102
104
  setError(err instanceof Error ? err.message : String(err));
105
+ return null;
103
106
  }
104
107
  }, [host]);
108
+ const newConversation = useCallback(async () => {
109
+ return createConversation();
110
+ }, [createConversation]);
105
111
  return {
106
112
  conversation,
107
113
  messages,
@@ -111,5 +117,6 @@ export function useConversation({ host, conversationId, }) {
111
117
  clearMessages,
112
118
  switchConversation,
113
119
  newConversation,
120
+ createConversation,
114
121
  };
115
122
  }
@@ -1,5 +1,6 @@
1
1
  import type { LocalHost } from '@hunterzhu/pulse-server';
2
- import type { ApprovalRequest, DisplayMessage } from '../types.js';
2
+ import type { ApprovalRequest, AskRequest, DisplayMessage, LaneDisplay } from '../types.js';
3
+ export declare function describeFactStatus(data: unknown): string;
3
4
  export declare function useRun({ host, conversationId, addAssistantMessage, }: {
4
5
  host: LocalHost | null;
5
6
  conversationId: string | null;
@@ -9,8 +10,12 @@ export declare function useRun({ host, conversationId, addAssistantMessage, }: {
9
10
  currentStep: string | null;
10
11
  error: string | null;
11
12
  approvalRequest: ApprovalRequest | null;
12
- sendMessage: (text: string) => Promise<void>;
13
- resumeActive: () => Promise<void>;
13
+ askRequest: AskRequest | null;
14
+ lanes: LaneDisplay[];
15
+ approvalSubmitting: boolean;
16
+ sendMessage: (text: string, targetConversationId?: string) => Promise<void>;
17
+ resumeActive: (targetConversationId?: string) => Promise<void>;
14
18
  approveAction: (effectId: string, approved: boolean, reason?: string) => Promise<void>;
19
+ replyAsk: (effectId: string, value: Record<string, unknown>) => Promise<void>;
15
20
  cancelRun: () => Promise<void>;
16
21
  };
@@ -1,14 +1,48 @@
1
1
  import { useState, useRef, useCallback, useEffect } from 'react';
2
2
  function toolStatus(value) {
3
- if (value === 'succeeded' || value === 'failed' || value === 'running')
3
+ if (value === 'succeeded' || value === 'failed' || value === 'running' || value === 'cancelled')
4
4
  return value;
5
5
  return 'running';
6
6
  }
7
+ export function describeFactStatus(data) {
8
+ if (typeof data === 'string') {
9
+ if (data === 'human.input.received')
10
+ return '已收到你的输入,正在安排处理...';
11
+ if (data === 'human.input.dispatched')
12
+ return '已安排优先处理你的输入...';
13
+ if (data === 'human.input.deferred')
14
+ return '输入已记录,将在当前副作用安全收尾后处理...';
15
+ return data;
16
+ }
17
+ if (!data || typeof data !== 'object' || Array.isArray(data))
18
+ return '正在执行...';
19
+ const payload = data;
20
+ const decision = payload.decision ?? payload.action;
21
+ if (typeof payload.inputId === 'string' && decision === undefined) {
22
+ return '已收到你的输入,调度器正在决定如何处理...';
23
+ }
24
+ if (decision === 'spawn')
25
+ return '已启动优先交互任务,正在处理你的输入...';
26
+ if (decision === 'respond')
27
+ return '已收到回复,正在继续当前任务...';
28
+ if (decision === 'steer')
29
+ return '正在根据你的输入调整当前任务...';
30
+ if (decision === 'cancel')
31
+ return '正在按你的输入取消相关任务...';
32
+ if (decision === 'defer')
33
+ return '输入已记录,等待安全时机处理...';
34
+ if (typeof payload.reason === 'string')
35
+ return `输入处理暂缓:${payload.reason}`;
36
+ return '正在执行...';
37
+ }
7
38
  export function useRun({ host, conversationId, addAssistantMessage, }) {
8
39
  const [isRunning, setIsRunning] = useState(false);
9
40
  const [currentStep, setCurrentStep] = useState(null);
10
41
  const [error, setError] = useState(null);
11
42
  const [approvalRequest, setApprovalRequest] = useState(null);
43
+ const [askRequest, setAskRequest] = useState(null);
44
+ const [approvalSubmitting, setApprovalSubmitting] = useState(false);
45
+ const [lanes, setLanes] = useState([]);
12
46
  const runRef = useRef(null);
13
47
  const consumeRun = useCallback(async (run) => {
14
48
  runRef.current = run;
@@ -20,8 +54,30 @@ export function useRun({ host, conversationId, addAssistantMessage, }) {
20
54
  toolCalls: [],
21
55
  runId: run.id,
22
56
  };
23
- addAssistantMessage({ ...assistantMessage, toolCalls: [] });
57
+ let assistantStarted = false;
58
+ const ensureAssistant = () => {
59
+ if (assistantStarted)
60
+ return;
61
+ assistantStarted = true;
62
+ addAssistantMessage({ ...assistantMessage, toolCalls: [] });
63
+ };
24
64
  for await (const event of run.events) {
65
+ if (event.type === 'notice') {
66
+ const data = event.data && typeof event.data === 'object' && !Array.isArray(event.data)
67
+ ? event.data
68
+ : {};
69
+ const text = typeof data.text === 'string' ? data.text : '';
70
+ if (text) {
71
+ addAssistantMessage({
72
+ id: `notice-${run.id}-${event.seq}`,
73
+ role: 'system',
74
+ text,
75
+ createdAt: new Date().toISOString(),
76
+ });
77
+ }
78
+ continue;
79
+ }
80
+ ensureAssistant();
25
81
  switch (event.type) {
26
82
  case 'text':
27
83
  assistantMessage.text += String(event.data ?? '');
@@ -57,6 +113,31 @@ export function useRun({ host, conversationId, addAssistantMessage, }) {
57
113
  const input = payload.input && typeof payload.input === 'object' && !Array.isArray(payload.input)
58
114
  ? payload.input
59
115
  : {};
116
+ if (input.kind === 'ask' && (input.type === 'choice' || input.type === 'multi' || input.type === 'input')) {
117
+ const options = Array.isArray(input.options)
118
+ ? input.options.flatMap((option) => {
119
+ if (!option || typeof option !== 'object' || Array.isArray(option))
120
+ return [];
121
+ const item = option;
122
+ return typeof item.label === 'string' && typeof item.value === 'string' ? [{ label: item.label, value: item.value }] : [];
123
+ })
124
+ : undefined;
125
+ setApprovalRequest(null);
126
+ setAskRequest({
127
+ effectId,
128
+ toolName: typeof input.toolName === 'string' ? input.toolName : `ask.${input.type}`,
129
+ type: input.type,
130
+ prompt: typeof input.prompt === 'string' ? input.prompt : '请输入你的回答。',
131
+ ...(options && options.length ? { options } : {}),
132
+ ...(typeof input.min === 'number' ? { min: input.min } : {}),
133
+ ...(typeof input.max === 'number' ? { max: input.max } : {}),
134
+ ...(typeof input.placeholder === 'string' ? { placeholder: input.placeholder } : {}),
135
+ ...(typeof input.defaultValue === 'string' ? { defaultValue: input.defaultValue } : {}),
136
+ });
137
+ setCurrentStep('等待你的回答...');
138
+ break;
139
+ }
140
+ setAskRequest(null);
60
141
  const tools = Array.isArray(input.tools)
61
142
  ? input.tools.flatMap((tool) => {
62
143
  if (!tool || typeof tool !== 'object' || Array.isArray(tool))
@@ -84,22 +165,51 @@ export function useRun({ host, conversationId, addAssistantMessage, }) {
84
165
  break;
85
166
  }
86
167
  case 'fact':
87
- if (typeof event.data === 'string') {
88
- setCurrentStep(event.data);
89
- }
90
- else if (event.data && typeof event.data === 'object') {
91
- setCurrentStep('正在执行...');
168
+ if (event.data && typeof event.data === 'object' && !Array.isArray(event.data)) {
169
+ const fact = event.data;
170
+ if (fact.type === 'lane.snapshot' && Array.isArray(fact.lanes)) {
171
+ setLanes(fact.lanes.flatMap((lane) => {
172
+ if (!lane || typeof lane !== 'object' || Array.isArray(lane))
173
+ return [];
174
+ const item = lane;
175
+ if (typeof item.id !== 'string' || typeof item.status !== 'string' || typeof item.goal !== 'string')
176
+ return [];
177
+ return [{
178
+ id: item.id,
179
+ status: item.status,
180
+ goal: item.goal,
181
+ ...(typeof item.activity === 'string' ? { activity: item.activity } : {}),
182
+ }];
183
+ }));
184
+ break;
185
+ }
92
186
  }
187
+ setCurrentStep(describeFactStatus(event.data));
93
188
  break;
94
189
  case 'error':
95
190
  setError(String(event.data ?? '发生未知错误'));
96
191
  setIsRunning(false);
97
192
  setCurrentStep(null);
98
193
  setApprovalRequest(null);
194
+ setAskRequest(null);
195
+ setLanes([]);
99
196
  break;
100
197
  case 'complete':
101
198
  setIsRunning(false);
102
199
  setCurrentStep(null);
200
+ setApprovalRequest(null);
201
+ setAskRequest(null);
202
+ if (event.data && typeof event.data === 'object' && !Array.isArray(event.data)) {
203
+ const completion = event.data;
204
+ const completionError = completion.error;
205
+ if (completion.status === 'failed' && completionError && typeof completionError === 'object' && !Array.isArray(completionError)) {
206
+ const error = completionError;
207
+ setError(`${String(error.code ?? 'RUN_FAILED')}: ${String(error.message ?? '运行失败')}`);
208
+ }
209
+ else if (completion.status === 'failed') {
210
+ setError('RUN_FAILED: 运行失败');
211
+ }
212
+ }
103
213
  break;
104
214
  }
105
215
  }
@@ -108,16 +218,29 @@ export function useRun({ host, conversationId, addAssistantMessage, }) {
108
218
  setIsRunning(false);
109
219
  setCurrentStep(null);
110
220
  setApprovalRequest(null);
221
+ setAskRequest(null);
111
222
  runRef.current = null;
112
223
  }, []);
113
- const sendMessage = useCallback(async (text) => {
114
- if (!host || !conversationId || runRef.current)
224
+ const sendMessage = useCallback(async (text, targetConversationId) => {
225
+ const activeConversationId = targetConversationId ?? conversationId;
226
+ if (!host || !activeConversationId)
115
227
  return;
228
+ if (runRef.current) {
229
+ try {
230
+ await runRef.current.submitHumanInput(text);
231
+ setError(null);
232
+ setCurrentStep('已接收输入,调度器正在决定如何处理...');
233
+ }
234
+ catch (e) {
235
+ setError(e instanceof Error ? e.message : String(e));
236
+ }
237
+ return;
238
+ }
116
239
  setIsRunning(true);
117
240
  setError(null);
118
241
  setCurrentStep('思考中...');
119
242
  try {
120
- const run = await host.sendMessage(conversationId, { text });
243
+ const run = await host.sendMessage(activeConversationId, { text });
121
244
  await consumeRun(run);
122
245
  }
123
246
  catch (e) {
@@ -127,14 +250,15 @@ export function useRun({ host, conversationId, addAssistantMessage, }) {
127
250
  finishRun();
128
251
  }
129
252
  }, [host, conversationId, consumeRun, finishRun]);
130
- const resumeActive = useCallback(async () => {
131
- if (!host || !conversationId || runRef.current)
253
+ const resumeActive = useCallback(async (targetConversationId) => {
254
+ const activeConversationId = targetConversationId ?? conversationId;
255
+ if (!host || !activeConversationId || runRef.current)
132
256
  return;
133
257
  setIsRunning(true);
134
258
  setError(null);
135
259
  setCurrentStep('正在恢复未完成的运行...');
136
260
  try {
137
- const run = await host.resumeRun(conversationId);
261
+ const run = await host.resumeRun(activeConversationId);
138
262
  await consumeRun(run);
139
263
  }
140
264
  catch (e) {
@@ -150,12 +274,41 @@ export function useRun({ host, conversationId, addAssistantMessage, }) {
150
274
  void run.cancel('USER_INTERRUPT');
151
275
  }, []);
152
276
  const approveAction = useCallback(async (effectId, approved, reason) => {
153
- if (!effectId || !runRef.current)
277
+ if (!effectId || !runRef.current || approvalSubmitting)
154
278
  return;
155
- await runRef.current.reply(effectId, { approved, ...(approved ? {} : { reason: reason || '拒绝执行' }) });
156
- setApprovalRequest(null);
157
- setCurrentStep('审批已提交,正在继续...');
158
- }, []);
279
+ setApprovalSubmitting(true);
280
+ try {
281
+ await runRef.current.reply(effectId, { approved, ...(approved ? {} : { reason: reason || '拒绝执行' }) });
282
+ setApprovalRequest(null);
283
+ setCurrentStep('审批已提交,正在继续...');
284
+ setError(null);
285
+ }
286
+ catch (e) {
287
+ setError(`审批提交失败: ${e instanceof Error ? e.message : String(e)}`);
288
+ setCurrentStep('审批仍在等待,请重新选择。');
289
+ }
290
+ finally {
291
+ setApprovalSubmitting(false);
292
+ }
293
+ }, [approvalSubmitting]);
294
+ const replyAsk = useCallback(async (effectId, value) => {
295
+ if (!effectId || !runRef.current || approvalSubmitting)
296
+ return;
297
+ setApprovalSubmitting(true);
298
+ try {
299
+ await runRef.current.reply(effectId, value);
300
+ setAskRequest(null);
301
+ setCurrentStep('回答已提交,正在继续...');
302
+ setError(null);
303
+ }
304
+ catch (e) {
305
+ setError(`回答提交失败: ${e instanceof Error ? e.message : String(e)}`);
306
+ setCurrentStep('仍在等待你的回答,请重新选择。');
307
+ }
308
+ finally {
309
+ setApprovalSubmitting(false);
310
+ }
311
+ }, [approvalSubmitting]);
159
312
  const cancelRun = useCallback(async () => {
160
313
  if (runRef.current) {
161
314
  await runRef.current.cancel('USER_CANCELLED');
@@ -168,9 +321,13 @@ export function useRun({ host, conversationId, addAssistantMessage, }) {
168
321
  currentStep,
169
322
  error,
170
323
  approvalRequest,
324
+ askRequest,
325
+ lanes,
326
+ approvalSubmitting,
171
327
  sendMessage,
172
328
  resumeActive,
173
329
  approveAction,
330
+ replyAsk,
174
331
  cancelRun,
175
332
  };
176
333
  }
@@ -6,7 +6,9 @@ export interface SlashCommandDependencies {
6
6
  onArtifacts?: () => void | Promise<void>;
7
7
  onExit?: () => void | Promise<void>;
8
8
  onQuit?: () => void | Promise<void>;
9
+ onCancel?: () => void | Promise<void>;
9
10
  onNew?: () => void | Promise<void>;
11
+ onResume?: () => void | Promise<void>;
10
12
  onSessions?: () => void | Promise<void>;
11
13
  onDelete?: (args: string) => void | Promise<void>;
12
14
  onExport?: (args: string) => void | Promise<void>;
@@ -7,7 +7,9 @@ export function useSlashCommands(deps) {
7
7
  { name: '/artifacts', description: '查看当前产物', execute: async () => deps.onArtifacts?.() },
8
8
  { name: '/exit', description: '退出程序', execute: async () => deps.onExit?.() },
9
9
  { name: '/quit', aliases: ['/q'], description: '退出程序', execute: async () => deps.onQuit?.() },
10
+ { name: '/cancel', aliases: ['/stop'], description: '取消当前运行(保留会话)', execute: async () => deps.onCancel?.() },
10
11
  { name: '/new', description: '开启新会话', execute: async () => deps.onNew?.() },
12
+ { name: '/resume', description: '恢复上一次会话或未完成运行', execute: async () => deps.onResume?.() },
11
13
  { name: '/sessions', description: '查看所有会话', execute: async () => deps.onSessions?.() },
12
14
  { name: '/delete', description: '删除会话 [id]', execute: async (args) => deps.onDelete?.(args) },
13
15
  { name: '/export', description: '导出会话 [markdown|json]', execute: async (args) => deps.onExport?.(args) },
package/dist/types.d.ts CHANGED
@@ -31,9 +31,16 @@ export interface ToolCallDisplay {
31
31
  name: string;
32
32
  arguments?: Record<string, unknown> | undefined;
33
33
  result?: unknown;
34
- status: 'running' | 'succeeded' | 'failed';
34
+ status: 'running' | 'succeeded' | 'failed' | 'cancelled';
35
35
  durationMs?: number | undefined;
36
36
  }
37
+ /** Runtime lane snapshot rendered in the bottom status HUD. */
38
+ export interface LaneDisplay {
39
+ id: string;
40
+ status: string;
41
+ goal: string;
42
+ activity?: string | undefined;
43
+ }
37
44
  /** Token 统计数据 */
38
45
  export interface TokenStatsData {
39
46
  inputTokens: number;
@@ -55,6 +62,21 @@ export interface ApprovalRequest {
55
62
  input: Record<string, unknown>;
56
63
  }> | undefined;
57
64
  }
65
+ export type AskType = 'choice' | 'multi' | 'input';
66
+ export interface AskRequest {
67
+ effectId: string;
68
+ toolName: string;
69
+ type: AskType;
70
+ prompt: string;
71
+ options?: Array<{
72
+ label: string;
73
+ value: string;
74
+ }> | undefined;
75
+ min?: number | undefined;
76
+ max?: number | undefined;
77
+ placeholder?: string | undefined;
78
+ defaultValue?: string | undefined;
79
+ }
58
80
  /** 应用状态模式 */
59
81
  export type AppMode = 'chat' | 'sessions' | 'help' | 'config';
60
82
  /** 解析后的命令行参数 */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hunterzhu/pulse-cli",
3
- "version": "0.1.5",
3
+ "version": "0.1.7",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "https://github.com/zhuhengtan/Pulse"
@@ -19,7 +19,7 @@
19
19
  "build": "tsc -p tsconfig.json"
20
20
  },
21
21
  "dependencies": {
22
- "@hunterzhu/pulse-server": "0.1.5",
22
+ "@hunterzhu/pulse-server": "0.1.7",
23
23
  "ink": "^7.1.1",
24
24
  "react": "^19.0.0",
25
25
  "ink-spinner": "^5.0.0",