@zhin.js/client 2.0.3 → 2.0.4

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 (35) hide show
  1. package/client/index.ts +6 -0
  2. package/client/mediaSrc.ts +6 -1
  3. package/client/orchestration/OrchestrationRunsPage.tsx +217 -0
  4. package/client/orchestration/registerOrchestrationConsole.test.ts +26 -0
  5. package/client/orchestration/registerOrchestrationConsole.ts +17 -0
  6. package/client/segments.test.ts +16 -0
  7. package/client/segments.ts +39 -0
  8. package/client/types.ts +5 -5
  9. package/dist/index.d.ts +3 -0
  10. package/dist/index.d.ts.map +1 -1
  11. package/dist/index.js +4 -0
  12. package/dist/index.js.map +1 -1
  13. package/dist/mediaSrc.d.ts +1 -1
  14. package/dist/mediaSrc.d.ts.map +1 -1
  15. package/dist/mediaSrc.js +7 -1
  16. package/dist/mediaSrc.js.map +1 -1
  17. package/dist/orchestration/OrchestrationRunsPage.d.ts +2 -0
  18. package/dist/orchestration/OrchestrationRunsPage.d.ts.map +1 -0
  19. package/dist/orchestration/OrchestrationRunsPage.js +65 -0
  20. package/dist/orchestration/OrchestrationRunsPage.js.map +1 -0
  21. package/dist/orchestration/registerOrchestrationConsole.d.ts +4 -0
  22. package/dist/orchestration/registerOrchestrationConsole.d.ts.map +1 -0
  23. package/dist/orchestration/registerOrchestrationConsole.js +16 -0
  24. package/dist/orchestration/registerOrchestrationConsole.js.map +1 -0
  25. package/dist/segments.d.ts +9 -0
  26. package/dist/segments.d.ts.map +1 -0
  27. package/dist/segments.js +35 -0
  28. package/dist/segments.js.map +1 -0
  29. package/dist/types.d.ts +4 -3
  30. package/dist/types.d.ts.map +1 -1
  31. package/package.json +13 -4
  32. package/dist/bootstrap/loadConsoleEntries.test.d.ts +0 -2
  33. package/dist/bootstrap/loadConsoleEntries.test.d.ts.map +0 -1
  34. package/dist/bootstrap/loadConsoleEntries.test.js +0 -27
  35. package/dist/bootstrap/loadConsoleEntries.test.js.map +0 -1
package/client/index.ts CHANGED
@@ -4,6 +4,9 @@ export * from "./types";
4
4
  // Media URL resolution
5
5
  export { resolveMediaSrc, pickMediaRawUrl, type MediaKind } from "./mediaSrc";
6
6
 
7
+ // Segment IM visibility (inbox vs agent panel)
8
+ export { segmentsForImDelivery, segmentsForAgentPanel } from "./segments.js";
9
+
7
10
  // Console app singleton (pagemanager / registry style)
8
11
  export {
9
12
  app,
@@ -47,3 +50,6 @@ export {
47
50
  type FetchConsoleEntriesOptions,
48
51
  type LoadConsoleEntriesOptions,
49
52
  } from "./bootstrap/loadConsoleEntries.js";
53
+
54
+ export { registerOrchestrationConsole } from "./orchestration/registerOrchestrationConsole.js";
55
+ export { default as OrchestrationRunsPage } from "./orchestration/OrchestrationRunsPage.js";
@@ -43,9 +43,14 @@ export function resolveMediaSrc(
43
43
  return `data:${defaultMime};base64,${b64}`
44
44
  }
45
45
 
46
- /** 从 segment.data 取常见媒体字段 */
46
+ /** 从 segment.data 取常见媒体字段(优先 canonical MediaRef) */
47
47
  export function pickMediaRawUrl(data: Record<string, unknown> | undefined): string | undefined {
48
48
  if (!data) return undefined
49
+ const media = data.media
50
+ if (media && typeof media === 'object' && media !== null) {
51
+ const value = (media as { value?: unknown }).value
52
+ if (typeof value === 'string' && value.trim()) return value.trim()
53
+ }
49
54
  const v = data.url ?? data.file ?? data.src ?? data.href
50
55
  return typeof v === 'string' && v.trim() ? v.trim() : undefined
51
56
  }
@@ -0,0 +1,217 @@
1
+ import { useCallback, useState } from 'react';
2
+ import { apiFetch } from '../console-utils/remoteApi.js';
3
+
4
+ type OrchestrationTaskRow = {
5
+ id: string;
6
+ name: string;
7
+ status: string;
8
+ executor_kind?: string;
9
+ assigned_to?: string;
10
+ result_summary?: string;
11
+ error?: string;
12
+ };
13
+
14
+ type OrchestrationEventRow = {
15
+ seq: number;
16
+ type: string;
17
+ task_id?: string;
18
+ payload_json?: string;
19
+ created_at?: number;
20
+ };
21
+
22
+ type RunListItem = {
23
+ run: { id: string; session_key: string; status: string; title: string };
24
+ tasks: OrchestrationTaskRow[];
25
+ };
26
+
27
+ type RunDetail = RunListItem & {
28
+ events?: OrchestrationEventRow[];
29
+ };
30
+
31
+ function parsePayload(raw?: string): string {
32
+ if (!raw?.trim()) return '';
33
+ try {
34
+ const parsed = JSON.parse(raw) as Record<string, unknown>;
35
+ return JSON.stringify(parsed, null, 2);
36
+ } catch {
37
+ return raw;
38
+ }
39
+ }
40
+
41
+ export default function OrchestrationRunsPage() {
42
+ const [sessionKey, setSessionKey] = useState('');
43
+ const [runs, setRuns] = useState<RunListItem[]>([]);
44
+ const [selected, setSelected] = useState<RunDetail | null>(null);
45
+ const [loading, setLoading] = useState(false);
46
+ const [error, setError] = useState('');
47
+
48
+ const loadRuns = useCallback(async () => {
49
+ if (!sessionKey.trim()) {
50
+ setError('请输入 sessionKey');
51
+ return;
52
+ }
53
+ setLoading(true);
54
+ setError('');
55
+ setSelected(null);
56
+ try {
57
+ const res = await apiFetch(
58
+ `/api/agent/orchestration/runs?sessionKey=${encodeURIComponent(sessionKey.trim())}`,
59
+ );
60
+ const body = await res.json() as { success?: boolean; error?: string; data?: { runs?: RunListItem[] } };
61
+ if (!res.ok || !body.success) {
62
+ throw new Error(body.error ?? `HTTP ${res.status}`);
63
+ }
64
+ setRuns(body.data?.runs ?? []);
65
+ } catch (err) {
66
+ setError(err instanceof Error ? err.message : String(err));
67
+ setRuns([]);
68
+ } finally {
69
+ setLoading(false);
70
+ }
71
+ }, [sessionKey]);
72
+
73
+ const loadRunDetail = useCallback(async (runId: string) => {
74
+ setLoading(true);
75
+ setError('');
76
+ try {
77
+ const res = await apiFetch(`/api/agent/orchestration/runs/${encodeURIComponent(runId)}`);
78
+ const body = await res.json() as { success?: boolean; error?: string; data?: RunDetail };
79
+ if (!res.ok || !body.success || !body.data) {
80
+ throw new Error(body.error ?? `HTTP ${res.status}`);
81
+ }
82
+ setSelected(body.data);
83
+ } catch (err) {
84
+ setError(err instanceof Error ? err.message : String(err));
85
+ } finally {
86
+ setLoading(false);
87
+ }
88
+ }, []);
89
+
90
+ return (
91
+ <div className="p-4 space-y-4 max-w-5xl">
92
+ <h1 className="text-lg font-semibold">编排 Run / Task / Event</h1>
93
+ <p className="text-sm text-muted-foreground">
94
+ 从 OrchestrationKernel 投影(`GET /api/agent/orchestration/*`)。sessionKey 格式:
95
+ <code className="mx-1">platform:endpointId:kind:sceneId</code>
96
+ </p>
97
+
98
+ <div className="flex flex-wrap gap-2 items-end">
99
+ <label className="flex flex-col gap-1 text-sm flex-1 min-w-[240px]">
100
+ sessionKey
101
+ <input
102
+ className="border rounded px-2 py-1 text-sm bg-background"
103
+ value={sessionKey}
104
+ onChange={(e) => setSessionKey(e.target.value)}
105
+ placeholder="sandbox:solo-bot:private:user1"
106
+ />
107
+ </label>
108
+ <button
109
+ type="button"
110
+ className="border rounded px-3 py-1 text-sm hover:bg-muted"
111
+ disabled={loading}
112
+ onClick={() => void loadRuns()}
113
+ >
114
+ 查询 Runs
115
+ </button>
116
+ </div>
117
+
118
+ {error ? <p className="text-sm text-red-600">{error}</p> : null}
119
+
120
+ <div className="grid gap-4 md:grid-cols-2">
121
+ <section className="border rounded p-3 space-y-2">
122
+ <h2 className="text-sm font-medium">Runs ({runs.length})</h2>
123
+ {runs.length === 0 ? (
124
+ <p className="text-sm text-muted-foreground">无数据</p>
125
+ ) : (
126
+ <ul className="space-y-2 text-sm">
127
+ {runs.map((item) => (
128
+ <li key={item.run.id} className="border rounded p-2">
129
+ <button
130
+ type="button"
131
+ className="text-left w-full hover:underline"
132
+ onClick={() => void loadRunDetail(item.run.id)}
133
+ >
134
+ <div className="font-mono text-xs">{item.run.id}</div>
135
+ <div>{item.run.title || '(无标题)'}</div>
136
+ <div className="text-muted-foreground">
137
+ {item.run.status}
138
+ {' · '}
139
+ {item.tasks.length}
140
+ {' tasks'}
141
+ </div>
142
+ </button>
143
+ </li>
144
+ ))}
145
+ </ul>
146
+ )}
147
+ </section>
148
+
149
+ <section className="border rounded p-3 space-y-3">
150
+ <h2 className="text-sm font-medium">Run 详情</h2>
151
+ {!selected ? (
152
+ <p className="text-sm text-muted-foreground">选择左侧 Run</p>
153
+ ) : (
154
+ <>
155
+ <div className="text-sm space-y-1">
156
+ <div>
157
+ <span className="text-muted-foreground">ID </span>
158
+ <code>{selected.run.id}</code>
159
+ </div>
160
+ <div>
161
+ <span className="text-muted-foreground">状态 </span>
162
+ {selected.run.status}
163
+ </div>
164
+ </div>
165
+
166
+ <div>
167
+ <h3 className="text-xs font-medium uppercase text-muted-foreground mb-1">Tasks</h3>
168
+ <ul className="space-y-2 text-sm">
169
+ {selected.tasks.map((task) => (
170
+ <li key={task.id} className="border rounded p-2 font-mono text-xs">
171
+ <div>
172
+ {task.id}
173
+ {' · '}
174
+ {task.status}
175
+ {' · '}
176
+ {task.executor_kind ?? 'local'}
177
+ </div>
178
+ <div>{task.name}</div>
179
+ {task.result_summary ? (
180
+ <div className="mt-1 whitespace-pre-wrap break-words">{task.result_summary}</div>
181
+ ) : null}
182
+ {task.error ? (
183
+ <div className="mt-1 text-red-600 whitespace-pre-wrap">{task.error}</div>
184
+ ) : null}
185
+ </li>
186
+ ))}
187
+ </ul>
188
+ </div>
189
+
190
+ <div>
191
+ <h3 className="text-xs font-medium uppercase text-muted-foreground mb-1">Events</h3>
192
+ <ul className="space-y-2 text-xs max-h-64 overflow-auto">
193
+ {(selected.events ?? []).map((ev) => (
194
+ <li key={ev.seq} className="border rounded p-2">
195
+ <div>
196
+ #
197
+ {ev.seq}
198
+ {' '}
199
+ {ev.type}
200
+ {ev.task_id ? ` · task ${ev.task_id}` : ''}
201
+ </div>
202
+ {ev.payload_json ? (
203
+ <pre className="mt-1 whitespace-pre-wrap break-words text-[10px] opacity-80">
204
+ {parsePayload(ev.payload_json)}
205
+ </pre>
206
+ ) : null}
207
+ </li>
208
+ ))}
209
+ </ul>
210
+ </div>
211
+ </>
212
+ )}
213
+ </section>
214
+ </div>
215
+ </div>
216
+ );
217
+ }
@@ -0,0 +1,26 @@
1
+ import { describe, expect, it, vi } from 'vitest';
2
+ import { registerOrchestrationConsole } from './registerOrchestrationConsole.js';
3
+
4
+ describe('registerOrchestrationConsole', () => {
5
+ it('registers orchestration route and tool', () => {
6
+ const addRoute = vi.fn();
7
+ const addTool = vi.fn();
8
+ const React = { createElement: vi.fn((type) => ({ type })) };
9
+
10
+ registerOrchestrationConsole({
11
+ React: React as never,
12
+ addRoute,
13
+ addPage: addRoute,
14
+ addTool,
15
+ });
16
+
17
+ expect(addRoute).toHaveBeenCalledWith(expect.objectContaining({
18
+ path: '/console/orchestration',
19
+ name: '编排',
20
+ }));
21
+ expect(addTool).toHaveBeenCalledWith(expect.objectContaining({
22
+ id: 'orchestration',
23
+ path: '/console/orchestration',
24
+ }));
25
+ });
26
+ });
@@ -0,0 +1,17 @@
1
+ import type { PluginRegisterHostApi } from '@zhin.js/contract';
2
+ import OrchestrationRunsPage from './OrchestrationRunsPage.js';
3
+
4
+ /** Remote Console v1.1 — OrchestrationKernel Run/Task/Event 投影页 */
5
+ export function registerOrchestrationConsole(api: PluginRegisterHostApi): void {
6
+ api.addRoute({
7
+ path: '/console/orchestration',
8
+ name: '编排',
9
+ element: api.React.createElement(OrchestrationRunsPage),
10
+ meta: { order: 40, group: 'Agent' },
11
+ });
12
+ api.addTool({
13
+ id: 'orchestration',
14
+ name: '编排',
15
+ path: '/console/orchestration',
16
+ });
17
+ }
@@ -0,0 +1,16 @@
1
+ import { describe, expect, it } from 'vitest';
2
+ import { segmentsForAgentPanel, segmentsForImDelivery } from '../client/segments.js';
3
+
4
+ describe('console segmentsForImDelivery', () => {
5
+ it('inbox view strips AI-only segments', () => {
6
+ const full = [
7
+ { type: 'thinking', data: { text: 'plan' } },
8
+ { type: 'text', data: { text: 'hi' } },
9
+ { type: 'tool_call', data: { name: 'bash' } },
10
+ ];
11
+ expect(segmentsForImDelivery(full)).toEqual([
12
+ { type: 'text', data: { text: 'hi' } },
13
+ ]);
14
+ expect(segmentsForAgentPanel(full)).toEqual(full);
15
+ });
16
+ });
@@ -0,0 +1,39 @@
1
+ import type { MessageSegment } from './types.js';
2
+
3
+ /** IM 可见段白名单(与 core segment-contract/delivery 对齐) */
4
+ const IM_VISIBLE_TYPES = new Set([
5
+ 'text', 'mention', 'image', 'video', 'audio', 'voice', 'record', 'file',
6
+ 'face', 'reply', 'forward', 'link', 'dice', 'rps', 'markdown', 'html',
7
+ 'qrcode', 'tts', 'keyboard', 'action',
8
+ ]);
9
+
10
+ const AI_ONLY_TYPES = new Set(['thinking', 'tool_call']);
11
+
12
+ function isSegmentLike(value: unknown): value is MessageSegment {
13
+ return (
14
+ typeof value === 'object'
15
+ && value !== null
16
+ && typeof (value as MessageSegment).type === 'string'
17
+ && 'data' in value
18
+ );
19
+ }
20
+
21
+ /**
22
+ * Inbox / 用户 IM 视图:仅展示 IM-visible 段(剔除 thinking、tool_call)。
23
+ * Agent 面板应使用全量 segments,勿调用此函数。
24
+ */
25
+ export function segmentsForImDelivery(segments: readonly unknown[]): MessageSegment[] {
26
+ const out: MessageSegment[] = [];
27
+ for (const item of segments) {
28
+ if (!isSegmentLike(item)) continue;
29
+ if (AI_ONLY_TYPES.has(item.type)) continue;
30
+ if (!IM_VISIBLE_TYPES.has(item.type)) continue;
31
+ out.push(item);
32
+ }
33
+ return out;
34
+ }
35
+
36
+ /** Agent 面板全量 segments(identity,便于双视图 API 对称) */
37
+ export function segmentsForAgentPanel(segments: readonly MessageSegment[]): MessageSegment[] {
38
+ return [...segments];
39
+ }
package/client/types.ts CHANGED
@@ -1,8 +1,9 @@
1
- // 消息段类型定义 - 客户端版本
1
+ // 消息段类型定义 - 客户端版本(对齐 core Segment SSOT)
2
2
  export interface MessageSegment {
3
- /** record:如 ICQQ 语音等,展示时按音频处理 */
4
- type: 'text' | 'image' | 'at' | 'face' | 'video' | 'audio' | 'record' | 'file' | 'reply'
5
- data: Record<string, any>
3
+ /** record:如 ICQQ 语音等,展示时按音频处理;thinking/tool_call 仅 agent 面板展示 */
4
+ type: 'text' | 'mention' | 'at' | 'image' | 'face' | 'video' | 'audio' | 'record' | 'file' | 'reply' | 'forward' | 'keyboard' | 'action' | 'thinking' | 'tool_call' | string
5
+ data: Record<string, unknown>
6
+ platform?: Record<string, unknown>
6
7
  }
7
8
 
8
9
  // 消息元素别名(兼容不同命名习惯)
@@ -10,4 +11,3 @@ export type MessageElement = MessageSegment
10
11
 
11
12
  // 发送内容类型
12
13
  export type SendContent = MessageSegment | MessageSegment[] | string
13
-
package/dist/index.d.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  export * from "./types";
2
2
  export { resolveMediaSrc, pickMediaRawUrl, type MediaKind } from "./mediaSrc";
3
+ export { segmentsForImDelivery, segmentsForAgentPanel } from "./segments.js";
3
4
  export { app, type ConsoleApp, type AddRouteInput, type AddToolInput, type ConsoleRouteRecord, type RouteTreeNode, type ToolTreeNode, type ConsoleRouteRenderer, } from "./app";
4
5
  export * from "./websocket";
5
6
  export { configureConsole, getRuntimeEnv } from "./runtime/index.js";
@@ -7,4 +8,6 @@ export { createRegistryStore, useRegistry, type RegistryStore, } from "./store/c
7
8
  export { cn } from "./console-utils/cn.js";
8
9
  export { apiFetch, getApiBase, getToken, resolveApiUrl, resolveWebSocketUrl, } from "./console-utils/remoteApi.js";
9
10
  export { fetchConsoleEntries, createPluginRegisterHostApi, getRegisterFn, loadConsoleEntries, registerConsolePluginsFromEntries, type CreatePluginRegisterHostApiOptions, type FetchConsoleEntriesOptions, type LoadConsoleEntriesOptions, } from "./bootstrap/loadConsoleEntries.js";
11
+ export { registerOrchestrationConsole } from "./orchestration/registerOrchestrationConsole.js";
12
+ export { default as OrchestrationRunsPage } from "./orchestration/OrchestrationRunsPage.js";
10
13
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../client/index.ts"],"names":[],"mappings":"AACA,cAAc,SAAS,CAAC;AAGxB,OAAO,EAAE,eAAe,EAAE,eAAe,EAAE,KAAK,SAAS,EAAE,MAAM,YAAY,CAAC;AAG9E,OAAO,EACL,GAAG,EACH,KAAK,UAAU,EACf,KAAK,aAAa,EAClB,KAAK,YAAY,EACjB,KAAK,kBAAkB,EACvB,KAAK,aAAa,EAClB,KAAK,YAAY,EACjB,KAAK,oBAAoB,GAC1B,MAAM,OAAO,CAAC;AAGf,cAAc,aAAa,CAAC;AAE5B,OAAO,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAErE,OAAO,EACL,mBAAmB,EACnB,WAAW,EACX,KAAK,aAAa,GACnB,MAAM,gCAAgC,CAAC;AAExC,OAAO,EAAE,EAAE,EAAE,MAAM,uBAAuB,CAAC;AAE3C,OAAO,EACL,QAAQ,EACR,UAAU,EACV,QAAQ,EACR,aAAa,EACb,mBAAmB,GACpB,MAAM,8BAA8B,CAAC;AAEtC,OAAO,EACL,mBAAmB,EACnB,2BAA2B,EAC3B,aAAa,EACb,kBAAkB,EAClB,iCAAiC,EACjC,KAAK,kCAAkC,EACvC,KAAK,0BAA0B,EAC/B,KAAK,yBAAyB,GAC/B,MAAM,mCAAmC,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../client/index.ts"],"names":[],"mappings":"AACA,cAAc,SAAS,CAAC;AAGxB,OAAO,EAAE,eAAe,EAAE,eAAe,EAAE,KAAK,SAAS,EAAE,MAAM,YAAY,CAAC;AAG9E,OAAO,EAAE,qBAAqB,EAAE,qBAAqB,EAAE,MAAM,eAAe,CAAC;AAG7E,OAAO,EACL,GAAG,EACH,KAAK,UAAU,EACf,KAAK,aAAa,EAClB,KAAK,YAAY,EACjB,KAAK,kBAAkB,EACvB,KAAK,aAAa,EAClB,KAAK,YAAY,EACjB,KAAK,oBAAoB,GAC1B,MAAM,OAAO,CAAC;AAGf,cAAc,aAAa,CAAC;AAE5B,OAAO,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAErE,OAAO,EACL,mBAAmB,EACnB,WAAW,EACX,KAAK,aAAa,GACnB,MAAM,gCAAgC,CAAC;AAExC,OAAO,EAAE,EAAE,EAAE,MAAM,uBAAuB,CAAC;AAE3C,OAAO,EACL,QAAQ,EACR,UAAU,EACV,QAAQ,EACR,aAAa,EACb,mBAAmB,GACpB,MAAM,8BAA8B,CAAC;AAEtC,OAAO,EACL,mBAAmB,EACnB,2BAA2B,EAC3B,aAAa,EACb,kBAAkB,EAClB,iCAAiC,EACjC,KAAK,kCAAkC,EACvC,KAAK,0BAA0B,EAC/B,KAAK,yBAAyB,GAC/B,MAAM,mCAAmC,CAAC;AAE3C,OAAO,EAAE,4BAA4B,EAAE,MAAM,iDAAiD,CAAC;AAC/F,OAAO,EAAE,OAAO,IAAI,qBAAqB,EAAE,MAAM,0CAA0C,CAAC"}
package/dist/index.js CHANGED
@@ -2,6 +2,8 @@
2
2
  export * from "./types";
3
3
  // Media URL resolution
4
4
  export { resolveMediaSrc, pickMediaRawUrl } from "./mediaSrc";
5
+ // Segment IM visibility (inbox vs agent panel)
6
+ export { segmentsForImDelivery, segmentsForAgentPanel } from "./segments.js";
5
7
  // Console app singleton (pagemanager / registry style)
6
8
  export { app, } from "./app";
7
9
  // WebSocket (business data only)
@@ -11,4 +13,6 @@ export { createRegistryStore, useRegistry, } from "./store/createRegistryStore.j
11
13
  export { cn } from "./console-utils/cn.js";
12
14
  export { apiFetch, getApiBase, getToken, resolveApiUrl, resolveWebSocketUrl, } from "./console-utils/remoteApi.js";
13
15
  export { fetchConsoleEntries, createPluginRegisterHostApi, getRegisterFn, loadConsoleEntries, registerConsolePluginsFromEntries, } from "./bootstrap/loadConsoleEntries.js";
16
+ export { registerOrchestrationConsole } from "./orchestration/registerOrchestrationConsole.js";
17
+ export { default as OrchestrationRunsPage } from "./orchestration/OrchestrationRunsPage.js";
14
18
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../client/index.ts"],"names":[],"mappings":"AAAA,QAAQ;AACR,cAAc,SAAS,CAAC;AAExB,uBAAuB;AACvB,OAAO,EAAE,eAAe,EAAE,eAAe,EAAkB,MAAM,YAAY,CAAC;AAE9E,uDAAuD;AACvD,OAAO,EACL,GAAG,GAQJ,MAAM,OAAO,CAAC;AAEf,iCAAiC;AACjC,cAAc,aAAa,CAAC;AAE5B,OAAO,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAErE,OAAO,EACL,mBAAmB,EACnB,WAAW,GAEZ,MAAM,gCAAgC,CAAC;AAExC,OAAO,EAAE,EAAE,EAAE,MAAM,uBAAuB,CAAC;AAE3C,OAAO,EACL,QAAQ,EACR,UAAU,EACV,QAAQ,EACR,aAAa,EACb,mBAAmB,GACpB,MAAM,8BAA8B,CAAC;AAEtC,OAAO,EACL,mBAAmB,EACnB,2BAA2B,EAC3B,aAAa,EACb,kBAAkB,EAClB,iCAAiC,GAIlC,MAAM,mCAAmC,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../client/index.ts"],"names":[],"mappings":"AAAA,QAAQ;AACR,cAAc,SAAS,CAAC;AAExB,uBAAuB;AACvB,OAAO,EAAE,eAAe,EAAE,eAAe,EAAkB,MAAM,YAAY,CAAC;AAE9E,+CAA+C;AAC/C,OAAO,EAAE,qBAAqB,EAAE,qBAAqB,EAAE,MAAM,eAAe,CAAC;AAE7E,uDAAuD;AACvD,OAAO,EACL,GAAG,GAQJ,MAAM,OAAO,CAAC;AAEf,iCAAiC;AACjC,cAAc,aAAa,CAAC;AAE5B,OAAO,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAErE,OAAO,EACL,mBAAmB,EACnB,WAAW,GAEZ,MAAM,gCAAgC,CAAC;AAExC,OAAO,EAAE,EAAE,EAAE,MAAM,uBAAuB,CAAC;AAE3C,OAAO,EACL,QAAQ,EACR,UAAU,EACV,QAAQ,EACR,aAAa,EACb,mBAAmB,GACpB,MAAM,8BAA8B,CAAC;AAEtC,OAAO,EACL,mBAAmB,EACnB,2BAA2B,EAC3B,aAAa,EACb,kBAAkB,EAClB,iCAAiC,GAIlC,MAAM,mCAAmC,CAAC;AAE3C,OAAO,EAAE,4BAA4B,EAAE,MAAM,iDAAiD,CAAC;AAC/F,OAAO,EAAE,OAAO,IAAI,qBAAqB,EAAE,MAAM,0CAA0C,CAAC"}
@@ -11,6 +11,6 @@ export type MediaKind = 'image' | 'video' | 'audio';
11
11
  * 与群内日报、html-test 等插件生成的 `base64://${buffer.toString('base64')}` 一致。
12
12
  */
13
13
  export declare function resolveMediaSrc(raw: string | undefined | null, kind?: MediaKind): string | undefined;
14
- /** 从 segment.data 取常见媒体字段 */
14
+ /** 从 segment.data 取常见媒体字段(优先 canonical MediaRef) */
15
15
  export declare function pickMediaRawUrl(data: Record<string, unknown> | undefined): string | undefined;
16
16
  //# sourceMappingURL=mediaSrc.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"mediaSrc.d.ts","sourceRoot":"","sources":["../client/mediaSrc.ts"],"names":[],"mappings":"AAAA,4CAA4C;AAC5C,MAAM,MAAM,SAAS,GAAG,OAAO,GAAG,OAAO,GAAG,OAAO,CAAA;AAInD;;;;;;;;;GASG;AACH,wBAAgB,eAAe,CAC7B,GAAG,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,EAC9B,IAAI,GAAE,SAAmB,GACxB,MAAM,GAAG,SAAS,CAyBpB;AAED,6BAA6B;AAC7B,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,CAI7F"}
1
+ {"version":3,"file":"mediaSrc.d.ts","sourceRoot":"","sources":["../client/mediaSrc.ts"],"names":[],"mappings":"AAAA,4CAA4C;AAC5C,MAAM,MAAM,SAAS,GAAG,OAAO,GAAG,OAAO,GAAG,OAAO,CAAA;AAInD;;;;;;;;;GASG;AACH,wBAAgB,eAAe,CAC7B,GAAG,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,EAC9B,IAAI,GAAE,SAAmB,GACxB,MAAM,GAAG,SAAS,CAyBpB;AAED,oDAAoD;AACpD,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,CAS7F"}
package/dist/mediaSrc.js CHANGED
@@ -32,10 +32,16 @@ export function resolveMediaSrc(raw, kind = 'image') {
32
32
  const b64 = payload.replace(/\s/g, '');
33
33
  return `data:${defaultMime};base64,${b64}`;
34
34
  }
35
- /** 从 segment.data 取常见媒体字段 */
35
+ /** 从 segment.data 取常见媒体字段(优先 canonical MediaRef) */
36
36
  export function pickMediaRawUrl(data) {
37
37
  if (!data)
38
38
  return undefined;
39
+ const media = data.media;
40
+ if (media && typeof media === 'object' && media !== null) {
41
+ const value = media.value;
42
+ if (typeof value === 'string' && value.trim())
43
+ return value.trim();
44
+ }
39
45
  const v = data.url ?? data.file ?? data.src ?? data.href;
40
46
  return typeof v === 'string' && v.trim() ? v.trim() : undefined;
41
47
  }
@@ -1 +1 @@
1
- {"version":3,"file":"mediaSrc.js","sourceRoot":"","sources":["../client/mediaSrc.ts"],"names":[],"mappings":"AAGA,MAAM,YAAY,GAAG,WAAW,CAAA;AAEhC;;;;;;;;;GASG;AACH,MAAM,UAAU,eAAe,CAC7B,GAA8B,EAC9B,OAAkB,OAAO;IAEzB,IAAI,GAAG,IAAI,IAAI,IAAI,OAAO,GAAG,KAAK,QAAQ;QAAE,OAAO,SAAS,CAAA;IAC5D,MAAM,CAAC,GAAG,GAAG,CAAC,IAAI,EAAE,CAAA;IACpB,IAAI,CAAC,CAAC;QAAE,OAAO,SAAS,CAAA;IAExB,IAAI,CAAC,CAAC,UAAU,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,UAAU,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,UAAU,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;QAC1G,OAAO,CAAC,CAAA;IACV,CAAC;IAED,IAAI,CAAC,CAAC,CAAC,UAAU,CAAC,YAAY,CAAC,EAAE,CAAC;QAChC,OAAO,CAAC,CAAA;IACV,CAAC;IAED,MAAM,OAAO,GAAG,CAAC,CAAC,KAAK,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAA;IAChE,IAAI,CAAC,OAAO;QAAE,OAAO,SAAS,CAAA;IAE9B,0CAA0C;IAC1C,IAAI,8BAA8B,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;QACjD,OAAO,QAAQ,OAAO,EAAE,CAAA;IAC1B,CAAC;IAED,MAAM,WAAW,GACf,IAAI,KAAK,OAAO,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,IAAI,KAAK,OAAO,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,YAAY,CAAA;IAChF,MAAM,GAAG,GAAG,OAAO,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAA;IACtC,OAAO,QAAQ,WAAW,WAAW,GAAG,EAAE,CAAA;AAC5C,CAAC;AAED,6BAA6B;AAC7B,MAAM,UAAU,eAAe,CAAC,IAAyC;IACvE,IAAI,CAAC,IAAI;QAAE,OAAO,SAAS,CAAA;IAC3B,MAAM,CAAC,GAAG,IAAI,CAAC,GAAG,IAAI,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,GAAG,IAAI,IAAI,CAAC,IAAI,CAAA;IACxD,OAAO,OAAO,CAAC,KAAK,QAAQ,IAAI,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,SAAS,CAAA;AACjE,CAAC"}
1
+ {"version":3,"file":"mediaSrc.js","sourceRoot":"","sources":["../client/mediaSrc.ts"],"names":[],"mappings":"AAGA,MAAM,YAAY,GAAG,WAAW,CAAA;AAEhC;;;;;;;;;GASG;AACH,MAAM,UAAU,eAAe,CAC7B,GAA8B,EAC9B,OAAkB,OAAO;IAEzB,IAAI,GAAG,IAAI,IAAI,IAAI,OAAO,GAAG,KAAK,QAAQ;QAAE,OAAO,SAAS,CAAA;IAC5D,MAAM,CAAC,GAAG,GAAG,CAAC,IAAI,EAAE,CAAA;IACpB,IAAI,CAAC,CAAC;QAAE,OAAO,SAAS,CAAA;IAExB,IAAI,CAAC,CAAC,UAAU,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,UAAU,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,UAAU,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;QAC1G,OAAO,CAAC,CAAA;IACV,CAAC;IAED,IAAI,CAAC,CAAC,CAAC,UAAU,CAAC,YAAY,CAAC,EAAE,CAAC;QAChC,OAAO,CAAC,CAAA;IACV,CAAC;IAED,MAAM,OAAO,GAAG,CAAC,CAAC,KAAK,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAA;IAChE,IAAI,CAAC,OAAO;QAAE,OAAO,SAAS,CAAA;IAE9B,0CAA0C;IAC1C,IAAI,8BAA8B,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;QACjD,OAAO,QAAQ,OAAO,EAAE,CAAA;IAC1B,CAAC;IAED,MAAM,WAAW,GACf,IAAI,KAAK,OAAO,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,IAAI,KAAK,OAAO,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,YAAY,CAAA;IAChF,MAAM,GAAG,GAAG,OAAO,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAA;IACtC,OAAO,QAAQ,WAAW,WAAW,GAAG,EAAE,CAAA;AAC5C,CAAC;AAED,oDAAoD;AACpD,MAAM,UAAU,eAAe,CAAC,IAAyC;IACvE,IAAI,CAAC,IAAI;QAAE,OAAO,SAAS,CAAA;IAC3B,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAA;IACxB,IAAI,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;QACzD,MAAM,KAAK,GAAI,KAA6B,CAAC,KAAK,CAAA;QAClD,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,IAAI,EAAE;YAAE,OAAO,KAAK,CAAC,IAAI,EAAE,CAAA;IACpE,CAAC;IACD,MAAM,CAAC,GAAG,IAAI,CAAC,GAAG,IAAI,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,GAAG,IAAI,IAAI,CAAC,IAAI,CAAA;IACxD,OAAO,OAAO,CAAC,KAAK,QAAQ,IAAI,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,SAAS,CAAA;AACjE,CAAC"}
@@ -0,0 +1,2 @@
1
+ export default function OrchestrationRunsPage(): import("react").JSX.Element;
2
+ //# sourceMappingURL=OrchestrationRunsPage.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"OrchestrationRunsPage.d.ts","sourceRoot":"","sources":["../../client/orchestration/OrchestrationRunsPage.tsx"],"names":[],"mappings":"AAwCA,MAAM,CAAC,OAAO,UAAU,qBAAqB,gCAgL5C"}
@@ -0,0 +1,65 @@
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
+ import { useCallback, useState } from 'react';
3
+ import { apiFetch } from '../console-utils/remoteApi.js';
4
+ function parsePayload(raw) {
5
+ if (!raw?.trim())
6
+ return '';
7
+ try {
8
+ const parsed = JSON.parse(raw);
9
+ return JSON.stringify(parsed, null, 2);
10
+ }
11
+ catch {
12
+ return raw;
13
+ }
14
+ }
15
+ export default function OrchestrationRunsPage() {
16
+ const [sessionKey, setSessionKey] = useState('');
17
+ const [runs, setRuns] = useState([]);
18
+ const [selected, setSelected] = useState(null);
19
+ const [loading, setLoading] = useState(false);
20
+ const [error, setError] = useState('');
21
+ const loadRuns = useCallback(async () => {
22
+ if (!sessionKey.trim()) {
23
+ setError('请输入 sessionKey');
24
+ return;
25
+ }
26
+ setLoading(true);
27
+ setError('');
28
+ setSelected(null);
29
+ try {
30
+ const res = await apiFetch(`/api/agent/orchestration/runs?sessionKey=${encodeURIComponent(sessionKey.trim())}`);
31
+ const body = await res.json();
32
+ if (!res.ok || !body.success) {
33
+ throw new Error(body.error ?? `HTTP ${res.status}`);
34
+ }
35
+ setRuns(body.data?.runs ?? []);
36
+ }
37
+ catch (err) {
38
+ setError(err instanceof Error ? err.message : String(err));
39
+ setRuns([]);
40
+ }
41
+ finally {
42
+ setLoading(false);
43
+ }
44
+ }, [sessionKey]);
45
+ const loadRunDetail = useCallback(async (runId) => {
46
+ setLoading(true);
47
+ setError('');
48
+ try {
49
+ const res = await apiFetch(`/api/agent/orchestration/runs/${encodeURIComponent(runId)}`);
50
+ const body = await res.json();
51
+ if (!res.ok || !body.success || !body.data) {
52
+ throw new Error(body.error ?? `HTTP ${res.status}`);
53
+ }
54
+ setSelected(body.data);
55
+ }
56
+ catch (err) {
57
+ setError(err instanceof Error ? err.message : String(err));
58
+ }
59
+ finally {
60
+ setLoading(false);
61
+ }
62
+ }, []);
63
+ return (_jsxs("div", { className: "p-4 space-y-4 max-w-5xl", children: [_jsx("h1", { className: "text-lg font-semibold", children: "\u7F16\u6392 Run / Task / Event" }), _jsxs("p", { className: "text-sm text-muted-foreground", children: ["\u4ECE OrchestrationKernel \u6295\u5F71\uFF08`GET /api/agent/orchestration/*`\uFF09\u3002sessionKey \u683C\u5F0F\uFF1A", _jsx("code", { className: "mx-1", children: "platform:endpointId:kind:sceneId" })] }), _jsxs("div", { className: "flex flex-wrap gap-2 items-end", children: [_jsxs("label", { className: "flex flex-col gap-1 text-sm flex-1 min-w-[240px]", children: ["sessionKey", _jsx("input", { className: "border rounded px-2 py-1 text-sm bg-background", value: sessionKey, onChange: (e) => setSessionKey(e.target.value), placeholder: "sandbox:solo-bot:private:user1" })] }), _jsx("button", { type: "button", className: "border rounded px-3 py-1 text-sm hover:bg-muted", disabled: loading, onClick: () => void loadRuns(), children: "\u67E5\u8BE2 Runs" })] }), error ? _jsx("p", { className: "text-sm text-red-600", children: error }) : null, _jsxs("div", { className: "grid gap-4 md:grid-cols-2", children: [_jsxs("section", { className: "border rounded p-3 space-y-2", children: [_jsxs("h2", { className: "text-sm font-medium", children: ["Runs (", runs.length, ")"] }), runs.length === 0 ? (_jsx("p", { className: "text-sm text-muted-foreground", children: "\u65E0\u6570\u636E" })) : (_jsx("ul", { className: "space-y-2 text-sm", children: runs.map((item) => (_jsx("li", { className: "border rounded p-2", children: _jsxs("button", { type: "button", className: "text-left w-full hover:underline", onClick: () => void loadRunDetail(item.run.id), children: [_jsx("div", { className: "font-mono text-xs", children: item.run.id }), _jsx("div", { children: item.run.title || '(无标题)' }), _jsxs("div", { className: "text-muted-foreground", children: [item.run.status, ' · ', item.tasks.length, ' tasks'] })] }) }, item.run.id))) }))] }), _jsxs("section", { className: "border rounded p-3 space-y-3", children: [_jsx("h2", { className: "text-sm font-medium", children: "Run \u8BE6\u60C5" }), !selected ? (_jsx("p", { className: "text-sm text-muted-foreground", children: "\u9009\u62E9\u5DE6\u4FA7 Run" })) : (_jsxs(_Fragment, { children: [_jsxs("div", { className: "text-sm space-y-1", children: [_jsxs("div", { children: [_jsx("span", { className: "text-muted-foreground", children: "ID " }), _jsx("code", { children: selected.run.id })] }), _jsxs("div", { children: [_jsx("span", { className: "text-muted-foreground", children: "\u72B6\u6001 " }), selected.run.status] })] }), _jsxs("div", { children: [_jsx("h3", { className: "text-xs font-medium uppercase text-muted-foreground mb-1", children: "Tasks" }), _jsx("ul", { className: "space-y-2 text-sm", children: selected.tasks.map((task) => (_jsxs("li", { className: "border rounded p-2 font-mono text-xs", children: [_jsxs("div", { children: [task.id, ' · ', task.status, ' · ', task.executor_kind ?? 'local'] }), _jsx("div", { children: task.name }), task.result_summary ? (_jsx("div", { className: "mt-1 whitespace-pre-wrap break-words", children: task.result_summary })) : null, task.error ? (_jsx("div", { className: "mt-1 text-red-600 whitespace-pre-wrap", children: task.error })) : null] }, task.id))) })] }), _jsxs("div", { children: [_jsx("h3", { className: "text-xs font-medium uppercase text-muted-foreground mb-1", children: "Events" }), _jsx("ul", { className: "space-y-2 text-xs max-h-64 overflow-auto", children: (selected.events ?? []).map((ev) => (_jsxs("li", { className: "border rounded p-2", children: [_jsxs("div", { children: ["#", ev.seq, ' ', ev.type, ev.task_id ? ` · task ${ev.task_id}` : ''] }), ev.payload_json ? (_jsx("pre", { className: "mt-1 whitespace-pre-wrap break-words text-[10px] opacity-80", children: parsePayload(ev.payload_json) })) : null] }, ev.seq))) })] })] }))] })] })] }));
64
+ }
65
+ //# sourceMappingURL=OrchestrationRunsPage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"OrchestrationRunsPage.js","sourceRoot":"","sources":["../../client/orchestration/OrchestrationRunsPage.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ import type { PluginRegisterHostApi } from '@zhin.js/contract';
2
+ /** Remote Console v1.1 — OrchestrationKernel Run/Task/Event 投影页 */
3
+ export declare function registerOrchestrationConsole(api: PluginRegisterHostApi): void;
4
+ //# sourceMappingURL=registerOrchestrationConsole.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registerOrchestrationConsole.d.ts","sourceRoot":"","sources":["../../client/orchestration/registerOrchestrationConsole.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,mBAAmB,CAAC;AAG/D,mEAAmE;AACnE,wBAAgB,4BAA4B,CAAC,GAAG,EAAE,qBAAqB,GAAG,IAAI,CAY7E"}
@@ -0,0 +1,16 @@
1
+ import OrchestrationRunsPage from './OrchestrationRunsPage.js';
2
+ /** Remote Console v1.1 — OrchestrationKernel Run/Task/Event 投影页 */
3
+ export function registerOrchestrationConsole(api) {
4
+ api.addRoute({
5
+ path: '/console/orchestration',
6
+ name: '编排',
7
+ element: api.React.createElement(OrchestrationRunsPage),
8
+ meta: { order: 40, group: 'Agent' },
9
+ });
10
+ api.addTool({
11
+ id: 'orchestration',
12
+ name: '编排',
13
+ path: '/console/orchestration',
14
+ });
15
+ }
16
+ //# sourceMappingURL=registerOrchestrationConsole.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registerOrchestrationConsole.js","sourceRoot":"","sources":["../../client/orchestration/registerOrchestrationConsole.ts"],"names":[],"mappings":"AACA,OAAO,qBAAqB,MAAM,4BAA4B,CAAC;AAE/D,mEAAmE;AACnE,MAAM,UAAU,4BAA4B,CAAC,GAA0B;IACrE,GAAG,CAAC,QAAQ,CAAC;QACX,IAAI,EAAE,wBAAwB;QAC9B,IAAI,EAAE,IAAI;QACV,OAAO,EAAE,GAAG,CAAC,KAAK,CAAC,aAAa,CAAC,qBAAqB,CAAC;QACvD,IAAI,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE;KACpC,CAAC,CAAC;IACH,GAAG,CAAC,OAAO,CAAC;QACV,EAAE,EAAE,eAAe;QACnB,IAAI,EAAE,IAAI;QACV,IAAI,EAAE,wBAAwB;KAC/B,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,9 @@
1
+ import type { MessageSegment } from './types.js';
2
+ /**
3
+ * Inbox / 用户 IM 视图:仅展示 IM-visible 段(剔除 thinking、tool_call)。
4
+ * Agent 面板应使用全量 segments,勿调用此函数。
5
+ */
6
+ export declare function segmentsForImDelivery(segments: readonly unknown[]): MessageSegment[];
7
+ /** Agent 面板全量 segments(identity,便于双视图 API 对称) */
8
+ export declare function segmentsForAgentPanel(segments: readonly MessageSegment[]): MessageSegment[];
9
+ //# sourceMappingURL=segments.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"segments.d.ts","sourceRoot":"","sources":["../client/segments.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAoBjD;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,SAAS,OAAO,EAAE,GAAG,cAAc,EAAE,CASpF;AAED,iDAAiD;AACjD,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,SAAS,cAAc,EAAE,GAAG,cAAc,EAAE,CAE3F"}
@@ -0,0 +1,35 @@
1
+ /** IM 可见段白名单(与 core segment-contract/delivery 对齐) */
2
+ const IM_VISIBLE_TYPES = new Set([
3
+ 'text', 'mention', 'image', 'video', 'audio', 'voice', 'record', 'file',
4
+ 'face', 'reply', 'forward', 'link', 'dice', 'rps', 'markdown', 'html',
5
+ 'qrcode', 'tts', 'keyboard', 'action',
6
+ ]);
7
+ const AI_ONLY_TYPES = new Set(['thinking', 'tool_call']);
8
+ function isSegmentLike(value) {
9
+ return (typeof value === 'object'
10
+ && value !== null
11
+ && typeof value.type === 'string'
12
+ && 'data' in value);
13
+ }
14
+ /**
15
+ * Inbox / 用户 IM 视图:仅展示 IM-visible 段(剔除 thinking、tool_call)。
16
+ * Agent 面板应使用全量 segments,勿调用此函数。
17
+ */
18
+ export function segmentsForImDelivery(segments) {
19
+ const out = [];
20
+ for (const item of segments) {
21
+ if (!isSegmentLike(item))
22
+ continue;
23
+ if (AI_ONLY_TYPES.has(item.type))
24
+ continue;
25
+ if (!IM_VISIBLE_TYPES.has(item.type))
26
+ continue;
27
+ out.push(item);
28
+ }
29
+ return out;
30
+ }
31
+ /** Agent 面板全量 segments(identity,便于双视图 API 对称) */
32
+ export function segmentsForAgentPanel(segments) {
33
+ return [...segments];
34
+ }
35
+ //# sourceMappingURL=segments.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"segments.js","sourceRoot":"","sources":["../client/segments.ts"],"names":[],"mappings":"AAEA,qDAAqD;AACrD,MAAM,gBAAgB,GAAG,IAAI,GAAG,CAAC;IAC/B,MAAM,EAAE,SAAS,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM;IACvE,MAAM,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,UAAU,EAAE,MAAM;IACrE,QAAQ,EAAE,KAAK,EAAE,UAAU,EAAE,QAAQ;CACtC,CAAC,CAAC;AAEH,MAAM,aAAa,GAAG,IAAI,GAAG,CAAC,CAAC,UAAU,EAAE,WAAW,CAAC,CAAC,CAAC;AAEzD,SAAS,aAAa,CAAC,KAAc;IACnC,OAAO,CACL,OAAO,KAAK,KAAK,QAAQ;WACtB,KAAK,KAAK,IAAI;WACd,OAAQ,KAAwB,CAAC,IAAI,KAAK,QAAQ;WAClD,MAAM,IAAI,KAAK,CACnB,CAAC;AACJ,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,qBAAqB,CAAC,QAA4B;IAChE,MAAM,GAAG,GAAqB,EAAE,CAAC;IACjC,KAAK,MAAM,IAAI,IAAI,QAAQ,EAAE,CAAC;QAC5B,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC;YAAE,SAAS;QACnC,IAAI,aAAa,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC;YAAE,SAAS;QAC3C,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC;YAAE,SAAS;QAC/C,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACjB,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED,iDAAiD;AACjD,MAAM,UAAU,qBAAqB,CAAC,QAAmC;IACvE,OAAO,CAAC,GAAG,QAAQ,CAAC,CAAC;AACvB,CAAC"}
package/dist/types.d.ts CHANGED
@@ -1,7 +1,8 @@
1
1
  export interface MessageSegment {
2
- /** record:如 ICQQ 语音等,展示时按音频处理 */
3
- type: 'text' | 'image' | 'at' | 'face' | 'video' | 'audio' | 'record' | 'file' | 'reply';
4
- data: Record<string, any>;
2
+ /** record:如 ICQQ 语音等,展示时按音频处理;thinking/tool_call 仅 agent 面板展示 */
3
+ type: 'text' | 'mention' | 'at' | 'image' | 'face' | 'video' | 'audio' | 'record' | 'file' | 'reply' | 'forward' | 'keyboard' | 'action' | 'thinking' | 'tool_call' | string;
4
+ data: Record<string, unknown>;
5
+ platform?: Record<string, unknown>;
5
6
  }
6
7
  export type MessageElement = MessageSegment;
7
8
  export type SendContent = MessageSegment | MessageSegment[] | string;
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../client/types.ts"],"names":[],"mappings":"AACA,MAAM,WAAW,cAAc;IAC7B,iCAAiC;IACjC,IAAI,EAAE,MAAM,GAAG,OAAO,GAAG,IAAI,GAAG,MAAM,GAAG,OAAO,GAAG,OAAO,GAAG,QAAQ,GAAG,MAAM,GAAG,OAAO,CAAA;IACxF,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAA;CAC1B;AAGD,MAAM,MAAM,cAAc,GAAG,cAAc,CAAA;AAG3C,MAAM,MAAM,WAAW,GAAG,cAAc,GAAG,cAAc,EAAE,GAAG,MAAM,CAAA"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../client/types.ts"],"names":[],"mappings":"AACA,MAAM,WAAW,cAAc;IAC7B,iEAAiE;IACjE,IAAI,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,GAAG,OAAO,GAAG,MAAM,GAAG,OAAO,GAAG,OAAO,GAAG,QAAQ,GAAG,MAAM,GAAG,OAAO,GAAG,SAAS,GAAG,UAAU,GAAG,QAAQ,GAAG,UAAU,GAAG,WAAW,GAAG,MAAM,CAAA;IAC5K,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IAC7B,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CACnC;AAGD,MAAM,MAAM,cAAc,GAAG,cAAc,CAAA;AAG3C,MAAM,MAAM,WAAW,GAAG,cAAc,GAAG,cAAc,EAAE,GAAG,MAAM,CAAA"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zhin.js/client",
3
- "version": "2.0.3",
3
+ "version": "2.0.4",
4
4
  "description": "Zhin Remote Console client SDK (entries loader, app registry, REST/SSE) — UI lives in zhin-console repo",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -14,7 +14,7 @@
14
14
  "dependencies": {
15
15
  "clsx": "^2.1.1",
16
16
  "tailwind-merge": "^3.6.0",
17
- "@zhin.js/contract": "1.0.1"
17
+ "@zhin.js/contract": "1.0.2"
18
18
  },
19
19
  "peerDependencies": {
20
20
  "react": ">=18"
@@ -24,9 +24,9 @@
24
24
  "client"
25
25
  ],
26
26
  "devDependencies": {
27
- "@types/react": "^19.2.15",
27
+ "@types/react": "^19.2.17",
28
28
  "@types/react-dom": "^19.2.3",
29
- "react": "^19.2.6",
29
+ "react": "^19.2.7",
30
30
  "rimraf": "^6.0.1",
31
31
  "typescript": "^6.0.2"
32
32
  },
@@ -39,6 +39,15 @@
39
39
  "access": "public",
40
40
  "registry": "https://registry.npmjs.org"
41
41
  },
42
+ "license": "MIT",
43
+ "author": {
44
+ "name": "lc-cn",
45
+ "email": "admin@liucl.cn",
46
+ "url": "https://github.com/lc-cn"
47
+ },
48
+ "engines": {
49
+ "node": "^20.19.0 || >=22.12.0"
50
+ },
42
51
  "scripts": {
43
52
  "build": "tsc",
44
53
  "clean": "rimraf dist"
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=loadConsoleEntries.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"loadConsoleEntries.test.d.ts","sourceRoot":"","sources":["../../client/bootstrap/loadConsoleEntries.test.ts"],"names":[],"mappings":""}
@@ -1,27 +0,0 @@
1
- import { describe, expect, it, vi } from "vitest";
2
- import { createPluginRegisterHostApi, getRegisterFn } from "./loadConsoleEntries.js";
3
- describe("console entries bootstrap", () => {
4
- it("resolves named register export", () => {
5
- const register = () => { };
6
- expect(getRegisterFn({ register })).toBe(register);
7
- });
8
- it("resolves default register export", () => {
9
- const register = () => { };
10
- expect(getRegisterFn({ default: { register } })).toBe(register);
11
- });
12
- it("returns null when no register export exists", () => {
13
- expect(getRegisterFn({ default: {} })).toBeNull();
14
- });
15
- it("creates a host API with addPage aliased to addRoute", () => {
16
- const React = {};
17
- const addRoute = vi.fn();
18
- const addTool = vi.fn(() => "tool-id");
19
- const api = createPluginRegisterHostApi({ React, addRoute, addTool });
20
- api.addPage({ path: "/x", name: "x", element: "page" });
21
- api.addRoute({ path: "/y", name: "y", element: "route" });
22
- expect(api.React).toBe(React);
23
- expect(addRoute).toHaveBeenCalledTimes(2);
24
- expect(api.addTool({ id: "t", name: "T" })).toBe("tool-id");
25
- });
26
- });
27
- //# sourceMappingURL=loadConsoleEntries.test.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"loadConsoleEntries.test.js","sourceRoot":"","sources":["../../client/bootstrap/loadConsoleEntries.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAClD,OAAO,EAAE,2BAA2B,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AAErF,QAAQ,CAAC,2BAA2B,EAAE,GAAG,EAAE;IACzC,EAAE,CAAC,gCAAgC,EAAE,GAAG,EAAE;QACxC,MAAM,QAAQ,GAAG,GAAG,EAAE,GAAE,CAAC,CAAC;QAC1B,MAAM,CAAC,aAAa,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IACrD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,kCAAkC,EAAE,GAAG,EAAE;QAC1C,MAAM,QAAQ,GAAG,GAAG,EAAE,GAAE,CAAC,CAAC;QAC1B,MAAM,CAAC,aAAa,CAAC,EAAE,OAAO,EAAE,EAAE,QAAQ,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IAClE,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,6CAA6C,EAAE,GAAG,EAAE;QACrD,MAAM,CAAC,aAAa,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC;IACpD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,qDAAqD,EAAE,GAAG,EAAE;QAC7D,MAAM,KAAK,GAAG,EAAS,CAAC;QACxB,MAAM,QAAQ,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC;QACzB,MAAM,OAAO,GAAG,EAAE,CAAC,EAAE,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;QACvC,MAAM,GAAG,GAAG,2BAA2B,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC,CAAC;QAEtE,GAAG,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,EAAE,OAAO,EAAE,MAAa,EAAE,CAAC,CAAC;QAC/D,GAAG,CAAC,QAAQ,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,EAAE,OAAO,EAAE,OAAc,EAAE,CAAC,CAAC;QACjE,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAC9B,MAAM,CAAC,QAAQ,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAC;QAC1C,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,EAAE,EAAE,GAAG,EAAE,IAAI,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IAC9D,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}