@modesto_ma/dsh-channels 0.2.0 → 0.4.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/README.md +115 -39
- package/docs/access-control-design.md +1 -1
- package/docs/attachment-pipeline-v2.md +318 -0
- package/docs/feasibility-and-design.md +54 -26
- package/docs/feishu-onboarding.md +123 -15
- package/docs/persistence.md +4 -4
- package/docs/refactor-plan.md +7 -6
- package/docs/workspace-isolation-design.md +81 -0
- package/lib/client.js +30 -15
- package/lib/client.js.map +1 -1
- package/lib/index.js +11008 -5132
- package/lib/index.js.map +1 -1
- package/package.json +1 -1
- package/src/cards/index.ts +1 -0
- package/src/cards/onboarding.ts +23 -0
- package/src/cards/primitives.ts +20 -0
- package/src/cards/streaming.ts +310 -291
- package/src/cleanup.ts +267 -119
- package/src/client/panel/cleanup-card.tsx +4 -2
- package/src/client/panel/workspace-tab.tsx +1 -1
- package/src/config.ts +221 -13
- package/src/domain.ts +141 -3
- package/src/feishu/agent-context.ts +66 -16
- package/src/feishu/inbound-attachments.ts +440 -3
- package/src/feishu/manifest.ts +270 -0
- package/src/feishu/message-read.ts +1333 -0
- package/src/feishu/native-attachments.ts +998 -0
- package/src/feishu/pending-attachments.ts +562 -0
- package/src/feishu/tools.ts +2345 -0
- package/src/feishu-channel.ts +55 -0
- package/src/host/agent.ts +55 -0
- package/src/host/attachments.ts +210 -0
- package/src/host/index.ts +1 -0
- package/src/index.ts +8 -6
- package/src/routing/inbound.ts +730 -81
- package/src/service.ts +536 -50
- package/src/session/isolation.ts +277 -0
- package/src/session/manager.ts +120 -23
- package/src/session/repair.ts +2 -3
- package/src/session/routes.ts +2 -0
- package/src/session-commands.ts +41 -14
- package/src/settings/contract.ts +43 -21
- package/src/settings/overlay.ts +124 -13
- package/src/settings/surface.ts +147 -14
- package/src/streamer.ts +70 -30
- package/src/workspaces.ts +74 -31
package/src/feishu-channel.ts
CHANGED
|
@@ -88,6 +88,26 @@ export interface FeishuChannel {
|
|
|
88
88
|
fileKey: string,
|
|
89
89
|
type: 'image' | 'file',
|
|
90
90
|
): Promise<ResourceChunkStream>
|
|
91
|
+
/** P0 probe surface: raw `im.v1.message.get` (quoted / merged-forward container). */
|
|
92
|
+
messageGet?(messageId: string): Promise<unknown>
|
|
93
|
+
/**
|
|
94
|
+
* Batch read surface: raw `im.v1.message.mget` (≤50 message ids). The SDK
|
|
95
|
+
* 1.76 client does not expose this endpoint as a typed method, so the
|
|
96
|
+
* adapter calls it through `Client.request`; every caller must tolerate the
|
|
97
|
+
* method being absent (older channels / stubs) and fall back to `message.get`.
|
|
98
|
+
*/
|
|
99
|
+
messageMget?(messageIds: readonly string[]): Promise<unknown>
|
|
100
|
+
/** P0 probe surface: raw `im.v1.message.list` (thread / chat history). */
|
|
101
|
+
messageList?(params: RawMessageListParams): Promise<unknown>
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/** Query for the raw `im.v1.message.list` endpoint. */
|
|
105
|
+
export interface RawMessageListParams {
|
|
106
|
+
container_id_type: 'chat' | 'thread'
|
|
107
|
+
container_id: string
|
|
108
|
+
page_size?: number
|
|
109
|
+
page_token?: string
|
|
110
|
+
sort_type?: 'ByCreateTimeAsc' | 'ByCreateTimeDesc'
|
|
91
111
|
}
|
|
92
112
|
|
|
93
113
|
/** Ordered byte chunks of one inbound resource. */
|
|
@@ -256,6 +276,41 @@ class LarkChannelAdapter implements FeishuChannel {
|
|
|
256
276
|
return res?.data?.items?.[0]?.thread_id
|
|
257
277
|
}
|
|
258
278
|
|
|
279
|
+
async messageGet(messageId: string): Promise<unknown> {
|
|
280
|
+
const message = this.channel.rawClient.im.v1.message as unknown as {
|
|
281
|
+
get(input: { path: { message_id: string } }): Promise<unknown>
|
|
282
|
+
}
|
|
283
|
+
return await message.get({ path: { message_id: messageId } })
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
async messageMget(messageIds: readonly string[]): Promise<unknown> {
|
|
287
|
+
// SDK 1.76 has no typed `im.v1.message.mget`; the endpoint is
|
|
288
|
+
// `GET /open-apis/im/v1/messages/mget` with *repeated* `message_ids`
|
|
289
|
+
// query params (comma-separated ids are rejected by Feishu with 99992354).
|
|
290
|
+
// Axios would serialize an array with brackets, so the query string is
|
|
291
|
+
// built explicitly inside the URL.
|
|
292
|
+
if (messageIds.length === 0 || messageIds.length > 50) {
|
|
293
|
+
throw new Error(`message.mget accepts 1-50 message ids (got ${messageIds.length})`)
|
|
294
|
+
}
|
|
295
|
+
const query = messageIds
|
|
296
|
+
.map(messageId => `message_ids=${encodeURIComponent(messageId)}`)
|
|
297
|
+
.join('&')
|
|
298
|
+
const client = this.channel.rawClient as unknown as {
|
|
299
|
+
request(input: { method: string; url: string }): Promise<unknown>
|
|
300
|
+
}
|
|
301
|
+
return await client.request({
|
|
302
|
+
method: 'GET',
|
|
303
|
+
url: `/open-apis/im/v1/messages/mget?${query}&card_msg_content_type=raw_card_content`,
|
|
304
|
+
})
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
async messageList(params: RawMessageListParams): Promise<unknown> {
|
|
308
|
+
const message = this.channel.rawClient.im.v1.message as unknown as {
|
|
309
|
+
list(input: { params: RawMessageListParams }): Promise<unknown>
|
|
310
|
+
}
|
|
311
|
+
return await message.list({ params })
|
|
312
|
+
}
|
|
313
|
+
|
|
259
314
|
async downloadResource(
|
|
260
315
|
messageId: string,
|
|
261
316
|
fileKey: string,
|
package/src/host/agent.ts
CHANGED
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
* @module dsh-channels/host/agent
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
+
import type { AttachmentStore } from './attachments.ts'
|
|
8
9
|
import type { CommandRuntime } from './commands.ts'
|
|
9
10
|
import type { Session, SessionId, UserMessage } from './core.ts'
|
|
10
11
|
|
|
@@ -58,10 +59,64 @@ export interface SystemPromptRuntime {
|
|
|
58
59
|
section(section: PromptSection): () => void
|
|
59
60
|
}
|
|
60
61
|
|
|
62
|
+
/** One model-facing content block a channel tool may project (text/image/file). */
|
|
63
|
+
export interface ToolContentBlock {
|
|
64
|
+
readonly type: string
|
|
65
|
+
readonly [key: string]: unknown
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/** One tool execution's cooperative cancellation signal. */
|
|
69
|
+
export interface ToolExecution {
|
|
70
|
+
readonly signal: AbortSignal
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/** Canonical output contract of one channel tool registration. */
|
|
74
|
+
export interface ToolOutputContract {
|
|
75
|
+
readonly schema: Record<string, unknown>
|
|
76
|
+
render(args: Record<string, unknown>, value: unknown): readonly ToolContentBlock[]
|
|
77
|
+
presentationMeta?(args: Record<string, unknown>, value: unknown): unknown
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* One model-facing tool registration. Kept structural (no runtime import of
|
|
82
|
+
* the host's `@deepseek-ai/dsh-tools` package) so the plugin keeps its
|
|
83
|
+
* zero-host-dependency stance.
|
|
84
|
+
*/
|
|
85
|
+
export interface ToolDefinition {
|
|
86
|
+
readonly name: string
|
|
87
|
+
readonly description: string
|
|
88
|
+
readonly parameters: Record<string, unknown>
|
|
89
|
+
readonly output: ToolOutputContract
|
|
90
|
+
readonly timeoutMs?: number
|
|
91
|
+
execute(
|
|
92
|
+
args: Record<string, unknown>,
|
|
93
|
+
exec: ToolExecution,
|
|
94
|
+
): Promise<unknown> | unknown
|
|
95
|
+
presentCall?(args: Record<string, unknown>): unknown
|
|
96
|
+
presentResult?(args: Record<string, unknown>, value: unknown): unknown
|
|
97
|
+
readonly isConcurrencySafe?: () => boolean
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/** The Agent-scoped slice of the host `tools` registry. */
|
|
101
|
+
export interface ToolRuntime {
|
|
102
|
+
register(definition: ToolDefinition): unknown
|
|
103
|
+
}
|
|
104
|
+
|
|
61
105
|
export interface AgentContext {
|
|
62
106
|
commands: CommandRuntime
|
|
63
107
|
/** Present inside a setup scope that injected `systemPrompt`. */
|
|
64
108
|
systemPrompt?: SystemPromptRuntime
|
|
109
|
+
/** Present inside a setup scope that injected `tools`. */
|
|
110
|
+
tools?: ToolRuntime
|
|
111
|
+
/**
|
|
112
|
+
* Present inside a setup scope that injected `attachments` (the DSH native
|
|
113
|
+
* attachment store). Optional: headless or legacy hosts, and test doubles,
|
|
114
|
+
* may not mount it, so consumers resolve it through the degradation-aware
|
|
115
|
+
* helper in `src/feishu/native-attachments.ts` instead of assuming presence.
|
|
116
|
+
*/
|
|
117
|
+
attachments?: AttachmentStore
|
|
118
|
+
/** Safe service lookup (returns undefined for absent services). */
|
|
119
|
+
get?(name: string): unknown
|
|
65
120
|
/** Register an Agent-scoped model-call override. */
|
|
66
121
|
on(
|
|
67
122
|
event: 'agent/request',
|
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Host bridge, attachment surface: the minimal `ctx.attachments` face this
|
|
3
|
+
* plugin consumes (durable image/file storage) plus the content-block and
|
|
4
|
+
* prompt-part shapes it produces.
|
|
5
|
+
*
|
|
6
|
+
* Everything here is declared locally and structurally. The DSH attachment
|
|
7
|
+
* packages are never imported at runtime and are not runtime dependencies of
|
|
8
|
+
* this plugin, so these types mirror their published shapes by convention:
|
|
9
|
+
* only the members this plugin actually reads or calls are modeled, and every
|
|
10
|
+
* service lookup tolerates a deployment without the service. The exact
|
|
11
|
+
* upstream package (`@deepseek-ai/dsh-attachment`, DSH 0.2.1-rc.2) has more
|
|
12
|
+
* operations (batches, request projection, encoded uploads); add them here
|
|
13
|
+
* only when a task needs them.
|
|
14
|
+
*
|
|
15
|
+
* @module dsh-channels/host/attachments
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
// ---- Durable attachment vocabulary --------------------------------------
|
|
19
|
+
|
|
20
|
+
/** Opaque content-addressed attachment identifier (never a filesystem path). */
|
|
21
|
+
export type AttachmentId = string
|
|
22
|
+
|
|
23
|
+
/** Raster image formats accepted by the version-one attachment path. */
|
|
24
|
+
export type ImageMediaType = 'image/png' | 'image/jpeg' | 'image/webp' | 'image/gif'
|
|
25
|
+
|
|
26
|
+
/** Durable, serializable reference to one immutable normalized image. */
|
|
27
|
+
export interface ImageAttachmentRef {
|
|
28
|
+
/** Opaque storage identifier; never a filesystem path or bearer URL. */
|
|
29
|
+
attachmentId: AttachmentId
|
|
30
|
+
/** Media type verified from the stored bytes. */
|
|
31
|
+
mediaType: ImageMediaType
|
|
32
|
+
/** Exact encoded byte length. */
|
|
33
|
+
bytes: number
|
|
34
|
+
/** Intrinsic encoded width in pixels. */
|
|
35
|
+
width: number
|
|
36
|
+
/** Intrinsic encoded height in pixels. */
|
|
37
|
+
height: number
|
|
38
|
+
/** Optional display name stripped of local path information. */
|
|
39
|
+
name?: string
|
|
40
|
+
/**
|
|
41
|
+
* Input dimensions after applying EXIF orientation and before normalization
|
|
42
|
+
* scaling. Present only when normalization reduced the image.
|
|
43
|
+
*/
|
|
44
|
+
originalDimensions?: {
|
|
45
|
+
width: number
|
|
46
|
+
height: number
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Durable, serializable reference to one verbatim stored file. Files are
|
|
52
|
+
* stored byte-for-byte with no normalization; `attachmentId` is the sha256
|
|
53
|
+
* digest of exactly those bytes.
|
|
54
|
+
*/
|
|
55
|
+
export interface FileAttachmentRef {
|
|
56
|
+
/** Opaque content-addressed storage identifier; never a filesystem path. */
|
|
57
|
+
attachmentId: AttachmentId
|
|
58
|
+
/** Sanitized display filename, also the stored object's leaf name. */
|
|
59
|
+
name: string
|
|
60
|
+
/** Exact byte length. */
|
|
61
|
+
bytes: number
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/** Deployment-resolved image limits used by upload admission. */
|
|
65
|
+
export interface ImageAttachmentLimits {
|
|
66
|
+
maxImageBytes: number
|
|
67
|
+
maxImagesPerMessage: number
|
|
68
|
+
maxMessageImageBytes: number
|
|
69
|
+
maxImagePixels: number
|
|
70
|
+
/** Maximum intrinsic width and maximum intrinsic height in pixels for one image. */
|
|
71
|
+
maxImageDimension: number
|
|
72
|
+
mediaTypes: readonly ImageMediaType[]
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/** Request to validate and durably commit one image. */
|
|
76
|
+
export interface SaveImageAttachment {
|
|
77
|
+
/** Encoded bytes, checked against the declared media type by the service. */
|
|
78
|
+
data: Uint8Array
|
|
79
|
+
/** Caller-declared media type, checked against fully decoded bytes. */
|
|
80
|
+
mediaType: ImageMediaType
|
|
81
|
+
/** Optional display name; never interpreted as a path. */
|
|
82
|
+
name?: string
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/** Request to durably commit one file from bounded byte chunks. */
|
|
86
|
+
export interface SaveFileStreamAttachment {
|
|
87
|
+
/** Exact file bytes in order; providers must not retain the whole sequence. */
|
|
88
|
+
data: AsyncIterable<Uint8Array>
|
|
89
|
+
/** Optional cancellation for source reads and storage writes. */
|
|
90
|
+
signal?: AbortSignal
|
|
91
|
+
/** Optional display name; never interpreted as a path. */
|
|
92
|
+
name?: string
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/** One text/image part of host prompt content whose images still need admission. */
|
|
96
|
+
export type PromptContentPart = {
|
|
97
|
+
readonly type: 'text'
|
|
98
|
+
readonly text: string
|
|
99
|
+
} | {
|
|
100
|
+
readonly type: 'image'
|
|
101
|
+
readonly mediaType: ImageMediaType
|
|
102
|
+
readonly data: string
|
|
103
|
+
readonly name?: string
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/** Host prompt content whose file receipts are resolved and whose image bytes await admission. */
|
|
107
|
+
export type AttachmentAdmissionPart = PromptContentPart | {
|
|
108
|
+
readonly type: 'file'
|
|
109
|
+
readonly attachment: FileAttachmentRef
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/** Host-admitted prompt content with every attachment represented by its durable reference. */
|
|
113
|
+
export type AdmittedPromptContentPart = {
|
|
114
|
+
readonly type: 'text'
|
|
115
|
+
readonly text: string
|
|
116
|
+
} | {
|
|
117
|
+
readonly type: 'image'
|
|
118
|
+
readonly attachment: ImageAttachmentRef
|
|
119
|
+
} | {
|
|
120
|
+
readonly type: 'file'
|
|
121
|
+
readonly attachment: FileAttachmentRef
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
// ---- Content blocks -----------------------------------------------------
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* A durable raster image reference as it appears in model content
|
|
128
|
+
* (`ImageBlock` in `@deepseek-ai/dsh-llm`). The block is role-neutral; this
|
|
129
|
+
* plugin only produces it for user content.
|
|
130
|
+
*/
|
|
131
|
+
export interface ImageBlock {
|
|
132
|
+
type: 'image'
|
|
133
|
+
/** Immutable bytes and intrinsic display metadata owned by the service. */
|
|
134
|
+
attachment: ImageAttachmentRef
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* A durable verbatim file reference as it appears in model content
|
|
139
|
+
* (`FileBlock` in `@deepseek-ai/dsh-llm`). Files never reach a provider as
|
|
140
|
+
* bytes: request assembly projects them to handle text, so a channel tool that
|
|
141
|
+
* cannot deliver this block must fall back to {@link formatFileHandle}-style
|
|
142
|
+
* text instead.
|
|
143
|
+
*/
|
|
144
|
+
export interface FileBlock {
|
|
145
|
+
type: 'file'
|
|
146
|
+
/** Immutable verbatim bytes and display metadata owned by the service. */
|
|
147
|
+
attachment: FileAttachmentRef
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
// ---- Failure vocabulary -------------------------------------------------
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* Stable attachment failure codes the host routes on
|
|
154
|
+
* (`AttachmentErrorCode` in `@deepseek-ai/dsh-attachment`). Kept as a
|
|
155
|
+
* type-only union; the runtime classifier lives in the Feishu storage module.
|
|
156
|
+
*/
|
|
157
|
+
export type AttachmentErrorCode =
|
|
158
|
+
| 'TOO_MANY_IMAGES'
|
|
159
|
+
| 'IMAGES_TOO_LARGE'
|
|
160
|
+
| 'UNSUPPORTED_IMAGE_TYPE'
|
|
161
|
+
| 'INVALID_IMAGE_BASE64'
|
|
162
|
+
| 'INVALID_IMAGE'
|
|
163
|
+
| 'IMAGE_TYPE_MISMATCH'
|
|
164
|
+
| 'IMAGE_TOO_LARGE'
|
|
165
|
+
| 'IMAGE_TOO_MANY_PIXELS'
|
|
166
|
+
| 'IMAGE_DIMENSION_TOO_LARGE'
|
|
167
|
+
| 'INVALID_FILE_BASE64'
|
|
168
|
+
| 'INVALID_ATTACHMENT_REF'
|
|
169
|
+
| 'ATTACHMENT_CORRUPT'
|
|
170
|
+
| 'ATTACHMENT_WRITE_FAILED'
|
|
171
|
+
| 'ATTACHMENT_NOT_FOUND'
|
|
172
|
+
| 'ATTACHMENT_READ_FAILED'
|
|
173
|
+
| 'ATTACHMENT_PROJECTION_UNSUPPORTED'
|
|
174
|
+
| 'ATTACHMENT_FILES_UNSUPPORTED'
|
|
175
|
+
|
|
176
|
+
// ---- Service surface ----------------------------------------------------
|
|
177
|
+
|
|
178
|
+
/**
|
|
179
|
+
* The narrow `ctx.attachments` service face. Every method mirrors the
|
|
180
|
+
* upstream contract; callers must go through a module that tolerates absence
|
|
181
|
+
* (for example `src/feishu/native-attachments.ts`) rather than branching on
|
|
182
|
+
* this type themselves, so the degradation path exists in exactly one place.
|
|
183
|
+
*/
|
|
184
|
+
export interface AttachmentStore {
|
|
185
|
+
/** Deployment-resolved image policy; absent on minimal embedding hosts. */
|
|
186
|
+
readonly imageLimits?: ImageAttachmentLimits
|
|
187
|
+
/** Validate, normalize, and durably commit one image. */
|
|
188
|
+
saveImage(input: SaveImageAttachment): Promise<ImageAttachmentRef>
|
|
189
|
+
/** Durably commit one verbatim file from bounded chunks (backpressure, no full buffering). */
|
|
190
|
+
saveFileStream(input: SaveFileStreamAttachment): Promise<FileAttachmentRef>
|
|
191
|
+
/**
|
|
192
|
+
* Locate the verbatim stored file object in the harness host filesystem.
|
|
193
|
+
* @returns an absolute host path, or undefined when this backend is not
|
|
194
|
+
* host-file-backed.
|
|
195
|
+
* @throws an attachment error when the durable reference is invalid.
|
|
196
|
+
*/
|
|
197
|
+
fileHostPath(ref: FileAttachmentRef): string | undefined
|
|
198
|
+
/**
|
|
199
|
+
* Locate the provider-owned normalized image object in the harness host
|
|
200
|
+
* filesystem.
|
|
201
|
+
* @returns an absolute host path, or undefined when this backend is not
|
|
202
|
+
* host-file-backed.
|
|
203
|
+
* @throws an attachment error when the durable reference is invalid.
|
|
204
|
+
*/
|
|
205
|
+
imageHostPath(ref: ImageAttachmentRef): string | undefined
|
|
206
|
+
/** Replace every uploaded image in one host prompt with its durable reference. */
|
|
207
|
+
admitPromptContent(content: readonly AttachmentAdmissionPart[]): Promise<AdmittedPromptContentPart[]>
|
|
208
|
+
/** Optional host-provided classifier for attachment failures (cross-install safe). */
|
|
209
|
+
isAttachmentError?(error: unknown): boolean
|
|
210
|
+
}
|
package/src/host/index.ts
CHANGED
package/src/index.ts
CHANGED
|
@@ -3,12 +3,14 @@
|
|
|
3
3
|
*
|
|
4
4
|
* 一个 dsh 实例对应一个飞书机器人;用户通过私聊、群聊 @、话题群 @ 三种方式
|
|
5
5
|
* 发起会话。每条触发消息:立即加 “Typing” 表情 → 以话题形式回复(创建话题)
|
|
6
|
-
* → 绑定 DSH session → 卡片 2.0 流式回复(推理折叠面板 +
|
|
7
|
-
*
|
|
6
|
+
* → 绑定 DSH session → 卡片 2.0 流式回复(推理折叠面板 + 临时活动行 +
|
|
7
|
+
* 富文本正文 + 结算页脚,默认 500ms 刷新)→ 流式结束移除 Typing,成功更新为
|
|
8
8
|
* “DONE”,失败显示结构化错误并更新为 “No”。
|
|
9
9
|
*
|
|
10
10
|
* 工作区归属:私聊一人一工作区;群聊中每个用户在该群拥有独立工作区
|
|
11
|
-
*
|
|
11
|
+
* (工作区是会话 header cwd,保证 GUI 归属与沙箱边界)。每个话题在该工作区
|
|
12
|
+
* 内拥有独立的工作目录(`topics/<话题>`,Git 仓库工作区可自动改用 worktree),
|
|
13
|
+
* 因此话题之间的文件互不干扰,而工作区数量只随用户增长。
|
|
12
14
|
*
|
|
13
15
|
* @module dsh-channels
|
|
14
16
|
*/
|
|
@@ -51,7 +53,7 @@ export type { HostDirectoryPickerService, SettingsDirectoryPicker } from './sett
|
|
|
51
53
|
export { isSameOriginRequest, mountSettingsRoutes, registerSettingsRoutes } from './settings/routes.ts'
|
|
52
54
|
export type { HostWebServer } from './settings/routes.ts'
|
|
53
55
|
export type { ApprovalOutcome, ApprovalRequest, ApprovalAnswererListener, AssistantStreamFrame, AskUserQuestionAnswer, AskUserQuestionAnswerItem, AskUserQuestionItem, AskUserQuestionRequestEvent, UserQuestionAnswererListener, AgentCancelCause, SessionStatsView, TokenUsageView, ContextPressureView, SessionProjections } from './dsh-types.ts'
|
|
54
|
-
export { buildCard, buildInterruptionCard, cardJsonBytes, CARD_MAX_BYTES, CARD_TARGET_BYTES,
|
|
56
|
+
export { buildCard, buildInterruptionCard, cardJsonBytes, CARD_MAX_BYTES, CARD_TARGET_BYTES, REASONING_MAX_BYTES, INTERRUPTION_NOTICE, MAX_TABLES_PER_CARD, PANEL_TITLES, PANEL_CHEVRON_TOKEN, segmentCardContent, splitBodyForCard, stripTables, tableBlocks, TRUNCATION_SUFFIX, buildApprovalCard, buildApprovalSettledCard, buildQuestionCard, buildQuestionSettledCard, MAX_QUESTION_OPTIONS } from './cards.ts'
|
|
55
57
|
export { ApprovalAnswerer } from './approvals.ts'
|
|
56
58
|
export { QuestionAnswerer } from './questions.ts'
|
|
57
59
|
export { armModelCommand, buildCommandResultCard, CHANNEL_COMMAND_NAMES, commandResultCardKind, isSupportedCommand, parseSlashCommand, registerChannelCommands, registerModelCommand, RouteOperationQueue, SUPPORTED_COMMAND_NAMES, supportedCommandHelp, supportedCommandList } from './commands.ts'
|
|
@@ -61,8 +63,8 @@ export { createLogicalSessionExport, DSH_CHANNELS_VERSION, LOGICAL_EXPORT_FORMAT
|
|
|
61
63
|
export { addUsage, applyProjectionViews, averageDecodeTokensPerSecond, averageTtftMs, cacheHitPct, EMPTY_TOTALS, foldAll, foldEvent, foldSessionStats, measureSessionContext, readProjectionViews, usageFromBuckets } from './stats.ts'
|
|
62
64
|
export { FeishuService } from './service.ts'
|
|
63
65
|
export { TurnStreamer } from './streamer.ts'
|
|
64
|
-
export { ensureWorkspace, stagingPathFor, topicTokenFor, workspacePathFor, workspaceTitleFor } from './workspaces.ts'
|
|
65
|
-
export { accessGroupRecordSchema, accessRequestRecordSchema, accessUserRecordSchema, appendSessionHistory, chatRouteKey, expiredRouteRecordSchema, feishuDomain, normalizeRouteRecord, normalizeSessionHistory, routeRecordSchema, sessionHistoryEntrySchema, inflightSnapshotSchema, processedRecordSchema } from './domain.ts'
|
|
66
|
+
export { ensureWorkspace, legacyTopicWorkspaceRoot, stagingPathFor, stagingRoot, topicDirFor, topicTokenFor, workspacePathFor, workspaceTitleFor, worktreeBranchFor } from './workspaces.ts'
|
|
67
|
+
export { accessGroupRecordSchema, accessRequestRecordSchema, accessUserRecordSchema, appendSessionHistory, chatRouteKey, expiredRouteRecordSchema, feishuDomain, normalizeRouteRecord, normalizeSessionHistory, routeRecordSchema, sessionDirOf, sessionHistoryEntrySchema, inflightSnapshotSchema, processedRecordSchema } from './domain.ts'
|
|
66
68
|
|
|
67
69
|
/** Cordis function-plugin name. */
|
|
68
70
|
export const name = 'channels'
|