@deepseek-ai/dsh-client-file-upload 0.1.6-alpha.1 → 0.1.7-alpha.1

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/lib/client.js CHANGED
@@ -55,10 +55,11 @@ window.__ModuleLoader__.load({
55
55
  this.name = "RemoteError";
56
56
  }
57
57
  };
58
- //#endregion
59
- //#region lib/types/protocol.js
60
- /** Authenticated raw-byte route owned by the file-upload service. */
61
- const FILE_UPLOAD_PATH = "/api/session/uploadFileBinary";
58
+ /**
59
+ * Browser-relative form of {@link FILE_UPLOAD_PATH}; see
60
+ * .agents/notes/implemented/architecture/2026-09-14-web-document-relative-app-routes.md.
61
+ */
62
+ const FILE_UPLOAD_ROUTE = "/api/session/uploadFileBinary".slice(1);
62
63
  //#endregion
63
64
  //#region lib/types/client/runtime.js
64
65
  /** Background browser upload implementation for Blob and byte-stream bodies. */
@@ -180,7 +181,7 @@ window.__ModuleLoader__.load({
180
181
  const query = new URLSearchParams({ sessionId });
181
182
  if (name !== void 0) query.set("name", name);
182
183
  const response = await this.post({
183
- path: `${FILE_UPLOAD_PATH}?${query.toString()}`,
184
+ path: `${FILE_UPLOAD_ROUTE}?${query.toString()}`,
184
185
  body: data,
185
186
  headers: { "content-type": "application/octet-stream" },
186
187
  ...signal === void 0 ? {} : { signal },
@@ -204,7 +205,7 @@ window.__ModuleLoader__.load({
204
205
  ...request.body instanceof ReadableStream ? { duplex: "half" } : {},
205
206
  ...request.signal === void 0 ? {} : { signal: request.signal }
206
207
  };
207
- const response = await customFetch(resolveUrl(request.path), init);
208
+ const response = await customFetch(request.path, init);
208
209
  return {
209
210
  status: response.status,
210
211
  body: await response.text()
@@ -259,7 +260,7 @@ window.__ModuleLoader__.load({
259
260
  }
260
261
  request.signal?.addEventListener("abort", abort, { once: true });
261
262
  const message = {
262
- url: resolveUrl(request.path).href,
263
+ url: new URL(request.path, document.baseURI).href,
263
264
  body: request.body,
264
265
  headers: request.headers ?? {}
265
266
  };
@@ -268,11 +269,6 @@ window.__ModuleLoader__.load({
268
269
  });
269
270
  } };
270
271
  }
271
- function resolveUrl(path) {
272
- const pageLocation = Reflect.get(globalThis, "location");
273
- const origin = typeof pageLocation === "object" && pageLocation !== null && "origin" in pageLocation && typeof pageLocation.origin === "string" ? pageLocation.origin : void 0;
274
- return new URL(path, origin === void 0 || origin === "null" ? "http://dsh.internal" : origin);
275
- }
276
272
  function parseFileUploadResult(body) {
277
273
  const value = JSON.parse(body);
278
274
  if (!isRecord(value) || typeof value.ok !== "boolean") throw new TypeError("file upload transport returned an invalid result");
package/lib/index.js CHANGED
@@ -71,6 +71,7 @@ async function* requestBodyChunks(body) {
71
71
  //#region lib/types/protocol.js
72
72
  /** Authenticated raw-byte route owned by the file-upload service. */
73
73
  const FILE_UPLOAD_PATH = "/api/session/uploadFileBinary";
74
+ FILE_UPLOAD_PATH.slice(1);
74
75
  //#endregion
75
76
  //#region lib/types/index.js
76
77
  /** Host file-upload service: streamed intake and Agent-scoped staged receipts. */
@@ -1,19 +1,22 @@
1
1
  /* Generated by @deepseek-ai/dsh-typert-generator from FaceModel — do not edit. */
2
2
  import { z } from 'zod'
3
3
 
4
- const _deepseek_ai_dsh_client_file_upload_fileUploads_upload_parameter_0$schema = z.intersection(z.string(), z.unknown())
5
- const _deepseek_ai_dsh_client_file_upload_fileUploads_upload_parameter_1$schema = z.object({
4
+ let _deepseek_ai_dsh_client_file_upload_fileUploads_upload_parameter_0$schema$value
5
+ const _deepseek_ai_dsh_client_file_upload_fileUploads_upload_parameter_0$schema = () => (_deepseek_ai_dsh_client_file_upload_fileUploads_upload_parameter_0$schema$value ??= z.intersection(z.string(), z.unknown()))
6
+ let _deepseek_ai_dsh_client_file_upload_fileUploads_upload_parameter_1$schema$value
7
+ const _deepseek_ai_dsh_client_file_upload_fileUploads_upload_parameter_1$schema = () => (_deepseek_ai_dsh_client_file_upload_fileUploads_upload_parameter_1$schema$value ??= z.object({
6
8
  'data': z.string().readonly(),
7
9
  'name': z.string().readonly().optional(),
8
- })
9
- const _deepseek_ai_dsh_client_file_upload_fileUploads_upload_result$schema = z.object({
10
+ }))
11
+ let _deepseek_ai_dsh_client_file_upload_fileUploads_upload_result$schema$value
12
+ const _deepseek_ai_dsh_client_file_upload_fileUploads_upload_result$schema = () => (_deepseek_ai_dsh_client_file_upload_fileUploads_upload_result$schema$value ??= z.object({
10
13
  'receiptId': z.intersection(z.string(), z.unknown()).readonly(),
11
14
  'file': z.object({
12
15
  'attachmentId': z.intersection(z.string(), z.unknown()),
13
16
  'name': z.string(),
14
17
  'bytes': z.number(),
15
18
  }).readonly(),
16
- })
19
+ }))
17
20
 
18
21
  export const TYPERT = {
19
22
  package: '@deepseek-ai/dsh-client-file-upload',
@@ -40,7 +43,7 @@ export const TYPERT = {
40
43
  codec: {
41
44
  mode: 'strict',
42
45
  typeSymbol: '@deepseek-ai/dsh-session/types#SessionId',
43
- schema: _deepseek_ai_dsh_client_file_upload_fileUploads_upload_parameter_0$schema,
46
+ create: _deepseek_ai_dsh_client_file_upload_fileUploads_upload_parameter_0$schema,
44
47
  },
45
48
  },
46
49
  {
@@ -50,7 +53,7 @@ export const TYPERT = {
50
53
  codec: {
51
54
  mode: 'strict',
52
55
  typeSymbol: '@deepseek-ai/dsh-client-file-upload/types#EncodedFileUploadRequest',
53
- schema: _deepseek_ai_dsh_client_file_upload_fileUploads_upload_parameter_1$schema,
56
+ create: _deepseek_ai_dsh_client_file_upload_fileUploads_upload_parameter_1$schema,
54
57
  },
55
58
  },
56
59
  ],
@@ -58,7 +61,7 @@ export const TYPERT = {
58
61
  result: {
59
62
  mode: 'strict',
60
63
  typeSymbol: '@deepseek-ai/dsh-client-file-upload/types#FileUploadValue',
61
- schema: _deepseek_ai_dsh_client_file_upload_fileUploads_upload_result$schema,
64
+ create: _deepseek_ai_dsh_client_file_upload_fileUploads_upload_result$schema,
62
65
  },
63
66
  sourceLocation: {"file":"packages/client/file-upload/src/index.ts","line":106,"column":3},
64
67
  },
@@ -155,7 +158,7 @@ export const TYPERT = {
155
158
  },
156
159
  {
157
160
  "name": "AssistantMessage",
158
- "declaration": "export interface AssistantMessage extends Message {\n readonly role: 'assistant';\n readonly source: ModelMessageSource;\n}"
161
+ "declaration": "export interface AssistantMessage extends MessageBase {\n readonly role: 'assistant';\n readonly source: ModelMessageSource;\n}"
159
162
  },
160
163
  {
161
164
  "name": "AssistantProviderMetadata",
@@ -193,6 +196,10 @@ export const TYPERT = {
193
196
  "name": "CommandSourceMap",
194
197
  "declaration": "export interface CommandSourceMap {\n user: { kind: 'user'; };\n}"
195
198
  },
199
+ {
200
+ "name": "CompactionCheckpointSource",
201
+ "declaration": "export type CompactionCheckpointSource = typeof COMPACT_CHECKPOINT_MARKER & { readonly compactionId: CompactionId; readonly sourceCommandId?: CommandId; };"
202
+ },
196
203
  {
197
204
  "name": "CompactionId",
198
205
  "declaration": "export type CompactionId = Branded<'CompactionId'>;"
@@ -203,7 +210,7 @@ export const TYPERT = {
203
210
  },
204
211
  {
205
212
  "name": "ContentBlockMap",
206
- "declaration": "export interface ContentBlockMap {\n text: TextBlock;\n reasoning: ReasoningBlock;\n image: ImageBlock;\n file: FileBlock;\n 'tool-call': ToolCallBlock;\n 'tool-result': ToolResultBlock;\n}"
213
+ "declaration": "export interface ContentBlockMap {\n text: TextBlock;\n reasoning: ReasoningBlock;\n image: ImageBlock;\n file: FileBlock;\n 'tool-call': ToolCallBlock;\n 'tool-addition': ToolAdditionBlock;\n 'tool-removal': ToolRemovalBlock;\n}"
207
214
  },
208
215
  {
209
216
  "name": "ContentBlockType",
@@ -221,13 +228,17 @@ export const TYPERT = {
221
228
  "name": "ContinuableSubagentDescriptorData",
222
229
  "declaration": "export interface ContinuableSubagentDescriptorData extends SubagentDescriptorBase {\n readonly mode: 'continuable';\n readonly label: string;\n readonly agentProvider?: string;\n readonly agentModel?: string;\n readonly agentReasoningEffort?: ReasoningEffortId;\n readonly persona?: string;\n readonly toolFilter?: ToolRestriction;\n}"
223
230
  },
231
+ {
232
+ "name": "DeveloperMessage",
233
+ "declaration": "export interface DeveloperMessage extends MessageBase {\n readonly role: 'developer';\n}"
234
+ },
224
235
  {
225
236
  "name": "EncodedFileUploadRequest",
226
237
  "declaration": "export interface EncodedFileUploadRequest {\n readonly data: string;\n readonly name?: string;\n}"
227
238
  },
228
239
  {
229
240
  "name": "EpochHeader",
230
- "declaration": "export interface EpochHeader {\n config: LlmCallConfig;\n adapterDefaults?: LlmCallConfigAdapterDefaults;\n tools?: ToolSchema[];\n}"
241
+ "declaration": "export interface EpochHeader {\n config: LlmCallConfig;\n adapterDefaults?: LlmCallConfigAdapterDefaults;\n tools?: ToolSchema[];\n system?: never;\n}"
231
242
  },
232
243
  {
233
244
  "name": "FeedbackCategory",
@@ -329,6 +340,10 @@ export const TYPERT = {
329
340
  "name": "JsonValue",
330
341
  "declaration": "export type JsonValue = null | boolean | number | string | JsonValue[] | { [key: string]: JsonValue; };"
331
342
  },
343
+ {
344
+ "name": "KnownCatalogMode",
345
+ "declaration": "export type KnownCatalogMode = { readonly mode: 'one-shot'; readonly label?: string; } | { readonly mode: 'continuable'; readonly label: string; };"
346
+ },
332
347
  {
333
348
  "name": "LlmCallConfig",
334
349
  "declaration": "export interface LlmCallConfig {\n provider: string;\n model: string;\n reasoningEffort?: ReasoningEffortId;\n temperature?: number;\n maxTokens?: number;\n stop?: string[];\n}"
@@ -343,7 +358,11 @@ export const TYPERT = {
343
358
  },
344
359
  {
345
360
  "name": "Message",
346
- "declaration": "export interface Message {\n readonly id: MessageId;\n readonly role: 'system' | 'user' | 'assistant';\n readonly content: ContentBlock[];\n readonly source: MessageSource;\n}"
361
+ "declaration": "export type Message = MessageRoleMap[keyof MessageRoleMap];"
362
+ },
363
+ {
364
+ "name": "MessageBase",
365
+ "declaration": "export interface MessageBase {\n readonly id: MessageId;\n readonly content: readonly ContentBlock[];\n readonly source: MessageSource;\n}"
347
366
  },
348
367
  {
349
368
  "name": "MessageFeedbackDelete",
@@ -369,13 +388,17 @@ export const TYPERT = {
369
388
  "name": "MessageId",
370
389
  "declaration": "export type MessageId = Branded<'MessageId'>;"
371
390
  },
391
+ {
392
+ "name": "MessageRoleMap",
393
+ "declaration": "export interface MessageRoleMap {\n system: SystemMessage;\n developer: DeveloperMessage;\n user: UserMessage;\n assistant: AssistantMessage;\n tool: ToolResultMessage;\n}"
394
+ },
372
395
  {
373
396
  "name": "MessageSource",
374
397
  "declaration": "export type MessageSource = MessageSourceMap[keyof MessageSourceMap];"
375
398
  },
376
399
  {
377
400
  "name": "MessageSourceMap",
378
- "declaration": "export interface MessageSourceMap {\n user: { kind: 'user'; };\n plugin: { kind: 'plugin'; plugin: string; } & ContextFormed;\n model: ModelMessageSource;\n tool: ToolMessageSource;\n 'user-rpc': { kind: 'user'; rpcId: SessionRequestId; clientTimeZone?: string; };\n 'agent-message': AgentMessageSource;\n 'subagent-settled': SubagentSettledMessageSource;\n 'skill-invocation': SkillInvocationSource;\n 'team-message': TeamMessageSource;\n goal: GoalMessageSource;\n 'session-reference': SessionReferenceSource;\n}"
401
+ "declaration": "export interface MessageSourceMap {\n user: { kind: 'user'; };\n model: ModelMessageSource;\n tool: ToolMessageSource;\n 'system-prompt': SystemPromptMessageSource;\n 'model-selection': { kind: 'model-selection'; } & ContextFormed;\n 'user-approval': { kind: 'user-approval'; } & ContextFormed;\n 'ptc-mode': { kind: 'ptc-mode'; };\n 'tool-registry': { kind: 'tool-registry'; };\n 'user-rpc': { kind: 'user'; rpcId: SessionRequestId; clientTimeZone?: string; };\n 'agent-message': AgentMessageSource;\n 'subagent-settled': SubagentSettledMessageSource;\n 'skill-invocation': SkillInvocationSource;\n 'cordis-host-runner': { kind: 'cordis-host-runner'; };\n 'team-message': TeamMessageSource;\n goal: GoalMessageSource;\n 'compact-checkpoint': CompactionCheckpointSource;\n 'session-reference': SessionReferenceSource;\n}"
379
402
  },
380
403
  {
381
404
  "name": "ModelMessageSource",
@@ -435,7 +458,7 @@ export const TYPERT = {
435
458
  },
436
459
  {
437
460
  "name": "Session",
438
- "declaration": "export class Session {\n get surface(): SessionSurface;\n readonly header: SessionHeader;\n readonly inheritedEventCount: SessionLogOffset;\n get id(): SessionId;\n readonly firstLiveSeq: SessionLogOffset;\n eventAt(seq: SessionSeq): SessionEvent | undefined;\n snapshotEvents(fromSeq: SessionLogOffset = SessionLogOffset(0), toSeqExclusive: SessionLogOffset = this.seq): readonly SessionEvent[];\n ownEvents(): readonly SessionEvent[];\n isOwnSeq(seq: SessionSeq): boolean;\n get seq(): SessionLogOffset;\n append<T extends SessionEventType>(type: T, data: SessionEventMap[T], ...opts: T extends SurfaceEventType ? [opts: SurfaceIntent<T>] : []): SessionEvent<T>;\n requestHeader(): EpochHeader | undefined;\n requestContext(): RequestContext | undefined;\n deriveMessages(): Message[];\n deriveEventMessage(event: SessionEvent): Message | null;\n}"
461
+ "declaration": "export class Session {\n get surface(): SessionSurface;\n readonly header: SessionHeader;\n readonly inheritedEventCount: SessionLogOffset;\n get id(): SessionId;\n readonly firstLiveSeq: SessionLogOffset;\n readonly firstLifecycleSeq: SessionLogOffset;\n eventAt(seq: SessionSeq): SessionEvent | undefined;\n snapshotEvents(fromSeq: SessionLogOffset = SessionLogOffset(0), toSeqExclusive: SessionLogOffset = this.seq): readonly SessionEvent[];\n ownEvents(): readonly SessionEvent[];\n isOwnSeq(seq: SessionSeq): boolean;\n get seq(): SessionLogOffset;\n append<T extends SessionEventType>(type: T, data: SessionEventMap[T], ...opts: T extends SurfaceEventType ? [opts: SurfaceIntent<T>] : []): SessionEvent<T>;\n requestHeader(): EpochHeader | undefined;\n requestContext(): RequestContext | undefined;\n deriveMessages(): Message[];\n deriveEventMessage(event: SessionEvent): Message | null;\n}"
439
462
  },
440
463
  {
441
464
  "name": "SessionEvent",
@@ -443,7 +466,7 @@ export const TYPERT = {
443
466
  },
444
467
  {
445
468
  "name": "SessionEventMap",
446
- "declaration": "export interface SessionEventMap {\n 'turn/start': { turn: number; };\n 'turn/end': { turn: number; reason: TurnEndReason; };\n 'step/start': { turn: number; step: number; };\n 'step/end': { turn: number; step: number; };\n 'user/message': UserMessage;\n 'system/message': { turn: number; step: number; message: SystemMessage; };\n 'assistant/message': { turn: number; step: number; message: AssistantMessage; stream: AssistantStreamRecord[]; usage?: TokenUsage; interrupted?: true; };\n 'assistant/attempt': { turn: number; step: number; stream: AssistantStreamRecord[]; };\n 'tool/call': { turn: number; step: number; callId: ToolCallId; name: string; arguments: string; };\n 'tool/result': { turn: number; step: number; message: ToolResultMessage; error?: { name: string; code: string; reason?: string; }; meta?: JsonValue; };\n 'request/header': { header: EpochHeader; reason: RequestHeaderReason; startsSeries?: true; };\n 'request/context': RequestContext;\n 'session/end-seed': { inherited?: true; };\n 'agent/inbox/spliced': { target: InboxTarget; start: number; removedCount?: number; inserted: UserMessage[]; outcome?: 'canceled'; };\n 'sandbox/mode': { mode: SandboxMode; source?: 'delegation'; };\n 'approval/asked': { id: ApprovalRequestId; toolName: string; callId?: ToolCallId; reason?: string; };\n 'approval/decided': { id: ApprovalRequestId; outcome: ApprovalOutcome; };\n 'approval/policy': { policy: ApprovalPolicy; source?: 'delegation'; };\n 'tool/ptc-dispatch-start': PtcDispatchStartEventData;\n 'tool/ptc-dispatch': PtcDispatchEventData;\n 'agent-preset/selected': { agentPreset: string; };\n 'command/run': { commandId: CommandId; name: string; args?: string; source: CommandSource; };\n 'command/done': { commandId: CommandId; kind: 'success' | 'error'; text?: string; sourceEventSeq?: import('@deepseek-ai/dsh-session/types').SessionSeq; };\n 'image/offload': { targets: ImageOffloadTarget[]; };\n 'session/title': SessionTitleEventData;\n 'todo/write': { todos: TodoItem[]; };\n 'model/selection': ModelSelection;\n 'subagent/descriptor': SubagentDescriptorData;\n 'permission/preset': { preset: string; };\n 'subagent/catalog': SubagentCatalogEvent;\n 'feedback/record': FeedbackRecord;\n 'team/member': { version: 2; teamId: TeamId; member: TeamMemberSnapshot; };\n 'team/task': { version: 2; teamId: TeamId; task: TeamTaskSnapshot; };\n 'team/message/queued': { version: 2; teamId: TeamId; message: TeamMessageSnapshot; };\n 'team/message/delivered': { version: 2; teamId: TeamId; messageId: TeamMessageId; targetId: SessionId; };\n 'goal/change': GoalChangeMeta;\n 'feedback/message-put': MessageFeedbackPut;\n 'feedback/message-delete': MessageFeedbackDelete;\n 'compaction/start': { compactionId: CompactionId; sourceCommandId?: CommandId; turn: number | null; };\n 'compaction/summary': { compactionId: CompactionId; sourceCommandId?: CommandId; summary: ContentBlock[]; shadowedRange: { start: SessionSeq; end: SessionSeq; }; shadowedSeqs: SessionSeq[]; shadowedTokenCount: number; provider: string; model: string; maxTokens?: number; usage?: TokenUsage; } & ({ rawOutput: ContentBlock[]; llmStreamCall: true; } | { rawOutput?: ContentBlock[]; llmStreamCall?: never; });\n 'compaction/end': { compactionId: CompactionId; sourceCommandId?: CommandId; turn: number | null; error?: string; };\n 'compaction/prune': { shadowedRange: { start: SessionSeq; end: SessionSeq; }; shadowedSeqs: SessionSeq[]; shadowedTokenCount: number; };\n}"
469
+ "declaration": "export interface SessionEventMap {\n 'turn/start': { turn: number; };\n 'turn/end': { turn: number; reason: TurnEndReason; };\n 'step/start': { turn: number; step: number; };\n 'step/end': { turn: number; step: number; };\n 'user/message': UserMessage;\n 'developer/message': { turn: number; step: number; message: DeveloperMessage; headerSeq?: SessionSeq; };\n 'system/message': { turn: number; step: number; message: SystemMessage; };\n 'assistant/message': { turn: number; step: number; message: AssistantMessage; stream: AssistantStreamRecord[]; usage?: TokenUsage; interrupted?: true; };\n 'assistant/attempt': { turn: number; step: number; stream: AssistantStreamRecord[]; };\n 'tool/call': { turn: number; step: number; callId: ToolCallId; name: string; arguments: string; };\n 'tool/result': { turn: number; step: number; message: ToolResultMessage; error?: { name: string; code: string; reason?: string; }; meta?: JsonValue; };\n 'request/header': { header: EpochHeader; reason: RequestHeaderReason; startsSeries?: true; };\n 'request/context': RequestContext;\n 'session/end-seed': { inherited?: true; };\n 'agent/inbox/spliced': { target: InboxTarget; start: number; removedCount?: number; inserted: UserMessage[]; outcome?: 'canceled'; };\n 'sandbox/mode': { mode: SandboxMode; source?: 'delegation'; };\n 'approval/asked': { id: ApprovalRequestId; toolName: string; callId?: ToolCallId; reason?: string; };\n 'approval/decided': { id: ApprovalRequestId; outcome: ApprovalOutcome; };\n 'approval/policy': { policy: ApprovalPolicy; source?: 'delegation'; };\n 'tool/ptc-dispatch-start': PtcDispatchStartEventData;\n 'tool/ptc-dispatch': PtcDispatchEventData;\n 'agent-preset/selected': { agentPreset: string; };\n 'command/run': { commandId: CommandId; name: string; args?: string; source: CommandSource; };\n 'command/done': { commandId: CommandId; kind: 'success' | 'error'; text?: string; sourceEventSeq?: import('@deepseek-ai/dsh-session/types').SessionSeq; };\n 'image/offload': { targets: ImageOffloadTarget[]; };\n 'session/title': SessionTitleEventData;\n 'todo/write': { todos: TodoItem[]; };\n 'model/selection': ModelSelection;\n 'subagent/descriptor': SubagentDescriptorData;\n 'permission/preset': { preset: string; };\n 'subagent/catalog': SubagentCatalogEvent;\n 'feedback/record': FeedbackRecord;\n 'team/member': { version: 2; teamId: TeamId; member: TeamMemberSnapshot; };\n 'team/task': { version: 2; teamId: TeamId; task: TeamTaskSnapshot; };\n 'team/message/queued': { version: 2; teamId: TeamId; message: TeamMessageSnapshot; };\n 'team/message/delivered': { version: 2; teamId: TeamId; messageId: TeamMessageId; targetId: SessionId; };\n 'goal/change': GoalChangeMeta;\n 'feedback/message-put': MessageFeedbackPut;\n 'feedback/message-delete': MessageFeedbackDelete;\n 'compaction/start': { compactionId: CompactionId; sourceCommandId?: CommandId; turn: number | null; };\n 'compaction/summary': { compactionId: CompactionId; sourceCommandId?: CommandId; summary: ContentBlock[]; shadowedRange: { start: SessionSeq; end: SessionSeq; }; shadowedSeqs: SessionSeq[]; shadowedTokenCount: number; provider: string; model: string; maxTokens?: number; usage?: TokenUsage; } & ({ rawOutput: ContentBlock[]; llmStreamCall: true; } | { rawOutput?: ContentBlock[]; llmStreamCall?: never; });\n 'compaction/end': { compactionId: CompactionId; sourceCommandId?: CommandId; turn: number | null; error?: string; };\n 'compaction/prune': { shadowedRange: { start: SessionSeq; end: SessionSeq; }; shadowedSeqs: SessionSeq[]; shadowedTokenCount: number; };\n}"
447
470
  },
448
471
  {
449
472
  "name": "SessionEventType",
@@ -503,7 +526,7 @@ export const TYPERT = {
503
526
  },
504
527
  {
505
528
  "name": "SubagentCatalogEvent",
506
- "declaration": "export type SubagentCatalogEvent = { readonly version: 0; readonly childId: SessionId; readonly childCreatedAt: number; } & ({ readonly mode: 'one-shot'; readonly label?: string; } | { readonly mode: 'continuable'; readonly label: string; });"
529
+ "declaration": "export type SubagentCatalogEvent = { readonly childId: SessionId; readonly childCreatedAt: number; } & (({ readonly version: 0; } & KnownCatalogMode) | ({ readonly version: 1; } & (KnownCatalogMode | { readonly mode: 'unknown'; readonly label?: string; })));"
507
530
  },
508
531
  {
509
532
  "name": "SubagentDescriptorBase",
@@ -519,7 +542,7 @@ export const TYPERT = {
519
542
  },
520
543
  {
521
544
  "name": "SurfaceEventType",
522
- "declaration": "export type SurfaceEventType = 'system/message' | 'user/message' | 'assistant/message' | 'tool/result';"
545
+ "declaration": "export type SurfaceEventType = 'system/message' | 'developer/message' | 'user/message' | 'assistant/message' | 'tool/result';"
523
546
  },
524
547
  {
525
548
  "name": "SurfaceIntent",
@@ -531,7 +554,11 @@ export const TYPERT = {
531
554
  },
532
555
  {
533
556
  "name": "SystemMessage",
534
- "declaration": "export interface SystemMessage extends Message {\n readonly role: 'system';\n readonly source: MessageSourceMap['plugin'];\n}"
557
+ "declaration": "export interface SystemMessage extends MessageBase {\n readonly role: 'system';\n readonly source: MessageSourceMap['system-prompt'];\n}"
558
+ },
559
+ {
560
+ "name": "SystemPromptMessageSource",
561
+ "declaration": "export interface SystemPromptMessageSource {\n kind: 'system-prompt';\n}"
535
562
  },
536
563
  {
537
564
  "name": "SystemPromptUpdate",
@@ -585,6 +612,10 @@ export const TYPERT = {
585
612
  "name": "TokenUsage",
586
613
  "declaration": "export interface TokenUsage {\n inputTokens: number;\n outputTokens: number;\n totalTokens?: number;\n cacheReadTokens?: number;\n cacheWriteTokens?: number;\n reasoningTokens?: number;\n}"
587
614
  },
615
+ {
616
+ "name": "ToolAdditionBlock",
617
+ "declaration": "export interface ToolAdditionBlock {\n type: 'tool-addition';\n toolName: string;\n tool?: never;\n}"
618
+ },
588
619
  {
589
620
  "name": "ToolCallBlock",
590
621
  "declaration": "export interface ToolCallBlock {\n type: 'tool-call';\n id: ToolCallId;\n name: string;\n arguments: string;\n}"
@@ -598,20 +629,20 @@ export const TYPERT = {
598
629
  "declaration": "export interface ToolMessageSource {\n kind: 'tool';\n callId: ToolCallId;\n}"
599
630
  },
600
631
  {
601
- "name": "ToolRestriction",
602
- "declaration": "export interface ToolRestriction {\n readonly allow?: readonly string[];\n readonly deny?: readonly string[];\n}"
632
+ "name": "ToolRemovalBlock",
633
+ "declaration": "export interface ToolRemovalBlock {\n type: 'tool-removal';\n toolName: string;\n}"
603
634
  },
604
635
  {
605
- "name": "ToolResultBlock",
606
- "declaration": "export interface ToolResultBlock {\n type: 'tool-result';\n toolCallId: ToolCallId;\n content: ContentBlock[];\n isError?: boolean;\n}"
636
+ "name": "ToolRestriction",
637
+ "declaration": "export interface ToolRestriction {\n readonly allow?: readonly string[];\n readonly deny?: readonly string[];\n}"
607
638
  },
608
639
  {
609
640
  "name": "ToolResultMessage",
610
- "declaration": "export interface ToolResultMessage extends Message {\n readonly role: 'user';\n readonly content: [ToolResultBlock];\n readonly source: ToolMessageSource;\n}"
641
+ "declaration": "export interface ToolResultMessage extends MessageBase {\n readonly role: 'tool';\n readonly source: ToolMessageSource;\n readonly toolCallId: ToolCallId;\n readonly isError?: boolean;\n}"
611
642
  },
612
643
  {
613
644
  "name": "ToolSchema",
614
- "declaration": "export interface ToolSchema {\n name: string;\n description: string;\n parameters: Record<string, unknown>;\n}"
645
+ "declaration": "export interface ToolSchema {\n deferLoading?: true;\n name: string;\n description: string;\n parameters: Record<string, unknown>;\n}"
615
646
  },
616
647
  {
617
648
  "name": "TurnEndCancelCause",
@@ -623,11 +654,11 @@ export const TYPERT = {
623
654
  },
624
655
  {
625
656
  "name": "TurnEndReasonMap",
626
- "declaration": "export interface TurnEndReasonMap {\n completed: { kind: 'completed'; };\n aborted: { kind: 'aborted'; reason: TurnEndCancelCause; };\n blocked: { kind: 'blocked'; };\n error: { kind: 'error'; error: LlmFailure; };\n 'max-tokens': { kind: 'max-tokens'; };\n interrupted: { kind: 'interrupted'; };\n}"
657
+ "declaration": "export interface TurnEndReasonMap {\n completed: { kind: 'completed'; };\n aborted: { kind: 'aborted'; reason: TurnEndCancelCause; };\n blocked: { kind: 'blocked'; };\n error: { kind: 'error'; error: LlmFailure; };\n 'max-tokens': { kind: 'max-tokens'; };\n interrupted: { kind: 'interrupted'; };\n forked: { kind: 'forked'; };\n}"
627
658
  },
628
659
  {
629
660
  "name": "UserMessage",
630
- "declaration": "export interface UserMessage extends Message {\n readonly role: 'user';\n}"
661
+ "declaration": "export interface UserMessage extends MessageBase {\n readonly role: 'user';\n}"
631
662
  }
632
663
  ]
633
664
  }
@@ -1,19 +1,22 @@
1
1
  /* Generated by @deepseek-ai/dsh-typert-generator from the Host FaceModel — do not edit. */
2
2
  import { z } from 'zod'
3
3
 
4
- const _deepseek_ai_dsh_client_file_upload_fileUploads_upload_parameter_0$schema = z.intersection(z.string(), z.unknown())
5
- const _deepseek_ai_dsh_client_file_upload_fileUploads_upload_parameter_1$schema = z.object({
4
+ let _deepseek_ai_dsh_client_file_upload_fileUploads_upload_parameter_0$schema$value
5
+ const _deepseek_ai_dsh_client_file_upload_fileUploads_upload_parameter_0$schema = () => (_deepseek_ai_dsh_client_file_upload_fileUploads_upload_parameter_0$schema$value ??= z.intersection(z.string(), z.unknown()))
6
+ let _deepseek_ai_dsh_client_file_upload_fileUploads_upload_parameter_1$schema$value
7
+ const _deepseek_ai_dsh_client_file_upload_fileUploads_upload_parameter_1$schema = () => (_deepseek_ai_dsh_client_file_upload_fileUploads_upload_parameter_1$schema$value ??= z.object({
6
8
  'data': z.string().readonly(),
7
9
  'name': z.string().readonly().optional(),
8
- })
9
- const _deepseek_ai_dsh_client_file_upload_fileUploads_upload_result$schema = z.object({
10
+ }))
11
+ let _deepseek_ai_dsh_client_file_upload_fileUploads_upload_result$schema$value
12
+ const _deepseek_ai_dsh_client_file_upload_fileUploads_upload_result$schema = () => (_deepseek_ai_dsh_client_file_upload_fileUploads_upload_result$schema$value ??= z.object({
10
13
  'receiptId': z.intersection(z.string(), z.unknown()).readonly(),
11
14
  'file': z.object({
12
15
  'attachmentId': z.intersection(z.string(), z.unknown()),
13
16
  'name': z.string(),
14
17
  'bytes': z.number(),
15
18
  }).readonly(),
16
- })
19
+ }))
17
20
 
18
21
  export const TYPERT_REMOTE = {
19
22
  package: '@deepseek-ai/dsh-client-file-upload',
@@ -37,7 +40,7 @@ export const TYPERT_REMOTE = {
37
40
  codec: {
38
41
  mode: 'strict',
39
42
  typeSymbol: '@deepseek-ai/dsh-session/types#SessionId',
40
- schema: _deepseek_ai_dsh_client_file_upload_fileUploads_upload_parameter_0$schema,
43
+ create: _deepseek_ai_dsh_client_file_upload_fileUploads_upload_parameter_0$schema,
41
44
  },
42
45
  },
43
46
  {
@@ -47,7 +50,7 @@ export const TYPERT_REMOTE = {
47
50
  codec: {
48
51
  mode: 'strict',
49
52
  typeSymbol: '@deepseek-ai/dsh-client-file-upload/types#EncodedFileUploadRequest',
50
- schema: _deepseek_ai_dsh_client_file_upload_fileUploads_upload_parameter_1$schema,
53
+ create: _deepseek_ai_dsh_client_file_upload_fileUploads_upload_parameter_1$schema,
51
54
  },
52
55
  },
53
56
  ],
@@ -55,7 +58,7 @@ export const TYPERT_REMOTE = {
55
58
  result: {
56
59
  mode: 'strict',
57
60
  typeSymbol: '@deepseek-ai/dsh-client-file-upload/types#FileUploadValue',
58
- schema: _deepseek_ai_dsh_client_file_upload_fileUploads_upload_result$schema,
61
+ create: _deepseek_ai_dsh_client_file_upload_fileUploads_upload_result$schema,
59
62
  },
60
63
  sourceLocation: {"file":"packages/client/file-upload/src/index.ts","line":106,"column":3},
61
64
  },
@@ -5,6 +5,7 @@ import type { SessionId } from '@deepseek-ai/dsh-session/types';
5
5
  import type { FileUploadValue } from '../types.ts';
6
6
  import type { FileUploadBody, FileUploadService } from './contract.ts';
7
7
  interface FileUploadRequest {
8
+ /** Document-relative app-owned upload route, query string included. */
8
9
  readonly path: string;
9
10
  readonly body: FileUploadBody;
10
11
  readonly headers?: Readonly<Record<string, string>>;
@@ -2,7 +2,7 @@
2
2
  import { Service } from '@deepseek-ai/cordis';
3
3
  import { bytesToBase64 } from '@deepseek-ai/dsh-util-crypto';
4
4
  import { RemoteError } from '@deepseek-ai/dsh-typert-protocol';
5
- import { FILE_UPLOAD_PATH } from "../protocol.js";
5
+ import { FILE_UPLOAD_ROUTE } from "../protocol.js";
6
6
  /**
7
7
  * Self-contained Worker body; its string form becomes the Blob Worker source.
8
8
  * @param scope - Worker global used for requests and progress messages.
@@ -112,7 +112,7 @@ export class FileUploadRuntime extends Service {
112
112
  if (name !== undefined)
113
113
  query.set('name', name);
114
114
  const response = await this.post({
115
- path: `${FILE_UPLOAD_PATH}?${query.toString()}`,
115
+ path: `${FILE_UPLOAD_ROUTE}?${query.toString()}`,
116
116
  body: data,
117
117
  headers: { 'content-type': 'application/octet-stream' },
118
118
  ...(signal === undefined ? {} : { signal }),
@@ -139,7 +139,7 @@ function customTransport(customFetch) {
139
139
  ...(request.body instanceof ReadableStream ? { duplex: 'half' } : {}),
140
140
  ...(request.signal === undefined ? {} : { signal: request.signal }),
141
141
  };
142
- const response = await customFetch(resolveUrl(request.path), init);
142
+ const response = await customFetch(request.path, init);
143
143
  return { status: response.status, body: await response.text() };
144
144
  },
145
145
  };
@@ -195,7 +195,8 @@ function workerTransport() {
195
195
  }
196
196
  request.signal?.addEventListener('abort', abort, { once: true });
197
197
  const message = {
198
- url: resolveUrl(request.path).href,
198
+ // The Worker's own base is `blob:`, so its request URL must be absolute.
199
+ url: new URL(request.path, document.baseURI).href,
199
200
  body: request.body,
200
201
  headers: request.headers ?? {},
201
202
  };
@@ -207,14 +208,6 @@ function workerTransport() {
207
208
  },
208
209
  };
209
210
  }
210
- function resolveUrl(path) {
211
- const pageLocation = Reflect.get(globalThis, 'location');
212
- const origin = typeof pageLocation === 'object' && pageLocation !== null
213
- && 'origin' in pageLocation && typeof pageLocation.origin === 'string'
214
- ? pageLocation.origin
215
- : undefined;
216
- return new URL(path, origin === undefined || origin === 'null' ? 'http://dsh.internal' : origin);
217
- }
218
211
  function parseFileUploadResult(body) {
219
212
  const value = JSON.parse(body);
220
213
  if (!isRecord(value) || typeof value.ok !== 'boolean') {
@@ -1,3 +1,8 @@
1
1
  /** Authenticated raw-byte route owned by the file-upload service. */
2
2
  export declare const FILE_UPLOAD_PATH = "/api/session/uploadFileBinary";
3
+ /**
4
+ * Browser-relative form of {@link FILE_UPLOAD_PATH}; see
5
+ * .agents/notes/implemented/architecture/2026-09-14-web-document-relative-app-routes.md.
6
+ */
7
+ export declare const FILE_UPLOAD_ROUTE: string;
3
8
  //# sourceMappingURL=protocol.d.ts.map
@@ -1,3 +1,8 @@
1
1
  /** Authenticated raw-byte route owned by the file-upload service. */
2
2
  export const FILE_UPLOAD_PATH = '/api/session/uploadFileBinary';
3
+ /**
4
+ * Browser-relative form of {@link FILE_UPLOAD_PATH}; see
5
+ * .agents/notes/implemented/architecture/2026-09-14-web-document-relative-app-routes.md.
6
+ */
7
+ export const FILE_UPLOAD_ROUTE = FILE_UPLOAD_PATH.slice(1);
3
8
  //# sourceMappingURL=protocol.js.map
@@ -18,11 +18,12 @@ export interface FileUploadValue {
18
18
  export type FileUploadReceiptId = Branded<'file-upload-receipt-id'>;
19
19
  /**
20
20
  * Fetch-shaped carrier installed by a page that owns its Host transport.
21
- * @param input - absolute same-origin upload URL.
21
+ * @param input - document-relative upload route; a carrier that needs an
22
+ * absolute URL resolves it against its own base.
22
23
  * @param init - raw request body, headers, and cancellation signal.
23
24
  * @returns the Host response.
24
25
  */
25
- export type FileUploadFetch = (input: URL, init: RequestInit) => Promise<Response>;
26
+ export type FileUploadFetch = (input: string | URL, init: RequestInit) => Promise<Response>;
26
27
  /** Pre-Cordis hook supplied by a page whose Host runs in another execution context. */
27
28
  export interface ClientFileUploadHooks {
28
29
  readonly fetch: FileUploadFetch;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@deepseek-ai/dsh-client-file-upload",
3
3
  "description": "Agent-scoped browser file upload, streaming intake, and staged receipt service",
4
- "version": "0.1.6-alpha.1",
4
+ "version": "0.1.7-alpha.1",
5
5
  "publishConfig": {
6
6
  "access": "public"
7
7
  },
@@ -59,23 +59,23 @@
59
59
  ],
60
60
  "dependencies": {
61
61
  "zod": "^4.4.3",
62
- "@deepseek-ai/dsh-typert-protocol": "^0.1.6-alpha.1",
63
- "@deepseek-ai/dsh-brand": "^0.1.6-alpha.1"
62
+ "@deepseek-ai/dsh-typert-protocol": "^0.1.7-alpha.1",
63
+ "@deepseek-ai/dsh-brand": "^0.1.7-alpha.1"
64
64
  },
65
65
  "peerDependencies": {
66
- "@deepseek-ai/cordis": "^4.0.2",
67
- "@deepseek-ai/dsh-scope": "^0.1.6-alpha.1"
66
+ "@deepseek-ai/cordis": "^4.0.3",
67
+ "@deepseek-ai/dsh-scope": "^0.1.7-alpha.1"
68
68
  },
69
69
  "devDependencies": {
70
- "@deepseek-ai/cordis": "^4.0.2",
71
- "@deepseek-ai/dsh-agent": "^0.1.6-alpha.1",
72
- "@deepseek-ai/dsh-client-connection": "^0.1.6-alpha.1",
73
- "@deepseek-ai/dsh-commands": "^0.1.6-alpha.1",
74
- "@deepseek-ai/dsh-scope": "^0.1.6-alpha.1",
75
- "@deepseek-ai/dsh-util-crypto": "^0.1.6-alpha.1",
76
- "@deepseek-ai/dsh-api-remotes": "^0.1.6-alpha.1",
77
- "@deepseek-ai/dsh-attachment": "^0.1.6-alpha.1",
78
- "@deepseek-ai/dsh-session": "^0.1.6-alpha.1"
70
+ "@deepseek-ai/dsh-agent": "^0.1.7-alpha.1",
71
+ "@deepseek-ai/cordis": "^4.0.3",
72
+ "@deepseek-ai/dsh-client-connection": "^0.1.7-alpha.1",
73
+ "@deepseek-ai/dsh-commands": "^0.1.7-alpha.1",
74
+ "@deepseek-ai/dsh-util-crypto": "^0.1.7-alpha.1",
75
+ "@deepseek-ai/dsh-api-remotes": "^0.1.7-alpha.1",
76
+ "@deepseek-ai/dsh-scope": "^0.1.7-alpha.1",
77
+ "@deepseek-ai/dsh-session": "^0.1.7-alpha.1",
78
+ "@deepseek-ai/dsh-attachment": "^0.1.7-alpha.1"
79
79
  },
80
80
  "scripts": {
81
81
  "bundle": "tsdown",