@agent-api/cli 0.2.0 → 0.2.1

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.
@@ -1,5 +1,5 @@
1
1
  export declare const cliName = "agent-tui";
2
2
  export declare const cliAuthor = "AgentsWay";
3
- export declare const cliVersion = "0.2.0";
3
+ export declare const cliVersion = "0.2.1";
4
4
  export declare const runtime: import("@agent-api/sdk/local").LocalRuntime;
5
5
  export declare function ensureRuntime(): Promise<import("@agent-api/sdk/local").LocalRuntime>;
@@ -3,7 +3,7 @@ import { cp, mkdir, readFile, rename, rm, stat, writeFile } from "node:fs/promis
3
3
  import path from "node:path";
4
4
  export const cliName = "agent-tui";
5
5
  export const cliAuthor = "AgentsWay";
6
- export const cliVersion = "0.2.0";
6
+ export const cliVersion = "0.2.1";
7
7
  const legacyCliName = "agent-api-cli";
8
8
  export const runtime = createLocalRuntime({
9
9
  appName: cliName,
@@ -22,14 +22,20 @@ export async function ensureRuntime() {
22
22
  return runtime;
23
23
  }
24
24
  async function migrateLegacyRuntime() {
25
- for (const key of ["config", "data", "cache", "logs"]) {
25
+ await migrateLegacyConfigDirectory();
26
+ for (const key of ["data", "cache", "logs"]) {
26
27
  await moveDirectoryIfNeeded(legacyRuntime.dirs[key], runtime.dirs[key]);
27
28
  }
28
29
  }
29
30
  async function moveDirectoryIfNeeded(from, to) {
30
- if (from === to || !(await isDirectory(from)) || await pathExists(to))
31
+ if (from === to || !(await isDirectory(from)))
31
32
  return;
32
33
  await mkdir(path.dirname(to), { recursive: true });
34
+ if (await pathExists(to)) {
35
+ await cp(from, to, { recursive: true, errorOnExist: false, force: false });
36
+ await rm(from, { recursive: true, force: true });
37
+ return;
38
+ }
33
39
  try {
34
40
  await rename(from, to);
35
41
  }
@@ -40,6 +46,39 @@ async function moveDirectoryIfNeeded(from, to) {
40
46
  await rm(from, { recursive: true, force: true });
41
47
  }
42
48
  }
49
+ async function migrateLegacyConfigDirectory() {
50
+ const from = legacyRuntime.dirs.config;
51
+ const to = runtime.dirs.config;
52
+ if (from === to || !(await isDirectory(from)))
53
+ return;
54
+ await mkdir(to, { recursive: true });
55
+ const legacyProfilesPath = path.join(from, "profiles.json");
56
+ const profilesPath = path.join(to, "profiles.json");
57
+ const legacyRaw = await readJSONRecord(legacyProfilesPath);
58
+ if (legacyRaw) {
59
+ const nextRaw = await readJSONRecord(profilesPath) ?? {};
60
+ const legacyProfiles = recordValue(legacyRaw.profiles);
61
+ const nextProfiles = recordValue(nextRaw.profiles);
62
+ const mergedProfiles = { ...legacyProfiles, ...nextProfiles };
63
+ const activeProfile = typeof nextRaw.activeProfile === "string"
64
+ ? nextRaw.activeProfile
65
+ : typeof legacyRaw.activeProfile === "string"
66
+ ? legacyRaw.activeProfile
67
+ : "default";
68
+ await writeJSON(profilesPath, { ...nextRaw, activeProfile, profiles: mergedProfiles });
69
+ const configurationPath = path.join(to, "configuration.json");
70
+ if ("workbench" in legacyRaw && !(await pathExists(configurationPath))) {
71
+ await writeJSON(configurationPath, { workbench: recordValue(legacyRaw.workbench) });
72
+ }
73
+ const conversationsPath = path.join(to, "conversations.json");
74
+ if ("conversations" in legacyRaw && !(await pathExists(conversationsPath))) {
75
+ await writeJSON(conversationsPath, { conversations: recordValue(legacyRaw.conversations) });
76
+ }
77
+ }
78
+ await copyFileIfMissing(path.join(from, "configuration.json"), path.join(to, "configuration.json"));
79
+ await copyFileIfMissing(path.join(from, "conversations.json"), path.join(to, "conversations.json"));
80
+ await rm(from, { recursive: true, force: true });
81
+ }
43
82
  async function splitMonolithicConfig() {
44
83
  const profilesPath = path.join(runtime.dirs.config, "profiles.json");
45
84
  const raw = await readJSONRecord(profilesPath);
@@ -66,6 +105,9 @@ async function splitMonolithicConfig() {
66
105
  await writeJSON(profilesPath, raw);
67
106
  }
68
107
  }
108
+ function recordValue(value) {
109
+ return value && typeof value === "object" && !Array.isArray(value) ? value : {};
110
+ }
69
111
  async function readJSONRecord(file) {
70
112
  try {
71
113
  const value = JSON.parse(await readFile(file, "utf8"));
@@ -81,6 +123,12 @@ async function writeJSON(file, value) {
81
123
  await mkdir(path.dirname(file), { recursive: true });
82
124
  await writeFile(file, `${JSON.stringify(value, null, 2)}\n`);
83
125
  }
126
+ async function copyFileIfMissing(from, to) {
127
+ if (!(await pathExists(from)) || await pathExists(to))
128
+ return;
129
+ await mkdir(path.dirname(to), { recursive: true });
130
+ await cp(from, to, { errorOnExist: true, force: false });
131
+ }
84
132
  async function pathExists(file) {
85
133
  try {
86
134
  await stat(file);
@@ -188,6 +188,10 @@ function WorkbenchApp({ authController, onLogin, onLogout, onDeleteProfile, onSw
188
188
  if (settings.activity) {
189
189
  dispatch({ type: "activity.add", level: "success", text: settings.activity });
190
190
  }
191
+ if (settings.notice) {
192
+ dispatch({ type: "message.add", role: "system", text: settings.notice });
193
+ dispatch({ type: "activity.add", level: "warning", text: "Shell isolation setup is not configured" });
194
+ }
191
195
  if (settings.warning) {
192
196
  dispatch({ type: "activity.add", level: "warning", text: settings.warning });
193
197
  }
@@ -8,6 +8,7 @@ export interface WorkbenchSettingsSnapshot {
8
8
  runPreset?: string;
9
9
  shellIsolation?: ShellIsolationPreferences;
10
10
  activity?: string;
11
+ notice?: string;
11
12
  warning?: string;
12
13
  }
13
14
  export interface WorkbenchSettingsController {
@@ -17,6 +17,7 @@ export function createWorkbenchSettingsController(options = {}) {
17
17
  defaultPreset: preferences.defaultPreset,
18
18
  ...(preferences.isolation ? { shellIsolation: preferences.isolation } : {}),
19
19
  ...(activity ? { activity } : {}),
20
+ ...(isolatorSetupNotice(preferences.isolation) ? { notice: isolatorSetupNotice(preferences.isolation) } : {}),
20
21
  ...(warning ? { warning } : {}),
21
22
  runPreset: shouldApplyDefaultPreset(agentOptions)
22
23
  ? effectiveDefaultPreset(preferences, agentOptions.preset)
@@ -25,7 +26,12 @@ export function createWorkbenchSettingsController(options = {}) {
25
26
  },
26
27
  async saveShellIsolationMode(value) {
27
28
  const mode = normalizeShellIsolationMode(value);
28
- const preferences = await updateWorkbenchPreferencesImpl({ isolation: { mode } });
29
+ const preferences = await updateWorkbenchPreferencesImpl({
30
+ isolation: {
31
+ mode,
32
+ installSkipped: mode === "none" ? true : false,
33
+ },
34
+ });
29
35
  return {
30
36
  ...settingsSnapshot(preferences),
31
37
  message: `Saved shell isolation mode: ${formatShellIsolation(preferences.isolation)}.`,
@@ -254,6 +260,21 @@ function userFacingError(error) {
254
260
  return error.message;
255
261
  return String(error);
256
262
  }
263
+ function isolatorSetupNotice(shellIsolation) {
264
+ if (process.env.AGENT_ISOLATOR_PATH)
265
+ return "";
266
+ if (shellIsolation?.installSkipped || shellIsolation?.mode === "none" || shellIsolation?.executablePath)
267
+ return "";
268
+ return [
269
+ "Local shell isolation is not configured yet.",
270
+ "",
271
+ "To enable it, set a verified target path and downloadable source URL:",
272
+ "/config isolator path <absolute-path>",
273
+ "/config isolator source <https-url>",
274
+ "",
275
+ "To skip this setup for future starts, use /config isolation none.",
276
+ ].join("\n");
277
+ }
257
278
  async function reconcileConfiguredIsolator(preferences, updatePreferences, installOptions, formatError) {
258
279
  const isolation = preferences.isolation;
259
280
  if (!isolation?.sourceURL || !isolation.executablePath)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agent-api/cli",
3
- "version": "0.2.0",
3
+ "version": "0.2.1",
4
4
  "description": "First-class command line interface for Agent API",
5
5
  "license": "MIT",
6
6
  "homepage": "https://github.com/scalebox-dev/agent-tui#readme",