@diskd-ai/sdk 5.1.2

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 (299) hide show
  1. package/LICENSE +190 -0
  2. package/README.md +1036 -0
  3. package/dist/agentHub/StreamProtocolFetcher.d.ts +55 -0
  4. package/dist/agentHub/StreamProtocolFetcher.d.ts.map +1 -0
  5. package/dist/agentHub/StreamProtocolFetcher.js +176 -0
  6. package/dist/agentHub/StreamProtocolFetcher.js.map +1 -0
  7. package/dist/agentHub/StreamProtocolHandler.d.ts +18 -0
  8. package/dist/agentHub/StreamProtocolHandler.d.ts.map +1 -0
  9. package/dist/agentHub/StreamProtocolHandler.js +63 -0
  10. package/dist/agentHub/StreamProtocolHandler.js.map +1 -0
  11. package/dist/agentHub/agentHub.d.ts +30 -0
  12. package/dist/agentHub/agentHub.d.ts.map +1 -0
  13. package/dist/agentHub/agentHub.js +200 -0
  14. package/dist/agentHub/agentHub.js.map +1 -0
  15. package/dist/agentHub/agentHubTypes.d.ts +110 -0
  16. package/dist/agentHub/agentHubTypes.d.ts.map +1 -0
  17. package/dist/agentHub/agentHubTypes.js +8 -0
  18. package/dist/agentHub/agentHubTypes.js.map +1 -0
  19. package/dist/agentHub/streamProtocolMap.d.ts +328 -0
  20. package/dist/agentHub/streamProtocolMap.d.ts.map +1 -0
  21. package/dist/agentHub/streamProtocolMap.js +8 -0
  22. package/dist/agentHub/streamProtocolMap.js.map +1 -0
  23. package/dist/auth/createApiKeyAuth.d.ts +11 -0
  24. package/dist/auth/createApiKeyAuth.d.ts.map +1 -0
  25. package/dist/auth/createApiKeyAuth.js +31 -0
  26. package/dist/auth/createApiKeyAuth.js.map +1 -0
  27. package/dist/auth/createAuth.d.ts +3 -0
  28. package/dist/auth/createAuth.d.ts.map +1 -0
  29. package/dist/auth/createAuth.js +128 -0
  30. package/dist/auth/createAuth.js.map +1 -0
  31. package/dist/auth/createAuthBrowser.d.ts +3 -0
  32. package/dist/auth/createAuthBrowser.d.ts.map +1 -0
  33. package/dist/auth/createAuthBrowser.js +104 -0
  34. package/dist/auth/createAuthBrowser.js.map +1 -0
  35. package/dist/auth/jwtClaims.d.ts +3 -0
  36. package/dist/auth/jwtClaims.d.ts.map +1 -0
  37. package/dist/auth/jwtClaims.js +23 -0
  38. package/dist/auth/jwtClaims.js.map +1 -0
  39. package/dist/auth/keyfile.d.ts +10 -0
  40. package/dist/auth/keyfile.d.ts.map +1 -0
  41. package/dist/auth/keyfile.js +28 -0
  42. package/dist/auth/keyfile.js.map +1 -0
  43. package/dist/auth/oidcDiscovery.d.ts +9 -0
  44. package/dist/auth/oidcDiscovery.d.ts.map +1 -0
  45. package/dist/auth/oidcDiscovery.js +27 -0
  46. package/dist/auth/oidcDiscovery.js.map +1 -0
  47. package/dist/auth/pkce.d.ts +4 -0
  48. package/dist/auth/pkce.d.ts.map +1 -0
  49. package/dist/auth/pkce.js +43 -0
  50. package/dist/auth/pkce.js.map +1 -0
  51. package/dist/auth/sessionStorage.d.ts +8 -0
  52. package/dist/auth/sessionStorage.d.ts.map +1 -0
  53. package/dist/auth/sessionStorage.js +8 -0
  54. package/dist/auth/sessionStorage.js.map +1 -0
  55. package/dist/auth/tokenRequests.d.ts +15 -0
  56. package/dist/auth/tokenRequests.d.ts.map +1 -0
  57. package/dist/auth/tokenRequests.js +89 -0
  58. package/dist/auth/tokenRequests.js.map +1 -0
  59. package/dist/auth/types.d.ts +35 -0
  60. package/dist/auth/types.d.ts.map +1 -0
  61. package/dist/auth/types.js +2 -0
  62. package/dist/auth/types.js.map +1 -0
  63. package/dist/auth/urlRuntime.d.ts +7 -0
  64. package/dist/auth/urlRuntime.d.ts.map +1 -0
  65. package/dist/auth/urlRuntime.js +17 -0
  66. package/dist/auth/urlRuntime.js.map +1 -0
  67. package/dist/browser/index.d.ts +8 -0
  68. package/dist/browser/index.d.ts.map +1 -0
  69. package/dist/browser/index.js +3 -0
  70. package/dist/browser/index.js.map +1 -0
  71. package/dist/calendar/calendar.d.ts +21 -0
  72. package/dist/calendar/calendar.d.ts.map +1 -0
  73. package/dist/calendar/calendar.js +105 -0
  74. package/dist/calendar/calendar.js.map +1 -0
  75. package/dist/calendar/calendarTypes.d.ts +191 -0
  76. package/dist/calendar/calendarTypes.d.ts.map +1 -0
  77. package/dist/calendar/calendarTypes.js +4 -0
  78. package/dist/calendar/calendarTypes.js.map +1 -0
  79. package/dist/contacts/contacts.d.ts +10 -0
  80. package/dist/contacts/contacts.d.ts.map +1 -0
  81. package/dist/contacts/contacts.js +86 -0
  82. package/dist/contacts/contacts.js.map +1 -0
  83. package/dist/contacts/contactsTypes.d.ts +81 -0
  84. package/dist/contacts/contactsTypes.d.ts.map +1 -0
  85. package/dist/contacts/contactsTypes.js +4 -0
  86. package/dist/contacts/contactsTypes.js.map +1 -0
  87. package/dist/drive/DriveRepository.d.ts +88 -0
  88. package/dist/drive/DriveRepository.d.ts.map +1 -0
  89. package/dist/drive/DriveRepository.js +156 -0
  90. package/dist/drive/DriveRepository.js.map +1 -0
  91. package/dist/drive/crontab.d.ts +7 -0
  92. package/dist/drive/crontab.d.ts.map +1 -0
  93. package/dist/drive/crontab.js +374 -0
  94. package/dist/drive/crontab.js.map +1 -0
  95. package/dist/drive/crontabTypes.d.ts +136 -0
  96. package/dist/drive/crontabTypes.d.ts.map +1 -0
  97. package/dist/drive/crontabTypes.js +2 -0
  98. package/dist/drive/crontabTypes.js.map +1 -0
  99. package/dist/drive/drive.d.ts +8 -0
  100. package/dist/drive/drive.d.ts.map +1 -0
  101. package/dist/drive/drive.js +711 -0
  102. package/dist/drive/drive.js.map +1 -0
  103. package/dist/drive/driveDb.d.ts +6 -0
  104. package/dist/drive/driveDb.d.ts.map +1 -0
  105. package/dist/drive/driveDb.js +220 -0
  106. package/dist/drive/driveDb.js.map +1 -0
  107. package/dist/drive/driveDbTypes.d.ts +138 -0
  108. package/dist/drive/driveDbTypes.d.ts.map +1 -0
  109. package/dist/drive/driveDbTypes.js +5 -0
  110. package/dist/drive/driveDbTypes.js.map +1 -0
  111. package/dist/drive/driveTypes.d.ts +322 -0
  112. package/dist/drive/driveTypes.d.ts.map +1 -0
  113. package/dist/drive/driveTypes.js +5 -0
  114. package/dist/drive/driveTypes.js.map +1 -0
  115. package/dist/drive/rpc.d.ts +14 -0
  116. package/dist/drive/rpc.d.ts.map +1 -0
  117. package/dist/drive/rpc.js +48 -0
  118. package/dist/drive/rpc.js.map +1 -0
  119. package/dist/drive/session.d.ts +7 -0
  120. package/dist/drive/session.d.ts.map +1 -0
  121. package/dist/drive/session.js +450 -0
  122. package/dist/drive/session.js.map +1 -0
  123. package/dist/drive/sessionBuilder.d.ts +33 -0
  124. package/dist/drive/sessionBuilder.d.ts.map +1 -0
  125. package/dist/drive/sessionBuilder.js +77 -0
  126. package/dist/drive/sessionBuilder.js.map +1 -0
  127. package/dist/drive/sessionObject.d.ts +57 -0
  128. package/dist/drive/sessionObject.d.ts.map +1 -0
  129. package/dist/drive/sessionObject.js +191 -0
  130. package/dist/drive/sessionObject.js.map +1 -0
  131. package/dist/drive/sessionTypes.d.ts +182 -0
  132. package/dist/drive/sessionTypes.d.ts.map +1 -0
  133. package/dist/drive/sessionTypes.js +2 -0
  134. package/dist/drive/sessionTypes.js.map +1 -0
  135. package/dist/drive/typeorm/DriveDriver.d.ts +27 -0
  136. package/dist/drive/typeorm/DriveDriver.d.ts.map +1 -0
  137. package/dist/drive/typeorm/DriveDriver.js +86 -0
  138. package/dist/drive/typeorm/DriveDriver.js.map +1 -0
  139. package/dist/drive/typeorm/DriveQueryRunner.d.ts +15 -0
  140. package/dist/drive/typeorm/DriveQueryRunner.d.ts.map +1 -0
  141. package/dist/drive/typeorm/DriveQueryRunner.js +76 -0
  142. package/dist/drive/typeorm/DriveQueryRunner.js.map +1 -0
  143. package/dist/drive/typeorm/createDriveDataSource.d.ts +3 -0
  144. package/dist/drive/typeorm/createDriveDataSource.d.ts.map +1 -0
  145. package/dist/drive/typeorm/createDriveDataSource.js +36 -0
  146. package/dist/drive/typeorm/createDriveDataSource.js.map +1 -0
  147. package/dist/drive/typeorm/datasourceTypes.d.ts +56 -0
  148. package/dist/drive/typeorm/datasourceTypes.d.ts.map +1 -0
  149. package/dist/drive/typeorm/datasourceTypes.js +5 -0
  150. package/dist/drive/typeorm/datasourceTypes.js.map +1 -0
  151. package/dist/drive/types.d.ts +48 -0
  152. package/dist/drive/types.d.ts.map +1 -0
  153. package/dist/drive/types.js +2 -0
  154. package/dist/drive/types.js.map +1 -0
  155. package/dist/env/apiKey.d.ts +2 -0
  156. package/dist/env/apiKey.d.ts.map +1 -0
  157. package/dist/env/apiKey.js +11 -0
  158. package/dist/env/apiKey.js.map +1 -0
  159. package/dist/env/baseUrl.d.ts +3 -0
  160. package/dist/env/baseUrl.d.ts.map +1 -0
  161. package/dist/env/baseUrl.js +31 -0
  162. package/dist/env/baseUrl.js.map +1 -0
  163. package/dist/inbox/inboxTypes.d.ts +34 -0
  164. package/dist/inbox/inboxTypes.d.ts.map +1 -0
  165. package/dist/inbox/inboxTypes.js +5 -0
  166. package/dist/inbox/inboxTypes.js.map +1 -0
  167. package/dist/index.d.ts +56 -0
  168. package/dist/index.d.ts.map +1 -0
  169. package/dist/index.js +43 -0
  170. package/dist/index.js.map +1 -0
  171. package/dist/llmRouter/llmRouter.d.ts +23 -0
  172. package/dist/llmRouter/llmRouter.d.ts.map +1 -0
  173. package/dist/llmRouter/llmRouter.js +566 -0
  174. package/dist/llmRouter/llmRouter.js.map +1 -0
  175. package/dist/llmRouter/llmRouterTypes.d.ts +350 -0
  176. package/dist/llmRouter/llmRouterTypes.d.ts.map +1 -0
  177. package/dist/llmRouter/llmRouterTypes.js +5 -0
  178. package/dist/llmRouter/llmRouterTypes.js.map +1 -0
  179. package/dist/mcpHub/mcpHub.d.ts +23 -0
  180. package/dist/mcpHub/mcpHub.d.ts.map +1 -0
  181. package/dist/mcpHub/mcpHub.js +223 -0
  182. package/dist/mcpHub/mcpHub.js.map +1 -0
  183. package/dist/mcpHub/mcpHubTypes.d.ts +228 -0
  184. package/dist/mcpHub/mcpHubTypes.d.ts.map +1 -0
  185. package/dist/mcpHub/mcpHubTypes.js +5 -0
  186. package/dist/mcpHub/mcpHubTypes.js.map +1 -0
  187. package/dist/mcpTools/mcpTools.d.ts +31 -0
  188. package/dist/mcpTools/mcpTools.d.ts.map +1 -0
  189. package/dist/mcpTools/mcpTools.js +144 -0
  190. package/dist/mcpTools/mcpTools.js.map +1 -0
  191. package/dist/mcpTools/mcpToolsTypes.d.ts +45 -0
  192. package/dist/mcpTools/mcpToolsTypes.d.ts.map +1 -0
  193. package/dist/mcpTools/mcpToolsTypes.js +5 -0
  194. package/dist/mcpTools/mcpToolsTypes.js.map +1 -0
  195. package/dist/messagesStore/messagesStore.d.ts +22 -0
  196. package/dist/messagesStore/messagesStore.d.ts.map +1 -0
  197. package/dist/messagesStore/messagesStore.js +402 -0
  198. package/dist/messagesStore/messagesStore.js.map +1 -0
  199. package/dist/messagesStore/messagesStoreTypes.d.ts +327 -0
  200. package/dist/messagesStore/messagesStoreTypes.d.ts.map +1 -0
  201. package/dist/messagesStore/messagesStoreTypes.js +11 -0
  202. package/dist/messagesStore/messagesStoreTypes.js.map +1 -0
  203. package/dist/node/fastDns.d.ts +2 -0
  204. package/dist/node/fastDns.d.ts.map +1 -0
  205. package/dist/node/fastDns.js +119 -0
  206. package/dist/node/fastDns.js.map +1 -0
  207. package/dist/operatives/operatives.d.ts +22 -0
  208. package/dist/operatives/operatives.d.ts.map +1 -0
  209. package/dist/operatives/operatives.js +199 -0
  210. package/dist/operatives/operatives.js.map +1 -0
  211. package/dist/operatives/operativesTypes.d.ts +141 -0
  212. package/dist/operatives/operativesTypes.d.ts.map +1 -0
  213. package/dist/operatives/operativesTypes.js +6 -0
  214. package/dist/operatives/operativesTypes.js.map +1 -0
  215. package/dist/platformEvents/platformEvents.d.ts +14 -0
  216. package/dist/platformEvents/platformEvents.d.ts.map +1 -0
  217. package/dist/platformEvents/platformEvents.js +70 -0
  218. package/dist/platformEvents/platformEvents.js.map +1 -0
  219. package/dist/platformEvents/platformEventsTypes.d.ts +31 -0
  220. package/dist/platformEvents/platformEventsTypes.d.ts.map +1 -0
  221. package/dist/platformEvents/platformEventsTypes.js +8 -0
  222. package/dist/platformEvents/platformEventsTypes.js.map +1 -0
  223. package/dist/projects/projects.d.ts +19 -0
  224. package/dist/projects/projects.d.ts.map +1 -0
  225. package/dist/projects/projects.js +52 -0
  226. package/dist/projects/projects.js.map +1 -0
  227. package/dist/projects/projectsTypes.d.ts +47 -0
  228. package/dist/projects/projectsTypes.d.ts.map +1 -0
  229. package/dist/projects/projectsTypes.js +4 -0
  230. package/dist/projects/projectsTypes.js.map +1 -0
  231. package/dist/routineRuns/routineRuns.d.ts +19 -0
  232. package/dist/routineRuns/routineRuns.d.ts.map +1 -0
  233. package/dist/routineRuns/routineRuns.js +47 -0
  234. package/dist/routineRuns/routineRuns.js.map +1 -0
  235. package/dist/routineRuns/routineRunsTypes.d.ts +39 -0
  236. package/dist/routineRuns/routineRunsTypes.d.ts.map +1 -0
  237. package/dist/routineRuns/routineRunsTypes.js +4 -0
  238. package/dist/routineRuns/routineRunsTypes.js.map +1 -0
  239. package/dist/routines/routines.d.ts +19 -0
  240. package/dist/routines/routines.d.ts.map +1 -0
  241. package/dist/routines/routines.js +77 -0
  242. package/dist/routines/routines.js.map +1 -0
  243. package/dist/routines/routinesTypes.d.ts +106 -0
  244. package/dist/routines/routinesTypes.d.ts.map +1 -0
  245. package/dist/routines/routinesTypes.js +4 -0
  246. package/dist/routines/routinesTypes.js.map +1 -0
  247. package/dist/sdk/diskd.d.ts +3 -0
  248. package/dist/sdk/diskd.d.ts.map +1 -0
  249. package/dist/sdk/diskd.js +126 -0
  250. package/dist/sdk/diskd.js.map +1 -0
  251. package/dist/sdk/http.d.ts +13 -0
  252. package/dist/sdk/http.d.ts.map +1 -0
  253. package/dist/sdk/http.js +80 -0
  254. package/dist/sdk/http.js.map +1 -0
  255. package/dist/sdk/types.d.ts +115 -0
  256. package/dist/sdk/types.d.ts.map +1 -0
  257. package/dist/sdk/types.js +2 -0
  258. package/dist/sdk/types.js.map +1 -0
  259. package/dist/testing/auth.d.ts +8 -0
  260. package/dist/testing/auth.d.ts.map +1 -0
  261. package/dist/testing/auth.js +14 -0
  262. package/dist/testing/auth.js.map +1 -0
  263. package/dist/testing/fetchMock.d.ts +17 -0
  264. package/dist/testing/fetchMock.d.ts.map +1 -0
  265. package/dist/testing/fetchMock.js +46 -0
  266. package/dist/testing/fetchMock.js.map +1 -0
  267. package/dist/testing/index.d.ts +11 -0
  268. package/dist/testing/index.d.ts.map +1 -0
  269. package/dist/testing/index.js +11 -0
  270. package/dist/testing/index.js.map +1 -0
  271. package/dist/testing/integration.d.ts +33 -0
  272. package/dist/testing/integration.d.ts.map +1 -0
  273. package/dist/testing/integration.js +32 -0
  274. package/dist/testing/integration.js.map +1 -0
  275. package/dist/testing/jsonRpc.d.ts +9 -0
  276. package/dist/testing/jsonRpc.d.ts.map +1 -0
  277. package/dist/testing/jsonRpc.js +24 -0
  278. package/dist/testing/jsonRpc.js.map +1 -0
  279. package/dist/testing/rpcMock.d.ts +16 -0
  280. package/dist/testing/rpcMock.d.ts.map +1 -0
  281. package/dist/testing/rpcMock.js +28 -0
  282. package/dist/testing/rpcMock.js.map +1 -0
  283. package/dist/tgUserbot/tgUserbot.d.ts +23 -0
  284. package/dist/tgUserbot/tgUserbot.d.ts.map +1 -0
  285. package/dist/tgUserbot/tgUserbot.js +314 -0
  286. package/dist/tgUserbot/tgUserbot.js.map +1 -0
  287. package/dist/tgUserbot/tgUserbotTypes.d.ts +124 -0
  288. package/dist/tgUserbot/tgUserbotTypes.d.ts.map +1 -0
  289. package/dist/tgUserbot/tgUserbotTypes.js +5 -0
  290. package/dist/tgUserbot/tgUserbotTypes.js.map +1 -0
  291. package/dist/webNavigator/webNavigator.d.ts +22 -0
  292. package/dist/webNavigator/webNavigator.d.ts.map +1 -0
  293. package/dist/webNavigator/webNavigator.js +46 -0
  294. package/dist/webNavigator/webNavigator.js.map +1 -0
  295. package/dist/webNavigator/webNavigatorTypes.d.ts +133 -0
  296. package/dist/webNavigator/webNavigatorTypes.d.ts.map +1 -0
  297. package/dist/webNavigator/webNavigatorTypes.js +5 -0
  298. package/dist/webNavigator/webNavigatorTypes.js.map +1 -0
  299. package/package.json +90 -0
package/README.md ADDED
@@ -0,0 +1,1036 @@
1
+ # @diskd-ai/sdk
2
+
3
+ Unified TypeScript SDK for the Upgraide platform APIs.
4
+
5
+ All services are accessible via the `diskd` factory, which provides a consistent
6
+ `diskd.auth.*` + namespaced service pattern across `diskd.os.*`, `diskd.platform.*`,
7
+ and `diskd.utils.*`:
8
+
9
+ ```ts
10
+ import { diskd } from '@diskd-ai/sdk';
11
+
12
+ const auth = diskd.auth.apiKey({ workspaceId: '...' });
13
+
14
+ const drive = diskd.os.drive({ version: 'v1', auth });
15
+ const sessions = diskd.platform.sessions({
16
+ auth,
17
+ scope: { scopeType: 'project', projectId: 'proj-1' },
18
+ });
19
+ const crontab = diskd.platform.crontab({
20
+ auth,
21
+ scope: { scopeType: 'project', projectId: 'proj-1' },
22
+ });
23
+ const db = diskd.os.database({ auth, dbName: '...', schema: { ... } });
24
+ const ds = diskd.os.datasource({ auth, dbName: '...', entities: [...] });
25
+ const llm = diskd.os.llm({ auth });
26
+ const agents = diskd.os.agents({ auth, workspaceId: '...' });
27
+ const mcp = diskd.os.mcp({ auth, workspaceId: '...' });
28
+ const messages = diskd.os.messagesStore({ auth });
29
+ const routines = diskd.platform.routines({ auth });
30
+ const operatives = diskd.platform.operatives({ auth });
31
+ const calendar = diskd.platform.calendar({ auth });
32
+ const tg = diskd.utils.tgUserBot({ auth, workspaceId: '...' });
33
+ const webNav = diskd.utils.webNavigator({ auth, workspaceId: '...' });
34
+ ```
35
+
36
+ Installation
37
+ ------------
38
+
39
+ 1. Configure `.npmrc` in your project (or `~/.npmrc`):
40
+
41
+ ```ini
42
+ @diskd:registry=https://gitlab.iosya.com/api/v4/projects/80/packages/npm/
43
+ //gitlab.iosya.com/api/v4/projects/80/packages/npm/:_authToken=${NPM_TOKEN}
44
+ ```
45
+
46
+ 2. Set `NPM_TOKEN` to a GitLab personal access token with `read_api` scope:
47
+
48
+ ```bash
49
+ export NPM_TOKEN=glpat-xxxxxxxxxxxx
50
+ ```
51
+
52
+ 3. Install:
53
+
54
+ ```bash
55
+ bun add @diskd-ai/sdk
56
+ ```
57
+
58
+ Install / build (repo)
59
+ ----------------------
60
+
61
+ ```bash
62
+ cd mono/platform-api
63
+ bun install
64
+ bun run build
65
+ ```
66
+
67
+ Authentication
68
+ --------------
69
+
70
+ The SDK supports two authentication modes via the `AuthModule` interface.
71
+
72
+ ### External clients (OAuth2)
73
+
74
+ Use `diskd.auth.credentials()` for OAuth2 service-account or PKCE browser flows:
75
+
76
+ ```ts
77
+ import { diskd } from '@diskd-ai/sdk';
78
+
79
+ const auth = await diskd.auth.credentials({
80
+ scopes: ['openid'],
81
+ keyfilePath: 'credentials.json',
82
+ });
83
+
84
+ const drive = diskd.os.drive({ version: 'v1', auth });
85
+ const sessions = diskd.platform.sessions({
86
+ auth,
87
+ scope: { scopeType: 'project', projectId: 'proj-1' },
88
+ });
89
+ const crontab = diskd.platform.crontab({
90
+ auth,
91
+ scope: { scopeType: 'project', projectId: 'proj-1' },
92
+ });
93
+ ```
94
+
95
+ ### Internal services (API key)
96
+
97
+ Use `diskd.auth.apiKey()` for service-to-service communication within the cluster:
98
+
99
+ ```ts
100
+ import { diskd } from '@diskd-ai/sdk';
101
+
102
+ const auth = diskd.auth.apiKey({ workspaceId: process.env.WORKSPACE_ID! });
103
+
104
+ const drive = diskd.os.drive({ version: 'v1', auth });
105
+ ```
106
+
107
+ `diskd.auth.apiKey()` reads `APIS_API_KEY` from the environment and fails fast when
108
+ either `APIS_API_KEY` or `APIS_BASE_URL` is missing.
109
+
110
+ Both auth modes produce identical client instances.
111
+
112
+ Environment variables
113
+ ---------------------
114
+
115
+ All resource APIs resolve from the centralized gateway base URL:
116
+
117
+ | Env Variable | Default |
118
+ |--------------|---------|
119
+ | `APIS_BASE_URL` | `https://apis.diskd.local:8080` |
120
+ | `APIS_API_KEY` | none |
121
+
122
+ The gateway is the single resource entrypoint. Public gateway URLs follow the
123
+ versioned convention `https://apis.example/v1/{namespace}/{module}`. The SDK
124
+ derives API paths from the same namespace structure as the public SDK surface
125
+ and lets the gateway handle API orchestration and auth strategy.
126
+
127
+ Derived default paths:
128
+ - `/v1/os/drive`
129
+ - `/v1/os/database`
130
+ - `/v1/os/llm`
131
+ - `/v1/os/agents`
132
+ - `/v1/os/mcp`
133
+ - `/v1/platform/sessions`
134
+ - `/v1/platform/crontab`
135
+ - `/v1/platform/operatives`
136
+ - `/v1/platform/projects`
137
+ - `/v1/platform/routines`
138
+ - `/v1/platform/events`
139
+ - `/v1/platform/calendar`
140
+ - `/v1/utils/tg-userbot`
141
+ - `/v1/utils/web-navigator`
142
+
143
+ You can still override a client with an explicit `url`, but the default mode is
144
+ the centralized gateway.
145
+
146
+ Gateway Decision
147
+ ----------------
148
+
149
+ This SDK does not treat resource APIs as independently-discovered hosts.
150
+ The canonical model is one centralized `apis` gateway behind `APIS_BASE_URL`.
151
+
152
+ That means:
153
+ - no per-service default env vars such as `LLM_ROUTER_BASE_URL`, `AGENT_HUB_BASE_URL`, or `MCP_HUB_BASE_URL`
154
+ - resource clients derive their route from `APIS_BASE_URL` plus a namespace-derived path prefix
155
+ - the gateway is responsible for request routing, API orchestration, and auth-strategy handling
156
+
157
+ Per-client `url` remains available only as an explicit override.
158
+
159
+ Drive API
160
+ ---------
161
+
162
+ ### Path operations
163
+
164
+ ```ts
165
+ await drive.init();
166
+ const entries = await drive.list({ path: '/' });
167
+ const dir = await drive.create({ dirName: 'my-folder' });
168
+ await drive.rename({ inode: dir.inode, newName: 'renamed-folder' });
169
+ await drive.delete({ inodes: [dir.inode], recursive: true });
170
+ const resolved = await drive.resolve({ inodes: ['inode1', 'inode2'] });
171
+ await drive.updateMetadata({ inode: 'abc', metadata: { key: 'value' } });
172
+ await drive.updateAttributes({ inode: 'abc', attributes: ['pinned'] });
173
+ ```
174
+
175
+ ### Upload (buffer + stream)
176
+
177
+ ```ts
178
+ // Buffer upload
179
+ const result = await drive.upload.file({
180
+ name: 'hello.txt',
181
+ data: new TextEncoder().encode('Hello, world!'),
182
+ mimeType: 'text/plain',
183
+ onProgress: (uploaded, total) => console.log(`${uploaded}/${total}`),
184
+ });
185
+
186
+ // Stream upload (large files)
187
+ const result = await drive.upload.file({
188
+ name: 'large.bin',
189
+ stream: readableStream,
190
+ size: 1_000_000_000,
191
+ sha256Root: 'precomputed-hex',
192
+ });
193
+ ```
194
+
195
+ ### Download (streaming)
196
+
197
+ ```ts
198
+ const file = await drive.download.file({
199
+ inode: 'abc123',
200
+ onProgress: (downloaded, total) => console.log(`${downloaded}/${total}`),
201
+ });
202
+ await file.stream.pipeTo(writableStream);
203
+ ```
204
+
205
+ ### File metadata, disk usage, tools
206
+
207
+ ```ts
208
+ const meta = await drive.files.metadata({ inode: 'abc' });
209
+ const usage = await drive.diskUsage();
210
+ const ls = await drive.tools.ls({ path: '/', recursive: true });
211
+ const grep = await drive.tools.grep({ pattern: 'TODO' });
212
+ ```
213
+
214
+ ### Sessions
215
+
216
+ The SDK exposes these session methods on `diskd.platform.sessions({ auth, scope })`:
217
+
218
+ - `start`
219
+ - `open`
220
+ - `save`
221
+ - `list`
222
+ - `delete`
223
+ - `message`
224
+
225
+ ```ts
226
+ const session = await sessions.start({
227
+ title: 'Deployment help',
228
+ });
229
+
230
+ await session.append([
231
+ sessions.message({ role: 'user', content: 'How do I deploy to production?' }),
232
+ ]);
233
+
234
+ const sessionList = await sessions.list();
235
+ ```
236
+
237
+ ### Crontab scheduler
238
+
239
+ The SDK exposes these scheduler methods on `diskd.platform.crontab({ auth, scope, timezone? })`.
240
+ If `timezone` is omitted, the SDK uses the caller runtime timezone by default.
241
+
242
+ - `save`
243
+ - `get`
244
+ - `getStatus`
245
+ - `listJobs`
246
+ - `runJob`
247
+ - `createJob`
248
+
249
+ ```ts
250
+ await crontab.createJob({
251
+ job: {
252
+ jobId: '01JABCD2FGH3JK4MNP5QRST6VW',
253
+ enabled: true,
254
+ schedule: {
255
+ minute: '*/5',
256
+ hour: '*',
257
+ dayOfMonth: '*',
258
+ month: '*',
259
+ dayOfWeek: '*',
260
+ },
261
+ request: {
262
+ method: 'POST',
263
+ url: 'https://example.internal/hooks/sync',
264
+ payload: {
265
+ kind: 'json',
266
+ value: { source: 'sdk-example' },
267
+ },
268
+ },
269
+ },
270
+ });
271
+
272
+ const status = await crontab.getStatus();
273
+ ```
274
+
275
+ See `examples/node/drive-upload-download.ts`, `examples/node/drive-session-external.ts`, and `examples/node/drive-crontab.ts`.
276
+
277
+ Messages Store API
278
+ ------------------
279
+
280
+ Channel-agnostic message storage on top of Drive. Each workspace mailbox is one
281
+ SQLite file under `/Mailboxes/<mailboxId>.mailbox`; attachment bytes live in
282
+ Drive under `/Mailboxes/<mailboxId>/<per-message-folder>/`. The wire is the
283
+ `messages_store/*` JSON-RPC namespace served by drive.
284
+
285
+ Use it to persist email (IMAP / JMAP), Telegram, WhatsApp, or any other
286
+ channel where messages live in folders inside per-account mailboxes. Message
287
+ `payload` is opaque JSON; the store never inspects it.
288
+
289
+ The client exposes four boundaries -- mailboxes, folders, messages, attachments
290
+ -- via a **functional scoping pattern**: each level returns a client that
291
+ captures its identifiers in a closure, so callers never repeat
292
+ `(mailboxId, folderId, externalId)` on every call.
293
+
294
+ ```ts
295
+ const messagesStore = diskd.os.messagesStore({ auth });
296
+ const mailbox = messagesStore.mailbox({ mailboxId: 'gmail-acme' });
297
+ const folder = mailbox.folder({ folderId: 'INBOX' });
298
+ const message = folder.message({ externalId: 'imap-uid-1001' });
299
+ ```
300
+
301
+ ### Mailboxes
302
+
303
+ ```ts
304
+ // Allocate the mailbox SQLite file under /Mailboxes/.
305
+ // metadata is opaque JSON, stashed on the underlying drive_databases record.
306
+ const created = await messagesStore.createMailbox({
307
+ mailboxId: 'gmail-acme',
308
+ displayName: 'acme@gmail.com',
309
+ metadata: { protocol: 'imap', host: 'imap.gmail.com' },
310
+ });
311
+ // → { mailboxId, dbInode, drivePath: '/Mailboxes/gmail-acme.mailbox' }
312
+
313
+ // Bind a mailbox-scoped client; subsequent calls don't repeat mailboxId.
314
+ const mailbox = messagesStore.mailbox({ mailboxId: 'gmail-acme' });
315
+
316
+ // Idempotent SQLite-schema bootstrap. Required before any folder/message ops.
317
+ await mailbox.init();
318
+
319
+ // Workspace-scoped enumeration.
320
+ const all = await messagesStore.listMailboxes();
321
+ // → readonly { mailboxId, displayName, dbInode, recordCount,
322
+ // sizeBytes, updatedAt }[]
323
+
324
+ // Cascade-delete (mailbox file + per-mailbox attachment subtree).
325
+ await mailbox.delete();
326
+ ```
327
+
328
+ ### Folders
329
+
330
+ `folderId` is opaque (caller-chosen) -- IMAP folder name, JMAP id, Telegram
331
+ chat_id, etc. Folder `metadata` is the natural place for protocol-specific
332
+ sync state (`UIDVALIDITY`/`UIDNEXT`/`HIGHESTMODSEQ` for IMAP, JMAP `state`,
333
+ Telegram pts, etc.). The store never reads it.
334
+
335
+ ```ts
336
+ // Idempotent upsert. created=true on first call, false thereafter.
337
+ await mailbox.upsertFolder({
338
+ folderId: 'INBOX',
339
+ displayName: 'Inbox',
340
+ metadata: { uidvalidity: 12345, uidnext: 1101 },
341
+ });
342
+
343
+ // List folders in this mailbox.
344
+ const folders = await mailbox.listFolders();
345
+
346
+ // Bind a folder-scoped client.
347
+ const folder = mailbox.folder({ folderId: 'INBOX' });
348
+
349
+ // Update display name / sync metadata via the scoped client (folderId implicit).
350
+ await folder.upsert({
351
+ displayName: 'Inbox',
352
+ metadata: { uidvalidity: 12345, uidnext: 1200 },
353
+ });
354
+
355
+ // Read one folder.
356
+ const summary = await folder.get();
357
+ // → { folderId, displayName, metadata, messageCount, updatedAt }
358
+
359
+ // Cascade-delete folder + messages + per-message attachments.
360
+ const result = await folder.delete();
361
+ // → { folderId, deleted, deletedMessageCount }
362
+ ```
363
+
364
+ ### Messages
365
+
366
+ `externalId` is the caller's idempotency key within the folder (IMAP UID
367
+ stringified, Telegram `message_id`, JMAP id, ...). `payload` is opaque JSON
368
+ the store never inspects.
369
+
370
+ A successful `upsertBatch` response means the batch is durable in S3 -- the
371
+ SQLite head is committed before the call returns.
372
+
373
+ ```ts
374
+ // Bulk insert-or-update by externalId.
375
+ const ub = await folder.upsertBatch({
376
+ items: [
377
+ {
378
+ externalId: 'imap-uid-1001',
379
+ payload: {
380
+ subject: 'Welcome to upgraide',
381
+ from: 'noreply@upgraide.dev',
382
+ receivedAt: '2026-04-28T13:21:32Z',
383
+ labels: ['inbox', 'unread'],
384
+ },
385
+ },
386
+ { externalId: 'imap-uid-1002', payload: { subject: 'Your weekly digest' } },
387
+ ],
388
+ });
389
+ // → { inserted: 2, updated: 0 }
390
+
391
+ // Cursor-paginated read.
392
+ let cursor: string | null = null;
393
+ do {
394
+ const page = await folder.listMessages({ limit: 100, cursor: cursor ?? undefined });
395
+ for (const m of page.items) {
396
+ // m.externalId, m.payload, m.createdAt, m.updatedAt
397
+ }
398
+ cursor = page.nextCursor;
399
+ } while (cursor);
400
+
401
+ // Single-message lookup.
402
+ const msg = await folder.getMessage({ externalId: 'imap-uid-1001' });
403
+
404
+ // Bulk delete; missing ids are silently skipped.
405
+ const del = await folder.deleteBatch({
406
+ externalIds: ['imap-uid-1001', 'imap-uid-1002'],
407
+ });
408
+ // → { deleted: 2 }
409
+ ```
410
+
411
+ ### Attachments
412
+
413
+ Attachments follow Drive's upload-intent contract (start → PUT bytes →
414
+ commit) but are scoped to a single message. The per-message Drive folder is
415
+ created lazily on the first `uploadStart` call.
416
+
417
+ ```ts
418
+ const message = folder.message({ externalId: 'imap-uid-1001' });
419
+
420
+ // 1. Begin upload -- get an intent + presigned URL.
421
+ const intent = await message.attachments.uploadStart({
422
+ attachmentId: 'att-1',
423
+ filename: 'invoice.pdf',
424
+ contentType: 'application/pdf',
425
+ sizeBytes: 12345,
426
+ });
427
+
428
+ // 2. PUT the bytes to intent.uploadUrl with header X-Upload-Intent-Id.
429
+ // (See Drive upload examples for streaming/buffer modes.)
430
+ const putRes = await fetch(intent.uploadUrl, {
431
+ method: 'PUT',
432
+ headers: { 'X-Upload-Intent-Id': intent.intentId, 'Content-Type': 'application/pdf' },
433
+ body: pdfBytes,
434
+ });
435
+ const { etag } = (await putRes.json()) as { etag: string };
436
+
437
+ // 3. Commit -- registers the attachment row.
438
+ await message.attachments.uploadCommit({
439
+ attachmentId: 'att-1',
440
+ intentId: intent.intentId,
441
+ etag,
442
+ });
443
+
444
+ // Enumerate this message's attachments.
445
+ const list = await message.attachments.list();
446
+
447
+ // Presigned download URL (with explicit expiresAt).
448
+ const dl = await message.attachments.downloadUrl({ attachmentId: 'att-1' });
449
+
450
+ // Delete the attachment row + its Drive file.
451
+ await message.attachments.delete({ attachmentId: 'att-1' });
452
+ ```
453
+
454
+ ### Auth modes
455
+
456
+ Same as the rest of the SDK -- both work:
457
+
458
+ ```ts
459
+ // API key (internal services / Tilt / port-forward).
460
+ const auth = diskd.auth.apiKey({ workspaceId: 'ws-...' });
461
+
462
+ // OAuth2 client-credentials (external clients).
463
+ const auth = await diskd.auth.credentials({
464
+ scopes: ['openid'],
465
+ keyfilePath: '.agents/credentials.json',
466
+ });
467
+
468
+ const messagesStore = diskd.os.messagesStore({ auth });
469
+ ```
470
+
471
+ Workspace identity is always auth-derived (`X-Workspace-Id` header from API
472
+ key, `ext.workspace_id` claim from OAuth JWT) -- never sent on the wire as a
473
+ parameter. See `examples/node/messages-store-example.ts` for a full
474
+ end-to-end walk-through.
475
+
476
+ Routines API
477
+ ------------
478
+
479
+ REST client for managing routines (automated workflows) scoped to profile or project:
480
+
481
+ ```ts
482
+ const routines = diskd.platform.routines({ auth });
483
+
484
+ // List routines in a scope
485
+ const all = await routines.list({ scope: 'workspace' });
486
+ const projectRoutines = await routines.list({ scope: 'project', projectName: 'my-project' });
487
+
488
+ // Get by slug
489
+ const routine = await routines.get({ slug: 'daily-summary', scope: 'workspace' });
490
+
491
+ // Create
492
+ const created = await routines.create({
493
+ name: 'Daily Summary',
494
+ scope: 'workspace',
495
+ operativeSlug: 'research-agent',
496
+ triggerType: 'rhythm',
497
+ trigger: { cron: '0 9 * * *' },
498
+ steps: [{ id: 'step-1', name: 'Summarize', action: 'summarize', order: 0 }],
499
+ });
500
+
501
+ // Update
502
+ const updated = await routines.update(
503
+ 'daily-summary',
504
+ { status: 'paused' },
505
+ { scopeType: 'workspace' },
506
+ );
507
+
508
+ // Delete
509
+ await routines.delete({ slug: 'daily-summary', scope: 'workspace' });
510
+ ```
511
+
512
+ Operatives API
513
+ --------------
514
+
515
+ REST client for managing operatives (AI agents) with attached files, skills, and MCP tools:
516
+
517
+ ```ts
518
+ const ops = diskd.platform.operatives({ auth });
519
+
520
+ // List operatives in a project
521
+ const list = await ops.list({ projectId: 'proj-1' });
522
+
523
+ // Get by id or slug
524
+ const operative = await ops.get('op-01');
525
+ const bySlug = await ops.getBySlug({ projectId: 'proj-1', slug: 'research-agent' });
526
+
527
+ // Create
528
+ const created = await ops.create({
529
+ projectId: 'proj-1',
530
+ name: 'Research Agent',
531
+ engine: 'deep',
532
+ engineProvider: 'anthropic',
533
+ engineModel: 'claude-4',
534
+ });
535
+
536
+ // Update
537
+ await ops.update('op-01', {
538
+ orders: 'You are a research assistant focused on academic papers.',
539
+ fileAccess: 'selected',
540
+ });
541
+
542
+ // Delete
543
+ await ops.delete('op-01');
544
+ ```
545
+
546
+ ### Operative files (Drive knowledge sources)
547
+
548
+ Attach Drive files from the operative's project chroot as knowledge sources:
549
+
550
+ ```ts
551
+ // Attach files (paths relative to project chroot)
552
+ await ops.files.add('op-01', { paths: ['/docs/knowledge-base', '/docs/readme.md'] });
553
+
554
+ // List attached files
555
+ const files = await ops.files.list('op-01');
556
+
557
+ // Detach a file
558
+ await ops.files.remove('op-01', files[0].id);
559
+ ```
560
+
561
+ ### Operative skills
562
+
563
+ ```ts
564
+ // Attach skills
565
+ await ops.skills.add('op-01', { refIds: ['web-search', 'code-review'] });
566
+
567
+ // List attached skills
568
+ const skills = await ops.skills.list('op-01');
569
+
570
+ // Detach a skill
571
+ await ops.skills.remove('op-01', skills[0].id);
572
+ ```
573
+
574
+ ### Operative MCP tools
575
+
576
+ ```ts
577
+ // Attach MCP tools
578
+ await ops.tools.add('op-01', { selectors: ['github/search_repos', 'slack/send_message'] });
579
+
580
+ // List attached tools
581
+ const tools = await ops.tools.list('op-01');
582
+
583
+ // Detach a tool
584
+ await ops.tools.remove('op-01', tools[0].id);
585
+ ```
586
+
587
+ Calendar API
588
+ ------------
589
+
590
+ REST client for workspace calendar management -- events, attendees, note links, attachments, and settings:
591
+
592
+ ```ts
593
+ const calendar = diskd.platform.calendar({ auth });
594
+
595
+ // Accounts and events
596
+ const accounts = await calendar.listAccounts();
597
+ const events = await calendar.listEvents({
598
+ startAfter: '2026-03-01T00:00:00Z',
599
+ startBefore: '2026-03-31T23:59:59Z',
600
+ });
601
+
602
+ // Event CRUD
603
+ const event = await calendar.createEvent({
604
+ calendarId: accounts[0].calendars[0].id,
605
+ title: 'Sprint Planning',
606
+ startAt: '2026-03-25T10:00:00Z',
607
+ endAt: '2026-03-25T11:00:00Z',
608
+ });
609
+
610
+ await calendar.updateEvent(event.id, {
611
+ title: 'Sprint Planning (updated)',
612
+ metadata: { timeBlockCategory: 'meeting' },
613
+ });
614
+
615
+ await calendar.deleteEvent(event.id);
616
+ ```
617
+
618
+ ### Attendees
619
+
620
+ ```ts
621
+ const attendee = await calendar.attendees.add(event.id, {
622
+ email: 'alice@example.com',
623
+ role: 'required',
624
+ });
625
+
626
+ await calendar.attendees.updateRsvp(event.id, attendee.id, 'yes');
627
+ await calendar.attendees.remove(event.id, attendee.id);
628
+ ```
629
+
630
+ ### Note links
631
+
632
+ ```ts
633
+ const link = await calendar.noteLinks.add(event.id, {
634
+ noteDiskPath: '/Projects/sprint/notes/planning.md',
635
+ title: 'Planning Notes',
636
+ linkType: 'context',
637
+ });
638
+
639
+ await calendar.noteLinks.remove(event.id, link.id);
640
+ ```
641
+
642
+ ### Attachments
643
+
644
+ ```ts
645
+ const attachment = await calendar.attachments.add(event.id, {
646
+ type: 'url',
647
+ title: 'Meeting Recording',
648
+ url: 'https://meet.example.com/recording/123',
649
+ });
650
+
651
+ await calendar.attachments.remove(event.id, attachment.id);
652
+ ```
653
+
654
+ ### Event metadata
655
+
656
+ Events support an extensible `metadata` JSONB field for cross-domain data:
657
+
658
+ ```ts
659
+ await calendar.updateEvent(event.id, {
660
+ metadata: {
661
+ timeBlockCategory: 'focus',
662
+ linkedNotes: [
663
+ { noteDiskPath: '/docs/spec.md', title: 'Spec', linkType: 'context' },
664
+ ],
665
+ },
666
+ });
667
+ ```
668
+
669
+ ### Settings
670
+
671
+ ```ts
672
+ const settings = await calendar.getSettings();
673
+ await calendar.updateSettings({
674
+ weekStartDay: 0,
675
+ defaultView: 'month',
676
+ timezone: 'America/New_York',
677
+ });
678
+ ```
679
+
680
+ Drive Database API
681
+ ------------------
682
+
683
+ JSON-RPC client for Drive's SQLite-backed database operations:
684
+
685
+ ```ts
686
+ const drive = diskd.os.drive({ version: 'v1', auth });
687
+
688
+ // Create a database with schema
689
+ const db = await drive.db.create({
690
+ name: 'myapp.workspace-123.main',
691
+ schema: {
692
+ users: {
693
+ id: { type: 'TEXT', primaryKey: true },
694
+ name: { type: 'TEXT', notNull: true },
695
+ email: { type: 'TEXT', notNull: true },
696
+ },
697
+ },
698
+ });
699
+
700
+ // Insert rows
701
+ await drive.db.insert({
702
+ name: 'myapp.workspace-123.main',
703
+ table: 'users',
704
+ rows: [{ id: '1', name: 'Alice', email: 'alice@example.com' }],
705
+ });
706
+
707
+ // Query with parameters
708
+ const result = await drive.db.query({
709
+ name: 'myapp.workspace-123.main',
710
+ sql: 'SELECT * FROM users WHERE id = ?',
711
+ parameters: ['1'],
712
+ });
713
+
714
+ // Commit, metadata, drop, resolve
715
+ await drive.db.commit({ name: 'myapp.workspace-123.main' });
716
+ const meta = await drive.db.metadata({ name: 'myapp.workspace-123.main' });
717
+ const resolved = await drive.db.resolveByInode({ dbInode: db.dbInode });
718
+ ```
719
+
720
+ Drive Repository (CRUD pattern)
721
+ --------------------------------
722
+
723
+ Higher-level database + table-scoped repository pattern -- ideal for services
724
+ that use Drive DB as their persistence layer:
725
+
726
+ ```ts
727
+ // Create database with schema
728
+ const db = diskd.os.database({
729
+ auth,
730
+ dbName: 'shop.workspace-123.main',
731
+ dbType: 'database',
732
+ schema: {
733
+ users: { id: { type: 'TEXT', primaryKey: true }, name: { type: 'TEXT', notNull: true } },
734
+ orders: { id: { type: 'TEXT', primaryKey: true }, user_id: { type: 'TEXT' }, total: { type: 'INTEGER' } },
735
+ },
736
+ });
737
+
738
+ await db.ensureCreated();
739
+
740
+ // Get table-scoped repositories
741
+ const users = db.repository('users');
742
+ const orders = db.repository('orders');
743
+
744
+ // Insert
745
+ await users.insert([{ id: 'u1', name: 'Alice' }, { id: 'u2', name: 'Bob' }]);
746
+
747
+ // Find with where, orderBy, limit, offset
748
+ const results = await users.find({
749
+ where: { name: 'Alice' },
750
+ orderBy: { column: 'name', direction: 'ASC' },
751
+ limit: 10,
752
+ });
753
+
754
+ // Find one (returns null if not found)
755
+ const alice = await users.findOne({ id: 'u1' });
756
+
757
+ // Count
758
+ const total = await orders.count();
759
+ const pending = await orders.count({ status: 'pending' });
760
+
761
+ // Update
762
+ await orders.update({ where: { id: 'o1' }, set: { status: 'shipped' } });
763
+
764
+ // Delete
765
+ await orders.deleteRows({ status: 'cancelled' });
766
+
767
+ // Raw SQL at database level for joins and complex queries
768
+ const summary = await db.query(`
769
+ SELECT u.name, SUM(o.total) AS revenue
770
+ FROM users u JOIN orders o ON o.user_id = u.id
771
+ GROUP BY u.id ORDER BY revenue DESC
772
+ `);
773
+
774
+ // Commit and metadata (database-level operations)
775
+ await db.commit();
776
+ const meta = await db.metadata();
777
+ ```
778
+
779
+ See `examples/node/drive-db-repository-example.ts`.
780
+
781
+ TypeORM Driver (`diskd.os.datasource()`)
782
+ -------------------------------------
783
+
784
+ Use TypeORM entities, relations, and repositories against Drive DB. SQL is routed
785
+ through Drive DB JSON-RPC, and TypeORM's transaction lifecycle maps to Drive DB's
786
+ commit/rollback semantics. Requires `typeorm` as a peer dependency.
787
+
788
+ ### Installation
789
+
790
+ ```bash
791
+ npm install @diskd-ai/sdk typeorm
792
+ ```
793
+
794
+ ### Usage
795
+
796
+ ```ts
797
+ import { diskd } from '@diskd-ai/sdk';
798
+ import { Entity, PrimaryColumn, Column } from 'typeorm';
799
+
800
+ // Define entities
801
+ @Entity({ name: 'users' })
802
+ class User {
803
+ @PrimaryColumn({ type: 'varchar', length: 26 })
804
+ id!: string;
805
+
806
+ @Column({ type: 'varchar' })
807
+ name!: string;
808
+
809
+ @Column({ type: 'varchar' })
810
+ email!: string;
811
+ }
812
+
813
+ // Create DataSource backed by Drive DB
814
+ process.env.APIS_BASE_URL ??= 'https://apis.diskd.local:8080';
815
+
816
+ const auth = diskd.auth.apiKey({ workspaceId: 'workspace-123' });
817
+
818
+ const ds = diskd.os.datasource({
819
+ auth,
820
+ url: `${process.env.APIS_BASE_URL}/v1/os/database/api/v1`,
821
+ dbName: 'shop.workspace-123.main',
822
+ entities: [User],
823
+ synchronize: true,
824
+ });
825
+
826
+ await ds.initialize();
827
+
828
+ // Standard TypeORM repository operations
829
+ const userRepo = ds.getRepository(User);
830
+ await userRepo.save({ id: 'u1', name: 'Alice', email: 'alice@example.com' });
831
+
832
+ const alice = await userRepo.findOneBy({ id: 'u1' });
833
+ const users = await userRepo.find({ order: { name: 'ASC' } });
834
+
835
+ // Persist to S3 (flush WAL)
836
+ await ds.driver.commit();
837
+
838
+ // Rollback discards uncommitted changes (revert to last commit)
839
+ await ds.driver.driveRollback();
840
+ ```
841
+
842
+ ### Transaction mapping
843
+
844
+ | TypeORM operation | Drive DB action |
845
+ |------------------------|----------------------------------------|
846
+ | `BEGIN TRANSACTION` | No-op (writes auto-accumulate in WAL) |
847
+ | `COMMIT` | `drive.db.commit()` -- flush WAL to S3 |
848
+ | `ROLLBACK` | `drive.db.rollback()` -- discard WAL |
849
+
850
+ ### Limitations (v1)
851
+
852
+ - No nested transactions / savepoints (deferred to v2)
853
+ - Affected row count returns 0 (each JSON-RPC call is a separate SQLite
854
+ connection; works fine for ULID-based entities)
855
+ - Schema introspection from live database is limited; `synchronize: true`
856
+ generates DDL directly
857
+
858
+ See `examples/node/typeorm-drive-example.ts` and `docs/typeorm-driver-design.md`.
859
+
860
+ LLM Router API
861
+ --------------
862
+
863
+ JSON-RPC 2.0 + NDJSON streaming for multi-provider LLM completions:
864
+
865
+ ```ts
866
+ const llm = diskd.os.llm({ auth });
867
+
868
+ // Non-streaming completion
869
+ const result = await llm.completions.create({
870
+ provider: 'openai', model: 'gpt-4o-mini',
871
+ messages: [{ role: 'user', content: 'Hello' }],
872
+ maxTokens: 64,
873
+ });
874
+
875
+ // Streaming
876
+ for await (const chunk of llm.completions.stream(params)) {
877
+ process.stdout.write(chunk.choices[0]?.delta?.content ?? '');
878
+ }
879
+
880
+ // Models, embeddings, OCR, audio transcription
881
+ const models = await llm.models.listAll();
882
+ const embeddings = await llm.embeddings.create({ provider: 'openai', model: 'text-embedding-3-small', input: ['text'] });
883
+ ```
884
+
885
+ See `examples/node/llm-router-example.ts`.
886
+
887
+ Agent Hub API
888
+ -------------
889
+
890
+ SSE streaming with `StreamProtocolHandler` + `StreamProtocolFetcher` for agent invocation:
891
+
892
+ ```ts
893
+ import { diskd, StreamProtocolHandler } from '@diskd-ai/sdk';
894
+
895
+ const agents = diskd.os.agents({ auth, workspaceId: '...' });
896
+
897
+ // List agents and models
898
+ const agentList = await agents.agents.list();
899
+ const models = await agents.agents.getSupportedModels('assistant');
900
+ const billing = await agents.billing.getAliases();
901
+
902
+ // Invoke with fluent stream handling
903
+ const handler = new StreamProtocolHandler()
904
+ .on('response.output_text.delta', (e) => process.stdout.write(e.delta))
905
+ .on('response.completed', (e) => console.log('done', e.response.usage))
906
+ .on('response.failed', (e) => console.error(e.response.error.message))
907
+ .on('error', (e) => console.error(e.message));
908
+
909
+ const stream = await agents.invoke({
910
+ agentName: 'assistant',
911
+ query: 'Hello',
912
+ agentOptions: { maxTokens: 256 },
913
+ });
914
+
915
+ stream.map((event) => handler.handle(event))
916
+ .stop(() => console.log('stream closed'))
917
+ .catch((err) => console.error(err));
918
+ ```
919
+
920
+ Stream protocol events include text deltas, function calls/results, content parts
921
+ (images, files, audio), web/file search lifecycle, external sources, plan updates,
922
+ notifications, and error/completion signals.
923
+
924
+ See `examples/node/agent-hub-example.ts`.
925
+
926
+ MCP Hub API
927
+ -----------
928
+
929
+ REST client for MCP server catalog, registry, and integrations:
930
+
931
+ ```ts
932
+ const mcp = diskd.os.mcp({ auth, workspaceId: '...' });
933
+
934
+ // Catalog
935
+ const catalog = await mcp.catalog.list({ search: 'github' });
936
+ const details = await mcp.catalog.getServerDetails(serverId);
937
+
938
+ // Registry (installed servers)
939
+ const registry = await mcp.registry.list();
940
+ const added = await mcp.registry.addServer({ catalogServerId: '...' });
941
+ await mcp.registry.toggleTool(serverId, toolId, false);
942
+ const logs = await mcp.registry.getServerLogs(serverId, { limit: 10 });
943
+ await mcp.registry.deleteServer(serverId);
944
+
945
+ // Env vars, connection settings, remote servers
946
+ await mcp.registry.upsertEnvVar(serverId, { key: 'TOKEN', value: '...' });
947
+ await mcp.registry.addRemoteServer({ name: 'My MCP', url: '...', authType: 'pat' });
948
+ ```
949
+
950
+ See `examples/node/mcp-hub-example.ts`.
951
+
952
+ Telegram Userbot API
953
+ --------------------
954
+
955
+ REST client for Telegram channel resolution, importing, and message retrieval:
956
+
957
+ ```ts
958
+ const tg = diskd.utils.tgUserBot({ auth, workspaceId: '...' });
959
+
960
+ // Resolve channel (public, no auth required)
961
+ const resolved = await tg.channels.resolve('durov');
962
+
963
+ // Channel operations
964
+ const channels = await tg.channels.list();
965
+ await tg.channels.add({ channelIdentifier: '@mychannel', limit: 1000 });
966
+ await tg.channels.sync({ telegramId: -1001234567890 });
967
+
968
+ // Messages and stats
969
+ const messages = await tg.channels.getMessages(channelId, { limit: 50, searchText: 'keyword' });
970
+ const stats = await tg.channels.getStats(channelId);
971
+ const status = await tg.channels.getStatus(channelId);
972
+
973
+ // Tasks
974
+ const tasks = await tg.tasks.list();
975
+ await tg.tasks.cancel(taskUuid);
976
+ ```
977
+
978
+ See `examples/node/tg-userbot-example.ts`.
979
+
980
+ Web Navigator API
981
+ -----------------
982
+
983
+ REST client for URL resolution and web scraping jobs:
984
+
985
+ ```ts
986
+ const webNav = diskd.utils.webNavigator({ auth, workspaceId: '...' });
987
+
988
+ // Resolve URL metadata
989
+ const meta = await webNav.resolve({ url: 'https://example.com' });
990
+
991
+ // Submit scrape job
992
+ const job = await webNav.scrape.submit({ url: 'https://example.com', depth: 1, maxPages: 10 });
993
+ const status = await webNav.scrape.getStatus(job.jobId);
994
+ const result = await webNav.scrape.getResult(job.jobId);
995
+ await webNav.scrape.cancel(job.jobId);
996
+ ```
997
+
998
+ See `examples/node/web-navigator-example.ts`.
999
+
1000
+ Web quickstart (Vite + PKCE)
1001
+ ----------------------------
1002
+
1003
+ Use `@diskd-ai/sdk/browser` and a standard OAuth2 Authorization Code + PKCE redirect.
1004
+
1005
+ Runnable example: `examples/web/` (see `examples/README.md`).
1006
+
1007
+ Publishing a new version
1008
+ ------------------------
1009
+
1010
+ 1. Bump the version in `package.json`:
1011
+
1012
+ ```bash
1013
+ npm version patch # 0.3.0 -> 0.3.1
1014
+ npm version minor # 0.3.0 -> 0.4.0
1015
+ npm version major # 0.3.0 -> 1.0.0
1016
+ ```
1017
+
1018
+ 2. Push the commit and tag:
1019
+
1020
+ ```bash
1021
+ git push gitlab main --tags
1022
+ ```
1023
+
1024
+ 3. The GitLab CI pipeline triggers on `v*.*.*` tags and automatically:
1025
+ - Builds the project
1026
+ - Runs unit tests and typecheck
1027
+ - Publishes to the GitLab Package Registry
1028
+
1029
+ 4. Verify at: `https://gitlab.iosya.com/upgraide-v2/platform-api/-/packages`
1030
+
1031
+ Docs and examples
1032
+ -----------------
1033
+
1034
+ - Quickstart: `docs/sdk-quickstart.md`
1035
+ - Examples: `examples/README.md`
1036
+ - Design: `docs/drive-session-sdk-design.md`