@kimchi-dev/kimchictl 0.0.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 (231) hide show
  1. package/LICENSE +203 -0
  2. package/README.md +105 -0
  3. package/bin/kimchictl.mjs +17 -0
  4. package/dist/api/http.d.ts +7 -0
  5. package/dist/api/http.d.ts.map +1 -0
  6. package/dist/api/http.js +60 -0
  7. package/dist/api/http.js.map +1 -0
  8. package/dist/api/keys.d.ts +7 -0
  9. package/dist/api/keys.d.ts.map +1 -0
  10. package/dist/api/keys.js +28 -0
  11. package/dist/api/keys.js.map +1 -0
  12. package/dist/api/me.d.ts +12 -0
  13. package/dist/api/me.d.ts.map +1 -0
  14. package/dist/api/me.js +28 -0
  15. package/dist/api/me.js.map +1 -0
  16. package/dist/api/resolver.d.ts +26 -0
  17. package/dist/api/resolver.d.ts.map +1 -0
  18. package/dist/api/resolver.js +62 -0
  19. package/dist/api/resolver.js.map +1 -0
  20. package/dist/api/resources.d.ts +16 -0
  21. package/dist/api/resources.d.ts.map +1 -0
  22. package/dist/api/resources.js +96 -0
  23. package/dist/api/resources.js.map +1 -0
  24. package/dist/api/templates.d.ts +19 -0
  25. package/dist/api/templates.d.ts.map +1 -0
  26. package/dist/api/templates.js +25 -0
  27. package/dist/api/templates.js.map +1 -0
  28. package/dist/api/tokens.d.ts +23 -0
  29. package/dist/api/tokens.d.ts.map +1 -0
  30. package/dist/api/tokens.js +51 -0
  31. package/dist/api/tokens.js.map +1 -0
  32. package/dist/api/types.d.ts +34 -0
  33. package/dist/api/types.d.ts.map +1 -0
  34. package/dist/api/types.js +32 -0
  35. package/dist/api/types.js.map +1 -0
  36. package/dist/api/wait.d.ts +17 -0
  37. package/dist/api/wait.d.ts.map +1 -0
  38. package/dist/api/wait.js +37 -0
  39. package/dist/api/wait.js.map +1 -0
  40. package/dist/api/workspaces.d.ts +33 -0
  41. package/dist/api/workspaces.d.ts.map +1 -0
  42. package/dist/api/workspaces.js +159 -0
  43. package/dist/api/workspaces.js.map +1 -0
  44. package/dist/auth/auth-file.d.ts +37 -0
  45. package/dist/auth/auth-file.d.ts.map +1 -0
  46. package/dist/auth/auth-file.js +100 -0
  47. package/dist/auth/auth-file.js.map +1 -0
  48. package/dist/auth/browser-login.d.ts +45 -0
  49. package/dist/auth/browser-login.d.ts.map +1 -0
  50. package/dist/auth/browser-login.js +195 -0
  51. package/dist/auth/browser-login.js.map +1 -0
  52. package/dist/auth/config-file.d.ts +4 -0
  53. package/dist/auth/config-file.d.ts.map +1 -0
  54. package/dist/auth/config-file.js +52 -0
  55. package/dist/auth/config-file.js.map +1 -0
  56. package/dist/auth/models-providers.d.ts +17 -0
  57. package/dist/auth/models-providers.d.ts.map +1 -0
  58. package/dist/auth/models-providers.js +63 -0
  59. package/dist/auth/models-providers.js.map +1 -0
  60. package/dist/auth/paths.d.ts +15 -0
  61. package/dist/auth/paths.d.ts.map +1 -0
  62. package/dist/auth/paths.js +25 -0
  63. package/dist/auth/paths.js.map +1 -0
  64. package/dist/auth/provider-ids.d.ts +4 -0
  65. package/dist/auth/provider-ids.d.ts.map +1 -0
  66. package/dist/auth/provider-ids.js +12 -0
  67. package/dist/auth/provider-ids.js.map +1 -0
  68. package/dist/auth/resolve.d.ts +19 -0
  69. package/dist/auth/resolve.d.ts.map +1 -0
  70. package/dist/auth/resolve.js +37 -0
  71. package/dist/auth/resolve.js.map +1 -0
  72. package/dist/cli.d.ts +2 -0
  73. package/dist/cli.d.ts.map +1 -0
  74. package/dist/cli.js +15 -0
  75. package/dist/cli.js.map +1 -0
  76. package/dist/commands/completion.d.ts +2 -0
  77. package/dist/commands/completion.d.ts.map +1 -0
  78. package/dist/commands/completion.js +71 -0
  79. package/dist/commands/completion.js.map +1 -0
  80. package/dist/commands/flags.d.ts +16 -0
  81. package/dist/commands/flags.d.ts.map +1 -0
  82. package/dist/commands/flags.js +23 -0
  83. package/dist/commands/flags.js.map +1 -0
  84. package/dist/commands/guard.d.ts +10 -0
  85. package/dist/commands/guard.d.ts.map +1 -0
  86. package/dist/commands/guard.js +41 -0
  87. package/dist/commands/guard.js.map +1 -0
  88. package/dist/commands/help.d.ts +4 -0
  89. package/dist/commands/help.d.ts.map +1 -0
  90. package/dist/commands/help.js +19 -0
  91. package/dist/commands/help.js.map +1 -0
  92. package/dist/commands/login.d.ts +18 -0
  93. package/dist/commands/login.d.ts.map +1 -0
  94. package/dist/commands/login.js +80 -0
  95. package/dist/commands/login.js.map +1 -0
  96. package/dist/commands/logout.d.ts +14 -0
  97. package/dist/commands/logout.d.ts.map +1 -0
  98. package/dist/commands/logout.js +41 -0
  99. package/dist/commands/logout.js.map +1 -0
  100. package/dist/commands/prompt.d.ts +9 -0
  101. package/dist/commands/prompt.d.ts.map +1 -0
  102. package/dist/commands/prompt.js +21 -0
  103. package/dist/commands/prompt.js.map +1 -0
  104. package/dist/commands/registry.d.ts +16 -0
  105. package/dist/commands/registry.d.ts.map +1 -0
  106. package/dist/commands/registry.js +35 -0
  107. package/dist/commands/registry.js.map +1 -0
  108. package/dist/commands/ssh.d.ts +15 -0
  109. package/dist/commands/ssh.d.ts.map +1 -0
  110. package/dist/commands/ssh.js +90 -0
  111. package/dist/commands/ssh.js.map +1 -0
  112. package/dist/commands/table.d.ts +3 -0
  113. package/dist/commands/table.d.ts.map +1 -0
  114. package/dist/commands/table.js +10 -0
  115. package/dist/commands/table.js.map +1 -0
  116. package/dist/commands/update.d.ts +16 -0
  117. package/dist/commands/update.d.ts.map +1 -0
  118. package/dist/commands/update.js +57 -0
  119. package/dist/commands/update.js.map +1 -0
  120. package/dist/commands/version.d.ts +2 -0
  121. package/dist/commands/version.d.ts.map +1 -0
  122. package/dist/commands/version.js +6 -0
  123. package/dist/commands/version.js.map +1 -0
  124. package/dist/commands/whoami.d.ts +7 -0
  125. package/dist/commands/whoami.d.ts.map +1 -0
  126. package/dist/commands/whoami.js +30 -0
  127. package/dist/commands/whoami.js.map +1 -0
  128. package/dist/commands/workspace.d.ts +15 -0
  129. package/dist/commands/workspace.d.ts.map +1 -0
  130. package/dist/commands/workspace.js +206 -0
  131. package/dist/commands/workspace.js.map +1 -0
  132. package/dist/run.d.ts +10 -0
  133. package/dist/run.d.ts.map +1 -0
  134. package/dist/run.js +30 -0
  135. package/dist/run.js.map +1 -0
  136. package/dist/ssh/bridge.d.ts +25 -0
  137. package/dist/ssh/bridge.d.ts.map +1 -0
  138. package/dist/ssh/bridge.js +95 -0
  139. package/dist/ssh/bridge.js.map +1 -0
  140. package/dist/ssh/config.d.ts +65 -0
  141. package/dist/ssh/config.d.ts.map +1 -0
  142. package/dist/ssh/config.js +198 -0
  143. package/dist/ssh/config.js.map +1 -0
  144. package/dist/ssh/connect.d.ts +27 -0
  145. package/dist/ssh/connect.d.ts.map +1 -0
  146. package/dist/ssh/connect.js +67 -0
  147. package/dist/ssh/connect.js.map +1 -0
  148. package/dist/ssh/tunnel.d.ts +29 -0
  149. package/dist/ssh/tunnel.d.ts.map +1 -0
  150. package/dist/ssh/tunnel.js +36 -0
  151. package/dist/ssh/tunnel.js.map +1 -0
  152. package/dist/test-support.d.ts +30 -0
  153. package/dist/test-support.d.ts.map +1 -0
  154. package/dist/test-support.js +67 -0
  155. package/dist/test-support.js.map +1 -0
  156. package/dist/updates/check.d.ts +18 -0
  157. package/dist/updates/check.d.ts.map +1 -0
  158. package/dist/updates/check.js +90 -0
  159. package/dist/updates/check.js.map +1 -0
  160. package/dist/updates/self.d.ts +36 -0
  161. package/dist/updates/self.d.ts.map +1 -0
  162. package/dist/updates/self.js +103 -0
  163. package/dist/updates/self.js.map +1 -0
  164. package/dist/version.d.ts +7 -0
  165. package/dist/version.d.ts.map +1 -0
  166. package/dist/version.js +7 -0
  167. package/dist/version.js.map +1 -0
  168. package/package.json +77 -0
  169. package/src/api/http.ts +70 -0
  170. package/src/api/keys.ts +40 -0
  171. package/src/api/me.ts +48 -0
  172. package/src/api/resolver.test.ts +109 -0
  173. package/src/api/resolver.ts +72 -0
  174. package/src/api/resources.test.ts +56 -0
  175. package/src/api/resources.ts +92 -0
  176. package/src/api/templates.ts +28 -0
  177. package/src/api/tokens.ts +80 -0
  178. package/src/api/types.ts +50 -0
  179. package/src/api/wait.ts +45 -0
  180. package/src/api/workspaces.ts +234 -0
  181. package/src/auth/auth-file.test.ts +176 -0
  182. package/src/auth/auth-file.ts +103 -0
  183. package/src/auth/browser-login.test.ts +93 -0
  184. package/src/auth/browser-login.ts +247 -0
  185. package/src/auth/config-file.test.ts +68 -0
  186. package/src/auth/config-file.ts +50 -0
  187. package/src/auth/models-providers.test.ts +63 -0
  188. package/src/auth/models-providers.ts +76 -0
  189. package/src/auth/paths.ts +28 -0
  190. package/src/auth/provider-ids.ts +15 -0
  191. package/src/auth/resolve.test.ts +72 -0
  192. package/src/auth/resolve.ts +46 -0
  193. package/src/cli.ts +16 -0
  194. package/src/commands/completion.test.ts +31 -0
  195. package/src/commands/completion.ts +77 -0
  196. package/src/commands/flags.ts +29 -0
  197. package/src/commands/guard.ts +44 -0
  198. package/src/commands/help.ts +20 -0
  199. package/src/commands/login.test.ts +159 -0
  200. package/src/commands/login.ts +94 -0
  201. package/src/commands/logout.test.ts +89 -0
  202. package/src/commands/logout.ts +53 -0
  203. package/src/commands/prompt.ts +21 -0
  204. package/src/commands/registry.ts +50 -0
  205. package/src/commands/ssh.test.ts +101 -0
  206. package/src/commands/ssh.ts +112 -0
  207. package/src/commands/table.test.ts +24 -0
  208. package/src/commands/table.ts +10 -0
  209. package/src/commands/update.test.ts +91 -0
  210. package/src/commands/update.ts +78 -0
  211. package/src/commands/version.ts +6 -0
  212. package/src/commands/whoami.test.ts +72 -0
  213. package/src/commands/whoami.ts +36 -0
  214. package/src/commands/workspace.test.ts +360 -0
  215. package/src/commands/workspace.ts +250 -0
  216. package/src/run.test.ts +53 -0
  217. package/src/run.ts +34 -0
  218. package/src/ssh/bridge.test.ts +70 -0
  219. package/src/ssh/bridge.ts +110 -0
  220. package/src/ssh/config.test.ts +213 -0
  221. package/src/ssh/config.ts +233 -0
  222. package/src/ssh/connect.test.ts +123 -0
  223. package/src/ssh/connect.ts +98 -0
  224. package/src/ssh/tunnel.test.ts +119 -0
  225. package/src/ssh/tunnel.ts +64 -0
  226. package/src/test-support.ts +77 -0
  227. package/src/updates/check.test.ts +99 -0
  228. package/src/updates/check.ts +117 -0
  229. package/src/updates/self.test.ts +117 -0
  230. package/src/updates/self.ts +131 -0
  231. package/src/version.ts +6 -0
@@ -0,0 +1,96 @@
1
+ /**
2
+ * Kubernetes quantity parsing (port of kimchi-dev:src/sandbox/cloud/resources.ts,
3
+ * trimmed to what the workspace list/detail rendering needs) plus display
4
+ * formatters for human tables.
5
+ */
6
+ /**
7
+ * Kubernetes quantity: mantissa, then EITHER an exponent OR a decimal/binary
8
+ * SI suffix — never both.
9
+ */
10
+ const QUANTITY_RE = /^([0-9]+(?:\.[0-9]+)?|\.[0-9]+)([eE][+-]?[0-9]+|n|u|m|k|M|G|T|P|E|Ki|Mi|Gi|Ti|Pi|Ei)?$/;
11
+ const DECIMAL_SUFFIX = {
12
+ n: 1e-9,
13
+ u: 1e-6,
14
+ m: 1e-3,
15
+ k: 1e3,
16
+ M: 1e6,
17
+ G: 1e9,
18
+ T: 1e12,
19
+ P: 1e15,
20
+ E: 1e18,
21
+ };
22
+ const BINARY_SUFFIX = {
23
+ Ki: 1024,
24
+ Mi: 1024 ** 2,
25
+ Gi: 1024 ** 3,
26
+ Ti: 1024 ** 4,
27
+ Pi: 1024 ** 5,
28
+ Ei: 1024 ** 6,
29
+ };
30
+ function parseQuantity(raw) {
31
+ if (typeof raw !== "string")
32
+ return undefined;
33
+ const match = QUANTITY_RE.exec(raw.trim());
34
+ if (!match)
35
+ return undefined;
36
+ const mantissa = Number.parseFloat(match[1] ?? "");
37
+ if (!Number.isFinite(mantissa))
38
+ return undefined;
39
+ const suffix = match[2];
40
+ if (suffix === undefined)
41
+ return mantissa;
42
+ if (/^[eE][+-]?[0-9]+$/.test(suffix)) {
43
+ return mantissa * 10 ** Number.parseInt(suffix.slice(1), 10);
44
+ }
45
+ return mantissa * (BINARY_SUFFIX[suffix] ?? DECIMAL_SUFFIX[suffix] ?? 1);
46
+ }
47
+ /** "200m" → 200, "1.5" → 1500. Undefined for absent/invalid. */
48
+ export function cpuQuantityToMillicores(raw) {
49
+ const cores = parseQuantity(raw);
50
+ return cores === undefined ? undefined : Math.round(cores * 1000);
51
+ }
52
+ /** "512Mi" → 536870912, "1G" → 1000000000. Undefined for absent/invalid. */
53
+ export function byteQuantityToBytes(raw) {
54
+ const bytes = parseQuantity(raw);
55
+ return bytes === undefined ? undefined : Math.round(bytes);
56
+ }
57
+ /** 1000 → "1", 1500 → "1.5", 250 → "250m", undefined → "-". */
58
+ export function formatMillicores(millicores) {
59
+ if (millicores === undefined)
60
+ return "-";
61
+ if (millicores < 1000)
62
+ return `${millicores}m`;
63
+ const cores = millicores / 1000;
64
+ return Number.isInteger(cores) ? String(cores) : cores.toFixed(2).replace(/0+$/, "").replace(/\.$/, "");
65
+ }
66
+ /** 2147483648 → "2Gi", 536870912 → "512Mi", undefined → "-". */
67
+ export function formatBytes(bytes) {
68
+ if (bytes === undefined)
69
+ return "-";
70
+ const GI = 1024 ** 3;
71
+ const MI = 1024 ** 2;
72
+ if (bytes >= GI)
73
+ return formatUnit(bytes / GI, "Gi");
74
+ if (bytes >= MI)
75
+ return formatUnit(bytes / MI, "Mi");
76
+ if (bytes >= 1024)
77
+ return formatUnit(bytes / 1024, "Ki");
78
+ return `${bytes}B`;
79
+ }
80
+ function formatUnit(value, suffix) {
81
+ return `${Number.isInteger(value) ? value : value.toFixed(1)}${suffix}`;
82
+ }
83
+ /** Relative age for table columns: "45s", "12m", "3h", "5d". */
84
+ export function formatAge(since, now = new Date()) {
85
+ const seconds = Math.max(0, Math.floor((now.getTime() - since.getTime()) / 1000));
86
+ if (seconds < 60)
87
+ return `${seconds}s`;
88
+ const minutes = Math.floor(seconds / 60);
89
+ if (minutes < 60)
90
+ return `${minutes}m`;
91
+ const hours = Math.floor(minutes / 60);
92
+ if (hours < 48)
93
+ return `${hours}h`;
94
+ return `${Math.floor(hours / 24)}d`;
95
+ }
96
+ //# sourceMappingURL=resources.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resources.js","sourceRoot":"../src/","sources":["api/resources.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Server-side workspace templates — PLACEHOLDER.
3
+ *
4
+ * Templates are created and stored in the API (they are not local files).
5
+ * The API contract is being finalised server-side; until it lands,
6
+ * `workspace create --template <name>` is accepted at the CLI and fails here
7
+ * with a graceful, actionable error instead of a 4xx surprise.
8
+ */
9
+ export declare class TemplatesUnavailableError extends Error {
10
+ constructor(templateName: string);
11
+ }
12
+ /**
13
+ * Resolve a template name to its create-time parameters.
14
+ *
15
+ * TODO(templates-api): replace with the real call once the contract lands —
16
+ * expected to return resources/dependencies applied at create time.
17
+ */
18
+ export declare function resolveTemplate(templateName: string): never;
19
+ //# sourceMappingURL=templates.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"templates.d.ts","sourceRoot":"../src/","sources":["api/templates.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,qBAAa,yBAA0B,SAAQ,KAAK;gBACvC,YAAY,EAAE,MAAM;CAOhC;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,YAAY,EAAE,MAAM,GAAG,KAAK,CAE3D"}
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Server-side workspace templates — PLACEHOLDER.
3
+ *
4
+ * Templates are created and stored in the API (they are not local files).
5
+ * The API contract is being finalised server-side; until it lands,
6
+ * `workspace create --template <name>` is accepted at the CLI and fails here
7
+ * with a graceful, actionable error instead of a 4xx surprise.
8
+ */
9
+ export class TemplatesUnavailableError extends Error {
10
+ constructor(templateName) {
11
+ super(`Workspace templates are not available yet (requested "${templateName}") — ` +
12
+ `the templates API is being finalised. Omit --template for now.`);
13
+ this.name = "TemplatesUnavailableError";
14
+ }
15
+ }
16
+ /**
17
+ * Resolve a template name to its create-time parameters.
18
+ *
19
+ * TODO(templates-api): replace with the real call once the contract lands —
20
+ * expected to return resources/dependencies applied at create time.
21
+ */
22
+ export function resolveTemplate(templateName) {
23
+ throw new TemplatesUnavailableError(templateName);
24
+ }
25
+ //# sourceMappingURL=templates.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"templates.js","sourceRoot":"../src/","sources":["api/templates.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,MAAM,OAAO,yBAA0B,SAAQ,KAAK;IACnD,YAAY,YAAoB;QAC/B,KAAK,CACJ,yDAAyD,YAAY,OAAO;YAC3E,gEAAgE,CACjE,CAAA;QACD,IAAI,CAAC,IAAI,GAAG,2BAA2B,CAAA;IACxC,CAAC;CACD;AAED;;;;;GAKG;AACH,MAAM,UAAU,eAAe,CAAC,YAAoB;IACnD,MAAM,IAAI,yBAAyB,CAAC,YAAY,CAAC,CAAA;AAClD,CAAC"}
@@ -0,0 +1,23 @@
1
+ import type { ApiOptions } from "./types.js";
2
+ /**
3
+ * Workspace token exchange + lifecycle RPCs (ports of the corresponding
4
+ * kimchi-dev:src/sandbox/cloud/auth.ts functions, without the harness's
5
+ * upsert semantics — kimchictl only resumes, never upserts).
6
+ */
7
+ /** Exchange the API key for a short-lived workspace JWT (WebSocket auth). */
8
+ export declare function exchangeWorkspaceToken(apiKey: string, workspaceId: string, options?: ApiOptions & {
9
+ orgId?: string;
10
+ }): Promise<{
11
+ token: string;
12
+ expireTime: string;
13
+ }>;
14
+ /**
15
+ * Resume a suspended (hibernated) workspace: POST …/workspaces/{id}:resume.
16
+ *
17
+ * Success and "workspace is not suspended" (the control plane's FailedPrecondition
18
+ * 400) both mean the workspace is running. Every other failure propagates.
19
+ */
20
+ export declare function resumeWorkspace(apiKey: string, workspaceId: string, options: ApiOptions & {
21
+ orgId: string;
22
+ }): Promise<void>;
23
+ //# sourceMappingURL=tokens.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tokens.d.ts","sourceRoot":"../src/","sources":["api/tokens.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA;AAG5C;;;;GAIG;AAEH,6EAA6E;AAC7E,wBAAsB,sBAAsB,CAC3C,MAAM,EAAE,MAAM,EACd,WAAW,EAAE,MAAM,EACnB,OAAO,CAAC,EAAE,UAAU,GAAG;IAAE,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,GACvC,OAAO,CAAC;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,CAAC,CAwBhD;AAED;;;;;GAKG;AACH,wBAAsB,eAAe,CACpC,MAAM,EAAE,MAAM,EACd,WAAW,EAAE,MAAM,EACnB,OAAO,EAAE,UAAU,GAAG;IAAE,KAAK,EAAE,MAAM,CAAA;CAAE,GACrC,OAAO,CAAC,IAAI,CAAC,CA4Bf"}
@@ -0,0 +1,51 @@
1
+ import { checkResponse, fetchWithTimeout, resolveEndpoint } from "./http.js";
2
+ import { RemoteNetworkError } from "./types.js";
3
+ /**
4
+ * Workspace token exchange + lifecycle RPCs (ports of the corresponding
5
+ * kimchi-dev:src/sandbox/cloud/auth.ts functions, without the harness's
6
+ * upsert semantics — kimchictl only resumes, never upserts).
7
+ */
8
+ /** Exchange the API key for a short-lived workspace JWT (WebSocket auth). */
9
+ export async function exchangeWorkspaceToken(apiKey, workspaceId, options) {
10
+ const endpoint = resolveEndpoint(options);
11
+ const fetchImpl = options?.fetch ?? globalThis.fetch;
12
+ const url = `${endpoint}/ai-optimizer/v1beta/workspace-tokens:exchange`;
13
+ const resp = await fetchWithTimeout(url, {
14
+ method: "POST",
15
+ headers: { Authorization: `Bearer ${apiKey}`, "Content-Type": "application/json" },
16
+ body: JSON.stringify({ workspaceId }),
17
+ }, fetchImpl, 30_000, options?.signal);
18
+ await checkResponse(resp, url);
19
+ const data = (await resp.json().catch(() => undefined));
20
+ if (typeof data?.token !== "string") {
21
+ throw new RemoteNetworkError(`Missing token in exchange response from ${endpoint}`);
22
+ }
23
+ return { token: data.token, expireTime: typeof data.expireTime === "string" ? data.expireTime : "" };
24
+ }
25
+ /**
26
+ * Resume a suspended (hibernated) workspace: POST …/workspaces/{id}:resume.
27
+ *
28
+ * Success and "workspace is not suspended" (the control plane's FailedPrecondition
29
+ * 400) both mean the workspace is running. Every other failure propagates.
30
+ */
31
+ export async function resumeWorkspace(apiKey, workspaceId, options) {
32
+ const endpoint = resolveEndpoint(options);
33
+ const fetchImpl = options?.fetch ?? globalThis.fetch;
34
+ const url = `${endpoint}/ai-optimizer/v1beta/organizations/${encodeURIComponent(options.orgId)}/workspaces/${encodeURIComponent(workspaceId)}:resume`;
35
+ const resp = await fetchWithTimeout(url, {
36
+ method: "POST",
37
+ headers: { Authorization: `Bearer ${apiKey}`, "Content-Type": "application/json" },
38
+ body: JSON.stringify({}),
39
+ }, fetchImpl, 30_000, options?.signal);
40
+ if (resp.ok)
41
+ return;
42
+ // Clone BEFORE consuming the body: checkResponse re-reads resp.text() and a
43
+ // second read of the same body fails in undici.
44
+ const rest = resp.clone();
45
+ const body = await resp.text().catch(() => "");
46
+ if (resp.status >= 400 && resp.status < 500 && body.includes("not suspended")) {
47
+ return;
48
+ }
49
+ await checkResponse(rest, url);
50
+ }
51
+ //# sourceMappingURL=tokens.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tokens.js","sourceRoot":"../src/","sources":["api/tokens.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,WAAW,CAAA;AAE5E,OAAO,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAA;AAE/C;;;;GAIG;AAEH,6EAA6E;AAC7E,MAAM,CAAC,KAAK,UAAU,sBAAsB,CAC3C,MAAc,EACd,WAAmB,EACnB,OAAyC;IAEzC,MAAM,QAAQ,GAAG,eAAe,CAAC,OAAO,CAAC,CAAA;IACzC,MAAM,SAAS,GAAG,OAAO,EAAE,KAAK,IAAI,UAAU,CAAC,KAAK,CAAA;IAEpD,MAAM,GAAG,GAAG,GAAG,QAAQ,gDAAgD,CAAA;IACvE,MAAM,IAAI,GAAG,MAAM,gBAAgB,CAClC,GAAG,EACH;QACC,MAAM,EAAE,MAAM;QACd,OAAO,EAAE,EAAE,aAAa,EAAE,UAAU,MAAM,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;QAClF,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,WAAW,EAAE,CAAC;KACrC,EACD,SAAS,EACT,MAAM,EACN,OAAO,EAAE,MAAM,CACf,CAAA;IAED,MAAM,aAAa,CAAC,IAAI,EAAE,GAAG,CAAC,CAAA;IAE9B,MAAM,IAAI,GAAG,CAAC,MAAM,IAAI,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAA0D,CAAA;IAChH,IAAI,OAAO,IAAI,EAAE,KAAK,KAAK,QAAQ,EAAE,CAAC;QACrC,MAAM,IAAI,kBAAkB,CAAC,2CAA2C,QAAQ,EAAE,CAAC,CAAA;IACpF,CAAC;IACD,OAAO,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,UAAU,EAAE,OAAO,IAAI,CAAC,UAAU,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,EAAE,CAAA;AACrG,CAAC;AAED;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CACpC,MAAc,EACd,WAAmB,EACnB,OAAuC;IAEvC,MAAM,QAAQ,GAAG,eAAe,CAAC,OAAO,CAAC,CAAA;IACzC,MAAM,SAAS,GAAG,OAAO,EAAE,KAAK,IAAI,UAAU,CAAC,KAAK,CAAA;IAEpD,MAAM,GAAG,GAAG,GAAG,QAAQ,sCAAsC,kBAAkB,CAAC,OAAO,CAAC,KAAK,CAAC,eAAe,kBAAkB,CAAC,WAAW,CAAC,SAAS,CAAA;IACrJ,MAAM,IAAI,GAAG,MAAM,gBAAgB,CAClC,GAAG,EACH;QACC,MAAM,EAAE,MAAM;QACd,OAAO,EAAE,EAAE,aAAa,EAAE,UAAU,MAAM,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;QAClF,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC;KACxB,EACD,SAAS,EACT,MAAM,EACN,OAAO,EAAE,MAAM,CACf,CAAA;IAED,IAAI,IAAI,CAAC,EAAE;QAAE,OAAM;IAEnB,4EAA4E;IAC5E,gDAAgD;IAChD,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,EAAE,CAAA;IACzB,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,CAAA;IAC9C,IAAI,IAAI,CAAC,MAAM,IAAI,GAAG,IAAI,IAAI,CAAC,MAAM,GAAG,GAAG,IAAI,IAAI,CAAC,QAAQ,CAAC,eAAe,CAAC,EAAE,CAAC;QAC/E,OAAM;IACP,CAAC;IAED,MAAM,aAAa,CAAC,IAAI,EAAE,GAAG,CAAC,CAAA;AAC/B,CAAC"}
@@ -0,0 +1,34 @@
1
+ /**
2
+ * Control-plane client types — mirror of the harness's
3
+ * kimchi-dev:src/sandbox/cloud types (trimmed to what kimchictl v1 needs).
4
+ */
5
+ export declare class RemoteAuthError extends Error {
6
+ readonly statusCode: number;
7
+ constructor(message: string, statusCode: number);
8
+ }
9
+ export declare class RemoteNetworkError extends Error {
10
+ constructor(message: string);
11
+ }
12
+ /**
13
+ * Thrown when the control plane rejects a request because the user's
14
+ * resource quota is exhausted (HTTP 429 with a quota body). The message is
15
+ * already user-facing — surface verbatim.
16
+ */
17
+ export declare class RemoteQuotaError extends RemoteNetworkError {
18
+ readonly statusCode: number;
19
+ constructor(message: string, statusCode: number);
20
+ }
21
+ export interface ApiOptions {
22
+ /**
23
+ * Override the cloud API endpoint. Resolution order:
24
+ * 1. this option
25
+ * 2. KIMCHI_REMOTE_ENDPOINT env var
26
+ * 3. production default https://app.kimchi.dev/api
27
+ */
28
+ endpoint?: string;
29
+ /** Override global fetch (tests). */
30
+ fetch?: typeof globalThis.fetch;
31
+ /** External abort signal. */
32
+ signal?: AbortSignal;
33
+ }
34
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"../src/","sources":["api/types.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,qBAAa,eAAgB,SAAQ,KAAK;aAGxB,UAAU,EAAE,MAAM;gBADlC,OAAO,EAAE,MAAM,EACC,UAAU,EAAE,MAAM;CAKnC;AAED,qBAAa,kBAAmB,SAAQ,KAAK;gBAChC,OAAO,EAAE,MAAM;CAI3B;AAED;;;;GAIG;AACH,qBAAa,gBAAiB,SAAQ,kBAAkB;aAGtC,UAAU,EAAE,MAAM;gBADlC,OAAO,EAAE,MAAM,EACC,UAAU,EAAE,MAAM;CAKnC;AAED,MAAM,WAAW,UAAU;IAC1B;;;;;OAKG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,qCAAqC;IACrC,KAAK,CAAC,EAAE,OAAO,UAAU,CAAC,KAAK,CAAA;IAC/B,6BAA6B;IAC7B,MAAM,CAAC,EAAE,WAAW,CAAA;CACpB"}
@@ -0,0 +1,32 @@
1
+ /**
2
+ * Control-plane client types — mirror of the harness's
3
+ * kimchi-dev:src/sandbox/cloud types (trimmed to what kimchictl v1 needs).
4
+ */
5
+ export class RemoteAuthError extends Error {
6
+ statusCode;
7
+ constructor(message, statusCode) {
8
+ super(message);
9
+ this.statusCode = statusCode;
10
+ this.name = "RemoteAuthError";
11
+ }
12
+ }
13
+ export class RemoteNetworkError extends Error {
14
+ constructor(message) {
15
+ super(message);
16
+ this.name = "RemoteNetworkError";
17
+ }
18
+ }
19
+ /**
20
+ * Thrown when the control plane rejects a request because the user's
21
+ * resource quota is exhausted (HTTP 429 with a quota body). The message is
22
+ * already user-facing — surface verbatim.
23
+ */
24
+ export class RemoteQuotaError extends RemoteNetworkError {
25
+ statusCode;
26
+ constructor(message, statusCode) {
27
+ super(message);
28
+ this.statusCode = statusCode;
29
+ this.name = "RemoteQuotaError";
30
+ }
31
+ }
32
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"../src/","sources":["api/types.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,OAAO,eAAgB,SAAQ,KAAK;IAGxB;IAFjB,YACC,OAAe,EACC,UAAkB;QAElC,KAAK,CAAC,OAAO,CAAC,CAAA;QAFE,eAAU,GAAV,UAAU,CAAQ;QAGlC,IAAI,CAAC,IAAI,GAAG,iBAAiB,CAAA;IAC9B,CAAC;CACD;AAED,MAAM,OAAO,kBAAmB,SAAQ,KAAK;IAC5C,YAAY,OAAe;QAC1B,KAAK,CAAC,OAAO,CAAC,CAAA;QACd,IAAI,CAAC,IAAI,GAAG,oBAAoB,CAAA;IACjC,CAAC;CACD;AAED;;;;GAIG;AACH,MAAM,OAAO,gBAAiB,SAAQ,kBAAkB;IAGtC;IAFjB,YACC,OAAe,EACC,UAAkB;QAElC,KAAK,CAAC,OAAO,CAAC,CAAA;QAFE,eAAU,GAAV,UAAU,CAAQ;QAGlC,IAAI,CAAC,IAAI,GAAG,kBAAkB,CAAA;IAC/B,CAAC;CACD"}
@@ -0,0 +1,17 @@
1
+ import type { ApiOptions } from "./types.js";
2
+ import { type Workspace } from "./workspaces.js";
3
+ /**
4
+ * Poll getWorkspace until the workspace is ACTIVE or the deadline passes.
5
+ * Shared by `workspace create` (post-create wait) and `ssh` (post-resume
6
+ * wait) — kap's 2s cadence, deadline-based, progress via onTick.
7
+ *
8
+ * Transient get failures (the workspace is still registering with the
9
+ * control plane) are tolerated until the deadline; auth failures abort.
10
+ */
11
+ export declare function waitForWorkspaceActive(apiKey: string, id: string, options: ApiOptions & {
12
+ timeoutMs: number;
13
+ pollMs?: number;
14
+ sleep?: (ms: number) => Promise<void>;
15
+ onTick?: (elapsedSeconds: number) => void;
16
+ }): Promise<Workspace>;
17
+ //# sourceMappingURL=wait.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"wait.d.ts","sourceRoot":"../src/","sources":["api/wait.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA;AAE5C,OAAO,EAAgB,KAAK,SAAS,EAAE,MAAM,iBAAiB,CAAA;AAE9D;;;;;;;GAOG;AACH,wBAAsB,sBAAsB,CAC3C,MAAM,EAAE,MAAM,EACd,EAAE,EAAE,MAAM,EACV,OAAO,EAAE,UAAU,GAAG;IACrB,SAAS,EAAE,MAAM,CAAA;IACjB,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,KAAK,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;IACrC,MAAM,CAAC,EAAE,CAAC,cAAc,EAAE,MAAM,KAAK,IAAI,CAAA;CACzC,GACC,OAAO,CAAC,SAAS,CAAC,CAuBpB"}
@@ -0,0 +1,37 @@
1
+ import { RemoteAuthError } from "./types.js";
2
+ import { getWorkspace } from "./workspaces.js";
3
+ /**
4
+ * Poll getWorkspace until the workspace is ACTIVE or the deadline passes.
5
+ * Shared by `workspace create` (post-create wait) and `ssh` (post-resume
6
+ * wait) — kap's 2s cadence, deadline-based, progress via onTick.
7
+ *
8
+ * Transient get failures (the workspace is still registering with the
9
+ * control plane) are tolerated until the deadline; auth failures abort.
10
+ */
11
+ export async function waitForWorkspaceActive(apiKey, id, options) {
12
+ const pollMs = options.pollMs ?? 2000;
13
+ const sleep = options.sleep ?? ((ms) => new Promise((resolve) => setTimeout(resolve, ms)));
14
+ const start = Date.now();
15
+ const deadline = start + options.timeoutMs;
16
+ let current;
17
+ while (Date.now() < deadline) {
18
+ await sleep(pollMs);
19
+ options.onTick?.(Math.round((Date.now() - start) / 1000));
20
+ try {
21
+ current = await getWorkspace(apiKey, id, options);
22
+ }
23
+ catch (err) {
24
+ if (err instanceof RemoteAuthError)
25
+ throw err;
26
+ continue;
27
+ }
28
+ if (current.status === "active")
29
+ break;
30
+ }
31
+ if (!current) {
32
+ // Every poll failed; fetch once without tolerance so the real error surfaces.
33
+ current = await getWorkspace(apiKey, id, options);
34
+ }
35
+ return current;
36
+ }
37
+ //# sourceMappingURL=wait.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"wait.js","sourceRoot":"../src/","sources":["api/wait.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,eAAe,EAAE,MAAM,YAAY,CAAA;AAC5C,OAAO,EAAE,YAAY,EAAkB,MAAM,iBAAiB,CAAA;AAE9D;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,sBAAsB,CAC3C,MAAc,EACd,EAAU,EACV,OAKC;IAED,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,IAAI,IAAI,CAAA;IACrC,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,IAAI,CAAC,CAAC,EAAU,EAAE,EAAE,CAAC,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,CAAC,CAAA;IAElG,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,EAAE,CAAA;IACxB,MAAM,QAAQ,GAAG,KAAK,GAAG,OAAO,CAAC,SAAS,CAAA;IAC1C,IAAI,OAA8B,CAAA;IAClC,OAAO,IAAI,CAAC,GAAG,EAAE,GAAG,QAAQ,EAAE,CAAC;QAC9B,MAAM,KAAK,CAAC,MAAM,CAAC,CAAA;QACnB,OAAO,CAAC,MAAM,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC,GAAG,IAAI,CAAC,CAAC,CAAA;QACzD,IAAI,CAAC;YACJ,OAAO,GAAG,MAAM,YAAY,CAAC,MAAM,EAAE,EAAE,EAAE,OAAO,CAAC,CAAA;QAClD,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACd,IAAI,GAAG,YAAY,eAAe;gBAAE,MAAM,GAAG,CAAA;YAC7C,SAAQ;QACT,CAAC;QACD,IAAI,OAAO,CAAC,MAAM,KAAK,QAAQ;YAAE,MAAK;IACvC,CAAC;IACD,IAAI,CAAC,OAAO,EAAE,CAAC;QACd,8EAA8E;QAC9E,OAAO,GAAG,MAAM,YAAY,CAAC,MAAM,EAAE,EAAE,EAAE,OAAO,CAAC,CAAA;IAClD,CAAC;IACD,OAAO,OAAO,CAAA;AACf,CAAC"}
@@ -0,0 +1,33 @@
1
+ import type { ApiOptions } from "./types.js";
2
+ export type WorkspaceStatus = "active" | "initializing" | "suspended" | "deleting" | "idle";
3
+ export interface Workspace {
4
+ /** Server id — also the command-line identifier (`workspace get <id>`, `ssh <id>`). */
5
+ id: string;
6
+ /** First DNS label of the URI — the user-facing name (NOT the server id). */
7
+ alias: string;
8
+ description: string;
9
+ status: WorkspaceStatus;
10
+ uri?: string;
11
+ host?: string;
12
+ createdAt: Date;
13
+ cpuMillicores?: number;
14
+ ramBytes?: number;
15
+ pvcSizeBytes?: number;
16
+ }
17
+ export interface WorkspaceCommandOptions extends ApiOptions {
18
+ /** Pre-resolved organization id — skips the verifyKey round-trip. */
19
+ orgId?: string;
20
+ }
21
+ export declare function listWorkspaces(apiKey: string, options?: WorkspaceCommandOptions): Promise<Workspace[]>;
22
+ export declare function getWorkspace(apiKey: string, id: string, options?: WorkspaceCommandOptions): Promise<Workspace>;
23
+ /**
24
+ * Create a workspace. Server generates the alias (like kap) — there is no
25
+ * client-side name input. Returns the created workspace (status likely
26
+ * "initializing"; callers may poll getWorkspace until "active").
27
+ */
28
+ export declare function createWorkspace(apiKey: string, options: WorkspaceCommandOptions & {
29
+ description?: string;
30
+ }): Promise<Workspace>;
31
+ export declare function deleteWorkspace(apiKey: string, id: string, options?: WorkspaceCommandOptions): Promise<void>;
32
+ export declare function mapWorkspace(raw: unknown, endpoint: string): Workspace;
33
+ //# sourceMappingURL=workspaces.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"workspaces.d.ts","sourceRoot":"../src/","sources":["api/workspaces.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA;AAe5C,MAAM,MAAM,eAAe,GAAG,QAAQ,GAAG,cAAc,GAAG,WAAW,GAAG,UAAU,GAAG,MAAM,CAAA;AAE3F,MAAM,WAAW,SAAS;IACzB,uFAAuF;IACvF,EAAE,EAAE,MAAM,CAAA;IACV,6EAA6E;IAC7E,KAAK,EAAE,MAAM,CAAA;IACb,WAAW,EAAE,MAAM,CAAA;IACnB,MAAM,EAAE,eAAe,CAAA;IACvB,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,SAAS,EAAE,IAAI,CAAA;IACf,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,YAAY,CAAC,EAAE,MAAM,CAAA;CACrB;AAED,MAAM,WAAW,uBAAwB,SAAQ,UAAU;IAC1D,qEAAqE;IACrE,KAAK,CAAC,EAAE,MAAM,CAAA;CACd;AAMD,wBAAsB,cAAc,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,uBAAuB,GAAG,OAAO,CAAC,SAAS,EAAE,CAAC,CAsD5G;AAED,wBAAsB,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,uBAAuB,GAAG,OAAO,CAAC,SAAS,CAAC,CAiBpH;AAED;;;;GAIG;AACH,wBAAsB,eAAe,CACpC,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,uBAAuB,GAAG;IAAE,WAAW,CAAC,EAAE,MAAM,CAAA;CAAE,GACzD,OAAO,CAAC,SAAS,CAAC,CAwBpB;AAED,wBAAsB,eAAe,CAAC,MAAM,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,uBAAuB,GAAG,OAAO,CAAC,IAAI,CAAC,CAclH;AAED,wBAAgB,YAAY,CAAC,GAAG,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,GAAG,SAAS,CAiDtE"}
@@ -0,0 +1,159 @@
1
+ import { checkResponse, fetchWithTimeout, resolveEndpoint } from "./http.js";
2
+ import { verifyApiKey } from "./keys.js";
3
+ import { byteQuantityToBytes, cpuQuantityToMillicores } from "./resources.js";
4
+ import { RemoteAuthError, RemoteNetworkError } from "./types.js";
5
+ /**
6
+ * Workspace client — mirrors the harness's (kimchi-dev:src/sandbox/cloud)
7
+ * calls against the same control-plane API, plus kap's server-named create.
8
+ *
9
+ * The control plane addresses workspaces by UUID id; users type the alias
10
+ * (first DNS label of the URI). api/resolver.ts maps between them.
11
+ */
12
+ const HARNESS_CLIENT_TYPE = "harness"; // matches kimchi-dev:src/sandbox/constants.ts
13
+ const LIST_WORKSPACES_PAGE_LIMIT = 200;
14
+ const LIST_WORKSPACES_PAGE_HARD_CAP = 10;
15
+ async function resolveOrgId(apiKey, options) {
16
+ return options?.orgId ?? (await verifyApiKey(apiKey, options));
17
+ }
18
+ export async function listWorkspaces(apiKey, options) {
19
+ const fetchImpl = options?.fetch ?? globalThis.fetch;
20
+ const endpoint = resolveEndpoint(options);
21
+ try {
22
+ const orgId = await resolveOrgId(apiKey, options);
23
+ const results = [];
24
+ let cursor = "";
25
+ for (let page = 0; page < LIST_WORKSPACES_PAGE_HARD_CAP; page++) {
26
+ const params = new URLSearchParams();
27
+ params.set("page.limit", String(LIST_WORKSPACES_PAGE_LIMIT));
28
+ params.set("clientType", HARNESS_CLIENT_TYPE);
29
+ if (cursor)
30
+ params.set("page.cursor", cursor);
31
+ const url = `${endpoint}/ai-optimizer/v1beta/organizations/${encodeURIComponent(orgId)}/workspaces?${params.toString()}`;
32
+ const resp = await fetchWithTimeout(url, { method: "GET", headers: { Authorization: `Bearer ${apiKey}`, Accept: "application/json" } }, fetchImpl, 30_000, options?.signal);
33
+ await checkResponse(resp, url);
34
+ const data = await resp.json().catch(() => undefined);
35
+ if (typeof data !== "object" || data === null) {
36
+ throw new RemoteNetworkError(`Unexpected response shape from ${endpoint}`);
37
+ }
38
+ const items = data.items;
39
+ if (!Array.isArray(items)) {
40
+ throw new RemoteNetworkError(`Missing items array in list-workspaces response from ${endpoint}`);
41
+ }
42
+ for (const item of items) {
43
+ results.push(mapWorkspace(item, endpoint));
44
+ }
45
+ const nextCursor = data.nextPageCursor;
46
+ if (typeof nextCursor !== "string" || nextCursor.length === 0) {
47
+ return results;
48
+ }
49
+ cursor = nextCursor;
50
+ }
51
+ return results;
52
+ }
53
+ catch (err) {
54
+ if (err instanceof RemoteAuthError || err instanceof RemoteNetworkError) {
55
+ throw err;
56
+ }
57
+ throw new RemoteNetworkError(err instanceof Error ? err.message : String(err));
58
+ }
59
+ }
60
+ export async function getWorkspace(apiKey, id, options) {
61
+ const fetchImpl = options?.fetch ?? globalThis.fetch;
62
+ const endpoint = resolveEndpoint(options);
63
+ const orgId = await resolveOrgId(apiKey, options);
64
+ const url = `${endpoint}/ai-optimizer/v1beta/organizations/${encodeURIComponent(orgId)}/workspaces/${encodeURIComponent(id)}`;
65
+ const resp = await fetchWithTimeout(url, { method: "GET", headers: { Authorization: `Bearer ${apiKey}` } }, fetchImpl, 30_000, options?.signal);
66
+ await checkResponse(resp, url);
67
+ const data = await resp.json().catch(() => undefined);
68
+ return mapWorkspace(data, endpoint);
69
+ }
70
+ /**
71
+ * Create a workspace. Server generates the alias (like kap) — there is no
72
+ * client-side name input. Returns the created workspace (status likely
73
+ * "initializing"; callers may poll getWorkspace until "active").
74
+ */
75
+ export async function createWorkspace(apiKey, options) {
76
+ const fetchImpl = options?.fetch ?? globalThis.fetch;
77
+ const endpoint = resolveEndpoint(options);
78
+ const orgId = await resolveOrgId(apiKey, options);
79
+ const url = `${endpoint}/ai-optimizer/v1beta/organizations/${encodeURIComponent(orgId)}/workspaces`;
80
+ const resp = await fetchWithTimeout(url, {
81
+ method: "POST",
82
+ headers: { Authorization: `Bearer ${apiKey}`, "Content-Type": "application/json" },
83
+ body: JSON.stringify({
84
+ ...(options.description ? { description: options.description } : {}),
85
+ clientType: HARNESS_CLIENT_TYPE,
86
+ }),
87
+ }, fetchImpl, 30_000, options?.signal);
88
+ await checkResponse(resp, url);
89
+ const data = await resp.json().catch(() => undefined);
90
+ return mapWorkspace(data, endpoint);
91
+ }
92
+ export async function deleteWorkspace(apiKey, id, options) {
93
+ const fetchImpl = options?.fetch ?? globalThis.fetch;
94
+ const endpoint = resolveEndpoint(options);
95
+ const orgId = await resolveOrgId(apiKey, options);
96
+ const url = `${endpoint}/ai-optimizer/v1beta/organizations/${encodeURIComponent(orgId)}/workspaces/${encodeURIComponent(id)}`;
97
+ const resp = await fetchWithTimeout(url, { method: "DELETE", headers: { Authorization: `Bearer ${apiKey}` } }, fetchImpl, 30_000, options?.signal);
98
+ await checkResponse(resp, url);
99
+ }
100
+ export function mapWorkspace(raw, endpoint) {
101
+ if (typeof raw !== "object" || raw === null) {
102
+ throw new RemoteNetworkError(`Invalid workspace entry in response from ${endpoint}`);
103
+ }
104
+ const r = raw;
105
+ const id = typeof r.id === "string" && r.id.length > 0 ? r.id : undefined;
106
+ if (!id) {
107
+ throw new RemoteNetworkError(`Missing workspace id in response from ${endpoint}`);
108
+ }
109
+ const uri = typeof r.uri === "string" && r.uri.length > 0 ? r.uri : undefined;
110
+ const alias = uri?.split(".")[0] || id;
111
+ let createdAt;
112
+ if (typeof r.createTime === "string") {
113
+ const parsed = new Date(r.createTime);
114
+ if (!Number.isNaN(parsed.getTime()))
115
+ createdAt = parsed;
116
+ }
117
+ let host;
118
+ if (uri) {
119
+ try {
120
+ host = new URL(uri.includes("://") ? uri : `wss://${uri}`).hostname;
121
+ }
122
+ catch {
123
+ host = undefined; // tolerate URIs URL can't parse — host is display-only here
124
+ }
125
+ }
126
+ // Provisioned sizes arrive nested under spec.resources as Kubernetes
127
+ // quantity strings ("200m", "512Mi", "10Gi").
128
+ const spec = typeof r.spec === "object" && r.spec !== null ? r.spec : undefined;
129
+ const res = spec && typeof spec.resources === "object" && spec.resources !== null
130
+ ? spec.resources
131
+ : undefined;
132
+ return {
133
+ id,
134
+ alias,
135
+ description: typeof r.description === "string" ? r.description : "",
136
+ status: mapWorkspaceStatus(r.status),
137
+ uri,
138
+ host,
139
+ createdAt: createdAt ?? new Date(0),
140
+ cpuMillicores: cpuQuantityToMillicores(res?.cpu),
141
+ ramBytes: byteQuantityToBytes(res?.memory),
142
+ pvcSizeBytes: byteQuantityToBytes(res?.pvcSize),
143
+ };
144
+ }
145
+ function mapWorkspaceStatus(raw) {
146
+ switch (raw) {
147
+ case "ACTIVE":
148
+ return "active";
149
+ case "INITIALIZING":
150
+ return "initializing";
151
+ case "SUSPENDED":
152
+ return "suspended";
153
+ case "DELETING":
154
+ return "deleting";
155
+ default:
156
+ return "idle";
157
+ }
158
+ }
159
+ //# sourceMappingURL=workspaces.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"workspaces.js","sourceRoot":"../src/","sources":["api/workspaces.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,37 @@
1
+ /**
2
+ * Shared auth.json access — a port of the kimchi harness's `syncPiAuth`
3
+ * (kimchi-dev:src/pi-auth.ts). The file format is the harness's pi auth
4
+ * storage:
5
+ *
6
+ * { "<providerId>": { "type": "api_key", "key": "…" }, … }
7
+ *
8
+ * written pretty-printed (2-space indent, trailing newline), mode 0600, under
9
+ * a proper-lockfile lock. kimchictl must stay byte-compatible: the harness
10
+ * reads the entries this writes, and vice versa.
11
+ *
12
+ * Difference vs the harness port: the harness derives provider ids from
13
+ * models.json and throws when it is missing; kimchictl takes the ids as a
14
+ * parameter (the login command derives them from models.json when present and
15
+ * from the models metadata API otherwise) so it can run on machines that
16
+ * have never installed the harness.
17
+ */
18
+ /** Read the raw auth.json map. Returns {} when the file is absent or blank. */
19
+ export declare function readAuthJson(authPath: string): Record<string, unknown>;
20
+ /** Read the saved Kimchi API key, if the shared auth.json has one. */
21
+ export declare function readSavedApiKey(authPath: string): string | undefined;
22
+ /**
23
+ * Replace all Kimchi-managed entries in auth.json: delete every existing
24
+ * kimchi provider credential (`kimchi-dev`, `kimchi-dev/*`,
25
+ * `kimchi-experimental`), then, when apiKey is non-empty, write
26
+ * `{ type: "api_key", key }` for each id in providerIds (deduped,
27
+ * "kimchi-dev" always included). Empty apiKey = pure clear.
28
+ *
29
+ * Non-Kimchi providers are preserved untouched. Mirrors the harness: no-op
30
+ * content only re-chmods to 0600 instead of rewriting.
31
+ */
32
+ export declare function syncSharedAuth(authPath: string, apiKey: string, providerIds: readonly string[]): Promise<void>;
33
+ /** Remove all Kimchi credentials from auth.json (logout path). No-op when absent. */
34
+ export declare function clearSharedAuth(authPath: string): Promise<void>;
35
+ /** Kimchi provider ids listed in an existing harness models.json ({} when absent/unreadable). */
36
+ export declare function kimchiProviderIdsFromModelsJson(modelsPath: string): string[];
37
+ //# sourceMappingURL=auth-file.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth-file.d.ts","sourceRoot":"../src/","sources":["auth/auth-file.ts"],"names":[],"mappings":"AAMA;;;;;;;;;;;;;;;;GAgBG;AAEH,+EAA+E;AAC/E,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAGtE;AAED,sEAAsE;AACtE,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAMpE;AAED;;;;;;;;;GASG;AACH,wBAAsB,cAAc,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,SAAS,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAgCpH;AAED,qFAAqF;AACrF,wBAAsB,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAErE;AAED,iGAAiG;AACjG,wBAAgB,+BAA+B,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,EAAE,CAa5E"}