svamp-cli 0.2.342 → 0.2.356

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 (67) hide show
  1. package/bin/skills/artifact/SKILL.md +19 -5
  2. package/bin/skills/crew/SKILL.md +62 -13
  3. package/dist/DefaultTransport-vfp78fug.mjs +47 -0
  4. package/dist/GeminiTransport-3OkhtFRO.mjs +130 -0
  5. package/dist/KimiTransport-D8n009Tr.mjs +141 -0
  6. package/dist/acpAgentConfig-CObOPlA8.mjs +48 -0
  7. package/dist/acpBackend-UaBD4zL3.mjs +925 -0
  8. package/dist/{adminCommands-CRTBDZan.mjs → adminCommands-BvsYnRDA.mjs} +2 -18
  9. package/dist/{agentCommands-BuO988tJ.mjs → agentCommands-D91RcjqQ.mjs} +6 -23
  10. package/dist/api-BHjyC0Ph.mjs +157 -0
  11. package/dist/{auth--WS0wezs.mjs → auth-CRz8TsEl.mjs} +1 -22
  12. package/dist/bootStatus-DqtNgJch.mjs +143 -0
  13. package/dist/claudeAuth-C0wc1GTM.mjs +291 -0
  14. package/dist/cli.mjs +2948 -5
  15. package/dist/codexAppServerBackend-VGsYtbqg.mjs +786 -0
  16. package/dist/codexProvider-BtxYc5Rj.mjs +68 -0
  17. package/dist/{commands-DDuGBSsz.mjs → commands-B-yczgz_.mjs} +115 -49
  18. package/dist/{commands-DU4B-4Gh.mjs → commands-BMeDrpSv.mjs} +55 -25
  19. package/dist/{commands-DXLOKJOj.mjs → commands-BbmypSgx.mjs} +62 -27
  20. package/dist/{commands-C0HQiu-S.mjs → commands-BkdbelFo.mjs} +78 -38
  21. package/dist/{commands-DXM17M6n.mjs → commands-C13-yE2R.mjs} +42 -19
  22. package/dist/{commands-BKb1g8Gq.mjs → commands-CoOc4qiw.mjs} +20 -30
  23. package/dist/{commands-BsKgZ5sQ.mjs → commands-DW5RnHZw.mjs} +2 -19
  24. package/dist/{commands-Cwxy-C5N.mjs → commands-sPvRcG3J.mjs} +10 -32
  25. package/dist/cron-hHGdb5kU.mjs +132 -0
  26. package/dist/detectIsolation-CrV8IFDv.mjs +339 -0
  27. package/dist/envFlag-COOuJ3AH.mjs +11 -0
  28. package/dist/fileLock-BMPwCrB6.mjs +80 -0
  29. package/dist/{fleet-BHzlAvnu.mjs → fleet-Ca-UjJNL.mjs} +122 -36
  30. package/dist/flushExit-C-i6SGjj.mjs +37 -0
  31. package/dist/friendlyName-1UZcyDhu.mjs +586 -0
  32. package/dist/{headlessCli-C2gvOpOt.mjs → headlessCli-C8HzQvis.mjs} +3 -21
  33. package/dist/hookSettings-FFc1pi8j.mjs +10546 -0
  34. package/dist/{httpServer-Be1Hcddr.mjs → httpServer-BzEDbOGn.mjs} +14 -5
  35. package/dist/hyphaClient-ybivOjZo.mjs +49 -0
  36. package/dist/index.mjs +40 -8
  37. package/dist/instance-CeHz5C8v.mjs +203 -0
  38. package/dist/kimiProvider-DbxODebR.mjs +69 -0
  39. package/dist/kimiSetup-NGsoYB5h.mjs +48 -0
  40. package/dist/loopVerify-DALtTk2V.mjs +444 -0
  41. package/dist/machineTools-DygM1jXW.mjs +580 -0
  42. package/dist/model-CUHojegn.mjs +66 -0
  43. package/dist/{notifyCommands-0aZUwKQK.mjs → notifyCommands-CCUE18Q-.mjs} +3 -18
  44. package/dist/package-BrsiNutS.mjs +64 -0
  45. package/dist/pinnedCodex-XW4qvOAe.mjs +11 -0
  46. package/dist/pinnedNono-5ZHb6328.mjs +15 -0
  47. package/dist/{rpc-rAQQ1q8t.mjs → rpc-CBkSkzsI.mjs} +38 -6
  48. package/dist/{rpc-B2Lc2BAB.mjs → rpc-ccY7xvlo.mjs} +33 -22
  49. package/dist/{run-C7QVfyw4.mjs → run-DCq3aEiF.mjs} +17 -9
  50. package/dist/run-DDmeV9K3.mjs +9826 -0
  51. package/dist/sandboxDetect-Cdzsj5TC.mjs +19 -0
  52. package/dist/{scheduler-CzF4lOe_.mjs → scheduler-BkVJ27Ki.mjs} +38 -6
  53. package/dist/securityContext-Cm5UTCuD.mjs +218 -0
  54. package/dist/serveAuth-4M0vwMyj.mjs +460 -0
  55. package/dist/{serveCommands-EIEqdaVu.mjs → serveCommands-CLhkccJM.mjs} +13 -34
  56. package/dist/sharingNotificationSync-qGIQ-3yf.mjs +359 -0
  57. package/dist/{sideband-BoutiRJi.mjs → sideband-68HhGT0i.mjs} +1 -21
  58. package/dist/store-B4E6NzG6.mjs +356 -0
  59. package/dist/store-fi0f-ff1.mjs +184 -0
  60. package/dist/types-57J3Re0n.mjs +17 -0
  61. package/dist/wantsHelp-6bMOeNUz.mjs +5 -0
  62. package/dist/wrapCommand-CdNawSaa.mjs +117 -0
  63. package/package.json +3 -3
  64. package/dist/cli-B24CmIli.mjs +0 -2780
  65. package/dist/package-CTbGYaJG.mjs +0 -64
  66. package/dist/run-CF4kAVPW.mjs +0 -26508
  67. package/dist/sandboxDetect-DNTcbgWD.mjs +0 -12
@@ -89,11 +89,24 @@ function createChannelHttpServer(deps) {
89
89
  m = u.pathname.match(/^\/channel\/([\w.-]+)\/events$/);
90
90
  if (m) {
91
91
  const cid = m[1];
92
+ let closed = false;
93
+ const markClosed = () => {
94
+ closed = true;
95
+ };
96
+ req.on("close", markClosed);
97
+ req.on("aborted", markClosed);
92
98
  let rpc2 = await findOwner(deps, cid);
93
99
  if (!rpc2?.channelReceive) {
94
100
  res.writeHead(404).end("not found");
95
101
  return;
96
102
  }
103
+ if (closed || res.destroyed) {
104
+ try {
105
+ res.end();
106
+ } catch {
107
+ }
108
+ return;
109
+ }
97
110
  const live = _sseStreams.get(cid) || 0;
98
111
  if (live >= MAX_SSE_STREAMS_PER_CHANNEL) {
99
112
  res.writeHead(429, { "content-type": "application/json", "retry-after": "5" }).end(JSON.stringify({ error: `too many concurrent event streams for this channel (max ${MAX_SSE_STREAMS_PER_CHANNEL})` }));
@@ -105,10 +118,6 @@ function createChannelHttpServer(deps) {
105
118
  let cursor = Number(u.searchParams.get("cursor") || 0);
106
119
  res.writeHead(200, { "content-type": "text/event-stream", "cache-control": "no-cache", connection: "keep-alive", "x-accel-buffering": "no" });
107
120
  res.write(": connected\n\n");
108
- let closed = false;
109
- req.on("close", () => {
110
- closed = true;
111
- });
112
121
  let released = false;
113
122
  const releaseSlot = () => {
114
123
  if (released) return;
@@ -120,7 +129,7 @@ function createChannelHttpServer(deps) {
120
129
  req.on("close", releaseSlot);
121
130
  try {
122
131
  const MIN_LOOP_MS = 1e3;
123
- while (!closed) {
132
+ while (!closed && !res.destroyed) {
124
133
  const started = Date.now();
125
134
  let out;
126
135
  try {
@@ -0,0 +1,49 @@
1
+ let connectToServerFn = null;
2
+ async function getConnectToServer() {
3
+ if (!connectToServerFn) {
4
+ const mod = await import('hypha-rpc');
5
+ connectToServerFn = mod.connectToServer || mod.default && mod.default.connectToServer || mod.hyphaWebsocketClient && mod.hyphaWebsocketClient.connectToServer;
6
+ if (!connectToServerFn) {
7
+ throw new Error("Could not find connectToServer in hypha-rpc module");
8
+ }
9
+ }
10
+ return connectToServerFn;
11
+ }
12
+ async function connectToHypha(config) {
13
+ const connectToServer = await getConnectToServer();
14
+ const workspace = config.token ? parseWorkspaceFromToken(config.token) : void 0;
15
+ const server = await Promise.race([
16
+ connectToServer({
17
+ server_url: config.serverUrl,
18
+ token: config.token,
19
+ client_id: config.clientId,
20
+ name: config.name || "svamp-cli",
21
+ workspace,
22
+ ...config.transport ? { transport: config.transport } : {}
23
+ }),
24
+ new Promise((_, reject) => setTimeout(() => reject(new Error(
25
+ "Timeout connecting to Hypha server (30s). A previous daemon may still be connected. Retrying..."
26
+ )), 3e4))
27
+ ]);
28
+ if (!server.on && server.rpc) {
29
+ server.on = server.rpc.on.bind(server.rpc);
30
+ server.off = server.rpc.off.bind(server.rpc);
31
+ server.emit = server.rpc.emit.bind(server.rpc);
32
+ }
33
+ return server;
34
+ }
35
+ function parseWorkspaceFromToken(token) {
36
+ try {
37
+ const payload = JSON.parse(Buffer.from(token.split(".")[1], "base64").toString());
38
+ const scope = payload.scope || "";
39
+ const match = scope.match(/wid:([^\s]+)/);
40
+ return match ? match[1] : void 0;
41
+ } catch {
42
+ return void 0;
43
+ }
44
+ }
45
+ function getHyphaServerUrl() {
46
+ return process.env.HYPHA_SERVER_URL || "http://localhost:9527";
47
+ }
48
+
49
+ export { connectToHypha as c, getHyphaServerUrl as g };
package/dist/index.mjs CHANGED
@@ -1,22 +1,54 @@
1
- export { c as connectToHypha, a as createSessionStore, d as daemonStatus, g as getHyphaServerUrl, r as registerMachineService, s as startDaemon, b as stopDaemon } from './run-CF4kAVPW.mjs';
2
- import 'os';
3
- import 'fs/promises';
1
+ export { c as connectToHypha, g as getHyphaServerUrl } from './hyphaClient-ybivOjZo.mjs';
2
+ export { c as createSessionStore, r as registerMachineService } from './hookSettings-FFc1pi8j.mjs';
3
+ export { d as daemonStatus, s as startDaemon, a as stopDaemon } from './run-DDmeV9K3.mjs';
4
4
  import 'fs';
5
5
  import 'path';
6
- import 'url';
7
- import 'child_process';
8
- import 'crypto';
9
- import 'node:fs';
10
- import 'node:path';
11
6
  import 'node:crypto';
7
+ import './types-57J3Re0n.mjs';
8
+ import './securityContext-Cm5UTCuD.mjs';
9
+ import 'node:fs';
10
+ import './machineTools-DygM1jXW.mjs';
12
11
  import 'node:child_process';
12
+ import './model-CUHojegn.mjs';
13
+ import 'child_process';
14
+ import 'fs/promises';
15
+ import 'crypto';
13
16
  import 'util';
14
17
  import 'http';
15
18
  import 'net';
19
+ import 'os';
20
+ import './instance-CeHz5C8v.mjs';
21
+ import './serveAuth-4M0vwMyj.mjs';
16
22
  import 'node:os';
23
+ import 'node:path';
24
+ import './envFlag-COOuJ3AH.mjs';
25
+ import './claudeAuth-C0wc1GTM.mjs';
26
+ import './fileLock-BMPwCrB6.mjs';
27
+ import './codexProvider-BtxYc5Rj.mjs';
28
+ import './friendlyName-1UZcyDhu.mjs';
17
29
  import 'node:events';
30
+ import './cron-hHGdb5kU.mjs';
31
+ import 'url';
32
+ import './sharingNotificationSync-qGIQ-3yf.mjs';
33
+ import './acpBackend-UaBD4zL3.mjs';
18
34
  import '@agentclientprotocol/sdk';
35
+ import './DefaultTransport-vfp78fug.mjs';
36
+ import './wrapCommand-CdNawSaa.mjs';
37
+ import './acpAgentConfig-CObOPlA8.mjs';
38
+ import './codexAppServerBackend-VGsYtbqg.mjs';
19
39
  import 'node:util';
20
40
  import 'node:readline';
41
+ import './pinnedCodex-XW4qvOAe.mjs';
42
+ import './GeminiTransport-3OkhtFRO.mjs';
43
+ import './KimiTransport-D8n009Tr.mjs';
44
+ import './kimiProvider-DbxODebR.mjs';
45
+ import './kimiSetup-NGsoYB5h.mjs';
46
+ import './detectIsolation-CrV8IFDv.mjs';
21
47
  import 'node:fs/promises';
48
+ import './pinnedNono-5ZHb6328.mjs';
49
+ import './bootStatus-DqtNgJch.mjs';
50
+ import './loopVerify-DALtTk2V.mjs';
51
+ import './store-B4E6NzG6.mjs';
52
+ import './api-BHjyC0Ph.mjs';
53
+ import './store-fi0f-ff1.mjs';
22
54
  import 'yaml';
@@ -0,0 +1,203 @@
1
+ import { existsSync, rmSync, readFileSync, mkdirSync, writeFileSync } from 'fs';
2
+ import { join } from 'path';
3
+ import { homedir } from 'os';
4
+
5
+ function svampHome() {
6
+ return process.env.SVAMP_HOME || join(homedir(), ".svamp");
7
+ }
8
+ function cacheFile() {
9
+ return join(svampHome(), "instance-config.json");
10
+ }
11
+ const CONFIG_FILENAME = "svamp.json";
12
+ let _config = null;
13
+ let _loaded = false;
14
+ let _cacheChecked = false;
15
+ let _source = "none";
16
+ function stripSlash$1(u) {
17
+ return u.replace(/\/+$/, "");
18
+ }
19
+ function getInstanceUrl() {
20
+ const raw = (process.env.SVAMP_INSTANCE_URL || "").trim();
21
+ return raw ? stripSlash$1(raw) : void 0;
22
+ }
23
+ function configUrlsFor(anchor) {
24
+ const base = stripSlash$1(anchor);
25
+ return [`${base}/${CONFIG_FILENAME}`, `${base}/.well-known/${CONFIG_FILENAME}`];
26
+ }
27
+ async function fetchConfig(anchor) {
28
+ for (const url of configUrlsFor(anchor)) {
29
+ try {
30
+ const resp = await fetch(url, { signal: AbortSignal.timeout(8e3) });
31
+ if (!resp.ok) continue;
32
+ const data = await resp.json();
33
+ if (data && typeof data === "object" && !Array.isArray(data)) {
34
+ return data;
35
+ }
36
+ } catch {
37
+ }
38
+ }
39
+ return null;
40
+ }
41
+ function readCache() {
42
+ try {
43
+ if (existsSync(cacheFile())) {
44
+ const data = JSON.parse(readFileSync(cacheFile(), "utf-8"));
45
+ if (data && typeof data === "object" && !Array.isArray(data)) return data;
46
+ }
47
+ } catch {
48
+ }
49
+ return null;
50
+ }
51
+ function writeCache(cfg) {
52
+ try {
53
+ mkdirSync(svampHome(), { recursive: true });
54
+ writeFileSync(cacheFile(), JSON.stringify(cfg, null, 2) + "\n", "utf-8");
55
+ } catch {
56
+ }
57
+ }
58
+ function applyConfig(cfg) {
59
+ _config = cfg;
60
+ if (cfg.hyphaServerUrl && typeof cfg.hyphaServerUrl === "string") {
61
+ process.env.HYPHA_SERVER_URL = stripSlash$1(cfg.hyphaServerUrl.trim());
62
+ }
63
+ }
64
+ async function loadInstanceConfig(opts = {}) {
65
+ if (_loaded && !opts.force) return _config;
66
+ const anchor = opts.anchor ? stripSlash$1(opts.anchor) : getInstanceUrl();
67
+ if (anchor) {
68
+ const fetched = await fetchConfig(anchor);
69
+ if (fetched) {
70
+ applyConfig(fetched);
71
+ writeCache(fetched);
72
+ _source = "fetched";
73
+ _loaded = true;
74
+ _cacheChecked = true;
75
+ return _config;
76
+ }
77
+ }
78
+ const cached = readCache();
79
+ if (cached) applyConfig(cached);
80
+ _source = cached ? "cache" : "none";
81
+ _loaded = true;
82
+ _cacheChecked = true;
83
+ return _config;
84
+ }
85
+ function getConfigSource() {
86
+ return _source;
87
+ }
88
+ function getLoadedConfig() {
89
+ if (!_loaded && !_cacheChecked) {
90
+ const cached = readCache();
91
+ if (cached) {
92
+ applyConfig(cached);
93
+ _source = "cache";
94
+ }
95
+ _cacheChecked = true;
96
+ }
97
+ return _config;
98
+ }
99
+ function clearInstanceConfigCache() {
100
+ _config = null;
101
+ _loaded = false;
102
+ _cacheChecked = false;
103
+ _source = "none";
104
+ try {
105
+ if (existsSync(cacheFile())) rmSync(cacheFile());
106
+ } catch {
107
+ }
108
+ }
109
+ function __setConfigForTest(cfg) {
110
+ _config = cfg;
111
+ _loaded = true;
112
+ _cacheChecked = true;
113
+ _source = cfg ? "fetched" : "none";
114
+ if (cfg) applyConfig(cfg);
115
+ }
116
+ function __resetForTest() {
117
+ _config = null;
118
+ _loaded = false;
119
+ _cacheChecked = false;
120
+ _source = "none";
121
+ }
122
+
123
+ var instanceConfig = /*#__PURE__*/Object.freeze({
124
+ __proto__: null,
125
+ CONFIG_FILENAME: CONFIG_FILENAME,
126
+ __resetForTest: __resetForTest,
127
+ __setConfigForTest: __setConfigForTest,
128
+ clearInstanceConfigCache: clearInstanceConfigCache,
129
+ configUrlsFor: configUrlsFor,
130
+ getConfigSource: getConfigSource,
131
+ getInstanceUrl: getInstanceUrl,
132
+ getLoadedConfig: getLoadedConfig,
133
+ loadInstanceConfig: loadInstanceConfig
134
+ });
135
+
136
+ function stripSlash(u) {
137
+ return u.replace(/\/+$/, "");
138
+ }
139
+ function notConfigured(what, key, legacy) {
140
+ const anchor = getInstanceUrl();
141
+ const where = anchor ? `Nothing usable was loaded from ${anchor} \u2014 check that ${anchor}/${CONFIG_FILENAME} serves a doc containing "${key}". If that is the wrong instance, re-run \`svamp login <frontend-url>\` with the frontend URL (NOT the Hypha server URL).` : `No instance URL is set \u2014 run \`svamp login <frontend-url>\`; the frontend serves /${CONFIG_FILENAME}.`;
142
+ return `${what} is not configured. ${where} Legacy override: ${legacy}. It is deployment-specific and never guessed.`;
143
+ }
144
+ function getHyphaServerUrl() {
145
+ const fromCfg = getLoadedConfig()?.hyphaServerUrl;
146
+ if (typeof fromCfg === "string" && fromCfg.trim()) return stripSlash(fromCfg.trim());
147
+ const env = (process.env.HYPHA_SERVER_URL || "").trim();
148
+ return env ? stripSlash(env) : void 0;
149
+ }
150
+ function getFrpsSubdomainHost() {
151
+ const fromCfg = getLoadedConfig()?.frps?.subdomainHost;
152
+ if (typeof fromCfg === "string" && fromCfg.trim()) return fromCfg.trim();
153
+ const env = (process.env.FRPS_SUBDOMAIN_HOST || "").trim();
154
+ if (env) return env;
155
+ throw new Error(notConfigured("frps subdomain host", "frps.subdomainHost", "FRPS_SUBDOMAIN_HOST"));
156
+ }
157
+ function getFrpsServerAddr() {
158
+ const fromCfg = getLoadedConfig()?.frps?.serverAddr;
159
+ if (typeof fromCfg === "string" && fromCfg.trim()) return fromCfg.trim();
160
+ const env = (process.env.FRPS_SERVER_ADDR || "").trim();
161
+ if (env) return env;
162
+ return `frps-ctrl.${getFrpsSubdomainHost()}`;
163
+ }
164
+ function getFrpsServerPort() {
165
+ const fromCfg = getLoadedConfig()?.frps?.serverPort;
166
+ if (typeof fromCfg === "number" && Number.isFinite(fromCfg)) return fromCfg;
167
+ const env = parseInt(process.env.FRPS_SERVER_PORT || "", 10);
168
+ return Number.isFinite(env) ? env : void 0;
169
+ }
170
+ function getSvampWebBaseUrl() {
171
+ const fromCfg = getLoadedConfig()?.web?.baseUrl;
172
+ if (typeof fromCfg === "string" && fromCfg.trim()) return stripSlash(fromCfg.trim());
173
+ const env = (process.env.SVAMP_WEB_URL || "").trim();
174
+ if (env) return stripSlash(env);
175
+ const instance = getInstanceUrl();
176
+ if (instance) return instance;
177
+ throw new Error(
178
+ 'Svamp web base URL is not configured. Serve a svamp.json with "web.baseUrl", log in with your frontend URL (svamp login <frontend-url>), or set SVAMP_WEB_URL (legacy).'
179
+ );
180
+ }
181
+ function getSkillsServerUrl() {
182
+ const fromCfg = getLoadedConfig()?.skills?.server;
183
+ if (typeof fromCfg === "string" && fromCfg.trim()) return stripSlash(fromCfg.trim());
184
+ const env = (process.env.HYPHA_SKILLS_SERVER || "").trim();
185
+ if (env) return stripSlash(env);
186
+ const server = getHyphaServerUrl();
187
+ if (server) return server;
188
+ throw new Error(
189
+ "Cannot determine skills marketplace server. Serve a svamp.json or set HYPHA_SERVER_URL."
190
+ );
191
+ }
192
+ function getSkillsWorkspace() {
193
+ const fromCfg = getLoadedConfig()?.skills?.workspace;
194
+ if (typeof fromCfg === "string" && fromCfg.trim()) return fromCfg.trim();
195
+ return (process.env.HYPHA_SKILLS_WORKSPACE || "").trim() || "hypha-cloud";
196
+ }
197
+ function getSkillsCollection() {
198
+ const fromCfg = getLoadedConfig()?.skills?.collection;
199
+ if (typeof fromCfg === "string" && fromCfg.trim()) return fromCfg.trim();
200
+ return (process.env.HYPHA_SKILLS_COLLECTION || "").trim() || "marketplace";
201
+ }
202
+
203
+ export { getSkillsServerUrl as a, getSkillsWorkspace as b, getSvampWebBaseUrl as c, getFrpsSubdomainHost as d, getFrpsServerPort as e, getFrpsServerAddr as f, getSkillsCollection as g, getHyphaServerUrl as h, instanceConfig as i, loadInstanceConfig as l };
@@ -0,0 +1,69 @@
1
+ const DEFAULT_KIMI_PROVIDER = "moonshotai";
2
+ const DEFAULT_KIMI_MODEL_BY_PROVIDER = {
3
+ moonshotai: "kimi-k2.5",
4
+ "moonshotai-cn": "kimi-k2-turbo-preview",
5
+ "kimi-for-coding": "kimi-for-coding"
6
+ };
7
+ function kimiDefaultModelId(cfg) {
8
+ if (cfg.model) {
9
+ const m = cfg.model.trim();
10
+ return m.includes("/") ? m.split("/").pop() || void 0 : m;
11
+ }
12
+ return DEFAULT_KIMI_MODEL_BY_PROVIDER[cfg.provider];
13
+ }
14
+ function kimiSpawnEnv(_env = process.env) {
15
+ return { KIMI_CLI_NO_AUTO_UPDATE: "1" };
16
+ }
17
+ function resolveKimiProvider(env = process.env) {
18
+ return {
19
+ provider: env.SVAMP_KIMI_PROVIDER || DEFAULT_KIMI_PROVIDER,
20
+ apiKey: env.SVAMP_KIMI_API_KEY || env.LLM_API_KEY || void 0,
21
+ apiBase: env.SVAMP_KIMI_API_BASE || env.LLM_API_BASE || void 0,
22
+ model: env.SVAMP_KIMI_MODEL || env.LLM_MODEL || void 0
23
+ };
24
+ }
25
+ function hasKimiProvider(cfg) {
26
+ return !!cfg.apiKey;
27
+ }
28
+ function buildKimiCatalogAddArgs(cfg) {
29
+ if (!hasKimiProvider(cfg)) return null;
30
+ const args = ["provider", "catalog", "add", cfg.provider];
31
+ if (cfg.apiBase) args.push("--base-url", cfg.apiBase);
32
+ const defaultModel = kimiDefaultModelId(cfg);
33
+ if (defaultModel) args.push("--default-model", defaultModel);
34
+ return args;
35
+ }
36
+ function kimiProviderConfigured(configTomlText, provider) {
37
+ if (!configTomlText) return false;
38
+ const header = `[providers.${provider}]`;
39
+ const idx = configTomlText.indexOf(header);
40
+ if (idx < 0) return false;
41
+ const rest = configTomlText.slice(idx + header.length);
42
+ const nextTable = rest.search(/\n\s*\[/);
43
+ const block = nextTable < 0 ? rest : rest.slice(0, nextTable);
44
+ return /(^|\n)\s*api_key\s*=/.test(block);
45
+ }
46
+ function kimiHasGlobalDefaultModel(configTomlText) {
47
+ if (!configTomlText) return false;
48
+ const firstTable = configTomlText.search(/(^|\n)\s*\[/);
49
+ const preamble = firstTable < 0 ? configTomlText : configTomlText.slice(0, firstTable);
50
+ return /(^|\n)\s*default_model\s*=/.test(preamble);
51
+ }
52
+ function kimiConfigComplete(configTomlText, provider) {
53
+ return kimiProviderConfigured(configTomlText, provider) && kimiHasGlobalDefaultModel(configTomlText);
54
+ }
55
+ function kimiModelMenu(env = process.env) {
56
+ return (env.SVAMP_KIMI_MODELS || "").split(",").map((s) => s.trim()).filter(Boolean).filter((m, i, a) => a.indexOf(m) === i);
57
+ }
58
+ function kimiDefaultModel(env = process.env) {
59
+ const menu = kimiModelMenu(env);
60
+ return env.SVAMP_KIMI_MODEL || env.LLM_MODEL || menu[0] || void 0;
61
+ }
62
+ function kimiClampModel(requested, env = process.env) {
63
+ const menu = kimiModelMenu(env);
64
+ if (!menu.length) return requested;
65
+ if (requested && menu.includes(requested)) return requested;
66
+ return kimiDefaultModel(env);
67
+ }
68
+
69
+ export { DEFAULT_KIMI_MODEL_BY_PROVIDER, DEFAULT_KIMI_PROVIDER, buildKimiCatalogAddArgs, hasKimiProvider, kimiClampModel, kimiConfigComplete, kimiDefaultModel, kimiDefaultModelId, kimiHasGlobalDefaultModel, kimiModelMenu, kimiProviderConfigured, kimiSpawnEnv, resolveKimiProvider };
@@ -0,0 +1,48 @@
1
+ import { execFile } from 'node:child_process';
2
+ import { readFileSync } from 'node:fs';
3
+ import { homedir } from 'node:os';
4
+ import { join } from 'node:path';
5
+ import { resolveKimiProvider, hasKimiProvider, kimiConfigComplete, buildKimiCatalogAddArgs } from './kimiProvider-DbxODebR.mjs';
6
+
7
+ const KIMI_CONFIG_PATH = join(homedir(), ".kimi-code", "config.toml");
8
+ function readKimiConfig() {
9
+ try {
10
+ return readFileSync(KIMI_CONFIG_PATH, "utf8");
11
+ } catch {
12
+ return null;
13
+ }
14
+ }
15
+ async function ensureKimiProviderConfigured(env = process.env, command = "kimi", log = () => {
16
+ }) {
17
+ const cfg = resolveKimiProvider(env);
18
+ if (!hasKimiProvider(cfg)) return false;
19
+ if (kimiConfigComplete(readKimiConfig(), cfg.provider)) return true;
20
+ const args = buildKimiCatalogAddArgs(cfg);
21
+ if (!args) return false;
22
+ try {
23
+ await new Promise((resolve, reject) => {
24
+ execFile(
25
+ command,
26
+ args,
27
+ {
28
+ timeout: 3e4,
29
+ // #0848: the API key travels in the child ENV, never on argv (argv is world-readable
30
+ // via ps / /proc/<pid>/cmdline). kimi reads KIMI_REGISTRY_API_KEY when --api-key is omitted.
31
+ env: { ...process.env, KIMI_CLI_NO_AUTO_UPDATE: "1", KIMI_REGISTRY_API_KEY: cfg.apiKey }
32
+ },
33
+ (err) => err ? reject(err) : resolve()
34
+ );
35
+ });
36
+ log(`[kimi] configured provider '${cfg.provider}' in ${KIMI_CONFIG_PATH}`);
37
+ const complete = kimiConfigComplete(readKimiConfig(), cfg.provider);
38
+ if (!complete) {
39
+ log(`[kimi] catalog add left ${KIMI_CONFIG_PATH} without a global default_model \u2014 \`kimi acp\` will refuse session/new ("no default model configured")`);
40
+ }
41
+ return complete;
42
+ } catch (err) {
43
+ log(`[kimi] provider auto-config failed (${err?.message || err}); session may need kimi-auth`);
44
+ return false;
45
+ }
46
+ }
47
+
48
+ export { ensureKimiProviderConfigured };