nolo-cli 0.1.13 → 0.1.14

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 (320) hide show
  1. package/README.md +9 -2
  2. package/agent-runtime/hostAdapter.ts +53 -0
  3. package/agent-runtime/index.ts +28 -0
  4. package/agent-runtime/localLoop.ts +62 -0
  5. package/agent-runtime/runtimeDecision.ts +70 -0
  6. package/agent-runtime/types.ts +87 -0
  7. package/agentRuntimeCommands.ts +139 -22
  8. package/agentRuntimeLocal.ts +7 -0
  9. package/ai/agent/_executeModel.ts +118 -0
  10. package/ai/agent/agentSlice.ts +544 -1
  11. package/ai/agent/appWorkingMemory.ts +126 -0
  12. package/ai/agent/avatarUtils.ts +24 -0
  13. package/ai/agent/buildEditingContext.ts +373 -0
  14. package/ai/agent/buildSystemPrompt.ts +532 -0
  15. package/ai/agent/cleanAgentMessages.ts +140 -0
  16. package/ai/agent/cliChatClient.ts +119 -0
  17. package/ai/agent/contextCompiler.ts +107 -0
  18. package/ai/agent/contextLayerContract.ts +44 -0
  19. package/ai/agent/createAgentSchema.ts +234 -0
  20. package/ai/agent/executeToolCall.ts +58 -0
  21. package/ai/agent/fetchAgentContexts.ts +42 -0
  22. package/ai/agent/generatePrompt.ts +3 -0
  23. package/ai/agent/getFullChatContextKeys.ts +168 -0
  24. package/ai/agent/hooks/fetchPublicAgents.ts +133 -0
  25. package/ai/agent/hooks/useAgentConfig.ts +61 -0
  26. package/ai/agent/hooks/useAgentDialog.ts +35 -0
  27. package/ai/agent/hooks/useAgentFormValidation.ts +202 -0
  28. package/ai/agent/hooks/usePublicAgents.ts +473 -0
  29. package/ai/agent/persistMessageWithFixedId.ts +37 -0
  30. package/ai/agent/planSlice.ts +259 -0
  31. package/ai/agent/referenceUtils.ts +229 -0
  32. package/ai/agent/runAgentBackground.ts +238 -0
  33. package/ai/agent/runAgentClientLoop.ts +138 -0
  34. package/ai/agent/runtimeGuidance.ts +97 -0
  35. package/ai/agent/runtimeServerBase.ts +37 -0
  36. package/ai/agent/server/fetchPublicAgents.ts +128 -0
  37. package/ai/agent/startParallelAgentStreams.ts +424 -0
  38. package/ai/agent/startupProtocol.ts +53 -0
  39. package/ai/agent/streamAgentChatTurn.ts +1299 -0
  40. package/ai/agent/streamAgentChatTurnUtils.ts +738 -0
  41. package/ai/agent/types.ts +71 -0
  42. package/ai/agent/utils/imageOutput.ts +39 -0
  43. package/ai/agent/utils/publicImageAgentMode.ts +26 -0
  44. package/ai/agent/utils/sortUtils.ts +250 -0
  45. package/ai/agent/web/referencePickerUtils.ts +146 -0
  46. package/ai/ai.locale.ts +1083 -0
  47. package/ai/chat/accumulateToolCallChunks.ts +95 -0
  48. package/ai/chat/fetchUtils.native.ts +276 -0
  49. package/ai/chat/fetchUtils.ts +153 -0
  50. package/ai/chat/inlineImageUrlsForCustomProvider.ts +117 -0
  51. package/ai/chat/parseApiError.ts +64 -0
  52. package/ai/chat/parseMultilineSSE.ts +95 -0
  53. package/ai/chat/sendOpenAICompletionsRequest.native.ts +682 -0
  54. package/ai/chat/sendOpenAICompletionsRequest.ts +712 -0
  55. package/ai/chat/sendOpenAIResponseRequest.ts +512 -0
  56. package/ai/chat/shouldUseServerProxy.ts +18 -0
  57. package/ai/chat/sseClient.native.ts +91 -0
  58. package/ai/chat/sseClient.ts +67 -0
  59. package/ai/chat/streamReader.native.ts +31 -0
  60. package/ai/chat/streamReader.ts +62 -0
  61. package/ai/chat/updateTotalUsage.ts +72 -0
  62. package/ai/context/buildReferenceContext.ts +437 -0
  63. package/ai/context/calculateContextUsage.ts +133 -0
  64. package/ai/context/retention.ts +165 -0
  65. package/ai/context/tokenUtils.ts +78 -0
  66. package/ai/index.ts +1 -1
  67. package/ai/llm/agentCapabilities.ts +74 -0
  68. package/ai/llm/calculateGeminiImageTokens.ts +57 -0
  69. package/ai/llm/deepinfra.ts +28 -0
  70. package/ai/llm/fireworks.ts +68 -0
  71. package/ai/llm/generateRequestBody.ts +165 -0
  72. package/ai/llm/getModelContextWindow.ts +84 -0
  73. package/ai/llm/getNoloKey.ts +37 -0
  74. package/ai/llm/getPricing.ts +232 -0
  75. package/ai/llm/hooks/useModelPricing.ts +75 -0
  76. package/ai/llm/imagePricing.ts +66 -0
  77. package/ai/llm/isResponseAPIModel.ts +13 -0
  78. package/ai/llm/kimi.ts +18 -0
  79. package/ai/llm/mimo.ts +71 -0
  80. package/ai/llm/mistral.ts +22 -0
  81. package/ai/llm/modelAvatar.ts +427 -0
  82. package/ai/llm/models.ts +45 -0
  83. package/ai/llm/openrouterModels.ts +141 -0
  84. package/ai/llm/providers.ts +307 -0
  85. package/ai/llm/reasoningModels.ts +28 -0
  86. package/ai/llm/types.ts +59 -0
  87. package/ai/llm/usageRequestOptions.ts +59 -0
  88. package/ai/memory/capture.ts +148 -0
  89. package/ai/memory/consolidate.ts +104 -0
  90. package/ai/memory/delete.ts +147 -0
  91. package/ai/memory/overlay.ts +84 -0
  92. package/ai/memory/query.ts +38 -0
  93. package/ai/memory/queryShared.ts +160 -0
  94. package/ai/memory/rank.ts +105 -0
  95. package/ai/memory/recentRelationshipRecap.ts +247 -0
  96. package/ai/memory/remember.ts +167 -0
  97. package/ai/memory/runtime.ts +76 -0
  98. package/ai/memory/store.ts +20 -0
  99. package/ai/memory/storeShared.ts +76 -0
  100. package/ai/memory/types.ts +46 -0
  101. package/ai/memory/understanding.ts +349 -0
  102. package/ai/memory/understandingGreeting.ts +264 -0
  103. package/ai/messages/type.ts +20 -0
  104. package/ai/policy/personalizationDialog.ts +333 -0
  105. package/ai/policy/runtimePolicy.ts +440 -0
  106. package/ai/policy/selfUpdateFields.ts +48 -0
  107. package/ai/policy/types.ts +64 -0
  108. package/ai/skills/referenceRuntime.ts +274 -0
  109. package/ai/skills/skillDiagnostics.ts +251 -0
  110. package/ai/skills/skillDocBuilder.ts +139 -0
  111. package/ai/skills/skillDocProtocol.ts +434 -0
  112. package/ai/skills/skillReferenceSummary.ts +63 -0
  113. package/ai/skills/skillSummaryMarker.ts +26 -0
  114. package/ai/token/calculatePrice.ts +546 -0
  115. package/ai/token/db.ts +98 -0
  116. package/ai/token/externalToolCost.ts +321 -0
  117. package/ai/token/hooks/useRecords.ts +65 -0
  118. package/ai/token/missingUsageEstimate.ts +42 -0
  119. package/ai/token/modelUsageQuery.ts +252 -0
  120. package/ai/token/normalizeUsage.ts +84 -0
  121. package/ai/token/openaiImageGenerationUsage.ts +56 -0
  122. package/ai/token/prepareTokenUsageData.ts +88 -0
  123. package/ai/token/query.ts +88 -0
  124. package/ai/token/queryUserTokens.ts +59 -0
  125. package/ai/token/resolveBillingTarget.ts +52 -0
  126. package/ai/token/saveTokenRecord.ts +53 -0
  127. package/ai/token/serverDialogProjection.ts +78 -0
  128. package/ai/token/serverTokenWriter.ts +143 -0
  129. package/ai/token/stats.ts +21 -0
  130. package/ai/token/tokenThunks.ts +24 -0
  131. package/ai/token/types.ts +93 -0
  132. package/ai/tools/agent/agentTools.ts +176 -0
  133. package/ai/tools/agent/agentUpdateShared.ts +311 -0
  134. package/ai/tools/agent/callAgentTool.ts +139 -0
  135. package/ai/tools/agent/createAgentTool.ts +512 -0
  136. package/ai/tools/agent/createDialogTool.ts +69 -0
  137. package/ai/tools/agent/createSkillAgentTool.ts +62 -0
  138. package/ai/tools/agent/parallelBudget.ts +221 -0
  139. package/ai/tools/agent/presets/appBuilderPreset.ts +147 -0
  140. package/ai/tools/agent/runLlmTool.ts +96 -0
  141. package/ai/tools/agent/runStreamingAgentTool.ts +73 -0
  142. package/ai/tools/agent/skillAgentArgs.ts +106 -0
  143. package/ai/tools/agent/skillAgentPreset.ts +89 -0
  144. package/ai/tools/agent/streamParallelAgentsTool.ts +122 -0
  145. package/ai/tools/agent/updateAgentTool.ts +96 -0
  146. package/ai/tools/agent/updateSelfTool.ts +113 -0
  147. package/ai/tools/amazonProductScraperTool.ts +86 -0
  148. package/ai/tools/apifyActorClient.ts +45 -0
  149. package/ai/tools/appEditGuard.ts +372 -0
  150. package/ai/tools/appReadSnapshot.ts +153 -0
  151. package/ai/tools/appTools.ts +1549 -0
  152. package/ai/tools/applyEditTool.ts +256 -0
  153. package/ai/tools/applyLineEditsTool.ts +312 -0
  154. package/ai/tools/browserTools/click.ts +33 -0
  155. package/ai/tools/browserTools/closeSession.ts +29 -0
  156. package/ai/tools/browserTools/common.ts +27 -0
  157. package/ai/tools/browserTools/openSession.ts +48 -0
  158. package/ai/tools/browserTools/readContent.ts +38 -0
  159. package/ai/tools/browserTools/selectOption.ts +46 -0
  160. package/ai/tools/browserTools/typeText.ts +42 -0
  161. package/ai/tools/category/createCategoryTool.ts +66 -0
  162. package/ai/tools/category/queryContentsByCategoryTool.ts +69 -0
  163. package/ai/tools/category/updateContentCategoryTool.ts +75 -0
  164. package/ai/tools/cfBrowserTools.ts +319 -0
  165. package/ai/tools/cfSpeechToTextTool.ts +49 -0
  166. package/ai/tools/checkEnvTool.ts +65 -0
  167. package/ai/tools/cloudflareCrawlTool.ts +289 -0
  168. package/ai/tools/codeSearchTool.ts +111 -0
  169. package/ai/tools/codeTools.ts +101 -0
  170. package/ai/tools/createDocTool.ts +132 -0
  171. package/ai/tools/createPlanTool.ts +999 -0
  172. package/ai/tools/createSkillDocTool.ts +155 -0
  173. package/ai/tools/createWorkflowTool.ts +154 -0
  174. package/ai/tools/deepseekOcrTool.ts +34 -0
  175. package/ai/tools/delayTool.ts +31 -0
  176. package/ai/tools/deleteSpacesTool.ts +325 -0
  177. package/ai/tools/deleteSpacesToolModel.ts +159 -0
  178. package/ai/tools/devReloadUtils.ts +29 -0
  179. package/ai/tools/dialogMessageSearch.ts +137 -0
  180. package/ai/tools/doctorSkillTool.ts +72 -0
  181. package/ai/tools/ecommerceScraperTool.ts +86 -0
  182. package/ai/tools/emailTools.ts +549 -0
  183. package/ai/tools/evalSkillTool.ts +92 -0
  184. package/ai/tools/exaSearchTool.ts +64 -0
  185. package/ai/tools/execBashTool.ts +379 -0
  186. package/ai/tools/executeSqlTool.ts +192 -0
  187. package/ai/tools/fetchWebpageSupport.ts +309 -0
  188. package/ai/tools/fetchWebpageTool.ts +84 -0
  189. package/ai/tools/geminiImagePreviewTool.ts +361 -0
  190. package/ai/tools/generateDocxTool.ts +215 -0
  191. package/ai/tools/googleSearchScraperTool.ts +106 -0
  192. package/ai/tools/importDataTool.ts +133 -0
  193. package/ai/tools/importSkillTool.ts +162 -0
  194. package/ai/tools/index.ts +1927 -0
  195. package/ai/tools/listFilesTool.ts +82 -0
  196. package/ai/tools/listUserSpacesTool.ts +113 -0
  197. package/ai/tools/modelUsageTools.ts +199 -0
  198. package/ai/tools/olmOcrTool.ts +34 -0
  199. package/ai/tools/openaiImageTool.ts +267 -0
  200. package/ai/tools/prepareTools.ts +23 -0
  201. package/ai/tools/readDocTool.ts +84 -0
  202. package/ai/tools/readFileTool.ts +211 -0
  203. package/ai/tools/readTool.ts +163 -0
  204. package/ai/tools/readXPostTool.ts +233 -0
  205. package/ai/tools/rememberMemoryTool.ts +84 -0
  206. package/ai/tools/remotionVideoTool.ts +151 -0
  207. package/ai/tools/searchDialogMessagesTool.ts +222 -0
  208. package/ai/tools/searchRepoTool.ts +115 -0
  209. package/ai/tools/searchWorkspaceTool.ts +259 -0
  210. package/ai/tools/skillFollowup.ts +86 -0
  211. package/ai/tools/surfWeatherTool.ts +169 -0
  212. package/ai/tools/table/addTableRowTool.ts +217 -0
  213. package/ai/tools/table/createTableTool.ts +315 -0
  214. package/ai/tools/table/rowTools.ts +366 -0
  215. package/ai/tools/table/schemaTools.ts +244 -0
  216. package/ai/tools/table/shareTableTool.ts +148 -0
  217. package/ai/tools/table/toolShared.ts +129 -0
  218. package/ai/tools/toolApiClient.ts +198 -0
  219. package/ai/tools/toolNameAliases.ts +57 -0
  220. package/ai/tools/toolResultError.ts +42 -0
  221. package/ai/tools/toolRunSlice.ts +303 -0
  222. package/ai/tools/toolSchemaCompatibility.ts +53 -0
  223. package/ai/tools/toolVisibility.ts +4 -0
  224. package/ai/tools/types.ts +20 -0
  225. package/ai/tools/uiAskChoiceTool.ts +104 -0
  226. package/ai/tools/updateContentTitleTool.ts +84 -0
  227. package/ai/tools/updateDocTool.ts +105 -0
  228. package/ai/tools/updateUserPreferenceProfileTool.ts +145 -0
  229. package/ai/tools/whisperTool.ts +77 -0
  230. package/ai/tools/writeFileTool.ts +210 -0
  231. package/ai/tools/youtubeScraperTool.ts +116 -0
  232. package/ai/tools/ziweiChartTool.ts +678 -0
  233. package/ai/types.ts +55 -0
  234. package/ai/workflow/workflowExecutor.ts +323 -0
  235. package/ai/workflow/workflowSlice.ts +73 -0
  236. package/ai/workflow/workflowTypes.ts +106 -0
  237. package/client/agentRun.test.ts +240 -0
  238. package/client/agentRun.ts +182 -19
  239. package/client/compactDialog.test.ts +238 -0
  240. package/client/localRuntimeAdapter.test.ts +135 -0
  241. package/client/localRuntimeAdapter.ts +244 -0
  242. package/client/profileConfig.test.ts +40 -0
  243. package/client/streamingOutput.test.ts +22 -0
  244. package/client/streamingOutput.ts +38 -0
  245. package/commandRegistry.ts +9 -2
  246. package/connector-experimental/index.ts +5 -0
  247. package/database/actions/cacheMergedUserData.ts +64 -0
  248. package/database/actions/common.ts +242 -0
  249. package/database/actions/deleteFile.ts +40 -0
  250. package/database/actions/fetchUserData.ts +16 -0
  251. package/database/actions/fileContent.ts +125 -0
  252. package/database/actions/patch.ts +155 -0
  253. package/database/actions/read.ts +337 -0
  254. package/database/actions/readAndWait.ts +224 -0
  255. package/database/actions/readRequestManager.ts +120 -0
  256. package/database/actions/remove.ts +94 -0
  257. package/database/actions/replication.ts +366 -0
  258. package/database/actions/upload.ts +174 -0
  259. package/database/actions/upsert.ts +56 -0
  260. package/database/actions/write.ts +126 -0
  261. package/database/client/db.native.ts +73 -0
  262. package/database/client/db.ts +51 -0
  263. package/database/client/fetchUserData.ts +61 -0
  264. package/database/client/handleError.ts +19 -0
  265. package/database/client/queryRequest.ts +21 -0
  266. package/database/config.ts +21 -0
  267. package/database/dbActionThunks.ts +1 -0
  268. package/database/dbSlice.ts +149 -0
  269. package/database/email.ts +42 -0
  270. package/database/fileRing.ts +51 -0
  271. package/database/fileSharding.ts +70 -0
  272. package/database/fileStorage.native.ts +92 -0
  273. package/database/fileStorage.ts +232 -0
  274. package/database/fileUrl.ts +34 -0
  275. package/database/hooks/useUserData.ts +489 -0
  276. package/database/index.ts +1 -0
  277. package/database/keys.ts +765 -0
  278. package/database/queryPrefixes.ts +14 -0
  279. package/database/requests.ts +443 -0
  280. package/database/runtimeServerContext.ts +35 -0
  281. package/database/server/MemoryDB.ts +76 -0
  282. package/database/server/actorAccess.ts +76 -0
  283. package/database/server/agentDelegation.ts +124 -0
  284. package/database/server/coreDataOwnership.ts +13 -0
  285. package/database/server/coreDataProxy.ts +76 -0
  286. package/database/server/cybotReadonly.ts +18 -0
  287. package/database/server/dataHandlers.ts +111 -0
  288. package/database/server/db.ts +118 -0
  289. package/database/server/dbPath.ts +20 -0
  290. package/database/server/delete.ts +499 -0
  291. package/database/server/emailRepository.ts +1480 -0
  292. package/database/server/ensureDbOpen.ts +12 -0
  293. package/database/server/fileRead.ts +337 -0
  294. package/database/server/fileService.ts +436 -0
  295. package/database/server/handleTransaction.ts +86 -0
  296. package/database/server/patch.ts +282 -0
  297. package/database/server/query.ts +138 -0
  298. package/database/server/read.ts +325 -0
  299. package/database/server/resourceAccess.ts +211 -0
  300. package/database/server/routes.ts +110 -0
  301. package/database/server/spaceMemberAuthority.ts +67 -0
  302. package/database/server/upload.ts +159 -0
  303. package/database/server/write.ts +494 -0
  304. package/database/server/writeAuthority.ts +133 -0
  305. package/database/sqliteDb.ts +46 -0
  306. package/database/table/deleteTable.ts +120 -0
  307. package/database/tenantPlacement.ts +57 -0
  308. package/database/tombstones.ts +52 -0
  309. package/database/userDataLoadDecision.ts +17 -0
  310. package/database/userDataMerge.ts +95 -0
  311. package/database/userPreferenceRegister.ts +108 -0
  312. package/database/utils/dbPath.ts +47 -0
  313. package/database/utils/ulid.native.ts +6 -0
  314. package/database/utils/ulid.ts +1 -0
  315. package/index.ts +25 -15
  316. package/localRuntimeDb.ts +28 -0
  317. package/package.json +16 -4
  318. package/runtimeModeArgs.ts +33 -0
  319. package/tui/readlineWorkspace.ts +1 -0
  320. package/tui/session.ts +22 -0
@@ -0,0 +1,499 @@
1
+ // 文件: database/server/delete.ts
2
+
3
+ import serverDb from "./db";
4
+ import { DataType } from "create/types";
5
+ import { deleteMessages } from "chat/messages/deleteMessages";
6
+ import { deleteTable } from "database/table/deleteTable";
7
+ import { isSystemAdmin, nolotusId } from "core/init";
8
+ import { authenticateRequest } from "auth/utils";
9
+ import { invalidatePublicAgentsCache } from "ai/agent/server/fetchPublicAgents";
10
+ import {
11
+ createFavoriteKey,
12
+ createFavoriteStatsKey,
13
+ isAgentKey,
14
+ shareKey,
15
+ } from "database/keys";
16
+ import { buildTombstoneRecord, isTombstoneRecord } from "database/tombstones";
17
+ import { canDeleteSpaceMemberRecord, parseSpaceMemberKey } from "./spaceMemberAuthority";
18
+ import {
19
+ bootstrapReplicatedTable,
20
+ findActiveLiveShareByTable,
21
+ isLiveTableShareRecord,
22
+ patchShareMeta,
23
+ replicateSharedTableMutation,
24
+ } from "../../share/server/tableReplication";
25
+
26
+ type DeleteRequest = Request & {
27
+ // 视你的路由库而定,这里假定有 params.id
28
+ params: {
29
+ id: string;
30
+ };
31
+ };
32
+
33
+ const CORS_HEADERS: Record<string, string> = {
34
+ "Access-Control-Allow-Origin": "*",
35
+ "Content-Type": "application/json",
36
+ };
37
+
38
+ const normalizeOrigin = (value: unknown): string =>
39
+ typeof value === "string" && value.trim().length > 0
40
+ ? value.trim().replace(/\/+$/, "")
41
+ : "";
42
+
43
+ const getRequestOrigin = (req: Request): string => {
44
+ try {
45
+ return normalizeOrigin(new URL(req.url).origin);
46
+ } catch {
47
+ return "";
48
+ }
49
+ };
50
+
51
+ const getForwardHeaders = (req: any): Record<string, string> => {
52
+ const headers: Record<string, string> = {
53
+ "Content-Type": "application/json",
54
+ };
55
+ const authHeader =
56
+ typeof req?.headers?.authorization === "string"
57
+ ? req.headers.authorization
58
+ : typeof req?.headers?.Authorization === "string"
59
+ ? req.headers.Authorization
60
+ : "";
61
+ if (authHeader) {
62
+ headers.Authorization = authHeader;
63
+ }
64
+ return headers;
65
+ };
66
+
67
+ const findLiveTableSharesByDbKey = async (tableDbKey: string) => {
68
+ const shares: any[] = [];
69
+ for await (const [dbKey, value] of serverDb.iterator({
70
+ gte: "share-",
71
+ lte: "share-\uffff",
72
+ })) {
73
+ if (
74
+ isLiveTableShareRecord(value, tableDbKey)
75
+ ) {
76
+ shares.push({
77
+ ...value,
78
+ dbKey,
79
+ });
80
+ }
81
+ }
82
+ return shares;
83
+ };
84
+
85
+ const propagateTableDeleteToReplicas = async (req: DeleteRequest, tableDbKey: string) => {
86
+ const currentOrigin = getRequestOrigin(req);
87
+ const shares = await findLiveTableSharesByDbKey(tableDbKey);
88
+ const forwardHeaders = getForwardHeaders(req);
89
+
90
+ for (const share of shares) {
91
+ const shareOrigin = normalizeOrigin(
92
+ share?.meta?.originServer ?? share?.data?.originServer
93
+ );
94
+ if (shareOrigin && shareOrigin !== currentOrigin) continue;
95
+
96
+ const replicaServers = Array.isArray(share?.meta?.replicaServers)
97
+ ? share.meta.replicaServers
98
+ : [];
99
+ for (const server of replicaServers) {
100
+ const normalizedServer = normalizeOrigin(server);
101
+ if (!normalizedServer || normalizedServer === currentOrigin) continue;
102
+ const response = await fetch(
103
+ `${normalizedServer}/api/v1/db/delete/${encodeURIComponent(tableDbKey)}?type=table`,
104
+ {
105
+ method: "DELETE",
106
+ headers: forwardHeaders,
107
+ }
108
+ );
109
+ if (!response.ok) {
110
+ const detail = await response.text();
111
+ throw new Error(
112
+ detail || `Replica table delete failed on ${normalizedServer}: HTTP ${response.status}`
113
+ );
114
+ }
115
+ }
116
+ }
117
+ };
118
+
119
+ /**
120
+ * 判断当前请求用户是否是「系统账号」并且在操作公共 cybot 资源。
121
+ *
122
+ * 约定:
123
+ * - 公共 cybot 资源 key 形如:cybot-pub-{cybotId}
124
+ * - 系统账号 id 为 nolotusId(来自 core/init)
125
+ */
126
+ const canSystemUserDeletePublicCybot = (
127
+ dbKey: string,
128
+ actionUserId?: string
129
+ ): boolean => {
130
+ const PUBLIC_CYBOT_KEY_PREFIX = "cybot-pub-";
131
+
132
+ const isPublicCybotKey = dbKey.startsWith(PUBLIC_CYBOT_KEY_PREFIX);
133
+ const isSystemUser = actionUserId === nolotusId;
134
+
135
+ return isPublicCybotKey && isSystemUser;
136
+ };
137
+
138
+ const canSystemAdminDeleteCommunityShare = (
139
+ dbKey: string,
140
+ actionUserId: string | undefined,
141
+ data: any
142
+ ): boolean => {
143
+ if (!isSystemAdmin(actionUserId)) return false;
144
+ if (!shareKey.isShareKey(dbKey)) return false;
145
+ return data?.meta?.visibility === "community";
146
+ };
147
+
148
+ export const handleDelete = async (req: DeleteRequest) => {
149
+ try {
150
+ const authResult = await authenticateRequest(req);
151
+ const actionUserId = authResult instanceof Response ? undefined : authResult.userId;
152
+
153
+ const { id } = req.params;
154
+ const url = new URL(req.url);
155
+ const type = url.searchParams.get("type");
156
+
157
+ // 1. 删除消息的专用分支
158
+ if (type === "messages") {
159
+ try {
160
+ const result = await deleteMessages(serverDb, id);
161
+ return new Response(JSON.stringify(result), {
162
+ status: 200,
163
+ headers: CORS_HEADERS,
164
+ });
165
+ } catch (err: any) {
166
+ if (err.notFound) {
167
+ return new Response(JSON.stringify({ message: "Messages already deleted or dialog not found", processingIds: [] }), {
168
+ status: 200,
169
+ headers: CORS_HEADERS,
170
+ });
171
+ }
172
+ throw err;
173
+ }
174
+ }
175
+
176
+ // 1.5 删除整张表(meta + 所有行 + 所有索引)的专用分支
177
+ if (type === "table") {
178
+ // 先拿 meta 数据做权限校验
179
+ let meta;
180
+ try {
181
+ meta = await serverDb.get(id);
182
+ } catch (err: any) {
183
+ if (err.notFound) {
184
+ return new Response(JSON.stringify({ message: "Table already deleted", processingIds: [] }), {
185
+ status: 200,
186
+ headers: CORS_HEADERS,
187
+ });
188
+ }
189
+ throw err;
190
+ }
191
+
192
+ const ownerId = meta?.userId as string | undefined;
193
+ const ownerMissing = ownerId == null;
194
+ const isOwner = actionUserId != null && ownerId === actionUserId;
195
+
196
+ // 表删除只按 owner 规则来判断
197
+ if (!ownerMissing && !isOwner) {
198
+ return new Response(
199
+ JSON.stringify({
200
+ error: "Unauthorized action: You do not own this table",
201
+ ownerId,
202
+ actionUserId,
203
+ processingIds: [],
204
+ }),
205
+ {
206
+ status: 403,
207
+ headers: CORS_HEADERS,
208
+ }
209
+ );
210
+ }
211
+
212
+ await propagateTableDeleteToReplicas(req, id);
213
+
214
+ // 真正执行整表删除
215
+ const { processingIds } = await deleteTable(serverDb, id);
216
+
217
+ return new Response(
218
+ JSON.stringify({
219
+ message: "Table delete request processed",
220
+ processingIds,
221
+ }),
222
+ {
223
+ status: 200,
224
+ headers: CORS_HEADERS,
225
+ }
226
+ );
227
+ }
228
+
229
+ // 2. 删除通用数据(单 key 删除)
230
+ let data;
231
+ try {
232
+ data = await serverDb.get(id);
233
+ } catch (err: any) {
234
+ if (err.notFound) {
235
+ return new Response(
236
+ JSON.stringify({
237
+ message: "Success (Key not found, possibly already deleted)",
238
+ processingIds: [id],
239
+ }),
240
+ {
241
+ status: 200,
242
+ headers: CORS_HEADERS,
243
+ }
244
+ );
245
+ }
246
+ throw err;
247
+ }
248
+
249
+ const isShareRecord = shareKey.isShareKey(id);
250
+ const ownerId = (
251
+ data?.userId ??
252
+ (isShareRecord ? data?.meta?.authorId : undefined)
253
+ ) as string | undefined;
254
+ const ownerMissing = ownerId == null && !isShareRecord;
255
+ const isOwner = actionUserId != null && ownerId === actionUserId;
256
+ const canSystemUserDeletePublicCybotResource =
257
+ canSystemUserDeletePublicCybot(id, actionUserId);
258
+ const canSystemAdminDeleteCommunityShareResource =
259
+ canSystemAdminDeleteCommunityShare(id, actionUserId, data);
260
+ const canDeleteSpaceMemberResource =
261
+ parseSpaceMemberKey(id) !== null &&
262
+ (await canDeleteSpaceMemberRecord({
263
+ dbKey: id,
264
+ actionUserId,
265
+ }));
266
+ const shouldInvalidatePublicAgents =
267
+ id.startsWith("agent-pub-") || id.startsWith("cybot-pub-");
268
+
269
+ if (
270
+ ownerMissing ||
271
+ isOwner ||
272
+ canDeleteSpaceMemberResource ||
273
+ canSystemUserDeletePublicCybotResource ||
274
+ canSystemAdminDeleteCommunityShareResource
275
+ ) {
276
+ if (data) {
277
+ if (isTombstoneRecord(data)) {
278
+ return new Response(
279
+ JSON.stringify({
280
+ message: "Delete request processed",
281
+ processingIds: [id],
282
+ }),
283
+ {
284
+ status: 200,
285
+ headers: CORS_HEADERS,
286
+ }
287
+ );
288
+ }
289
+
290
+ // Share 记录 → 物理删除(主记录 + 所有索引键);通用记录 → tombstone
291
+ if (isShareRecord) {
292
+ const indexes = shareKey.allIndexKeysFromShare(id, data);
293
+ const batch = serverDb.batch();
294
+ batch.del(id);
295
+ for (const ik of indexes) batch.del(ik);
296
+ await batch.write();
297
+ } else {
298
+ await serverDb.put(id, buildTombstoneRecord(data, new Date().toISOString()));
299
+ }
300
+
301
+ if (
302
+ data?.type === DataType.TABLE_ROW &&
303
+ typeof data?.tenantId === "string" &&
304
+ typeof data?.tableId === "string"
305
+ ) {
306
+ await replicateSharedTableMutation({
307
+ mutation: {
308
+ kind: "delete",
309
+ dbKey: id,
310
+ dataType: data.type,
311
+ tenantId: data.tenantId,
312
+ tableId: data.tableId,
313
+ },
314
+ originServer: getRequestOrigin(req),
315
+ replicaServers: [],
316
+ findActiveLiveShare: findActiveLiveShareByTable,
317
+ putMutationToReplica: async (server, mutation) => {
318
+ try {
319
+ const response = await fetch(
320
+ `${server}/api/v1/db/delete/${encodeURIComponent(mutation.dbKey)}`,
321
+ {
322
+ method: "DELETE",
323
+ headers: getForwardHeaders(req),
324
+ }
325
+ );
326
+ return {
327
+ ok: response.ok,
328
+ status: response.status,
329
+ detail: response.ok ? "" : await response.text(),
330
+ };
331
+ } catch (error: any) {
332
+ return {
333
+ ok: false,
334
+ detail: error?.message ?? "Replica row delete failed",
335
+ };
336
+ }
337
+ },
338
+ reconcileReplicaTable: async ({ shareDbKey, replicaServers }) => {
339
+ await bootstrapReplicatedTable({
340
+ shareDbKey,
341
+ shareRecord: {
342
+ dbKey: shareDbKey,
343
+ type: DataType.TABLE,
344
+ data: {
345
+ mode: "live",
346
+ tableDbKey: `meta-${data.tenantId}-${data.tableId}`,
347
+ },
348
+ meta: {
349
+ tableDbKey: `meta-${data.tenantId}-${data.tableId}`,
350
+ replicaServers,
351
+ },
352
+ },
353
+ tableDbKey: `meta-${data.tenantId}-${data.tableId}`,
354
+ tableOwnerId: data.tenantId,
355
+ originServer: getRequestOrigin(req),
356
+ replicaServers,
357
+ thunkApi: null,
358
+ putRecordToServer: async (server, dbKey, record) => {
359
+ try {
360
+ const response = await fetch(`${server}/api/v1/db/write/`, {
361
+ method: "POST",
362
+ headers: getForwardHeaders(req),
363
+ body: JSON.stringify({
364
+ data: record,
365
+ customKey: dbKey,
366
+ userId:
367
+ record?.userId ?? record?.tenantId ?? actionUserId,
368
+ }),
369
+ });
370
+ return {
371
+ ok: response.ok,
372
+ status: response.status,
373
+ detail: response.ok ? "" : await response.text(),
374
+ };
375
+ } catch (error: any) {
376
+ return {
377
+ ok: false,
378
+ detail: error?.message ?? "Replica reconcile request failed",
379
+ };
380
+ }
381
+ },
382
+ resetReplicaTable: async (server, tableDbKey) => {
383
+ try {
384
+ const response = await fetch(
385
+ `${server}/api/v1/db/delete/${encodeURIComponent(tableDbKey)}?type=table`,
386
+ {
387
+ method: "DELETE",
388
+ headers: getForwardHeaders(req),
389
+ }
390
+ );
391
+ return {
392
+ ok: response.ok,
393
+ status: response.status,
394
+ detail: response.ok ? "" : await response.text(),
395
+ };
396
+ } catch (error: any) {
397
+ return {
398
+ ok: false,
399
+ detail: error?.message ?? "Replica table reset failed",
400
+ };
401
+ }
402
+ },
403
+ patchShareMeta,
404
+ });
405
+ },
406
+ patchShareMeta,
407
+ });
408
+ }
409
+
410
+ if (shouldInvalidatePublicAgents) {
411
+ invalidatePublicAgentsCache();
412
+ }
413
+
414
+ // 如果被删除的是 Agent,则级联清理所有的收藏关系及统计
415
+ if (isAgentKey(id)) {
416
+ const { start, end } = createFavoriteKey.userRangeOfAgentKey(id);
417
+ const batch = serverDb.batch();
418
+
419
+ for await (const [reverseKey] of serverDb.iterator({
420
+ gte: start,
421
+ lte: end,
422
+ })) {
423
+ if (!reverseKey.startsWith(start)) continue;
424
+
425
+ // reverseKey: fav-agent-key-by-agent-{agentKey}-{userId}
426
+ const userId = reverseKey.slice(start.length);
427
+ if (userId) {
428
+ const primaryKey = createFavoriteKey.agentByKey(userId, id);
429
+ batch.del(primaryKey);
430
+ batch.del(reverseKey);
431
+ }
432
+ }
433
+
434
+ // 清理收藏统计
435
+ batch.del(createFavoriteStatsKey.agentByKey(id));
436
+
437
+ await batch.write();
438
+ }
439
+
440
+ // 如果被删除的是 Dialog,则级联清理该对话下的所有消息
441
+ // Dialog Key 结构: dialog-{userId}-{dialogId} (3 parts)
442
+ const parts = id.split("-");
443
+ if (parts[0] === "dialog" && parts.length === 3) {
444
+ const dialogId = parts[2];
445
+ if (dialogId) {
446
+ console.log(`[Delete] Cascading messages for dialog: ${dialogId}`);
447
+ await deleteMessages(serverDb, dialogId);
448
+ }
449
+ }
450
+ }
451
+
452
+ return new Response(
453
+ JSON.stringify({
454
+ message: "Delete request processed",
455
+ processingIds: [id],
456
+ }),
457
+ {
458
+ status: 200,
459
+ headers: CORS_HEADERS,
460
+ }
461
+ );
462
+ }
463
+
464
+ // 3. 无权限
465
+ const forbiddenReason = !actionUserId
466
+ ? "Missing or invalid auth token (or public key not found on this server)"
467
+ : `User ${actionUserId} does not match owner ${ownerId}`;
468
+
469
+ console.warn(`[Delete 403] ${forbiddenReason} for key: ${id}`);
470
+
471
+ return new Response(
472
+ JSON.stringify({
473
+ error: "Unauthorized action",
474
+ message: forbiddenReason,
475
+ ownerId,
476
+ actionUserId,
477
+ processingIds: [],
478
+ }),
479
+ {
480
+ status: 403,
481
+ headers: CORS_HEADERS,
482
+ }
483
+ );
484
+ } catch (error) {
485
+ console.error("Delete handler error:", error);
486
+
487
+ return new Response(
488
+ JSON.stringify({
489
+ error: "Internal server error",
490
+ message: error instanceof Error ? error.message : String(error),
491
+ processingIds: [],
492
+ }),
493
+ {
494
+ status: 500,
495
+ headers: CORS_HEADERS,
496
+ }
497
+ );
498
+ }
499
+ };