dsh-edge 0.1.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.
Files changed (159) hide show
  1. package/LICENSE +21 -0
  2. package/README.i18n.yaml +6 -0
  3. package/README.md +183 -0
  4. package/README.zh.md +183 -0
  5. package/THIRD_PARTY_NOTICES.md +199 -0
  6. package/dist/_headers +3 -0
  7. package/dist/assets/fonts/KaTeX_AMS-Regular-BQhdFMY1.woff2 +0 -0
  8. package/dist/assets/fonts/KaTeX_AMS-Regular-DMm9YOAa.woff +0 -0
  9. package/dist/assets/fonts/KaTeX_AMS-Regular-DRggAlZN.ttf +0 -0
  10. package/dist/assets/fonts/KaTeX_Caligraphic-Bold-ATXxdsX0.ttf +0 -0
  11. package/dist/assets/fonts/KaTeX_Caligraphic-Bold-BEiXGLvX.woff +0 -0
  12. package/dist/assets/fonts/KaTeX_Caligraphic-Bold-Dq_IR9rO.woff2 +0 -0
  13. package/dist/assets/fonts/KaTeX_Caligraphic-Regular-CTRA-rTL.woff +0 -0
  14. package/dist/assets/fonts/KaTeX_Caligraphic-Regular-Di6jR-x-.woff2 +0 -0
  15. package/dist/assets/fonts/KaTeX_Caligraphic-Regular-wX97UBjC.ttf +0 -0
  16. package/dist/assets/fonts/KaTeX_Fraktur-Bold-BdnERNNW.ttf +0 -0
  17. package/dist/assets/fonts/KaTeX_Fraktur-Bold-BsDP51OF.woff +0 -0
  18. package/dist/assets/fonts/KaTeX_Fraktur-Bold-CL6g_b3V.woff2 +0 -0
  19. package/dist/assets/fonts/KaTeX_Fraktur-Regular-CB_wures.ttf +0 -0
  20. package/dist/assets/fonts/KaTeX_Fraktur-Regular-CTYiF6lA.woff2 +0 -0
  21. package/dist/assets/fonts/KaTeX_Fraktur-Regular-Dxdc4cR9.woff +0 -0
  22. package/dist/assets/fonts/KaTeX_Main-Bold-Cx986IdX.woff2 +0 -0
  23. package/dist/assets/fonts/KaTeX_Main-Bold-Jm3AIy58.woff +0 -0
  24. package/dist/assets/fonts/KaTeX_Main-Bold-waoOVXN0.ttf +0 -0
  25. package/dist/assets/fonts/KaTeX_Main-BoldItalic-DxDJ3AOS.woff2 +0 -0
  26. package/dist/assets/fonts/KaTeX_Main-BoldItalic-DzxPMmG6.ttf +0 -0
  27. package/dist/assets/fonts/KaTeX_Main-BoldItalic-SpSLRI95.woff +0 -0
  28. package/dist/assets/fonts/KaTeX_Main-Italic-3WenGoN9.ttf +0 -0
  29. package/dist/assets/fonts/KaTeX_Main-Italic-BMLOBm91.woff +0 -0
  30. package/dist/assets/fonts/KaTeX_Main-Italic-NWA7e6Wa.woff2 +0 -0
  31. package/dist/assets/fonts/KaTeX_Main-Regular-B22Nviop.woff2 +0 -0
  32. package/dist/assets/fonts/KaTeX_Main-Regular-Dr94JaBh.woff +0 -0
  33. package/dist/assets/fonts/KaTeX_Main-Regular-ypZvNtVU.ttf +0 -0
  34. package/dist/assets/fonts/KaTeX_Math-BoldItalic-B3XSjfu4.ttf +0 -0
  35. package/dist/assets/fonts/KaTeX_Math-BoldItalic-CZnvNsCZ.woff2 +0 -0
  36. package/dist/assets/fonts/KaTeX_Math-BoldItalic-iY-2wyZ7.woff +0 -0
  37. package/dist/assets/fonts/KaTeX_Math-Italic-DA0__PXp.woff +0 -0
  38. package/dist/assets/fonts/KaTeX_Math-Italic-flOr_0UB.ttf +0 -0
  39. package/dist/assets/fonts/KaTeX_Math-Italic-t53AETM-.woff2 +0 -0
  40. package/dist/assets/fonts/KaTeX_SansSerif-Bold-CFMepnvq.ttf +0 -0
  41. package/dist/assets/fonts/KaTeX_SansSerif-Bold-D1sUS0GD.woff2 +0 -0
  42. package/dist/assets/fonts/KaTeX_SansSerif-Bold-DbIhKOiC.woff +0 -0
  43. package/dist/assets/fonts/KaTeX_SansSerif-Italic-C3H0VqGB.woff2 +0 -0
  44. package/dist/assets/fonts/KaTeX_SansSerif-Italic-DN2j7dab.woff +0 -0
  45. package/dist/assets/fonts/KaTeX_SansSerif-Italic-YYjJ1zSn.ttf +0 -0
  46. package/dist/assets/fonts/KaTeX_SansSerif-Regular-BNo7hRIc.ttf +0 -0
  47. package/dist/assets/fonts/KaTeX_SansSerif-Regular-CS6fqUqJ.woff +0 -0
  48. package/dist/assets/fonts/KaTeX_SansSerif-Regular-DDBCnlJ7.woff2 +0 -0
  49. package/dist/assets/fonts/KaTeX_Script-Regular-C5JkGWo-.ttf +0 -0
  50. package/dist/assets/fonts/KaTeX_Script-Regular-D3wIWfF6.woff2 +0 -0
  51. package/dist/assets/fonts/KaTeX_Script-Regular-D5yQViql.woff +0 -0
  52. package/dist/assets/fonts/KaTeX_Size1-Regular-C195tn64.woff +0 -0
  53. package/dist/assets/fonts/KaTeX_Size1-Regular-Dbsnue_I.ttf +0 -0
  54. package/dist/assets/fonts/KaTeX_Size1-Regular-mCD8mA8B.woff2 +0 -0
  55. package/dist/assets/fonts/KaTeX_Size2-Regular-B7gKUWhC.ttf +0 -0
  56. package/dist/assets/fonts/KaTeX_Size2-Regular-Dy4dx90m.woff2 +0 -0
  57. package/dist/assets/fonts/KaTeX_Size2-Regular-oD1tc_U0.woff +0 -0
  58. package/dist/assets/fonts/KaTeX_Size3-Regular-CTq5MqoE.woff +0 -0
  59. package/dist/assets/fonts/KaTeX_Size3-Regular-DgpXs0kz.ttf +0 -0
  60. package/dist/assets/fonts/KaTeX_Size4-Regular-BF-4gkZK.woff +0 -0
  61. package/dist/assets/fonts/KaTeX_Size4-Regular-DWFBv043.ttf +0 -0
  62. package/dist/assets/fonts/KaTeX_Size4-Regular-Dl5lxZxV.woff2 +0 -0
  63. package/dist/assets/fonts/KaTeX_Typewriter-Regular-C0xS9mPB.woff +0 -0
  64. package/dist/assets/fonts/KaTeX_Typewriter-Regular-CO6r4hn1.woff2 +0 -0
  65. package/dist/assets/fonts/KaTeX_Typewriter-Regular-D3Ib7_Hf.ttf +0 -0
  66. package/dist/assets/index-C-1AiF3k.js +112 -0
  67. package/dist/assets/index-CSGf6Qzd.css +1 -0
  68. package/dist/assets/langs/c-BIGW1oBm.js +2 -0
  69. package/dist/assets/langs/cpp-DIPi6g--.js +2 -0
  70. package/dist/assets/langs/csharp-DSvCPggb.js +2 -0
  71. package/dist/assets/langs/css-CLj8gQPS.js +2 -0
  72. package/dist/assets/langs/go-C27-OAKa.js +2 -0
  73. package/dist/assets/langs/html-CfGypltT.js +2 -0
  74. package/dist/assets/langs/ini-BEwlwnbL.js +2 -0
  75. package/dist/assets/langs/java-CylS5w8V.js +2 -0
  76. package/dist/assets/langs/kotlin-BdnUsdx6.js +2 -0
  77. package/dist/assets/langs/less-B1dDrJ26.js +2 -0
  78. package/dist/assets/langs/lua-BaeVxFsk.js +2 -0
  79. package/dist/assets/langs/markdown-Cvjx9yec.js +2 -0
  80. package/dist/assets/langs/mdx-Cmh6b_Ma.js +2 -0
  81. package/dist/assets/langs/php-D-uCvoST.js +2 -0
  82. package/dist/assets/langs/python-B6aJPvgy.js +2 -0
  83. package/dist/assets/langs/ruby-DEItuUFs.js +2 -0
  84. package/dist/assets/langs/rust-B1yitclQ.js +2 -0
  85. package/dist/assets/langs/scss-D5BDwBP9.js +2 -0
  86. package/dist/assets/langs/sql-CRqJ_cUM.js +2 -0
  87. package/dist/assets/langs/swift-D82vCrfD.js +2 -0
  88. package/dist/assets/langs/toml-vGWfd6FD.js +2 -0
  89. package/dist/assets/langs/xml-sdJ4AIDG.js +2 -0
  90. package/dist/assets/langs/yaml-Buea-lGh.js +2 -0
  91. package/dist/assets/vendor-Cjbwl5VI.js +411 -0
  92. package/dist/assets/vendor-CjyC-hUb.css +1 -0
  93. package/dist/favicon.svg +8 -0
  94. package/dist/index.html +35 -0
  95. package/dist/manifest.webmanifest +16 -0
  96. package/dist/plugins/@deepseek-ai/dsh-api-gateway/client.js +420 -0
  97. package/dist/plugins/@deepseek-ai/dsh-api-remotes/client.js +5937 -0
  98. package/dist/plugins/@deepseek-ai/dsh-client-connection/client.js +10207 -0
  99. package/dist/plugins/@deepseek-ai/dsh-client-locale/client.js +1231 -0
  100. package/dist/plugins/@deepseek-ai/dsh-client-modules/client.js +259 -0
  101. package/dist/plugins/@deepseek-ai/dsh-client-runtime/client.js +10539 -0
  102. package/dist/plugins/@deepseek-ai/dsh-client-ui-agent-preset/client.js +1725 -0
  103. package/dist/plugins/@deepseek-ai/dsh-client-ui-commands/client.js +1116 -0
  104. package/dist/plugins/@deepseek-ai/dsh-client-ui-conversation/client.js +9832 -0
  105. package/dist/plugins/@deepseek-ai/dsh-client-ui-deliverables/client.js +373 -0
  106. package/dist/plugins/@deepseek-ai/dsh-client-ui-edge/client.js +549 -0
  107. package/dist/plugins/@deepseek-ai/dsh-client-ui-input-trigger/client.js +859 -0
  108. package/dist/plugins/@deepseek-ai/dsh-client-ui-jobs/client.js +280 -0
  109. package/dist/plugins/@deepseek-ai/dsh-client-ui-layout/client.js +456 -0
  110. package/dist/plugins/@deepseek-ai/dsh-client-ui-model-selection/client.js +804 -0
  111. package/dist/plugins/@deepseek-ai/dsh-client-ui-permission-presets/client.js +461 -0
  112. package/dist/plugins/@deepseek-ai/dsh-client-ui-settings/client.js +254 -0
  113. package/dist/plugins/@deepseek-ai/dsh-client-ui-settings-general/client.js +609 -0
  114. package/dist/plugins/@deepseek-ai/dsh-client-ui-sidebar/client.js +292 -0
  115. package/dist/plugins/@deepseek-ai/dsh-client-ui-skill/client.js +327 -0
  116. package/dist/plugins/@deepseek-ai/dsh-client-ui-subagent/client.js +710 -0
  117. package/dist/plugins/@deepseek-ai/dsh-client-ui-theme/client.js +1312 -0
  118. package/dist/plugins/@deepseek-ai/dsh-client-ui-tool/client.js +1630 -0
  119. package/dist/plugins/@deepseek-ai/dsh-client-ui-trajectory/client.js +7370 -0
  120. package/dist/plugins/@deepseek-ai/dsh-client-ui-user-questions/client.js +700 -0
  121. package/dist/plugins/@deepseek-ai/dsh-client-ui-workflow-run/client.js +474 -0
  122. package/dist/plugins/@deepseek-ai/dsh-client-ui-workspace/client.js +2426 -0
  123. package/dist/plugins/@deepseek-ai/dsh-typert-registry/client.js +1372 -0
  124. package/package.json +97 -0
  125. package/scripts/assemble-web.mjs +230 -0
  126. package/scripts/bundle-size.d.mts +2 -0
  127. package/scripts/bundle-size.mjs +26 -0
  128. package/scripts/bundle.mjs +53 -0
  129. package/scripts/cli.d.mts +39 -0
  130. package/scripts/cli.mjs +496 -0
  131. package/scripts/install.d.mts +149 -0
  132. package/scripts/install.mjs +989 -0
  133. package/scripts/legal-files.mjs +24 -0
  134. package/scripts/verify-packed.mjs +32 -0
  135. package/scripts/wrangler-config.d.mts +18 -0
  136. package/scripts/wrangler-config.mjs +84 -0
  137. package/src/agent.ts +119 -0
  138. package/src/auth.ts +352 -0
  139. package/src/deepseek.ts +231 -0
  140. package/src/deployment.ts +147 -0
  141. package/src/direct-shell-core-empty.ts +10 -0
  142. package/src/direct-shell-protocol.ts +5 -0
  143. package/src/direct-shell.ts +341 -0
  144. package/src/do-session-persistence.ts +1064 -0
  145. package/src/edge-api.ts +796 -0
  146. package/src/edge-credentials.ts +56 -0
  147. package/src/edge-remotes.ts +41 -0
  148. package/src/edge-workspace-store.ts +339 -0
  149. package/src/http.ts +212 -0
  150. package/src/index.ts +196 -0
  151. package/src/instance.ts +1007 -0
  152. package/src/isolated-direct-shell-unavailable.ts +11 -0
  153. package/src/protocol.ts +39 -0
  154. package/src/release.ts +9 -0
  155. package/src/session-store.ts +1110 -0
  156. package/src/sse.ts +86 -0
  157. package/src/web-search.ts +38 -0
  158. package/src/workspace.ts +270 -0
  159. package/wrangler.jsonc +56 -0
package/src/index.ts ADDED
@@ -0,0 +1,196 @@
1
+ import { getWorkspace } from '@cloudflare/computer'
2
+ import type { EdgeShellResult } from './agent.ts'
3
+ import {
4
+ handleOwnerAuthRoute,
5
+ loginRedirect,
6
+ OWNER_SESSION_EXPIRY_HEADER,
7
+ resolveOwnerAuthConfig,
8
+ resolveOwnerSession,
9
+ unauthorizedResponse,
10
+ } from './auth.ts'
11
+ import {
12
+ EdgeHttpError,
13
+ MAX_SESSION_CREATE_BODY_BYTES,
14
+ MAX_TURN_BODY_BYTES,
15
+ MAX_WORKSPACE_EXEC_BODY_BYTES,
16
+ corsHeaders,
17
+ discardUnreadRequestBody,
18
+ errorResponse,
19
+ jsonResponse,
20
+ readBoundedBody,
21
+ readBoundedText,
22
+ readJsonObject,
23
+ } from './http.ts'
24
+ import type { EdgeEnv } from './instance.ts'
25
+ import { resolveEdgeDeploymentHealth } from './deployment.ts'
26
+ import {
27
+ executeWorkspaceCommand,
28
+ MAX_TEXT_FILE_BYTES,
29
+ readBoundedWorkspaceFile,
30
+ requireCommand,
31
+ requireWorkspacePath,
32
+ resolveEdgeCommandTimeoutPolicy,
33
+ } from './workspace.ts'
34
+
35
+ // The optional isolated shell reaches the owning Durable Object through these entrypoints.
36
+ export { WorkspaceProxy, WorkspaceServiceProxy } from '@cloudflare/computer'
37
+ export { DshEdgeInstance } from './instance.ts'
38
+
39
+ type Env = EdgeEnv
40
+
41
+ const OWNER_INSTANCE = 'owner'
42
+
43
+ export default {
44
+ async fetch(request, env): Promise<Response> {
45
+ if (request.method === 'OPTIONS') {
46
+ return new Response(null, {
47
+ status: 204,
48
+ headers: corsHeaders(),
49
+ })
50
+ }
51
+
52
+ try {
53
+ const url = new URL(request.url)
54
+ const auth = resolveOwnerAuthConfig(env.DSH_EDGE_ACCESS_KEY)
55
+ if (request.method === 'GET' && url.pathname === '/api/health') {
56
+ return jsonResponse(resolveEdgeDeploymentHealth(env))
57
+ }
58
+
59
+ const authResponse = await handleOwnerAuthRoute(request, auth)
60
+ if (authResponse !== undefined) return authResponse
61
+
62
+ const ownerSession = await resolveOwnerSession(request, auth)
63
+ if (url.pathname === '/') {
64
+ if (ownerSession === undefined) return loginRedirect()
65
+ return await env.ASSETS.fetch(request)
66
+ }
67
+ if (ownerSession === undefined) return unauthorizedResponse()
68
+
69
+ rejectCrossOriginAuthenticatedRequest(request, url)
70
+ rejectLegacyInstanceSelector(request, url)
71
+ const instanceStub = env.DSH_EDGE_INSTANCE.getByName(OWNER_INSTANCE)
72
+ if (isInstanceApiPath(url.pathname)) {
73
+ const response = await instanceStub.fetch(
74
+ await requestForInstance(request, ownerSession.expiresAt),
75
+ )
76
+ if (response.webSocket !== null) return response
77
+ const headers = new Headers(response.headers)
78
+ for (const [name, value] of Object.entries(corsHeaders())) headers.set(name, value)
79
+ return new Response(response.body, {
80
+ status: response.status,
81
+ statusText: response.statusText,
82
+ headers,
83
+ })
84
+ }
85
+ using workspace = await getWorkspace(
86
+ instanceStub as unknown as Parameters<typeof getWorkspace>[0],
87
+ )
88
+
89
+ if (url.pathname === '/api/workspace/file') {
90
+ const path = resolveWorkspacePath(url)
91
+ if (request.method === 'GET') {
92
+ const contents = await readBoundedWorkspaceFile(workspace.fs, path)
93
+ return new Response(contents, {
94
+ headers: {
95
+ ...corsHeaders(),
96
+ 'content-type': 'text/plain; charset=utf-8',
97
+ },
98
+ })
99
+ }
100
+ if (request.method === 'PUT') {
101
+ const contents = await readBoundedText(
102
+ request,
103
+ MAX_TEXT_FILE_BYTES,
104
+ 'Text files are limited to 1 MiB in the prototype API.',
105
+ )
106
+ await workspace.fs.mkdir(parentDirectory(path), { recursive: true })
107
+ await workspace.fs.writeFile(path, contents)
108
+ return jsonResponse({ ok: true, path })
109
+ }
110
+ if (request.method === 'DELETE') {
111
+ await workspace.fs.rm(path, { recursive: false })
112
+ return jsonResponse({ ok: true, path })
113
+ }
114
+ }
115
+
116
+ if (request.method === 'POST' && url.pathname === '/api/workspace/exec') {
117
+ const body = await readJsonObject(request, MAX_WORKSPACE_EXEC_BODY_BYTES)
118
+ const command = requireCommand(body.command)
119
+ const cwd = requireWorkspacePath(body.cwd ?? '/workspace')
120
+ const timeoutPolicy = resolveEdgeCommandTimeoutPolicy(
121
+ env.DSH_EDGE_DEFAULT_COMMAND_TIMEOUT_MS,
122
+ env.DSH_EDGE_MAX_COMMAND_TIMEOUT_MS,
123
+ )
124
+ const result = await executeWorkspaceCommand(workspace, command, cwd, timeoutPolicy)
125
+ return jsonResponse({
126
+ executionId: result.executionId,
127
+ status: result.status,
128
+ timedOut: result.timedOut,
129
+ exitCode: result.exitCode,
130
+ stdout: result.stdout,
131
+ stderr: result.stderr,
132
+ outputTruncated: result.outputTruncated,
133
+ } satisfies EdgeShellResult)
134
+ }
135
+
136
+ throw new EdgeHttpError(404, 'Route not found.')
137
+ } catch (error) {
138
+ await discardUnreadRequestBody(request)
139
+ return errorResponse(error)
140
+ }
141
+ },
142
+ } satisfies ExportedHandler<Env>
143
+
144
+ function rejectLegacyInstanceSelector(request: Request, url: URL): void {
145
+ if (request.headers.has('x-dsh-edge-instance') || url.searchParams.has('instance')) {
146
+ throw new EdgeHttpError(400, 'This deployment has one owner workspace; instance selectors are not supported.')
147
+ }
148
+ }
149
+
150
+ function rejectCrossOriginAuthenticatedRequest(request: Request, url: URL): void {
151
+ const origin = request.headers.get('origin')
152
+ if (origin !== null && origin !== url.origin) {
153
+ throw new EdgeHttpError(403, 'Cross-origin authenticated requests are not allowed.')
154
+ }
155
+ }
156
+
157
+ function resolveWorkspacePath(url: URL): string {
158
+ return requireWorkspacePath(url.searchParams.get('path'))
159
+ }
160
+
161
+ async function requestForInstance(request: Request, ownerSessionExpiresAt: number): Promise<Request> {
162
+ const headers = new Headers(request.headers)
163
+ headers.delete('cookie')
164
+ headers.delete('authorization')
165
+ headers.delete('x-dsh-edge-instance')
166
+ headers.set(OWNER_SESSION_EXPIRY_HEADER, String(ownerSessionExpiresAt))
167
+ if (request.body === null) return new Request(request, { headers })
168
+ const url = new URL(request.url)
169
+ const maxBytes = url.pathname.endsWith('/turn')
170
+ || url.pathname === '/api/session.prompt'
171
+ || url.pathname === '/api/session.updateQueue'
172
+ ? MAX_TURN_BODY_BYTES
173
+ : MAX_SESSION_CREATE_BODY_BYTES
174
+ const body = await readBoundedBody(
175
+ request,
176
+ maxBytes,
177
+ `Session request bodies are limited to ${maxBytes} bytes.`,
178
+ )
179
+ return new Request(request.url, {
180
+ method: request.method,
181
+ headers,
182
+ body,
183
+ })
184
+ }
185
+
186
+ function isInstanceApiPath(pathname: string): boolean {
187
+ return pathname.startsWith('/api/')
188
+ && pathname !== '/api/health'
189
+ && pathname !== '/api/workspace/file'
190
+ && pathname !== '/api/workspace/exec'
191
+ }
192
+
193
+ function parentDirectory(path: string): string {
194
+ const separator = path.lastIndexOf('/')
195
+ return separator <= 0 ? '/' : path.slice(0, separator)
196
+ }