@akanjs/cli 2.2.1 → 2.2.2-rc.0

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.
@@ -17,18 +17,6 @@ import { ChatOpenAI } from "@langchain/openai";
17
17
  import { Logger as Logger2 } from "akanjs/common";
18
18
  import chalk from "chalk";
19
19
 
20
- // pkgs/@akanjs/devkit/cloud/constants.ts
21
- var basePath = `${Bun.env.HOME ?? Bun.env.USERPROFILE}/.akan`;
22
- var configPath = `${basePath}/config.json`;
23
- var akanCloudHost = process.env.USE_AKANJS_PKGS === "true" ? "http://localhost" : "https://cloud.akanjs.com";
24
- var akanCloudUrl = `${akanCloudHost}${process.env.USE_AKANJS_PKGS === "true" ? ":8282" : ""}/api`;
25
- var defaultHostConfig = {};
26
- var defaultAkanGlobalConfig = {
27
- cloudHost: {},
28
- remoteEnvServers: {},
29
- llm: null
30
- };
31
-
32
20
  // pkgs/@akanjs/devkit/cloud/globalConfig.ts
33
21
  import { mkdir } from "fs/promises";
34
22
  import dayjs from "dayjs";
@@ -71,8 +59,19 @@ class FileSys {
71
59
  }
72
60
  }
73
61
 
62
+ // pkgs/@akanjs/devkit/cloud/constants.ts
63
+ var basePath = `${Bun.env.HOME ?? Bun.env.USERPROFILE}/.akan`;
64
+ var configPath = `${basePath}/config.json`;
65
+ var getDefaultHostConfig = (host = GlobalConfig.akanCloudHost) => ({ host });
66
+ var defaultAkanGlobalConfig = {
67
+ cloudHost: {},
68
+ remoteEnvServers: {},
69
+ llm: null
70
+ };
71
+
74
72
  // pkgs/@akanjs/devkit/cloud/globalConfig.ts
75
73
  class GlobalConfig {
74
+ static akanCloudHost = process.env.USE_AKANJS_PKGS === "true" ? `http://localhost:${process.env.CLOUD_HOST_PORT ?? 8283}` : "https://cloud.akanjs.com";
76
75
  static async#getAkanGlobalConfig() {
77
76
  const exists = await FileSys.fileExists(configPath);
78
77
  const akanConfig = exists ? await FileSys.readJson(configPath) : {};
@@ -87,13 +86,13 @@ class GlobalConfig {
87
86
  await mkdir(basePath, { recursive: true });
88
87
  await Bun.write(configPath, JSON.stringify(akanConfig, null, 2));
89
88
  }
90
- static async getHostConfig(host = akanCloudHost) {
89
+ static async getHostConfig(host = GlobalConfig.akanCloudHost) {
91
90
  const akanConfig = await GlobalConfig.#getAkanGlobalConfig();
92
- return GlobalConfig.toHostConfig(akanConfig.cloudHost[host] ?? defaultHostConfig);
91
+ return GlobalConfig.toHostConfig(akanConfig.cloudHost[host] ?? getDefaultHostConfig(host));
93
92
  }
94
- static async setHostConfig(host = akanCloudHost, config = {}) {
93
+ static async setHostConfig(config = getDefaultHostConfig()) {
95
94
  const akanConfig = await GlobalConfig.#getAkanGlobalConfig();
96
- akanConfig.cloudHost[host] = GlobalConfig.toHostConfigDto(config);
95
+ akanConfig.cloudHost[config.host] = GlobalConfig.toHostConfigDto(config);
97
96
  await GlobalConfig.#setAkanGlobalConfig(akanConfig);
98
97
  }
99
98
  static async getLlmConfig() {
@@ -145,6 +144,7 @@ class GlobalConfig {
145
144
  }
146
145
  static toHostConfigDto(hostConfig) {
147
146
  return {
147
+ host: hostConfig.host,
148
148
  auth: {
149
149
  accessToken: hostConfig.auth?.accessToken ? GlobalConfig.toAccessTokenDto(hostConfig.auth.accessToken) : undefined,
150
150
  self: hostConfig.auth?.self
@@ -153,6 +153,7 @@ class GlobalConfig {
153
153
  }
154
154
  static toHostConfig(hostConfigDto) {
155
155
  return {
156
+ host: hostConfigDto.host,
156
157
  auth: {
157
158
  accessToken: hostConfigDto.auth?.accessToken ? GlobalConfig.toAccessToken(hostConfigDto.auth.accessToken) : undefined,
158
159
  self: hostConfigDto.auth?.self
@@ -177,7 +178,7 @@ class HttpClient {
177
178
  ...headers
178
179
  }
179
180
  });
180
- return response.json();
181
+ return await response.json();
181
182
  }
182
183
  async getFile(url, localPath, headers) {
183
184
  const response = await fetch(`${this.baseUrl}${url}`, {
@@ -194,7 +195,7 @@ class HttpClient {
194
195
  body: isFormData ? data : JSON.stringify(data),
195
196
  headers: isFormData ? { ...this.headers, ...headers } : { "Content-Type": "application/json", ...this.headers, ...headers }
196
197
  });
197
- return response.json();
198
+ return await response.json();
198
199
  }
199
200
  setHeaders(headers) {
200
201
  Object.assign(this.headers, headers);
@@ -206,21 +207,25 @@ class CloudApi {
206
207
  #api;
207
208
  #accessToken = null;
208
209
  #workspace;
210
+ host;
211
+ url;
209
212
  static async fromHost(workspace, host) {
210
213
  const hostConfig = await GlobalConfig.getHostConfig(host);
211
214
  return new CloudApi(workspace, hostConfig);
212
215
  }
213
216
  constructor(workspace, hostConfig) {
214
217
  this.#workspace = workspace;
215
- const host = akanCloudHost;
216
- this.#api = new HttpClient(`${host}/api`);
217
218
  this.#accessToken = hostConfig.auth?.accessToken ?? null;
219
+ this.host = hostConfig.host;
220
+ this.url = `${this.host}/api`;
221
+ this.#api = new HttpClient(this.url);
218
222
  if (this.#accessToken && !GlobalConfig.needRefreshToken(this.#accessToken))
219
223
  this.#api.setHeaders({
220
224
  Authorization: `Bearer ${this.#accessToken.jwt}`
221
225
  });
222
226
  }
223
227
  async uploadEnv(devProjectId, file) {
228
+ await this.#ensureAccessTokenLive();
224
229
  const formData = new FormData;
225
230
  formData.append("devProjectId", devProjectId);
226
231
  formData.append("file", file);
@@ -228,18 +233,13 @@ class CloudApi {
228
233
  return data;
229
234
  }
230
235
  async downloadEnv(devProjectId) {
236
+ await this.#ensureAccessTokenLive();
231
237
  const localPath = `${this.#workspace.workspaceRoot}/local/env.tar`;
232
238
  await this.#api.getFile(`/downloadEnv/${devProjectId}`, localPath);
233
239
  return localPath;
234
240
  }
235
241
  async getRemoteAuthToken(remoteId) {
236
242
  try {
237
- if (this.#accessToken) {
238
- if (GlobalConfig.needRefreshToken(this.#accessToken))
239
- return await this.#refreshAuthToken();
240
- else
241
- return await this.#refreshAuthToken();
242
- }
243
243
  const accessToken = await this.#api.get(`/getRemoteAuthToken/${remoteId}`);
244
244
  this.#accessToken = GlobalConfig.toAccessToken(accessToken);
245
245
  this.#api.setHeaders({
@@ -250,14 +250,21 @@ class CloudApi {
250
250
  return null;
251
251
  }
252
252
  }
253
- async#refreshAuthToken() {
253
+ async#ensureAccessTokenLive({
254
+ allowUnauthorized = false
255
+ } = {}) {
256
+ if (!this.#accessToken)
257
+ throw new Error("No access token");
258
+ const needRefresh = GlobalConfig.needRefreshToken(this.#accessToken);
259
+ if (!needRefresh)
260
+ return this.#accessToken;
254
261
  const refreshToken = this.#accessToken?.refreshToken;
255
262
  if (!refreshToken)
256
263
  throw new Error("No refresh token");
257
264
  return await this.refreshAuthToken(refreshToken);
258
265
  }
259
266
  async refreshAuthToken(refreshToken) {
260
- const response = await this.#api.post(`/refreshRemoteAuthToken`, { refreshToken });
267
+ const response = await this.#api.post(`/refreshAuthToken`, { refreshToken });
261
268
  this.#accessToken = GlobalConfig.toAccessToken(response);
262
269
  this.#api.setHeaders({ Authorization: `Bearer ${this.#accessToken.jwt}` });
263
270
  return this.#accessToken;
@@ -333,10 +340,10 @@ class Spinner {
333
340
 
334
341
  // pkgs/@akanjs/devkit/aiEditor.ts
335
342
  var MAX_ASK_TRY = 300;
336
- var supportedLlmModels = [
337
- "deepseek-chat",
338
- "deepseek-reasoner"
339
- ];
343
+ var deepSeekLlmModels = ["deepseek-chat", "deepseek-reasoner"];
344
+ var openAiLlmModels = ["gpt-5.5", "gpt-4.1", "gpt-4.1-mini", "gpt-4o", "gpt-4o-mini"];
345
+ var supportedLlmModels = [...deepSeekLlmModels, ...openAiLlmModels];
346
+ var isOpenAiLlmModel = (model) => openAiLlmModels.includes(model);
340
347
  var parseTypescriptFileBlocks = (text) => {
341
348
  const fileBlocks = [];
342
349
  const codeBlockRegex = /```(?:typescript|ts|tsx)\s*\n([\s\S]*?)```/gi;
@@ -387,13 +394,26 @@ class AiSession {
387
394
  return session;
388
395
  }
389
396
  static #setChatModel(model, apiKey, { temperature = 0 } = {}) {
390
- AiSession.#chat = new ChatDeepSeek({
397
+ AiSession.#chat = AiSession.#createChatModel(model, apiKey, {
398
+ temperature,
399
+ streaming: true
400
+ });
401
+ return AiSession;
402
+ }
403
+ static #createChatModel(model, apiKey, { temperature = 0, streaming = false } = {}) {
404
+ if (isOpenAiLlmModel(model))
405
+ return new ChatOpenAI({
406
+ modelName: model,
407
+ temperature,
408
+ streaming,
409
+ openAIApiKey: apiKey
410
+ });
411
+ return new ChatDeepSeek({
391
412
  modelName: model,
392
413
  temperature,
393
- streaming: true,
414
+ streaming,
394
415
  apiKey
395
416
  });
396
- return AiSession;
397
417
  }
398
418
  static async getLlmConfig() {
399
419
  return await GlobalConfig.getLlmConfig();
@@ -414,11 +434,7 @@ class AiSession {
414
434
  const spinner = new Spinner("Validating LLM API key...", {
415
435
  prefix: `\uD83E\uDD16akan-editor`
416
436
  }).start();
417
- const chat = new ChatOpenAI({
418
- modelName,
419
- temperature: 0,
420
- configuration: { baseURL: "https://api.deepseek.com/v1", apiKey }
421
- });
437
+ const chat = AiSession.#createChatModel(modelName, apiKey);
422
438
  try {
423
439
  await chat.invoke("Hi, and just say 'ok'");
424
440
  spinner.succeed("LLM API key is valid");
package/index.js CHANGED
@@ -15,18 +15,6 @@ import { ChatOpenAI } from "@langchain/openai";
15
15
  import { Logger as Logger2 } from "akanjs/common";
16
16
  import chalk from "chalk";
17
17
 
18
- // pkgs/@akanjs/devkit/cloud/constants.ts
19
- var basePath = `${Bun.env.HOME ?? Bun.env.USERPROFILE}/.akan`;
20
- var configPath = `${basePath}/config.json`;
21
- var akanCloudHost = process.env.USE_AKANJS_PKGS === "true" ? "http://localhost" : "https://cloud.akanjs.com";
22
- var akanCloudUrl = `${akanCloudHost}${process.env.USE_AKANJS_PKGS === "true" ? ":8282" : ""}/api`;
23
- var defaultHostConfig = {};
24
- var defaultAkanGlobalConfig = {
25
- cloudHost: {},
26
- remoteEnvServers: {},
27
- llm: null
28
- };
29
-
30
18
  // pkgs/@akanjs/devkit/cloud/globalConfig.ts
31
19
  import { mkdir } from "fs/promises";
32
20
  import dayjs from "dayjs";
@@ -69,8 +57,19 @@ class FileSys {
69
57
  }
70
58
  }
71
59
 
60
+ // pkgs/@akanjs/devkit/cloud/constants.ts
61
+ var basePath = `${Bun.env.HOME ?? Bun.env.USERPROFILE}/.akan`;
62
+ var configPath = `${basePath}/config.json`;
63
+ var getDefaultHostConfig = (host = GlobalConfig.akanCloudHost) => ({ host });
64
+ var defaultAkanGlobalConfig = {
65
+ cloudHost: {},
66
+ remoteEnvServers: {},
67
+ llm: null
68
+ };
69
+
72
70
  // pkgs/@akanjs/devkit/cloud/globalConfig.ts
73
71
  class GlobalConfig {
72
+ static akanCloudHost = process.env.USE_AKANJS_PKGS === "true" ? `http://localhost:${process.env.CLOUD_HOST_PORT ?? 8283}` : "https://cloud.akanjs.com";
74
73
  static async#getAkanGlobalConfig() {
75
74
  const exists = await FileSys.fileExists(configPath);
76
75
  const akanConfig = exists ? await FileSys.readJson(configPath) : {};
@@ -85,13 +84,13 @@ class GlobalConfig {
85
84
  await mkdir(basePath, { recursive: true });
86
85
  await Bun.write(configPath, JSON.stringify(akanConfig, null, 2));
87
86
  }
88
- static async getHostConfig(host = akanCloudHost) {
87
+ static async getHostConfig(host = GlobalConfig.akanCloudHost) {
89
88
  const akanConfig = await GlobalConfig.#getAkanGlobalConfig();
90
- return GlobalConfig.toHostConfig(akanConfig.cloudHost[host] ?? defaultHostConfig);
89
+ return GlobalConfig.toHostConfig(akanConfig.cloudHost[host] ?? getDefaultHostConfig(host));
91
90
  }
92
- static async setHostConfig(host = akanCloudHost, config = {}) {
91
+ static async setHostConfig(config = getDefaultHostConfig()) {
93
92
  const akanConfig = await GlobalConfig.#getAkanGlobalConfig();
94
- akanConfig.cloudHost[host] = GlobalConfig.toHostConfigDto(config);
93
+ akanConfig.cloudHost[config.host] = GlobalConfig.toHostConfigDto(config);
95
94
  await GlobalConfig.#setAkanGlobalConfig(akanConfig);
96
95
  }
97
96
  static async getLlmConfig() {
@@ -143,6 +142,7 @@ class GlobalConfig {
143
142
  }
144
143
  static toHostConfigDto(hostConfig) {
145
144
  return {
145
+ host: hostConfig.host,
146
146
  auth: {
147
147
  accessToken: hostConfig.auth?.accessToken ? GlobalConfig.toAccessTokenDto(hostConfig.auth.accessToken) : undefined,
148
148
  self: hostConfig.auth?.self
@@ -151,6 +151,7 @@ class GlobalConfig {
151
151
  }
152
152
  static toHostConfig(hostConfigDto) {
153
153
  return {
154
+ host: hostConfigDto.host,
154
155
  auth: {
155
156
  accessToken: hostConfigDto.auth?.accessToken ? GlobalConfig.toAccessToken(hostConfigDto.auth.accessToken) : undefined,
156
157
  self: hostConfigDto.auth?.self
@@ -175,7 +176,7 @@ class HttpClient {
175
176
  ...headers
176
177
  }
177
178
  });
178
- return response.json();
179
+ return await response.json();
179
180
  }
180
181
  async getFile(url, localPath, headers) {
181
182
  const response = await fetch(`${this.baseUrl}${url}`, {
@@ -192,7 +193,7 @@ class HttpClient {
192
193
  body: isFormData ? data : JSON.stringify(data),
193
194
  headers: isFormData ? { ...this.headers, ...headers } : { "Content-Type": "application/json", ...this.headers, ...headers }
194
195
  });
195
- return response.json();
196
+ return await response.json();
196
197
  }
197
198
  setHeaders(headers) {
198
199
  Object.assign(this.headers, headers);
@@ -204,21 +205,25 @@ class CloudApi {
204
205
  #api;
205
206
  #accessToken = null;
206
207
  #workspace;
208
+ host;
209
+ url;
207
210
  static async fromHost(workspace, host) {
208
211
  const hostConfig = await GlobalConfig.getHostConfig(host);
209
212
  return new CloudApi(workspace, hostConfig);
210
213
  }
211
214
  constructor(workspace, hostConfig) {
212
215
  this.#workspace = workspace;
213
- const host = akanCloudHost;
214
- this.#api = new HttpClient(`${host}/api`);
215
216
  this.#accessToken = hostConfig.auth?.accessToken ?? null;
217
+ this.host = hostConfig.host;
218
+ this.url = `${this.host}/api`;
219
+ this.#api = new HttpClient(this.url);
216
220
  if (this.#accessToken && !GlobalConfig.needRefreshToken(this.#accessToken))
217
221
  this.#api.setHeaders({
218
222
  Authorization: `Bearer ${this.#accessToken.jwt}`
219
223
  });
220
224
  }
221
225
  async uploadEnv(devProjectId, file) {
226
+ await this.#ensureAccessTokenLive();
222
227
  const formData = new FormData;
223
228
  formData.append("devProjectId", devProjectId);
224
229
  formData.append("file", file);
@@ -226,18 +231,13 @@ class CloudApi {
226
231
  return data;
227
232
  }
228
233
  async downloadEnv(devProjectId) {
234
+ await this.#ensureAccessTokenLive();
229
235
  const localPath = `${this.#workspace.workspaceRoot}/local/env.tar`;
230
236
  await this.#api.getFile(`/downloadEnv/${devProjectId}`, localPath);
231
237
  return localPath;
232
238
  }
233
239
  async getRemoteAuthToken(remoteId) {
234
240
  try {
235
- if (this.#accessToken) {
236
- if (GlobalConfig.needRefreshToken(this.#accessToken))
237
- return await this.#refreshAuthToken();
238
- else
239
- return await this.#refreshAuthToken();
240
- }
241
241
  const accessToken = await this.#api.get(`/getRemoteAuthToken/${remoteId}`);
242
242
  this.#accessToken = GlobalConfig.toAccessToken(accessToken);
243
243
  this.#api.setHeaders({
@@ -248,14 +248,21 @@ class CloudApi {
248
248
  return null;
249
249
  }
250
250
  }
251
- async#refreshAuthToken() {
251
+ async#ensureAccessTokenLive({
252
+ allowUnauthorized = false
253
+ } = {}) {
254
+ if (!this.#accessToken)
255
+ throw new Error("No access token");
256
+ const needRefresh = GlobalConfig.needRefreshToken(this.#accessToken);
257
+ if (!needRefresh)
258
+ return this.#accessToken;
252
259
  const refreshToken = this.#accessToken?.refreshToken;
253
260
  if (!refreshToken)
254
261
  throw new Error("No refresh token");
255
262
  return await this.refreshAuthToken(refreshToken);
256
263
  }
257
264
  async refreshAuthToken(refreshToken) {
258
- const response = await this.#api.post(`/refreshRemoteAuthToken`, { refreshToken });
265
+ const response = await this.#api.post(`/refreshAuthToken`, { refreshToken });
259
266
  this.#accessToken = GlobalConfig.toAccessToken(response);
260
267
  this.#api.setHeaders({ Authorization: `Bearer ${this.#accessToken.jwt}` });
261
268
  return this.#accessToken;
@@ -331,10 +338,10 @@ class Spinner {
331
338
 
332
339
  // pkgs/@akanjs/devkit/aiEditor.ts
333
340
  var MAX_ASK_TRY = 300;
334
- var supportedLlmModels = [
335
- "deepseek-chat",
336
- "deepseek-reasoner"
337
- ];
341
+ var deepSeekLlmModels = ["deepseek-chat", "deepseek-reasoner"];
342
+ var openAiLlmModels = ["gpt-5.5", "gpt-4.1", "gpt-4.1-mini", "gpt-4o", "gpt-4o-mini"];
343
+ var supportedLlmModels = [...deepSeekLlmModels, ...openAiLlmModels];
344
+ var isOpenAiLlmModel = (model) => openAiLlmModels.includes(model);
338
345
  var parseTypescriptFileBlocks = (text) => {
339
346
  const fileBlocks = [];
340
347
  const codeBlockRegex = /```(?:typescript|ts|tsx)\s*\n([\s\S]*?)```/gi;
@@ -385,13 +392,26 @@ class AiSession {
385
392
  return session;
386
393
  }
387
394
  static #setChatModel(model, apiKey, { temperature = 0 } = {}) {
388
- AiSession.#chat = new ChatDeepSeek({
395
+ AiSession.#chat = AiSession.#createChatModel(model, apiKey, {
396
+ temperature,
397
+ streaming: true
398
+ });
399
+ return AiSession;
400
+ }
401
+ static #createChatModel(model, apiKey, { temperature = 0, streaming = false } = {}) {
402
+ if (isOpenAiLlmModel(model))
403
+ return new ChatOpenAI({
404
+ modelName: model,
405
+ temperature,
406
+ streaming,
407
+ openAIApiKey: apiKey
408
+ });
409
+ return new ChatDeepSeek({
389
410
  modelName: model,
390
411
  temperature,
391
- streaming: true,
412
+ streaming,
392
413
  apiKey
393
414
  });
394
- return AiSession;
395
415
  }
396
416
  static async getLlmConfig() {
397
417
  return await GlobalConfig.getLlmConfig();
@@ -412,11 +432,7 @@ class AiSession {
412
432
  const spinner = new Spinner("Validating LLM API key...", {
413
433
  prefix: `\uD83E\uDD16akan-editor`
414
434
  }).start();
415
- const chat = new ChatOpenAI({
416
- modelName,
417
- temperature: 0,
418
- configuration: { baseURL: "https://api.deepseek.com/v1", apiKey }
419
- });
435
+ const chat = AiSession.#createChatModel(modelName, apiKey);
420
436
  try {
421
437
  await chat.invoke("Hi, and just say 'ok'");
422
438
  spinner.succeed("LLM API key is valid");
@@ -11273,8 +11289,8 @@ class CloudRunner extends runner("cloud") {
11273
11289
  #getSshArgs(config, command3) {
11274
11290
  return [...config.port ? ["-p", config.port.toString()] : [], this.#getSshTarget(config), command3];
11275
11291
  }
11276
- async login(workspace) {
11277
- const config = await GlobalConfig.getHostConfig();
11292
+ async login(host, workspace) {
11293
+ const config = await GlobalConfig.getHostConfig(host);
11278
11294
  const cloudApi2 = new CloudApi(workspace, config);
11279
11295
  const self = config.auth ? await cloudApi2.getRemoteSelf() : null;
11280
11296
  if (self) {
@@ -11284,7 +11300,7 @@ class CloudRunner extends runner("cloud") {
11284
11300
  return true;
11285
11301
  }
11286
11302
  const remoteId = crypto.randomUUID();
11287
- const signinUrl = `${akanCloudUrl}/signin?remoteId=${remoteId}`;
11303
+ const signinUrl = `${cloudApi2.host}/remoteAuth?remoteId=${encodeURIComponent(remoteId)}`;
11288
11304
  Logger14.rawLog(chalk7.bold(`
11289
11305
  ${chalk7.green("\u27A4")} Authentication Required`));
11290
11306
  Logger14.rawLog(chalk7.dim("Please visit or click the following URL:"));
@@ -11310,12 +11326,10 @@ ${chalk7.green("\u27A4")} Authentication Required`));
11310
11326
  const accessToken = await cloudApi2.getRemoteAuthToken(remoteId);
11311
11327
  const self2 = await cloudApi2.getRemoteSelf();
11312
11328
  if (accessToken && self2) {
11313
- await GlobalConfig.setHostConfig(akanCloudHost, {
11314
- auth: { accessToken, self: self2 }
11315
- });
11329
+ await GlobalConfig.setHostConfig({ host: config.host, auth: { accessToken, self: self2 } });
11316
11330
  Logger14.rawLog(chalk7.green(`\r\u2713 Authentication successful!`));
11317
11331
  Logger14.rawLog(chalk7.green.bold(`
11318
- \u2728 Welcome aboard, ${self2.nickname}!`));
11332
+ \u2728 Welcome aboard, ${self2.nickname ?? "anonymous"}!`));
11319
11333
  Logger14.rawLog(chalk7.dim(`You're now ready to use Akan CLI!
11320
11334
  `));
11321
11335
  return true;
@@ -11324,12 +11338,12 @@ ${chalk7.green("\u27A4")} Authentication Required`));
11324
11338
  }
11325
11339
  throw new Error(chalk7.red("\u2716 Authentication timed out after 10 minutes. Please try again."));
11326
11340
  }
11327
- async logout() {
11328
- const config = await GlobalConfig.getHostConfig();
11341
+ async logout(host) {
11342
+ const config = await GlobalConfig.getHostConfig(host);
11329
11343
  if (config.auth?.self) {
11330
- await GlobalConfig.setHostConfig(akanCloudHost, {});
11344
+ await GlobalConfig.setHostConfig(getDefaultHostConfig(config.host));
11331
11345
  Logger14.rawLog(chalk7.magenta.bold(`
11332
- \uD83D\uDC4B Goodbye, ${config.auth.self.nickname}!`));
11346
+ \uD83D\uDC4B Goodbye, ${config.auth.self.nickname ?? "anonymous"}!`));
11333
11347
  Logger14.rawLog(chalk7.dim(`\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
11334
11348
  `));
11335
11349
  Logger14.rawLog(chalk7.cyan("You have been successfully logged out."));
@@ -11343,7 +11357,7 @@ ${chalk7.green("\u27A4")} Authentication Required`));
11343
11357
  }
11344
11358
  }
11345
11359
  async setLlm() {
11346
- await AiSession.init({ useExisting: true });
11360
+ await AiSession.init({ useExisting: false });
11347
11361
  }
11348
11362
  resetLlm() {
11349
11363
  AiSession.setLlmConfig(null);
@@ -11520,11 +11534,11 @@ ${chalk7.green("\u27A4")} Authentication Required`));
11520
11534
 
11521
11535
  // pkgs/@akanjs/cli/cloud/cloud.script.ts
11522
11536
  class CloudScript extends script("cloud", [CloudRunner, ApplicationScript, PackageScript]) {
11523
- async login(workspace) {
11524
- await this.cloudRunner.login(workspace);
11537
+ async login(host, workspace) {
11538
+ await this.cloudRunner.login(host, workspace);
11525
11539
  }
11526
- async logout(workspace) {
11527
- await this.cloudRunner.logout();
11540
+ async logout(host, workspace) {
11541
+ await this.cloudRunner.logout(host);
11528
11542
  }
11529
11543
  async setLlm(workspace) {
11530
11544
  await this.cloudRunner.setLlm();
@@ -11580,11 +11594,11 @@ var localRegistryUrl = () => process.env.AKAN_NPM_REGISTRY ?? "http://127.0.0.1:
11580
11594
  var resolveRegistryUrl = (registry) => registry === "local" ? localRegistryUrl() : undefined;
11581
11595
 
11582
11596
  class CloudCommand extends command("cloud", [CloudScript], ({ public: target }) => ({
11583
- login: target({ desc: "Login to Akan Cloud services" }).with(Workspace).exec(async function(workspace) {
11584
- await this.cloudScript.login(workspace);
11597
+ login: target({ desc: "Login to Akan Cloud services" }).option("host", String, { desc: "host of the cloud", default: GlobalConfig.akanCloudHost }).with(Workspace).exec(async function(host, workspace) {
11598
+ await this.cloudScript.login(host, workspace);
11585
11599
  }),
11586
- logout: target({ desc: "Logout from Akan Cloud services" }).with(Workspace).exec(async function(workspace) {
11587
- await this.cloudScript.logout(workspace);
11600
+ logout: target({ desc: "Logout from Akan Cloud services" }).option("host", String, { desc: "host of the cloud", default: GlobalConfig.akanCloudHost }).with(Workspace).exec(async function(host, workspace) {
11601
+ await this.cloudScript.logout(host, workspace);
11588
11602
  }),
11589
11603
  setLlm: target({ desc: "Configure LLM (Large Language Model) API key" }).with(Workspace).exec(async function(workspace) {
11590
11604
  await this.cloudScript.setLlm(workspace);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@akanjs/cli",
3
- "version": "2.2.1",
3
+ "version": "2.2.2-rc.0",
4
4
  "sourceType": "module",
5
5
  "type": "module",
6
6
  "publishConfig": {
@@ -35,7 +35,7 @@
35
35
  "@langchain/openai": "^1.4.6",
36
36
  "@tailwindcss/node": "^4.3.0",
37
37
  "@trapezedev/project": "^7.1.4",
38
- "akanjs": "2.2.1",
38
+ "akanjs": "2.2.2-rc.0",
39
39
  "chalk": "^5.6.2",
40
40
  "commander": "^14.0.3",
41
41
  "daisyui": "^5.5.20",