zam-core 0.10.9 → 0.10.11

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.
package/dist/cli/app.js CHANGED
@@ -892,9 +892,26 @@ function loadLibsql() {
892
892
  );
893
893
  }
894
894
  }
895
+ function isTransientRemoteDatabaseError(err) {
896
+ const message = err instanceof Error ? err.message : "";
897
+ return TRANSIENT_REMOTE_ERROR_PATTERNS.some(
898
+ (pattern) => pattern.test(message)
899
+ );
900
+ }
895
901
  async function openDatabase(options = {}) {
896
902
  const { dbPath, provider, isRemote, isEmbeddedReplica, configuredCloud } = resolveDatabaseTarget(options);
897
903
  const shouldInitialize = options.initialize === true || !isRemote && !isEmbeddedReplica && !existsSync2(dbPath);
904
+ const openViaHttpProvider = async (url) => {
905
+ const db = openRemoteDatabase({
906
+ url,
907
+ authToken: configuredCloud?.token ?? options.authToken
908
+ });
909
+ if (options.initialize) {
910
+ await db.exec(SCHEMA);
911
+ }
912
+ await runMigrations(db);
913
+ return db;
914
+ };
898
915
  if (provider === "remote") {
899
916
  const url = isRemote ? dbPath : options.syncUrl;
900
917
  if (!url) {
@@ -902,15 +919,7 @@ async function openDatabase(options = {}) {
902
919
  "The remote database provider is selected but no Turso URL is configured. Run: zam connector setup turso"
903
920
  );
904
921
  }
905
- const db2 = openRemoteDatabase({
906
- url,
907
- authToken: configuredCloud?.token ?? options.authToken
908
- });
909
- if (options.initialize) {
910
- await db2.exec(SCHEMA);
911
- }
912
- await runMigrations(db2);
913
- return db2;
922
+ return openViaHttpProvider(url);
914
923
  }
915
924
  if (shouldInitialize && !isRemote) {
916
925
  const dir = dirname2(dbPath);
@@ -956,39 +965,43 @@ async function openDatabase(options = {}) {
956
965
  }
957
966
  }
958
967
  } catch (nativeErr) {
959
- const fallbackUrl = isRemote ? dbPath : options.syncUrl;
960
- if (isRemote && !isEmbeddedReplica && fallbackUrl) {
961
- const db2 = openRemoteDatabase({
962
- url: fallbackUrl,
963
- authToken: configuredCloud?.token ?? options.authToken
964
- });
965
- if (options.initialize) {
966
- await db2.exec(SCHEMA);
967
- }
968
- await runMigrations(db2);
969
- return db2;
968
+ if (isRemote && !isEmbeddedReplica) {
969
+ return openViaHttpProvider(dbPath);
970
970
  }
971
971
  throw nativeErr;
972
972
  }
973
973
  } else {
974
974
  driver = openLocalSqlite(dbPath);
975
975
  }
976
- if (!isRemote && !isEmbeddedReplica) {
977
- driver.pragma("journal_mode = WAL");
978
- }
979
- driver.pragma("foreign_keys = ON");
980
- if (!isRemote) {
981
- driver.pragma("busy_timeout = 5000");
982
- }
983
- const db = wrapSyncDatabase(driver);
984
- if (isEmbeddedReplica) {
985
- await db.sync?.();
986
- }
987
- if (shouldInitialize) {
988
- await db.exec(SCHEMA);
976
+ const finishOpen = async () => {
977
+ if (!isRemote && !isEmbeddedReplica) {
978
+ driver.pragma("journal_mode = WAL");
979
+ }
980
+ driver.pragma("foreign_keys = ON");
981
+ if (!isRemote) {
982
+ driver.pragma("busy_timeout = 5000");
983
+ }
984
+ const db = wrapSyncDatabase(driver);
985
+ if (isEmbeddedReplica) {
986
+ await db.sync?.();
987
+ }
988
+ if (shouldInitialize) {
989
+ await db.exec(SCHEMA);
990
+ }
991
+ await runMigrations(db);
992
+ return db;
993
+ };
994
+ if (isRemote && !isEmbeddedReplica) {
995
+ try {
996
+ return await finishOpen();
997
+ } catch (err) {
998
+ if (isTransientRemoteDatabaseError(err)) {
999
+ return openViaHttpProvider(dbPath);
1000
+ }
1001
+ throw err;
1002
+ }
989
1003
  }
990
- await runMigrations(db);
991
- return db;
1004
+ return finishOpen();
992
1005
  }
993
1006
  function resolveProvider(options, credentialsMode, isRemote) {
994
1007
  if (options.provider) return options.provider;
@@ -1120,7 +1133,7 @@ async function runMigrations(db) {
1120
1133
  );
1121
1134
  }
1122
1135
  }
1123
- var DEFAULT_DB_DIR, DEFAULT_DB_PATH, require2;
1136
+ var DEFAULT_DB_DIR, DEFAULT_DB_PATH, require2, TRANSIENT_REMOTE_ERROR_PATTERNS;
1124
1137
  var init_connection = __esm({
1125
1138
  "src/kernel/db/connection.ts"() {
1126
1139
  "use strict";
@@ -1131,6 +1144,14 @@ var init_connection = __esm({
1131
1144
  DEFAULT_DB_DIR = join2(homedir2(), ".zam");
1132
1145
  DEFAULT_DB_PATH = join2(DEFAULT_DB_DIR, "zam.db");
1133
1146
  require2 = createRequire(import.meta.url);
1147
+ TRANSIENT_REMOTE_ERROR_PATTERNS = [
1148
+ /status=5\d\d/i,
1149
+ /websocket/i,
1150
+ /stream closed/i,
1151
+ /connection (?:closed|reset|refused)/i,
1152
+ /fetch failed/i,
1153
+ /\b(?:ETIMEDOUT|ENOTFOUND|ECONNREFUSED|ECONNRESET|EAI_AGAIN|EPIPE)\b/
1154
+ ];
1134
1155
  }
1135
1156
  });
1136
1157
 
@@ -7855,6 +7876,12 @@ function resolveVscodeExecutable(options = {}) {
7855
7876
  ] : ["/usr/bin/code", "/usr/local/bin/code", "/snap/bin/code"];
7856
7877
  return candidates.find((candidate) => exists(candidate)) ?? null;
7857
7878
  }
7879
+ function buildVscodeCliInvocation(command, args, platform = process.platform) {
7880
+ const needsShell = platform === "win32" && /\.(cmd|bat)$/i.test(command);
7881
+ if (!needsShell) return { command, args, shell: false };
7882
+ const quote = (value) => `"${value}"`;
7883
+ return { command: quote(command), args: args.map(quote), shell: true };
7884
+ }
7858
7885
  function packageVersion() {
7859
7886
  const parsed = JSON.parse(
7860
7887
  readFileSync11(join14(packageRoot2, "package.json"), "utf8")
@@ -7910,7 +7937,11 @@ function installVscodeExtension(options) {
7910
7937
  const existed = existsSync14(plan.launchConfigPath);
7911
7938
  const changed = !existed || readFileSync11(plan.launchConfigPath, "utf8") !== launchContent;
7912
7939
  const run = options.run ?? ((command, args) => {
7913
- execFileSync3(command, args, { stdio: "pipe" });
7940
+ const invocation = buildVscodeCliInvocation(command, args);
7941
+ execFileSync3(invocation.command, invocation.args, {
7942
+ stdio: "pipe",
7943
+ shell: invocation.shell
7944
+ });
7914
7945
  });
7915
7946
  run(plan.codePath, ["--install-extension", plan.vsixPath, "--force"]);
7916
7947
  if (changed) {
@@ -7967,7 +7998,7 @@ function resolveDeps(deps) {
7967
7998
  findZam: deps.findZam ?? (() => {
7968
7999
  const globalZam = findExecutable("zam");
7969
8000
  if (globalZam) return globalZam;
7970
- if (process.argv[1] && process.argv[1].endsWith("index.js")) {
8001
+ if (process.argv[1]?.endsWith("index.js")) {
7971
8002
  return process.argv[1];
7972
8003
  }
7973
8004
  return null;
@@ -10060,7 +10091,7 @@ async function readWebLink(url) {
10060
10091
  redirect: "manual",
10061
10092
  signal: controller.signal,
10062
10093
  headers: {
10063
- "User-Agent": "ZAM-Content-Studio/0.10.9"
10094
+ "User-Agent": "ZAM-Content-Studio/0.10.11"
10064
10095
  }
10065
10096
  });
10066
10097
  if (res.status >= 300 && res.status < 400) {
@@ -10445,9 +10476,11 @@ function findWorkspaceByPath(dir) {
10445
10476
  );
10446
10477
  }
10447
10478
  async function clearLegacyWorkspaceDir(db) {
10479
+ if (!db) return;
10448
10480
  await deleteSetting(db, LEGACY_WORKSPACE_DIR_KEY);
10449
10481
  }
10450
10482
  async function migrateLegacyWorkspaceDir(db) {
10483
+ if (!db) return void 0;
10451
10484
  const legacyDir = await getSetting(db, LEGACY_WORKSPACE_DIR_KEY);
10452
10485
  if (!legacyDir) return void 0;
10453
10486
  const path = resolve4(legacyDir);
@@ -29134,6 +29167,21 @@ async function withDb(fn, onError = defaultErrorHandler) {
29134
29167
  await db?.close();
29135
29168
  }
29136
29169
  }
29170
+ async function withOptionalDb(fn, onError = defaultErrorHandler) {
29171
+ let db = null;
29172
+ try {
29173
+ db = await openDatabase();
29174
+ } catch {
29175
+ db = null;
29176
+ }
29177
+ try {
29178
+ await fn(db);
29179
+ } catch (err) {
29180
+ onError(err.message);
29181
+ } finally {
29182
+ await db?.close();
29183
+ }
29184
+ }
29137
29185
  function jsonOut(data) {
29138
29186
  console.log(JSON.stringify(data, null, 2));
29139
29187
  }
@@ -29343,6 +29391,9 @@ function parseProviderScope(scope) {
29343
29391
  async function withDb2(fn) {
29344
29392
  await withDb(fn, jsonError);
29345
29393
  }
29394
+ async function withOptionalDb2(fn) {
29395
+ await withOptionalDb(fn, jsonError);
29396
+ }
29346
29397
  var bridgeCommand = new Command2("bridge").description(
29347
29398
  "Machine-readable JSON protocol for AI integration"
29348
29399
  );
@@ -29411,7 +29462,7 @@ bridgeCommand.command("update-check").description("Check whether a newer ZAM rel
29411
29462
  }
29412
29463
  });
29413
29464
  bridgeCommand.command("workspace-info").description("Report the workspace dir, its default, and the data dir (JSON)").action(async () => {
29414
- await withDb2(async (db) => {
29465
+ await withOptionalDb2(async (db) => {
29415
29466
  const activeWorkspace = await ensureActiveWorkspace(db);
29416
29467
  jsonOut2({
29417
29468
  activeWorkspaceId: activeWorkspace.id,
@@ -29452,7 +29503,7 @@ async function ensureDesktopWorkspace(db) {
29452
29503
  };
29453
29504
  }
29454
29505
  bridgeCommand.command("workspace-list").description("List configured ZAM workspaces (JSON)").action(async () => {
29455
- await withDb2(async (db) => {
29506
+ await withOptionalDb2(async (db) => {
29456
29507
  const activeWorkspace = await ensureActiveWorkspace(db);
29457
29508
  const workspaces = getConfiguredWorkspaces();
29458
29509
  jsonOut2({
@@ -29513,7 +29564,7 @@ bridgeCommand.command("workspace-add").description("Register an existing directo
29513
29564
  if (opts.id && !id) jsonError("A non-empty --id is required");
29514
29565
  const kind = parseBridgeWorkspaceKind(opts.kind);
29515
29566
  const skillLinks = wireSkills(path, parseSetupAgents(), { quiet: true });
29516
- await withDb2(async (db) => {
29567
+ await withOptionalDb2(async (db) => {
29517
29568
  const workspace = await activateWorkspacePath(db, path, {
29518
29569
  ...id ? { id } : {},
29519
29570
  ...opts.label ? { label: opts.label } : {},
@@ -29535,7 +29586,7 @@ bridgeCommand.command("workspace-remove").description("Unregister a ZAM workspac
29535
29586
  if (!id) jsonError("A non-empty --id is required");
29536
29587
  const workspace = getConfiguredWorkspaces().find((item) => item.id === id);
29537
29588
  if (!workspace) jsonError(`Workspace "${id}" is not configured`);
29538
- await withDb2(async (db) => {
29589
+ await withOptionalDb2(async (db) => {
29539
29590
  const { activeWorkspace, workspaces } = await removeWorkspaceAndResolveActive(db, id);
29540
29591
  const skillLinks = provisionConfiguredWorkspaces();
29541
29592
  jsonOut2({
@@ -29555,7 +29606,7 @@ bridgeCommand.command("set-workspace-dir").description("Set the personal workspa
29555
29606
  const dir = resolve6(raw);
29556
29607
  if (!existsSync21(dir)) jsonError(`Workspace path does not exist: ${dir}`);
29557
29608
  const skillLinks = wireSkills(dir, parseSetupAgents(), { quiet: true });
29558
- await withDb2(async (db) => {
29609
+ await withOptionalDb2(async (db) => {
29559
29610
  const workspace = await activateWorkspacePath(db, dir);
29560
29611
  jsonOut2({
29561
29612
  ok: true,
@@ -31155,6 +31206,7 @@ bridgeCommand.command("local-llm-hints").description("Detect installed local LLM
31155
31206
  var UI_WRITABLE_SETTINGS = /* @__PURE__ */ new Set([
31156
31207
  "llm.enabled",
31157
31208
  "llm.vision.enabled",
31209
+ "recall.quick_mode",
31158
31210
  "system.locale"
31159
31211
  ]);
31160
31212
  bridgeCommand.command("setting-set").description("Set a single allowlisted ZAM setting value (JSON)").requiredOption("--key <key>", "Setting key").requiredOption("--value <value>", "Setting value").action(async (opts) => {
@@ -31374,6 +31426,9 @@ bridgeCommand.command("get-settings").description("Get active ZAM settings (JSON
31374
31426
  enabled,
31375
31427
  url,
31376
31428
  model
31429
+ },
31430
+ recall: {
31431
+ quickMode: await getSetting(db, "recall.quick_mode") === "true"
31377
31432
  }
31378
31433
  });
31379
31434
  });
@@ -32856,8 +32911,17 @@ bridgeCommand.command("unassign-knowledge-context").description("Remove a token
32856
32911
  });
32857
32912
  });
32858
32913
  bridgeCommand.command("get-active-knowledge-context").description("Get the active knowledge context name (JSON)").action(async () => {
32859
- await withDb2(async (db) => {
32914
+ await withOptionalDb2(async (db) => {
32860
32915
  const configured = getActiveWorkspaceContext();
32916
+ if (!db) {
32917
+ jsonOut2({
32918
+ success: true,
32919
+ activeContext: configured ?? null,
32920
+ staleContext: null,
32921
+ validated: false
32922
+ });
32923
+ return;
32924
+ }
32861
32925
  const active = configured ? await getKnowledgeContextByName(db, configured) : void 0;
32862
32926
  jsonOut2({
32863
32927
  success: true,
@@ -32867,7 +32931,7 @@ bridgeCommand.command("get-active-knowledge-context").description("Get the activ
32867
32931
  });
32868
32932
  });
32869
32933
  bridgeCommand.command("set-active-knowledge-context").description("Set the active knowledge context name (JSON)").argument("[name]", "Context name to use (use empty/none to clear)").action(async (name) => {
32870
- await withDb2(async (db) => {
32934
+ await withOptionalDb2(async (db) => {
32871
32935
  if (!name || name === "none" || name === "null" || name === "undefined") {
32872
32936
  if (!setActiveWorkspaceContext(void 0)) {
32873
32937
  jsonError("No active workspace configured");
@@ -32875,6 +32939,13 @@ bridgeCommand.command("set-active-knowledge-context").description("Set the activ
32875
32939
  jsonOut2({ success: true, activeContext: null });
32876
32940
  return;
32877
32941
  }
32942
+ if (!db) {
32943
+ if (!setActiveWorkspaceContext(name)) {
32944
+ jsonError("No active workspace configured");
32945
+ }
32946
+ jsonOut2({ success: true, activeContext: name, validated: false });
32947
+ return;
32948
+ }
32878
32949
  const context = await getKnowledgeContextByName(db, name);
32879
32950
  if (!context) {
32880
32951
  jsonError(`Knowledge context not found: ${name}`);
@@ -36704,7 +36775,11 @@ import { Command as Command17 } from "commander";
36704
36775
  var settingsCommand = new Command17("settings").description(
36705
36776
  "Manage user settings"
36706
36777
  );
36707
- var BOOLEAN_SETTING_KEYS = /* @__PURE__ */ new Set(["llm.enabled", "llm.vision.enabled"]);
36778
+ var BOOLEAN_SETTING_KEYS = /* @__PURE__ */ new Set([
36779
+ "llm.enabled",
36780
+ "llm.vision.enabled",
36781
+ "recall.quick_mode"
36782
+ ]);
36708
36783
  function normalizeSettingValue(key, value) {
36709
36784
  if (!BOOLEAN_SETTING_KEYS.has(key)) return value;
36710
36785
  const lower = value.toLowerCase();