@xopcai/xopc 0.0.163 → 0.0.164

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 (166) hide show
  1. package/dist/browser-ext/manifest.json +1 -1
  2. package/dist/extensions/telegram/xopc.extension.json +1 -1
  3. package/dist/gateway/static/root/assets/{activity-store-Xj95LzTv.js → activity-store-DkALQFJT.js} +1 -1
  4. package/dist/gateway/static/root/assets/{agent-avatar-dicebear-C-QeUFwU.js → agent-avatar-dicebear-RpxkQtQ3.js} +1 -1
  5. package/dist/gateway/static/root/assets/agents-CxpwxMPE.js +2 -0
  6. package/dist/gateway/static/root/assets/{api-BTLmAm1_.js → api-DPIXEcIq.js} +1 -1
  7. package/dist/gateway/static/root/assets/{app-management-settings-panel-zc6Gf-S5.js → app-management-settings-panel-DLdjfMXB.js} +1 -1
  8. package/dist/gateway/static/root/assets/{appearance-settings-0fMLnOWn.js → appearance-settings-C89-uxkq.js} +1 -1
  9. package/dist/gateway/static/root/assets/apps-page-k-tZbaRB.js +1 -0
  10. package/dist/gateway/static/root/assets/{archive-plugin-DOiR_E21.js → archive-plugin-CqbH5geE.js} +1 -1
  11. package/dist/gateway/static/root/assets/{attachment-load-BxmYl1D1.js → attachment-load-CeU4Qiot.js} +1 -1
  12. package/dist/gateway/static/root/assets/{automation-suggestion-card-BhZOirad.js → automation-suggestion-card-WiOuqXq9.js} +1 -1
  13. package/dist/gateway/static/root/assets/automations-page-Bdn3dgC_.js +6 -0
  14. package/dist/gateway/static/root/assets/{binary-plugins-DTTKsvgk.js → binary-plugins-C5TdzrhJ.js} +1 -1
  15. package/dist/gateway/static/root/assets/{block-editor-C7se7iqg.js → block-editor-BjvWhphG.js} +47 -47
  16. package/dist/gateway/static/root/assets/browser-settings-page-GsVTGfGs.js +8 -0
  17. package/dist/gateway/static/root/assets/{browser-workflow-inputs-kxmStCcv.js → browser-workflow-inputs-DXmzQ3nk.js} +1 -1
  18. package/dist/gateway/static/root/assets/{browser-workflows-page-CwYf9OM_.js → browser-workflows-page-C1-ptRe4.js} +2 -2
  19. package/dist/gateway/static/root/assets/capabilities-settings-panel-6d4kVjzl.js +2 -0
  20. package/dist/gateway/static/root/assets/{capability-presets-api-BZKh2cWX.js → capability-presets-api-C0pVlUyc.js} +1 -1
  21. package/dist/gateway/static/root/assets/capability-presets-settings-panel-DCxy5Ls_.js +2 -0
  22. package/dist/gateway/static/root/assets/{channel-recipient-api-r7tdbnJE.js → channel-recipient-api-B5rLegwk.js} +1 -1
  23. package/dist/gateway/static/root/assets/channels-settings-Bg3P8k0f.js +1 -0
  24. package/dist/gateway/static/root/assets/channels-status-swr-DZZq0upi.js +1 -0
  25. package/dist/gateway/static/root/assets/{connector-logo-BpnQYAxA.js → connector-logo-CuI5w4qM.js} +1 -1
  26. package/dist/gateway/static/root/assets/connectors-page-6UR7yhIZ.js +2 -0
  27. package/dist/gateway/static/root/assets/desktop-pet-BvG8vDXZ.js +1 -0
  28. package/dist/gateway/static/root/assets/{desktop-pet-settings-uv8Grtgk.js → desktop-pet-settings-CR__kZ8C.js} +1 -1
  29. package/dist/gateway/static/root/assets/{directory-picker-path-field-C4TTvf7p.js → directory-picker-path-field-BblWMz3e.js} +1 -1
  30. package/dist/gateway/static/root/assets/{dreaming-settings-CzJAUPvM.js → dreaming-settings-DHMPugDE.js} +3 -3
  31. package/dist/gateway/static/root/assets/{extension-debug-page-Ci2mOYUt.js → extension-debug-page-ByVY1gZg.js} +1 -1
  32. package/dist/gateway/static/root/assets/{extension-page-DeXdmhXQ.js → extension-page-DLCKKtbK.js} +1 -1
  33. package/dist/gateway/static/root/assets/{extension-settings-page-C93vaOsU.js → extension-settings-page-M-rhlFBC.js} +1 -1
  34. package/dist/gateway/static/root/assets/{gateway-config-api-C31Hlblp.js → gateway-config-api-DZHqhbXH.js} +1 -1
  35. package/dist/gateway/static/root/assets/{gateway-settings-D3zS6RZh.js → gateway-settings-CZswIehx.js} +1 -1
  36. package/dist/gateway/static/root/assets/{gateway-startup-retry-CSRvCqxh.js → gateway-startup-retry-ulwTJovP.js} +1 -1
  37. package/dist/gateway/static/root/assets/goal-create-dialog-TbyRfDas.js +1 -0
  38. package/dist/gateway/static/root/assets/goal-detail-page-B-QBVOf2.js +4 -0
  39. package/dist/gateway/static/root/assets/{goals-config-api-D4wYNRrf.js → goals-config-api-DMxG6f0N.js} +1 -1
  40. package/dist/gateway/static/root/assets/goals-page-BGxki8BR.js +2 -0
  41. package/dist/gateway/static/root/assets/{goals-settings-Bx2jVvhQ.js → goals-settings-G-w1gCYD.js} +1 -1
  42. package/dist/gateway/static/root/assets/{heartbeat-settings-BEIF1eXy.js → heartbeat-settings-Csb90R59.js} +1 -1
  43. package/dist/gateway/static/root/assets/{index-HZdBKfk_.js → index-CGwuxvzr.js} +70 -70
  44. package/dist/gateway/static/root/assets/{keyboard-shortcuts-settings-DOEDpvTM.js → keyboard-shortcuts-settings-C_Bl3YOr.js} +1 -1
  45. package/dist/gateway/static/root/assets/local-app-workbench-page-BR2tBhO3.js +2 -0
  46. package/dist/gateway/static/root/assets/{local-apps-page-B0OpGpxv.js → local-apps-page-_8Rv-tSk.js} +1 -1
  47. package/dist/gateway/static/root/assets/{locale-store-Ys6RP7Be.js → locale-store-C_ax27uc.js} +1 -1
  48. package/dist/gateway/static/root/assets/logs-page-CwF0C_Z2.js +7 -0
  49. package/dist/gateway/static/root/assets/{markdown-split-CEZwysCH.js → markdown-split-CZnZS6gq.js} +1 -1
  50. package/dist/gateway/static/root/assets/{media-plugins-CpGKE7B0.js → media-plugins-C2XLYC6G.js} +1 -1
  51. package/dist/gateway/static/root/assets/{messages-BzI9Wx30.js → messages-C96Zjb0V.js} +2 -2
  52. package/dist/gateway/static/root/assets/{notes-page-CdiuDZ5a.js → notes-page-BkuZxTFo.js} +1 -1
  53. package/dist/gateway/static/root/assets/notes-workbench-CD4FADi7.js +4 -0
  54. package/dist/gateway/static/root/assets/{page-tabs-BkH5AVV2.js → page-tabs-DR2FGC4E.js} +1 -1
  55. package/dist/gateway/static/root/assets/{preview-open-alternatives-CQai8f9D.js → preview-open-alternatives-B65O8wBL.js} +1 -1
  56. package/dist/gateway/static/root/assets/{product-open-page-B2kSdB2b.js → product-open-page-Cag-utLH.js} +1 -1
  57. package/dist/gateway/static/root/assets/project-detail-page-COKtUblD.js +1 -0
  58. package/dist/gateway/static/root/assets/projects-page-QYmqanBN.js +1 -0
  59. package/dist/gateway/static/root/assets/remote-access-hub-BU_gBU0f.js +1 -0
  60. package/dist/gateway/static/root/assets/{save-bar-controls-NGYnO7n7.js → save-bar-controls-DCWpFnPc.js} +1 -1
  61. package/dist/gateway/static/root/assets/{schedule-field-nLOphnv3.js → schedule-field-ClacZdvE.js} +1 -1
  62. package/dist/gateway/static/root/assets/{schema-form-D0e90ndE.js → schema-form-BVlbEipU.js} +1 -1
  63. package/dist/gateway/static/root/assets/sessions-page-u-Pjbzfm.js +1 -0
  64. package/dist/gateway/static/root/assets/settings-advanced-gate-1Yck1PKq.js +1 -0
  65. package/dist/gateway/static/root/assets/{settings-form-section-X2Sl-EAk.js → settings-form-section-GSNlQWSW.js} +1 -1
  66. package/dist/gateway/static/root/assets/{settings-loading-skeleton-DOnUabm7.js → settings-loading-skeleton-08Ae5sB_.js} +1 -1
  67. package/dist/gateway/static/root/assets/{settings-page-C4UUNi1n.js → settings-page-BseJD4I-.js} +1 -1
  68. package/dist/gateway/static/root/assets/{settings-page-layout-C1yYqbT6.js → settings-page-layout-bSliH-Y3.js} +1 -1
  69. package/dist/gateway/static/root/assets/setup-status-panel-CGRhJVlt.js +1 -0
  70. package/dist/gateway/static/root/assets/{share-preview-page-Cfy_pH7V.js → share-preview-page-C114OpTx.js} +1 -1
  71. package/dist/gateway/static/root/assets/shares-settings-BRFpWFgI.js +1 -0
  72. package/dist/gateway/static/root/assets/skill-reload-api-cVjU2GnN.js +1 -0
  73. package/dist/gateway/static/root/assets/skills-page-CoMTjtRT.js +2 -0
  74. package/dist/gateway/static/root/assets/{system-settings-panel-Da81RJ6G.js → system-settings-panel-El8cDcTY.js} +1 -1
  75. package/dist/gateway/static/root/assets/{theme-store-DflSp9o4.js → theme-store-D37XLD_C.js} +1 -1
  76. package/dist/gateway/static/root/assets/{time-picker-BIkOW-2L.js → time-picker-CU7hhD8T.js} +1 -1
  77. package/dist/gateway/static/root/assets/{typed-models-lib--HptwFcD.js → typed-models-lib-kToxD7Rc.js} +1 -1
  78. package/dist/gateway/static/root/assets/{use-channel-catalog-CMHY4ZfW.js → use-channel-catalog-DBh0dOC9.js} +1 -1
  79. package/dist/gateway/static/root/assets/user-context-page-C0xYCSXB.js +1 -0
  80. package/dist/gateway/static/root/assets/{voice-api-key-field-nvIZerol.js → voice-api-key-field-DzEpwYaU.js} +1 -1
  81. package/dist/gateway/static/root/assets/work-discovery-page-DakZqR85.js +1 -0
  82. package/dist/gateway/static/root/assets/work-item-detail-page-CswqPbTT.js +1 -0
  83. package/dist/gateway/static/root/assets/work-page-DYRXEk8m.js +1 -0
  84. package/dist/gateway/static/root/assets/{workflow-run-setup-panel-D96MHABy.js → workflow-run-setup-panel-BwSxyVMM.js} +2 -2
  85. package/dist/gateway/static/root/assets/workflows-page-CiLSYGuN.js +11 -0
  86. package/dist/gateway/static/root/index.html +6 -6
  87. package/dist/package.js +1 -1
  88. package/dist/src/agent/embedded/model-runtime.d.ts +4 -0
  89. package/dist/src/agent/embedded/model-runtime.js +49 -0
  90. package/dist/src/agent/embedded/session-runner.js +3 -3
  91. package/dist/src/auth/credentials.js +45 -2
  92. package/dist/src/auth/index.js +2 -1
  93. package/dist/src/auth/oauth/anthropic.js +27 -24
  94. package/dist/src/auth/oauth/github-copilot.js +20 -15
  95. package/dist/src/auth/oauth/google-antigravity.js +9 -2
  96. package/dist/src/auth/oauth/google-gemini-cli.js +9 -2
  97. package/dist/src/auth/oauth/google-oauth/google-antigravity.js +47 -40
  98. package/dist/src/auth/oauth/google-oauth/google-gemini-cli.js +48 -41
  99. package/dist/src/auth/oauth/google-oauth/oauth-page.js +7 -2
  100. package/dist/src/auth/oauth/google-oauth/pkce.js +4 -1
  101. package/dist/src/auth/oauth/index.d.ts +2 -0
  102. package/dist/src/auth/oauth/index.js +24 -10
  103. package/dist/src/auth/oauth/kimi-coding.js +76 -71
  104. package/dist/src/auth/oauth/minimax-cn.js +78 -73
  105. package/dist/src/auth/oauth/minimax.js +78 -73
  106. package/dist/src/auth/oauth/openai-codex.js +31 -25
  107. package/dist/src/auth/oauth/pkce.js +4 -1
  108. package/dist/src/auth/oauth/registry.d.ts +13 -0
  109. package/dist/src/auth/oauth/registry.js +65 -0
  110. package/dist/src/auth/oauth/xopc-cloud.d.ts +2 -0
  111. package/dist/src/auth/oauth/xopc-cloud.js +101 -0
  112. package/dist/src/auth/sync-provider-auth.js +5 -0
  113. package/dist/src/cli/utils/oauth-providers.d.ts +3 -26
  114. package/dist/src/cli/utils/oauth-providers.js +6 -80
  115. package/dist/src/config/models-json.js +8 -0
  116. package/dist/src/gateway/heartbeat/service.js +1 -1
  117. package/dist/src/gateway/hono/oauth-async.js +3 -19
  118. package/dist/src/gateway/hono/oauth.js +3 -19
  119. package/dist/src/gateway/hono/routes/models.js +1 -55
  120. package/dist/src/heartbeat/index.js +1 -1
  121. package/dist/src/providers/domestic-presets.d.ts +0 -20
  122. package/dist/src/providers/domestic-presets.js +0 -25
  123. package/dist/src/providers/index.js +9 -0
  124. package/dist/src/providers/model-catalog-store.d.ts +20 -58
  125. package/dist/src/providers/model-catalog-store.js +18 -57
  126. package/dist/src/providers/model-catalog-sync-service.d.ts +3 -4
  127. package/dist/src/providers/model-catalog-sync-service.js +3 -13
  128. package/dist/src/providers/model-registry.js +0 -2
  129. package/dist/src/providers/xopc-cloud-model-source.d.ts +30 -0
  130. package/dist/src/providers/xopc-cloud-model-source.js +68 -0
  131. package/dist/src/work-discovery/analyzer.js +27 -14
  132. package/package.json +1 -1
  133. package/dist/gateway/static/root/assets/agents-DVKlWKJE.js +0 -2
  134. package/dist/gateway/static/root/assets/apps-page-BZXEJDIV.js +0 -1
  135. package/dist/gateway/static/root/assets/automations-page-B8CnkoXv.js +0 -6
  136. package/dist/gateway/static/root/assets/browser-settings-page-BCPWKI9V.js +0 -8
  137. package/dist/gateway/static/root/assets/capabilities-settings-panel-C7lr_mX2.js +0 -2
  138. package/dist/gateway/static/root/assets/capability-presets-settings-panel-Ble9kHRu.js +0 -2
  139. package/dist/gateway/static/root/assets/channels-settings-CtQQQHrv.js +0 -1
  140. package/dist/gateway/static/root/assets/channels-status-swr-_VirfMKW.js +0 -1
  141. package/dist/gateway/static/root/assets/connectors-page-BXWJSJeY.js +0 -2
  142. package/dist/gateway/static/root/assets/desktop-pet-B86W4a5c.js +0 -1
  143. package/dist/gateway/static/root/assets/goal-create-dialog-CWp2b7__.js +0 -1
  144. package/dist/gateway/static/root/assets/goal-detail-page-Dtm29FxD.js +0 -4
  145. package/dist/gateway/static/root/assets/goals-page-jMzBJs6e.js +0 -2
  146. package/dist/gateway/static/root/assets/local-app-workbench-page-CseW9jD3.js +0 -2
  147. package/dist/gateway/static/root/assets/logs-page-DVqPbth5.js +0 -7
  148. package/dist/gateway/static/root/assets/notes-workbench-mrc3xtpn.js +0 -4
  149. package/dist/gateway/static/root/assets/project-detail-page-CfhPJLkH.js +0 -1
  150. package/dist/gateway/static/root/assets/projects-page-BfMoKjdm.js +0 -1
  151. package/dist/gateway/static/root/assets/remote-access-hub-CrDtcsZ9.js +0 -1
  152. package/dist/gateway/static/root/assets/sessions-page-D3DbF3dV.js +0 -1
  153. package/dist/gateway/static/root/assets/settings-advanced-gate-BZp0O2dH.js +0 -1
  154. package/dist/gateway/static/root/assets/setup-status-panel-84iao4DZ.js +0 -1
  155. package/dist/gateway/static/root/assets/shares-settings-DtcwQvRG.js +0 -1
  156. package/dist/gateway/static/root/assets/skill-reload-api-L7j5Gc8Z.js +0 -1
  157. package/dist/gateway/static/root/assets/skills-page-1Ps8PjsP.js +0 -2
  158. package/dist/gateway/static/root/assets/user-context-page-BYAAs2iW.js +0 -1
  159. package/dist/gateway/static/root/assets/work-discovery-page-J35JkJ7_.js +0 -1
  160. package/dist/gateway/static/root/assets/work-item-detail-page-C4wYDYqV.js +0 -1
  161. package/dist/gateway/static/root/assets/work-page-DMvitV6c.js +0 -1
  162. package/dist/gateway/static/root/assets/workflows-page-JMN0nMbM.js +0 -11
  163. package/dist/src/agent/embedded/xopc-auth-storage.d.ts +0 -19
  164. package/dist/src/agent/embedded/xopc-auth-storage.js +0 -40
  165. package/dist/src/providers/xopc-cloud-connection.d.ts +0 -51
  166. package/dist/src/providers/xopc-cloud-connection.js +0 -196
@@ -1,19 +0,0 @@
1
- import { InMemoryCredentialStore } from '@earendil-works/pi-ai';
2
- import { ModelRuntime } from '@earendil-works/pi-coding-agent';
3
- /**
4
- * Resolve API keys the same way as {@link AgentManager} / gateway settings:
5
- * auth-profiles (agent + global), OAuth files, models.json, then env.
6
- */
7
- export declare function resolveXopcProviderApiKey(providerId: string): string | undefined;
8
- /**
9
- * pi-coding-agent {@link createAgentSession} defaults to `~/.pi/agent/auth.json` and env.
10
- * Gateway / webchat turns inject xopc credentials through {@link applyXopcProviderApiKey}.
11
- */
12
- export declare function createEmbeddedCredentialStore(): InMemoryCredentialStore;
13
- /** Create the pi model runtime used by embedded gateway / channel turns. */
14
- export declare function createEmbeddedModelRuntime(): Promise<ModelRuntime>;
15
- /**
16
- * Inject the resolved key as a runtime override (highest-priority, in-memory only) before
17
- * the session starts so request-time auth resolution finds it.
18
- */
19
- export declare function applyXopcProviderApiKey(modelRuntime: Pick<ModelRuntime, 'setRuntimeApiKey'>, providerId: string): Promise<void>;
@@ -1,40 +0,0 @@
1
- import { init_paths, resolveModelsJsonPath } from "../../config/paths.js";
2
- import { init_sync_provider_auth, resolveProviderApiKeySync } from "../../auth/sync-provider-auth.js";
3
- import { getApiKeySync, init_providers } from "../../providers/index.js";
4
- import { ModelRuntime } from "@earendil-works/pi-coding-agent";
5
- import { InMemoryCredentialStore } from "@earendil-works/pi-ai";
6
- //#region src/agent/embedded/xopc-auth-storage.ts
7
- init_sync_provider_auth();
8
- init_paths();
9
- init_providers();
10
- /**
11
- * Resolve API keys the same way as {@link AgentManager} / gateway settings:
12
- * auth-profiles (agent + global), OAuth files, models.json, then env.
13
- */
14
- function resolveXopcProviderApiKey(providerId) {
15
- return resolveProviderApiKeySync(providerId) ?? getApiKeySync(providerId);
16
- }
17
- /**
18
- * pi-coding-agent {@link createAgentSession} defaults to `~/.pi/agent/auth.json` and env.
19
- * Gateway / webchat turns inject xopc credentials through {@link applyXopcProviderApiKey}.
20
- */
21
- function createEmbeddedCredentialStore() {
22
- return new InMemoryCredentialStore();
23
- }
24
- /** Create the pi model runtime used by embedded gateway / channel turns. */
25
- function createEmbeddedModelRuntime() {
26
- return ModelRuntime.create({
27
- credentials: createEmbeddedCredentialStore(),
28
- modelsPath: resolveModelsJsonPath()
29
- });
30
- }
31
- /**
32
- * Inject the resolved key as a runtime override (highest-priority, in-memory only) before
33
- * the session starts so request-time auth resolution finds it.
34
- */
35
- async function applyXopcProviderApiKey(modelRuntime, providerId) {
36
- const key = resolveXopcProviderApiKey(providerId);
37
- if (key && key !== "extension-managed") await modelRuntime.setRuntimeApiKey(providerId, key, { allowNetwork: false });
38
- }
39
- //#endregion
40
- export { applyXopcProviderApiKey, createEmbeddedCredentialStore, createEmbeddedModelRuntime, resolveXopcProviderApiKey };
@@ -1,51 +0,0 @@
1
- import { type CredentialResolver } from '../auth/credentials.js';
2
- import { type ModelCatalogStore } from './model-catalog-store.js';
3
- export interface XopcCloudConnectionOptions {
4
- fetchImpl?: typeof fetch;
5
- consoleUrl?: string;
6
- routerUrl?: string;
7
- deviceIdPath?: string;
8
- catalogStore?: ModelCatalogStore;
9
- credentials?: Pick<CredentialResolver, 'saveApiKey' | 'revealGatewayStoredApiKey' | 'deleteProfile'>;
10
- refreshModels?: () => void;
11
- now?: () => number;
12
- }
13
- export type XopcCloudPollResult = {
14
- status: 'pending';
15
- } | {
16
- status: 'connected';
17
- modelCount: number;
18
- models: string[];
19
- recommendedModel: string | null;
20
- };
21
- export declare class XopcCloudHttpError extends Error {
22
- readonly status: number;
23
- readonly code?: string;
24
- constructor(message: string, status: number, code?: string);
25
- }
26
- export declare class XopcCloudConnectionService {
27
- private readonly pending;
28
- private readonly fetchImpl;
29
- private readonly consoleUrl;
30
- private readonly routerUrl;
31
- private readonly deviceIdPath;
32
- private readonly catalogStore;
33
- private readonly credentials;
34
- private readonly refreshModels;
35
- private readonly now;
36
- constructor(options?: XopcCloudConnectionOptions);
37
- start(clientType: 'electron' | 'web' | 'cli'): Promise<{
38
- requestId: string;
39
- authorizationUrl: string;
40
- expiresIn: number;
41
- pollInterval: number;
42
- }>;
43
- poll(requestId: string): Promise<XopcCloudPollResult>;
44
- refreshCatalog(): Promise<{
45
- status: 'disconnected' | 'unchanged' | 'updated';
46
- modelCount?: number;
47
- }>;
48
- private getOrCreateDeviceId;
49
- private fetchCatalog;
50
- private install;
51
- }
@@ -1,196 +0,0 @@
1
- import { init_paths_state, resolveStateDir } from "../config/paths-state.js";
2
- import { init_write_file_atomic, writeTextAtomicSync } from "../infra/write-file-atomic.js";
3
- import { getModelCatalogStore, init_model_catalog_store } from "./model-catalog-store.js";
4
- import { getModelRegistry, init_model_registry } from "./model-registry.js";
5
- import { getCredentialResolver, init_credentials } from "../auth/credentials.js";
6
- import { hostname } from "node:os";
7
- import { join } from "node:path";
8
- import { existsSync, readFileSync } from "node:fs";
9
- import { createHash, randomBytes } from "node:crypto";
10
- //#region src/providers/xopc-cloud-connection.ts
11
- init_credentials();
12
- init_paths_state();
13
- init_write_file_atomic();
14
- init_model_catalog_store();
15
- init_model_registry();
16
- const DEFAULT_CONSOLE_URL = "https://console.xopc.ai";
17
- const DEFAULT_ROUTER_URL = "https://router.xopc.ai/v1";
18
- const CONNECTION_TTL_MS = 5 * 6e4;
19
- var XopcCloudHttpError = class extends Error {
20
- constructor(message, status, code) {
21
- super(message);
22
- this.status = status;
23
- this.code = code;
24
- this.name = "XopcCloudHttpError";
25
- }
26
- };
27
- function normalizedBaseUrl(value) {
28
- return value.trim().replace(/\/+$/, "");
29
- }
30
- function parseJson(value, message) {
31
- if (!value || typeof value !== "object") throw new Error(message);
32
- return value;
33
- }
34
- var XopcCloudConnectionService = class {
35
- pending = /* @__PURE__ */ new Map();
36
- fetchImpl;
37
- consoleUrl;
38
- routerUrl;
39
- deviceIdPath;
40
- catalogStore;
41
- credentials;
42
- refreshModels;
43
- now;
44
- constructor(options = {}) {
45
- this.fetchImpl = options.fetchImpl ?? fetch;
46
- this.consoleUrl = normalizedBaseUrl(options.consoleUrl ?? process.env.XOPC_CONSOLE_URL ?? DEFAULT_CONSOLE_URL);
47
- this.routerUrl = normalizedBaseUrl(options.routerUrl ?? process.env.XOPC_MODEL_ROUTER_URL ?? DEFAULT_ROUTER_URL);
48
- this.deviceIdPath = options.deviceIdPath ?? join(resolveStateDir(), "xopc-cloud-device.json");
49
- this.catalogStore = options.catalogStore ?? getModelCatalogStore();
50
- this.credentials = options.credentials ?? getCredentialResolver();
51
- this.refreshModels = options.refreshModels ?? (() => getModelRegistry().refresh());
52
- this.now = options.now ?? Date.now;
53
- }
54
- async start(clientType) {
55
- const verifier = randomBytes(32).toString("base64url");
56
- const codeChallenge = createHash("sha256").update(verifier).digest("base64url");
57
- const response = await this.fetchImpl(`${this.consoleUrl}/api/v1/models/connect/requests`, {
58
- method: "POST",
59
- headers: { "content-type": "application/json" },
60
- body: JSON.stringify({
61
- codeChallenge,
62
- deviceId: this.getOrCreateDeviceId(),
63
- deviceName: hostname() || "XOPC device",
64
- clientType
65
- }),
66
- signal: AbortSignal.timeout(15e3)
67
- });
68
- const body = parseJson(await response.json().catch(() => null), "XOPC Console returned an invalid response");
69
- if (!response.ok || typeof body.requestId !== "string" || typeof body.authorizationUrl !== "string") throw new Error("Unable to start XOPC model connection");
70
- const authorizationUrl = new URL(body.authorizationUrl);
71
- if (authorizationUrl.origin !== new URL(this.consoleUrl).origin) throw new Error("XOPC Console returned an unsafe authorization URL");
72
- const expiresIn = typeof body.expiresIn === "number" ? body.expiresIn : CONNECTION_TTL_MS / 1e3;
73
- this.pending.set(body.requestId, {
74
- verifier,
75
- expiresAt: this.now() + expiresIn * 1e3
76
- });
77
- return {
78
- requestId: body.requestId,
79
- authorizationUrl: authorizationUrl.href,
80
- expiresIn,
81
- pollInterval: typeof body.pollInterval === "number" ? body.pollInterval : 2
82
- };
83
- }
84
- async poll(requestId) {
85
- const pending = this.pending.get(requestId);
86
- if (!pending) throw new Error("Connection request is not active");
87
- if (pending.expiresAt <= this.now()) {
88
- this.pending.delete(requestId);
89
- throw new Error("Connection request expired");
90
- }
91
- const tokenResponse = await this.fetchImpl(`${this.consoleUrl}/api/v1/models/connect/token`, {
92
- method: "POST",
93
- headers: { "content-type": "application/json" },
94
- body: JSON.stringify({
95
- requestId,
96
- codeVerifier: pending.verifier
97
- }),
98
- signal: AbortSignal.timeout(15e3)
99
- });
100
- if (tokenResponse.status === 202) return { status: "pending" };
101
- const token = parseJson(await tokenResponse.json().catch(() => null), "XOPC Console returned an invalid token response");
102
- if (!tokenResponse.ok || token.providerId !== "xopc-cloud" || typeof token.apiKey !== "string") throw new Error("Unable to complete XOPC model connection");
103
- const catalog = await this.fetchCatalog(token.apiKey);
104
- if (!catalog) throw new Error("XOPC model catalog was not available");
105
- await this.install(token.apiKey, catalog, true);
106
- this.pending.delete(requestId);
107
- return {
108
- status: "connected",
109
- modelCount: catalog.models.length,
110
- models: catalog.models.map((model) => model.id),
111
- recommendedModel: catalog.recommendedModel
112
- };
113
- }
114
- async refreshCatalog() {
115
- const apiKey = await this.credentials.revealGatewayStoredApiKey("xopc-cloud");
116
- if (!apiKey) return { status: "disconnected" };
117
- const previous = this.catalogStore.getSource("xopc-cloud");
118
- const catalog = await this.fetchCatalog(apiKey, previous?.etag);
119
- if (!catalog) {
120
- if (previous) this.catalogStore.saveSource("xopc-cloud", {
121
- ...previous,
122
- lastSuccessAt: this.now()
123
- });
124
- return { status: "unchanged" };
125
- }
126
- await this.install(apiKey, catalog, false);
127
- return {
128
- status: "updated",
129
- modelCount: catalog.models.length
130
- };
131
- }
132
- getOrCreateDeviceId() {
133
- if (existsSync(this.deviceIdPath)) try {
134
- const value = JSON.parse(readFileSync(this.deviceIdPath, "utf8"));
135
- if (typeof value.deviceId === "string" && value.deviceId.length >= 16) return value.deviceId;
136
- } catch {}
137
- const deviceId = randomBytes(32).toString("base64url");
138
- writeTextAtomicSync(this.deviceIdPath, JSON.stringify({ deviceId }), { mode: 384 });
139
- return deviceId;
140
- }
141
- async fetchCatalog(apiKey, etag) {
142
- const headers = new Headers({ authorization: `Bearer ${apiKey}` });
143
- if (etag) headers.set("if-none-match", etag);
144
- const response = await this.fetchImpl(`${this.routerUrl}/catalog`, {
145
- headers,
146
- signal: AbortSignal.timeout(15e3)
147
- });
148
- if (response.status === 304) return null;
149
- const rawBody = await response.json().catch(() => null);
150
- if (!response.ok) {
151
- const body = rawBody && typeof rawBody === "object" ? rawBody : null;
152
- const errorBody = body?.error && typeof body.error === "object" ? body.error : null;
153
- const code = typeof errorBody?.code === "string" ? errorBody.code : void 0;
154
- throw new XopcCloudHttpError(response.status === 401 || response.status === 403 ? "XOPC Model Service authorization expired. Reconnect the service." : "Unable to load the XOPC model catalog", response.status, code);
155
- }
156
- const catalog = parseJson(rawBody, "XOPC model catalog returned an invalid response");
157
- if (!Array.isArray(catalog.models)) throw new Error("Unable to load the XOPC model catalog");
158
- const models = catalog.models.flatMap((item) => {
159
- if (!item || typeof item !== "object") return [];
160
- const value = item;
161
- if (typeof value.id !== "string" || !value.id.trim() || value.id.includes("/")) return [];
162
- return [{
163
- id: value.id,
164
- name: typeof value.name === "string" && value.name.trim() ? value.name : value.id,
165
- maxOutputTokens: typeof value.maxOutputTokens === "number" && value.maxOutputTokens > 0 ? value.maxOutputTokens : null
166
- }];
167
- });
168
- if (models.length === 0) throw new Error("No XOPC models are currently available");
169
- return {
170
- models,
171
- recommendedModel: typeof catalog.recommendedModel === "string" ? catalog.recommendedModel : null,
172
- etag: response.headers.get("etag")
173
- };
174
- }
175
- async install(apiKey, catalog, saveCredential) {
176
- const previousKey = await this.credentials.revealGatewayStoredApiKey("xopc-cloud");
177
- if (saveCredential) await this.credentials.saveApiKey("xopc-cloud", apiKey, { envVar: null });
178
- try {
179
- this.catalogStore.replaceSourceModels("xopc-cloud", {
180
- providerId: "xopc-cloud",
181
- baseUrl: this.routerUrl,
182
- api: "openai-completions",
183
- etag: catalog.etag,
184
- recommendedModel: catalog.recommendedModel,
185
- lastSuccessAt: this.now()
186
- }, catalog.models);
187
- } catch (err) {
188
- if (saveCredential) if (previousKey) await this.credentials.saveApiKey("xopc-cloud", previousKey, { envVar: null });
189
- else await this.credentials.deleteProfile("xopc-cloud:default");
190
- throw err;
191
- }
192
- this.refreshModels();
193
- }
194
- };
195
- //#endregion
196
- export { XopcCloudConnectionService, XopcCloudHttpError };