bitfab-cli 0.2.166 → 0.2.168

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 (3) hide show
  1. package/README.md +3 -0
  2. package/dist/index.js +384 -318
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -9,4 +9,7 @@ npx bitfab-cli init # Detect editors, prompt if multiple
9
9
  npx bitfab-cli init --editor claude # Install for Claude Code
10
10
  npx bitfab-cli init --editor codex # Install for Codex
11
11
  npx bitfab-cli init --editor cursor # Install for Cursor
12
+ npx bitfab-cli session-logs enable # Enable session log collection
13
+ npx bitfab-cli session-logs disable # Disable session log collection
14
+ npx bitfab-cli session-logs status # Show the saved session log setting
12
15
  ```
package/dist/index.js CHANGED
@@ -1090,20 +1090,20 @@ var require_range = __commonJS({
1090
1090
  };
1091
1091
  var replaceTilde = (comp, options) => {
1092
1092
  const r = options.loose ? re[t.TILDELOOSE] : re[t.TILDE];
1093
- return comp.replace(r, (_, M, m, p5, pr) => {
1094
- debug("tilde", comp, _, M, m, p5, pr);
1093
+ return comp.replace(r, (_, M, m, p7, pr) => {
1094
+ debug("tilde", comp, _, M, m, p7, pr);
1095
1095
  let ret;
1096
1096
  if (isX(M)) {
1097
1097
  ret = "";
1098
1098
  } else if (isX(m)) {
1099
1099
  ret = `>=${M}.0.0 <${+M + 1}.0.0-0`;
1100
- } else if (isX(p5)) {
1100
+ } else if (isX(p7)) {
1101
1101
  ret = `>=${M}.${m}.0 <${M}.${+m + 1}.0-0`;
1102
1102
  } else if (pr) {
1103
1103
  debug("replaceTilde pr", pr);
1104
- ret = `>=${M}.${m}.${p5}-${pr} <${M}.${+m + 1}.0-0`;
1104
+ ret = `>=${M}.${m}.${p7}-${pr} <${M}.${+m + 1}.0-0`;
1105
1105
  } else {
1106
- ret = `>=${M}.${m}.${p5} <${M}.${+m + 1}.0-0`;
1106
+ ret = `>=${M}.${m}.${p7} <${M}.${+m + 1}.0-0`;
1107
1107
  }
1108
1108
  debug("tilde return", ret);
1109
1109
  return ret;
@@ -1116,14 +1116,14 @@ var require_range = __commonJS({
1116
1116
  debug("caret", comp, options);
1117
1117
  const r = options.loose ? re[t.CARETLOOSE] : re[t.CARET];
1118
1118
  const z2 = options.includePrerelease ? "-0" : "";
1119
- return comp.replace(r, (_, M, m, p5, pr) => {
1120
- debug("caret", comp, _, M, m, p5, pr);
1119
+ return comp.replace(r, (_, M, m, p7, pr) => {
1120
+ debug("caret", comp, _, M, m, p7, pr);
1121
1121
  let ret;
1122
1122
  if (isX(M)) {
1123
1123
  ret = "";
1124
1124
  } else if (isX(m)) {
1125
1125
  ret = `>=${M}.0.0${z2} <${+M + 1}.0.0-0`;
1126
- } else if (isX(p5)) {
1126
+ } else if (isX(p7)) {
1127
1127
  if (M === "0") {
1128
1128
  ret = `>=${M}.${m}.0${z2} <${M}.${+m + 1}.0-0`;
1129
1129
  } else {
@@ -1133,23 +1133,23 @@ var require_range = __commonJS({
1133
1133
  debug("replaceCaret pr", pr);
1134
1134
  if (M === "0") {
1135
1135
  if (m === "0") {
1136
- ret = `>=${M}.${m}.${p5}-${pr} <${M}.${m}.${+p5 + 1}-0`;
1136
+ ret = `>=${M}.${m}.${p7}-${pr} <${M}.${m}.${+p7 + 1}-0`;
1137
1137
  } else {
1138
- ret = `>=${M}.${m}.${p5}-${pr} <${M}.${+m + 1}.0-0`;
1138
+ ret = `>=${M}.${m}.${p7}-${pr} <${M}.${+m + 1}.0-0`;
1139
1139
  }
1140
1140
  } else {
1141
- ret = `>=${M}.${m}.${p5}-${pr} <${+M + 1}.0.0-0`;
1141
+ ret = `>=${M}.${m}.${p7}-${pr} <${+M + 1}.0.0-0`;
1142
1142
  }
1143
1143
  } else {
1144
1144
  debug("no pr");
1145
1145
  if (M === "0") {
1146
1146
  if (m === "0") {
1147
- ret = `>=${M}.${m}.${p5}${z2} <${M}.${m}.${+p5 + 1}-0`;
1147
+ ret = `>=${M}.${m}.${p7}${z2} <${M}.${m}.${+p7 + 1}-0`;
1148
1148
  } else {
1149
- ret = `>=${M}.${m}.${p5}${z2} <${M}.${+m + 1}.0-0`;
1149
+ ret = `>=${M}.${m}.${p7}${z2} <${M}.${+m + 1}.0-0`;
1150
1150
  }
1151
1151
  } else {
1152
- ret = `>=${M}.${m}.${p5} <${+M + 1}.0.0-0`;
1152
+ ret = `>=${M}.${m}.${p7} <${+M + 1}.0.0-0`;
1153
1153
  }
1154
1154
  }
1155
1155
  debug("caret return", ret);
@@ -1163,11 +1163,11 @@ var require_range = __commonJS({
1163
1163
  var replaceXRange = (comp, options) => {
1164
1164
  comp = comp.trim();
1165
1165
  const r = options.loose ? re[t.XRANGELOOSE] : re[t.XRANGE];
1166
- return comp.replace(r, (ret, gtlt, M, m, p5, pr) => {
1167
- debug("xRange", comp, ret, gtlt, M, m, p5, pr);
1166
+ return comp.replace(r, (ret, gtlt, M, m, p7, pr) => {
1167
+ debug("xRange", comp, ret, gtlt, M, m, p7, pr);
1168
1168
  const xM = isX(M);
1169
1169
  const xm = xM || isX(m);
1170
- const xp = xm || isX(p5);
1170
+ const xp = xm || isX(p7);
1171
1171
  const anyX = xp;
1172
1172
  if (gtlt === "=" && anyX) {
1173
1173
  gtlt = "";
@@ -1183,16 +1183,16 @@ var require_range = __commonJS({
1183
1183
  if (xm) {
1184
1184
  m = 0;
1185
1185
  }
1186
- p5 = 0;
1186
+ p7 = 0;
1187
1187
  if (gtlt === ">") {
1188
1188
  gtlt = ">=";
1189
1189
  if (xm) {
1190
1190
  M = +M + 1;
1191
1191
  m = 0;
1192
- p5 = 0;
1192
+ p7 = 0;
1193
1193
  } else {
1194
1194
  m = +m + 1;
1195
- p5 = 0;
1195
+ p7 = 0;
1196
1196
  }
1197
1197
  } else if (gtlt === "<=") {
1198
1198
  gtlt = "<";
@@ -1205,7 +1205,7 @@ var require_range = __commonJS({
1205
1205
  if (gtlt === "<") {
1206
1206
  pr = "-0";
1207
1207
  }
1208
- ret = `${gtlt + M}.${m}.${p5}${pr}`;
1208
+ ret = `${gtlt + M}.${m}.${p7}${pr}`;
1209
1209
  } else if (xm) {
1210
1210
  ret = `>=${M}.0.0${pr} <${+M + 1}.0.0-0`;
1211
1211
  } else if (xp) {
@@ -3109,7 +3109,7 @@ var require_util = __commonJS({
3109
3109
  }
3110
3110
  exports.evaluatedPropsToName = evaluatedPropsToName;
3111
3111
  function setEvaluated(gen, props, ps) {
3112
- Object.keys(ps).forEach((p5) => gen.assign((0, codegen_1._)`${props}${(0, codegen_1.getProperty)(p5)}`, true));
3112
+ Object.keys(ps).forEach((p7) => gen.assign((0, codegen_1._)`${props}${(0, codegen_1.getProperty)(p7)}`, true));
3113
3113
  }
3114
3114
  exports.setEvaluated = setEvaluated;
3115
3115
  var snippets = {};
@@ -3682,11 +3682,11 @@ var require_code2 = __commonJS({
3682
3682
  }
3683
3683
  exports.noPropertyInData = noPropertyInData;
3684
3684
  function allSchemaProperties(schemaMap) {
3685
- return schemaMap ? Object.keys(schemaMap).filter((p5) => p5 !== "__proto__") : [];
3685
+ return schemaMap ? Object.keys(schemaMap).filter((p7) => p7 !== "__proto__") : [];
3686
3686
  }
3687
3687
  exports.allSchemaProperties = allSchemaProperties;
3688
3688
  function schemaProperties(it, schemaMap) {
3689
- return allSchemaProperties(schemaMap).filter((p5) => !(0, util_1.alwaysValidSchema)(it, schemaMap[p5]));
3689
+ return allSchemaProperties(schemaMap).filter((p7) => !(0, util_1.alwaysValidSchema)(it, schemaMap[p7]));
3690
3690
  }
3691
3691
  exports.schemaProperties = schemaProperties;
3692
3692
  function callValidateCode({ schemaCode, data, it: { gen, topSchemaRef, schemaPath, errorPath }, it }, func, context, passSchema) {
@@ -4164,12 +4164,12 @@ var require_resolve = __commonJS({
4164
4164
  function getFullPath(resolver, id = "", normalize) {
4165
4165
  if (normalize !== false)
4166
4166
  id = normalizeId(id);
4167
- const p5 = resolver.parse(id);
4168
- return _getFullPath(resolver, p5);
4167
+ const p7 = resolver.parse(id);
4168
+ return _getFullPath(resolver, p7);
4169
4169
  }
4170
4170
  exports.getFullPath = getFullPath;
4171
- function _getFullPath(resolver, p5) {
4172
- const serialized = resolver.serialize(p5);
4171
+ function _getFullPath(resolver, p7) {
4172
+ const serialized = resolver.serialize(p7);
4173
4173
  return serialized.split("#")[0] + "#";
4174
4174
  }
4175
4175
  exports._getFullPath = _getFullPath;
@@ -4944,11 +4944,11 @@ var require_compile = __commonJS({
4944
4944
  return sch || this.schemas[ref] || resolveSchema.call(this, root, ref);
4945
4945
  }
4946
4946
  function resolveSchema(root, ref) {
4947
- const p5 = this.opts.uriResolver.parse(ref);
4948
- const refPath = (0, resolve_1._getFullPath)(this.opts.uriResolver, p5);
4947
+ const p7 = this.opts.uriResolver.parse(ref);
4948
+ const refPath = (0, resolve_1._getFullPath)(this.opts.uriResolver, p7);
4949
4949
  let baseId = (0, resolve_1.getFullPath)(this.opts.uriResolver, root.baseId, void 0);
4950
4950
  if (Object.keys(root.schema).length > 0 && refPath === baseId) {
4951
- return getJsonPointer.call(this, p5, root);
4951
+ return getJsonPointer.call(this, p7, root);
4952
4952
  }
4953
4953
  const id = (0, resolve_1.normalizeId)(refPath);
4954
4954
  const schOrRef = this.refs[id] || this.schemas[id];
@@ -4956,7 +4956,7 @@ var require_compile = __commonJS({
4956
4956
  const sch = resolveSchema.call(this, root, schOrRef);
4957
4957
  if (typeof (sch === null || sch === void 0 ? void 0 : sch.schema) !== "object")
4958
4958
  return;
4959
- return getJsonPointer.call(this, p5, sch);
4959
+ return getJsonPointer.call(this, p7, sch);
4960
4960
  }
4961
4961
  if (typeof (schOrRef === null || schOrRef === void 0 ? void 0 : schOrRef.schema) !== "object")
4962
4962
  return;
@@ -4970,7 +4970,7 @@ var require_compile = __commonJS({
4970
4970
  baseId = (0, resolve_1.resolveUrl)(this.opts.uriResolver, baseId, schId);
4971
4971
  return new SchemaEnv({ schema, schemaId, root, baseId });
4972
4972
  }
4973
- return getJsonPointer.call(this, p5, schOrRef);
4973
+ return getJsonPointer.call(this, p7, schOrRef);
4974
4974
  }
4975
4975
  exports.resolveSchema = resolveSchema;
4976
4976
  var PREVENT_SCOPE_CHANGE = /* @__PURE__ */ new Set([
@@ -6062,9 +6062,9 @@ var require_core = __commonJS({
6062
6062
  this.addSchema(_schema, ref, meta3);
6063
6063
  }
6064
6064
  async function _loadSchema(ref) {
6065
- const p5 = this._loading[ref];
6066
- if (p5)
6067
- return p5;
6065
+ const p7 = this._loading[ref];
6066
+ if (p7)
6067
+ return p7;
6068
6068
  try {
6069
6069
  return await (this._loading[ref] = loadSchema(ref));
6070
6070
  } finally {
@@ -6330,11 +6330,11 @@ var require_core = __commonJS({
6330
6330
  Ajv.ValidationError = validation_error_1.default;
6331
6331
  Ajv.MissingRefError = ref_error_1.default;
6332
6332
  exports.default = Ajv;
6333
- function checkOptions(checkOpts, options, msg, log5 = "error") {
6333
+ function checkOptions(checkOpts, options, msg, log7 = "error") {
6334
6334
  for (const key in checkOpts) {
6335
6335
  const opt = key;
6336
6336
  if (opt in options)
6337
- this.logger[log5](`${msg}: option ${key}. ${checkOpts[opt]}`);
6337
+ this.logger[log7](`${msg}: option ${key}. ${checkOpts[opt]}`);
6338
6338
  }
6339
6339
  }
6340
6340
  function getSchEnv(keyRef) {
@@ -7546,12 +7546,12 @@ var require_additionalProperties = __commonJS({
7546
7546
  const propsSchema = (0, util_1.schemaRefOrVal)(it, parentSchema.properties, "properties");
7547
7547
  definedProp = (0, code_1.isOwnProperty)(gen, propsSchema, key);
7548
7548
  } else if (props.length) {
7549
- definedProp = (0, codegen_1.or)(...props.map((p5) => (0, codegen_1._)`${key} === ${p5}`));
7549
+ definedProp = (0, codegen_1.or)(...props.map((p7) => (0, codegen_1._)`${key} === ${p7}`));
7550
7550
  } else {
7551
7551
  definedProp = codegen_1.nil;
7552
7552
  }
7553
7553
  if (patProps.length) {
7554
- definedProp = (0, codegen_1.or)(definedProp, ...patProps.map((p5) => (0, codegen_1._)`${(0, code_1.usePattern)(cxt, p5)}.test(${key})`));
7554
+ definedProp = (0, codegen_1.or)(definedProp, ...patProps.map((p7) => (0, codegen_1._)`${(0, code_1.usePattern)(cxt, p7)}.test(${key})`));
7555
7555
  }
7556
7556
  return (0, codegen_1.not)(definedProp);
7557
7557
  }
@@ -7631,7 +7631,7 @@ var require_properties = __commonJS({
7631
7631
  if (it.opts.unevaluated && allProps.length && it.props !== true) {
7632
7632
  it.props = util_1.mergeEvaluated.props(gen, (0, util_1.toHash)(allProps), it.props);
7633
7633
  }
7634
- const properties = allProps.filter((p5) => !(0, util_1.alwaysValidSchema)(it, schema[p5]));
7634
+ const properties = allProps.filter((p7) => !(0, util_1.alwaysValidSchema)(it, schema[p7]));
7635
7635
  if (properties.length === 0)
7636
7636
  return;
7637
7637
  const valid = gen.name("valid");
@@ -7681,7 +7681,7 @@ var require_patternProperties = __commonJS({
7681
7681
  const { gen, schema, data, parentSchema, it } = cxt;
7682
7682
  const { opts } = it;
7683
7683
  const patterns = (0, code_1.allSchemaProperties)(schema);
7684
- const alwaysValidPatterns = patterns.filter((p5) => (0, util_1.alwaysValidSchema)(it, schema[p5]));
7684
+ const alwaysValidPatterns = patterns.filter((p7) => (0, util_1.alwaysValidSchema)(it, schema[p7]));
7685
7685
  if (patterns.length === 0 || alwaysValidPatterns.length === patterns.length && (!it.opts.unevaluated || it.props === true)) {
7686
7686
  return;
7687
7687
  }
@@ -8820,7 +8820,7 @@ import { cancel as cancel2 } from "@clack/prompts";
8820
8820
 
8821
8821
  // src/init.ts
8822
8822
  import { execSync as execSync3 } from "child_process";
8823
- import * as p4 from "@clack/prompts";
8823
+ import * as p6 from "@clack/prompts";
8824
8824
 
8825
8825
  // ../bitfab-plugin-lib/dist/errors.js
8826
8826
  var NotAuthenticatedError = class extends Error {
@@ -9274,8 +9274,8 @@ function getServiceUrl() {
9274
9274
  if (project && typeof project.serviceUrl === "string") {
9275
9275
  return project.serviceUrl;
9276
9276
  }
9277
- const config2 = getConfigData();
9278
- return typeof config2.serviceUrl === "string" ? config2.serviceUrl : DEFAULT_SERVICE_URL;
9277
+ const config4 = getConfigData();
9278
+ return typeof config4.serviceUrl === "string" ? config4.serviceUrl : DEFAULT_SERVICE_URL;
9279
9279
  }
9280
9280
  function getApiKey() {
9281
9281
  if (process.env.BITFAB_API_KEY) {
@@ -9295,22 +9295,22 @@ function getVerbose() {
9295
9295
  if (process.env.BITFAB_VERBOSE === "false" || process.env.BITFAB_VERBOSE === "0") {
9296
9296
  return false;
9297
9297
  }
9298
- const config2 = getConfigData();
9299
- return config2.verbose === true;
9298
+ const config4 = getConfigData();
9299
+ return config4.verbose === true;
9300
9300
  }
9301
9301
  function getDebug() {
9302
9302
  if (process.env.BITFAB_DEBUG === "true" || process.env.BITFAB_DEBUG === "1") {
9303
9303
  return true;
9304
9304
  }
9305
- const config2 = getConfigData();
9306
- return config2.debug === true;
9305
+ const config4 = getConfigData();
9306
+ return config4.debug === true;
9307
9307
  }
9308
9308
  function getSessionLogConsentValue() {
9309
- const config2 = getConfigData();
9310
- if (config2.sessionLogConsent === true) {
9309
+ const config4 = getConfigData();
9310
+ if (config4.sessionLogConsent === true) {
9311
9311
  return true;
9312
9312
  }
9313
- if (config2.sessionLogConsent === false) {
9313
+ if (config4.sessionLogConsent === false) {
9314
9314
  return false;
9315
9315
  }
9316
9316
  return null;
@@ -9355,14 +9355,14 @@ function hasCredentials() {
9355
9355
  return getApiKey() !== null;
9356
9356
  }
9357
9357
  function getOrCreateInstallId() {
9358
- const config2 = getConfigData();
9359
- if (typeof config2.installId === "string" && config2.installId.length > 0) {
9360
- return config2.installId;
9358
+ const config4 = getConfigData();
9359
+ if (typeof config4.installId === "string" && config4.installId.length > 0) {
9360
+ return config4.installId;
9361
9361
  }
9362
9362
  const installId = crypto2.randomUUID();
9363
9363
  try {
9364
9364
  fs3.mkdirSync(GLOBAL_CONFIG_DIR, { recursive: true });
9365
- fs3.writeFileSync(GLOBAL_CONFIG_FILE, `${JSON.stringify({ ...config2, installId }, null, 2)}
9365
+ fs3.writeFileSync(GLOBAL_CONFIG_FILE, `${JSON.stringify({ ...config4, installId }, null, 2)}
9366
9366
  `);
9367
9367
  } catch {
9368
9368
  }
@@ -10191,9 +10191,9 @@ function processIsAlive(pid) {
10191
10191
  }
10192
10192
  }
10193
10193
  function unlinkQuietly(...paths) {
10194
- for (const p5 of paths) {
10194
+ for (const p7 of paths) {
10195
10195
  try {
10196
- fs9.unlinkSync(p5);
10196
+ fs9.unlinkSync(p7);
10197
10197
  } catch {
10198
10198
  }
10199
10199
  }
@@ -10988,19 +10988,19 @@ import path11 from "path";
10988
10988
 
10989
10989
  // ../bitfab-plugin-lib/dist/analytics.js
10990
10990
  async function reportHandoff(apiKey, pluginVersion, platform2, body) {
10991
- const config2 = getConfig();
10991
+ const config4 = getConfig();
10992
10992
  const headers = buildBitfabRequestHeaders(apiKey, pluginVersion, platform2);
10993
10993
  try {
10994
- const response = await fetch(`${config2.serviceUrl}/api/plugin/analytics/handoff`, {
10994
+ const response = await fetch(`${config4.serviceUrl}/api/plugin/analytics/handoff`, {
10995
10995
  method: "POST",
10996
10996
  headers,
10997
10997
  body: JSON.stringify(body)
10998
10998
  });
10999
- if (config2.debug && !response.ok) {
10999
+ if (config4.debug && !response.ok) {
11000
11000
  console.error(`reportHandoff: server returned ${response.status} for ${body.flow}`);
11001
11001
  }
11002
11002
  } catch (err) {
11003
- if (config2.debug) {
11003
+ if (config4.debug) {
11004
11004
  const message = err instanceof Error ? err.message : String(err);
11005
11005
  console.error(`reportHandoff: request failed for ${body.flow}: ${message}`);
11006
11006
  }
@@ -11254,9 +11254,9 @@ function createEventSubscription(channel, sessionId, onEvent, restoreFocus) {
11254
11254
  };
11255
11255
  }
11256
11256
  async function openStudioTo(path20, opts = {}) {
11257
- const config2 = getConfig();
11258
- const serviceUrl = config2.serviceUrl;
11259
- const apiKey = !opts.forceLogin && hasCredentials() ? config2.apiKey : null;
11257
+ const config4 = getConfig();
11258
+ const serviceUrl = config4.serviceUrl;
11259
+ const apiKey = !opts.forceLogin && hasCredentials() ? config4.apiKey : null;
11260
11260
  const key = resolveAgentSessionKey();
11261
11261
  const focusTarget = captureFocusTarget();
11262
11262
  const restoreFocus = () => applyFocusTarget(focusTarget);
@@ -11404,9 +11404,9 @@ async function verifyToken(serviceUrl, token) {
11404
11404
  async function runLogin(platform2, pluginVersion, options) {
11405
11405
  const exitOnComplete = options?.exitOnComplete ?? true;
11406
11406
  const force = options?.force ?? process.argv.includes("--force");
11407
- const config2 = getConfig();
11408
- if (!force && hasCredentials() && config2.apiKey) {
11409
- const who = await verifyToken(config2.serviceUrl, config2.apiKey);
11407
+ const config4 = getConfig();
11408
+ if (!force && hasCredentials() && config4.apiKey) {
11409
+ const who = await verifyToken(config4.serviceUrl, config4.apiKey);
11410
11410
  if (who) {
11411
11411
  const identity = who.user.email ?? "your account";
11412
11412
  console.log(`
@@ -11441,7 +11441,7 @@ Already logged in as ${identity}. Run the login command with --force to re-authe
11441
11441
  loopbackAvailable: false,
11442
11442
  ticketAvailable: false
11443
11443
  });
11444
- const who = await verifyToken(config2.serviceUrl, apiKey);
11444
+ const who = await verifyToken(config4.serviceUrl, apiKey);
11445
11445
  const greeting = who?.user.email ? `Logged in as ${who.user.email}.` : "Authentication successful.";
11446
11446
  console.log(`
11447
11447
  ${greeting}`);
@@ -12649,10 +12649,10 @@ function prefixIssues(path20, issues) {
12649
12649
  function unwrapMessage(message) {
12650
12650
  return typeof message === "string" ? message : message?.message;
12651
12651
  }
12652
- function finalizeIssue(iss, ctx, config2) {
12652
+ function finalizeIssue(iss, ctx, config4) {
12653
12653
  const full = { ...iss, path: iss.path ?? [] };
12654
12654
  if (!iss.message) {
12655
- const message = unwrapMessage(iss.inst?._zod.def?.error?.(iss)) ?? unwrapMessage(ctx?.error?.(iss)) ?? unwrapMessage(config2.customError?.(iss)) ?? unwrapMessage(config2.localeError?.(iss)) ?? "Invalid input";
12655
+ const message = unwrapMessage(iss.inst?._zod.def?.error?.(iss)) ?? unwrapMessage(ctx?.error?.(iss)) ?? unwrapMessage(config4.customError?.(iss)) ?? unwrapMessage(config4.localeError?.(iss)) ?? "Invalid input";
12656
12656
  full.message = message;
12657
12657
  }
12658
12658
  delete full.inst;
@@ -14632,7 +14632,7 @@ var $ZodUnion = /* @__PURE__ */ $constructor("$ZodUnion", (inst, def) => {
14632
14632
  defineLazy(inst._zod, "pattern", () => {
14633
14633
  if (def.options.every((o) => o._zod.pattern)) {
14634
14634
  const patterns = def.options.map((o) => o._zod.pattern);
14635
- return new RegExp(`^(${patterns.map((p5) => cleanRegex(p5.source)).join("|")})$`);
14635
+ return new RegExp(`^(${patterns.map((p7) => cleanRegex(p7.source)).join("|")})$`);
14636
14636
  }
14637
14637
  return void 0;
14638
14638
  });
@@ -21309,9 +21309,9 @@ var $ZodRegistry = class {
21309
21309
  return this;
21310
21310
  }
21311
21311
  get(schema) {
21312
- const p5 = schema._zod.parent;
21313
- if (p5) {
21314
- const pm = { ...this.get(p5) ?? {} };
21312
+ const p7 = schema._zod.parent;
21313
+ if (p7) {
21314
+ const pm = { ...this.get(p7) ?? {} };
21315
21315
  delete pm.id;
21316
21316
  const f = { ...pm, ...this._map.get(schema) };
21317
21317
  return Object.keys(f).length ? f : void 0;
@@ -30749,11 +30749,104 @@ var tracePlanTreeShape = external_exports.object({
30749
30749
  });
30750
30750
 
30751
30751
  // src/claude.ts
30752
- import { spawn as spawn5, spawnSync } from "child_process";
30752
+ import { spawn as spawn5 } from "child_process";
30753
30753
  import fs20 from "fs";
30754
30754
  import os15 from "os";
30755
30755
  import path17 from "path";
30756
+ import * as p3 from "@clack/prompts";
30757
+
30758
+ // src/cliEditor.ts
30759
+ import * as p2 from "@clack/prompts";
30760
+
30761
+ // src/editorCli.ts
30762
+ import { spawnSync } from "child_process";
30763
+ var SHELL_OPTS = process.platform === "win32" ? { shell: true } : {};
30764
+ function skipFlags(skip, flag) {
30765
+ return skip ? [flag] : [];
30766
+ }
30767
+ function runCli(bin, args) {
30768
+ const result = spawnSync(bin, [...args], { stdio: "pipe", ...SHELL_OPTS });
30769
+ if (result.status !== 0) {
30770
+ throw new Error(
30771
+ `${bin} ${args.join(" ")} failed${result.status === null ? "" : ` with status ${result.status}`}`
30772
+ );
30773
+ }
30774
+ return (result.stdout?.toString() ?? "") + (result.stderr?.toString() ?? "");
30775
+ }
30776
+ function launchCli(bin, args) {
30777
+ spawnSync(bin, [...args], { stdio: "inherit", ...SHELL_OPTS });
30778
+ }
30779
+
30780
+ // src/pluginRefresh.ts
30756
30781
  import * as p from "@clack/prompts";
30782
+ function pluginOutputIsUpToDate(output) {
30783
+ return output.includes("already") || output.includes("up to date");
30784
+ }
30785
+ function ensureLatestPlugin(pull) {
30786
+ const s = p.spinner();
30787
+ s.start("Checking for the latest bitfab plugin");
30788
+ try {
30789
+ const out = pull();
30790
+ s.stop(
30791
+ pluginOutputIsUpToDate(out) ? "Plugin already up to date" : "Plugin updated to latest"
30792
+ );
30793
+ } catch (err) {
30794
+ s.stop("Could not check for plugin updates");
30795
+ p.log.warn(
30796
+ `Continuing with the installed plugin version. ${err instanceof Error ? err.message : String(err)}`
30797
+ );
30798
+ }
30799
+ }
30800
+
30801
+ // src/cliEditor.ts
30802
+ function cliSetup(cfg, skipPermissions) {
30803
+ p2.log.info(`Launching ${cfg.setupCommand}...
30804
+ `);
30805
+ launchCli(cfg.cli, [
30806
+ ...skipFlags(skipPermissions, cfg.skipFlag),
30807
+ cfg.setupCommand
30808
+ ]);
30809
+ }
30810
+ function cliAssistant(cfg, args, skipPermissions) {
30811
+ const cmd = [cfg.assistantCommand, ...args].join(" ");
30812
+ p2.log.info(`Launching ${cmd}...
30813
+ `);
30814
+ launchCli(cfg.cli, [
30815
+ ...skipFlags(skipPermissions, cfg.skipFlag),
30816
+ cfg.assistantCommand,
30817
+ ...args
30818
+ ]);
30819
+ }
30820
+ function cliUpdate(cfg, args, skipPermissions) {
30821
+ const mode = args[0] === "plugin" || args[0] === "sdk" ? args[0] : "all";
30822
+ if (mode === "plugin" || mode === "all") {
30823
+ const s = p2.spinner();
30824
+ s.start("Updating bitfab plugin");
30825
+ let out;
30826
+ try {
30827
+ out = cfg.pullLatest();
30828
+ } catch (err) {
30829
+ s.stop("Plugin update failed");
30830
+ throw err;
30831
+ }
30832
+ s.stop(
30833
+ pluginOutputIsUpToDate(out) ? "Plugin already up to date" : "Plugin updated"
30834
+ );
30835
+ }
30836
+ if (mode === "sdk" || mode === "all") {
30837
+ p2.log.info(`Launching ${cfg.updateCommand} sdk...
30838
+ `);
30839
+ launchCli(cfg.cli, [
30840
+ ...skipFlags(skipPermissions, cfg.skipFlag),
30841
+ cfg.updateCommand,
30842
+ "sdk"
30843
+ ]);
30844
+ }
30845
+ }
30846
+
30847
+ // src/claude.ts
30848
+ var CLI = "claude";
30849
+ var SKIP_FLAG = "--dangerously-skip-permissions";
30757
30850
  var REPO = "Project-White-Rabbit/bitfab-claude-plugin";
30758
30851
  var MARKETPLACE = "bitfab";
30759
30852
  var PLUGIN_KEY = "bitfab@bitfab";
@@ -30761,11 +30854,10 @@ var SETUP_COMMAND = "/bitfab:setup";
30761
30854
  var ANALYZE_REPO_COMMAND = "/bitfab:setup analyze-repo";
30762
30855
  var ASSISTANT_COMMAND = "/bitfab:assistant";
30763
30856
  var UPDATE_COMMAND = "/bitfab:update";
30764
- var SHELL_OPTS = process.platform === "win32" ? { shell: true } : {};
30765
30857
  function runClaudeInstall() {
30766
- const s = p.spinner();
30858
+ const s = p3.spinner();
30767
30859
  s.start("Adding bitfab marketplace");
30768
- const marketplaceOut = runClaude(["plugin", "marketplace", "add", REPO]);
30860
+ const marketplaceOut = runCli(CLI, ["plugin", "marketplace", "add", REPO]);
30769
30861
  if (marketplaceOut.includes("already")) {
30770
30862
  s.stop("Marketplace already configured");
30771
30863
  } else {
@@ -30780,33 +30872,26 @@ function runClaudeInstall() {
30780
30872
  } else {
30781
30873
  s.stop("Auto-updates already enabled");
30782
30874
  }
30783
- s.start("Installing bitfab plugin");
30784
- const installOut = runClaude([
30785
- "plugin",
30786
- "install",
30787
- PLUGIN_KEY,
30788
- "--scope",
30789
- "user"
30790
- ]);
30791
- if (installOut.includes("already")) {
30792
- s.stop("Plugin already installed");
30793
- if (isPluginDisabled()) {
30794
- runClaude(["plugin", "enable", PLUGIN_KEY]);
30795
- p.log.step("Plugin enabled");
30796
- }
30797
- } else {
30875
+ const state = pluginState();
30876
+ if (state === "missing") {
30877
+ s.start("Installing bitfab plugin");
30878
+ runCli(CLI, ["plugin", "install", PLUGIN_KEY, "--scope", "user"]);
30798
30879
  s.stop("Plugin installed");
30880
+ } else {
30881
+ if (state === "disabled") {
30882
+ runCli(CLI, ["plugin", "enable", PLUGIN_KEY]);
30883
+ p3.log.step("Plugin enabled");
30884
+ }
30885
+ ensureLatestClaudePlugin();
30799
30886
  }
30800
- p.log.success("Bitfab plugin ready in Claude Code");
30887
+ p3.log.success("Bitfab plugin ready in Claude Code");
30801
30888
  }
30802
- function runClaudeSetup(skipPermissions) {
30803
- p.log.info(`Launching ${SETUP_COMMAND}...
30804
- `);
30805
- const flags = skipPermissions ? ["--dangerously-skip-permissions"] : [];
30806
- spawnSync("claude", [...flags, SETUP_COMMAND], {
30807
- stdio: "inherit",
30808
- ...SHELL_OPTS
30809
- });
30889
+ function pullLatestClaudePlugin() {
30890
+ runCli(CLI, ["plugin", "marketplace", "update", MARKETPLACE]);
30891
+ return runCli(CLI, ["plugin", "update", PLUGIN_KEY, "--scope", "user"]);
30892
+ }
30893
+ function ensureLatestClaudePlugin() {
30894
+ ensureLatestPlugin(pullLatestClaudePlugin);
30810
30895
  }
30811
30896
  async function runClaudeAnalyzeRepo(captureOverride, limit) {
30812
30897
  const logPath = analyzeRepoLogPath();
@@ -30816,20 +30901,20 @@ async function runClaudeAnalyzeRepo(captureOverride, limit) {
30816
30901
  }
30817
30902
  const command = limit === void 0 ? ANALYZE_REPO_COMMAND : `${ANALYZE_REPO_COMMAND} limit=${limit}`;
30818
30903
  const out = fs20.createWriteStream(logPath);
30819
- const spinner3 = p.spinner();
30820
- spinner3.start("Analyzing repo and drafting trace plans");
30904
+ const spinner5 = p3.spinner();
30905
+ spinner5.start("Analyzing repo and drafting trace plans");
30821
30906
  const stdoutChunks = [];
30822
30907
  try {
30823
30908
  const exitCode = await new Promise((resolve2, reject) => {
30824
30909
  const child = spawn5(
30825
- "claude",
30910
+ CLI,
30826
30911
  [
30827
30912
  "-p",
30828
30913
  command,
30829
30914
  "--output-format",
30830
30915
  "stream-json",
30831
30916
  "--verbose",
30832
- "--dangerously-skip-permissions"
30917
+ SKIP_FLAG
30833
30918
  ],
30834
30919
  { stdio: ["ignore", "pipe", "pipe"], env, ...SHELL_OPTS }
30835
30920
  );
@@ -30839,7 +30924,7 @@ async function runClaudeAnalyzeRepo(captureOverride, limit) {
30839
30924
  stdoutChunks.push(text);
30840
30925
  const label = latestActivityLabel(text);
30841
30926
  if (label) {
30842
- spinner3.message(label);
30927
+ spinner5.message(label);
30843
30928
  }
30844
30929
  });
30845
30930
  child.stderr.on("data", (chunk2) => out.write(chunk2));
@@ -30852,16 +30937,16 @@ async function runClaudeAnalyzeRepo(captureOverride, limit) {
30852
30937
  );
30853
30938
  }
30854
30939
  const uploaded = countUploadedTracePlans(stdoutChunks.join(""));
30855
- spinner3.stop(
30940
+ spinner5.stop(
30856
30941
  uploaded === 0 ? "No AI workflows found - nothing to upload" : `Uploaded ${uploaded} draft trace plan${uploaded === 1 ? "" : "s"} to Bitfab`
30857
30942
  );
30858
30943
  } catch (err) {
30859
- spinner3.stop("analyze-repo failed");
30944
+ spinner5.stop("analyze-repo failed");
30860
30945
  throw err;
30861
30946
  } finally {
30862
30947
  out.end();
30863
30948
  }
30864
- p.log.info(`Full run log: ${logPath}`);
30949
+ p3.log.info(`Full run log: ${logPath}`);
30865
30950
  }
30866
30951
  function latestActivityLabel(chunk2) {
30867
30952
  const lines = chunk2.split("\n").filter((l) => l.trim() !== "");
@@ -30973,59 +31058,13 @@ function analyzeRepoLogPath() {
30973
31058
  const stamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
30974
31059
  return path17.join(dir, `analyze-repo-${stamp}.jsonl`);
30975
31060
  }
30976
- function runClaudeAssistant(args, skipPermissions) {
30977
- const cmd = [ASSISTANT_COMMAND, ...args].join(" ");
30978
- p.log.info(`Launching ${cmd}...
30979
- `);
30980
- const flags = skipPermissions ? ["--dangerously-skip-permissions"] : [];
30981
- spawnSync("claude", [...flags, ASSISTANT_COMMAND, ...args], {
30982
- stdio: "inherit",
30983
- ...SHELL_OPTS
30984
- });
30985
- }
30986
- function runClaudeUpdate(args, skipPermissions) {
30987
- const mode = args[0] === "plugin" || args[0] === "sdk" ? args[0] : "all";
30988
- if (mode === "plugin" || mode === "all") {
30989
- const s = p.spinner();
30990
- s.start("Refreshing bitfab marketplace");
30991
- runClaude(["plugin", "marketplace", "update", MARKETPLACE]);
30992
- s.stop("Marketplace refreshed");
30993
- s.start("Updating bitfab plugin");
30994
- const out = runClaude(["plugin", "update", PLUGIN_KEY, "--scope", "user"]);
30995
- if (out.includes("already") || out.includes("up to date")) {
30996
- s.stop("Plugin already up to date");
30997
- } else {
30998
- s.stop("Plugin updated");
30999
- }
31000
- }
31001
- if (mode === "sdk" || mode === "all") {
31002
- p.log.info(`Launching ${UPDATE_COMMAND} sdk...
31003
- `);
31004
- const flags = skipPermissions ? ["--dangerously-skip-permissions"] : [];
31005
- spawnSync("claude", [...flags, UPDATE_COMMAND, "sdk"], {
31006
- stdio: "inherit",
31007
- ...SHELL_OPTS
31008
- });
31009
- }
31010
- }
31011
- function isPluginDisabled() {
31012
- const listOut = runClaude(["plugin", "list"]);
31013
- const pattern = new RegExp(
31014
- `${PLUGIN_KEY.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}\\n.*\\n.*\\n.*disabled`
31015
- );
31016
- return pattern.test(listOut);
31017
- }
31018
- function runClaude(args) {
31019
- const result = spawnSync("claude", [...args], {
31020
- stdio: "pipe",
31021
- ...SHELL_OPTS
31022
- });
31023
- if (result.status !== 0) {
31024
- throw new Error(
31025
- `claude ${args.join(" ")} failed${result.status === null ? "" : ` with status ${result.status}`}`
31026
- );
31061
+ function pluginState() {
31062
+ const listOut = runCli(CLI, ["plugin", "list"]);
31063
+ const key = PLUGIN_KEY.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
31064
+ if (!new RegExp(key).test(listOut)) {
31065
+ return "missing";
31027
31066
  }
31028
- return (result.stdout?.toString() ?? "") + (result.stderr?.toString() ?? "");
31067
+ return new RegExp(`${key}\\n.*\\n.*\\n.*disabled`).test(listOut) ? "disabled" : "enabled";
31029
31068
  }
31030
31069
  function enableAutoUpdate(settingsPath) {
31031
31070
  let settings = {};
@@ -31049,33 +31088,49 @@ function enableAutoUpdate(settingsPath) {
31049
31088
  `);
31050
31089
  return true;
31051
31090
  }
31091
+ var config2 = {
31092
+ cli: CLI,
31093
+ skipFlag: SKIP_FLAG,
31094
+ setupCommand: SETUP_COMMAND,
31095
+ assistantCommand: ASSISTANT_COMMAND,
31096
+ updateCommand: UPDATE_COMMAND,
31097
+ pullLatest: pullLatestClaudePlugin
31098
+ };
31099
+ var claudeAdapter = {
31100
+ label: "Claude Code",
31101
+ install: runClaudeInstall,
31102
+ ensureLatest: ensureLatestClaudePlugin,
31103
+ setup: (skipPermissions) => cliSetup(config2, skipPermissions),
31104
+ analyzeRepo: runClaudeAnalyzeRepo,
31105
+ assistant: (args, skipPermissions) => cliAssistant(config2, args, skipPermissions),
31106
+ update: (args, skipPermissions) => cliUpdate(config2, args, skipPermissions)
31107
+ };
31052
31108
 
31053
31109
  // src/codex.ts
31054
- import { spawnSync as spawnSync2 } from "child_process";
31055
31110
  import fs21 from "fs";
31056
31111
  import os16 from "os";
31057
31112
  import path18 from "path";
31058
- import * as p2 from "@clack/prompts";
31113
+ import * as p4 from "@clack/prompts";
31114
+ var CLI2 = "codex";
31115
+ var SKIP_FLAG2 = "--full-auto";
31059
31116
  var REPO2 = "Project-White-Rabbit/bitfab-codex-plugin";
31117
+ var MARKETPLACE2 = "bitfab";
31060
31118
  var PLUGIN_KEY2 = "bitfab@bitfab";
31061
31119
  var SETUP_COMMAND2 = "$bitfab:setup";
31062
31120
  var ASSISTANT_COMMAND2 = "$bitfab:assistant";
31063
31121
  var UPDATE_COMMAND2 = "$bitfab:update";
31064
- var SHELL_OPTS2 = process.platform === "win32" ? { shell: true } : {};
31122
+ function pullLatestCodexPlugin() {
31123
+ return runCli(CLI2, ["plugin", "marketplace", "upgrade", MARKETPLACE2]);
31124
+ }
31125
+ function ensureLatestCodexPlugin() {
31126
+ ensureLatestPlugin(pullLatestCodexPlugin);
31127
+ }
31065
31128
  function runCodexInstall() {
31066
- const s = p2.spinner();
31129
+ const s = p4.spinner();
31067
31130
  s.start("Adding bitfab marketplace");
31068
- const result = spawnSync2("codex", ["plugin", "marketplace", "add", REPO2], {
31069
- stdio: "pipe",
31070
- ...SHELL_OPTS2
31071
- });
31072
- if (result.status !== 0) {
31073
- throw new Error(
31074
- `codex plugin marketplace add failed${result.status === null ? "" : ` with status ${result.status}`}`
31075
- );
31076
- }
31077
- const out = (result.stdout?.toString() ?? "") + (result.stderr?.toString() ?? "");
31078
- if (out.includes("already")) {
31131
+ const out = runCli(CLI2, ["plugin", "marketplace", "add", REPO2]);
31132
+ const alreadyConfigured = out.includes("already");
31133
+ if (alreadyConfigured) {
31079
31134
  s.stop("Marketplace already configured");
31080
31135
  } else {
31081
31136
  s.stop("Marketplace added");
@@ -31089,68 +31144,19 @@ function runCodexInstall() {
31089
31144
  } else {
31090
31145
  s.stop("Plugin already enabled");
31091
31146
  }
31092
- p2.log.success("Bitfab plugin ready in Codex");
31093
- }
31094
- function runCodexSetup(skipPermissions) {
31095
- p2.log.info(`Launching ${SETUP_COMMAND2}...
31096
- `);
31097
- const flags = skipPermissions ? ["--full-auto"] : [];
31098
- spawnSync2("codex", [...flags, SETUP_COMMAND2], {
31099
- stdio: "inherit",
31100
- ...SHELL_OPTS2
31101
- });
31147
+ if (alreadyConfigured) {
31148
+ ensureLatestCodexPlugin();
31149
+ }
31150
+ p4.log.success("Bitfab plugin ready in Codex");
31102
31151
  }
31103
31152
  function runCodexAnalyzeRepo() {
31104
- p2.log.warn(
31153
+ p4.log.warn(
31105
31154
  "Headless analyze-repo is currently supported for Claude Code only."
31106
31155
  );
31107
- p2.log.info(
31156
+ p4.log.info(
31108
31157
  `To run it in Codex, launch ${SETUP_COMMAND2} analyze-repo interactively.`
31109
31158
  );
31110
31159
  }
31111
- function runCodexAssistant(args, skipPermissions) {
31112
- const cmd = [ASSISTANT_COMMAND2, ...args].join(" ");
31113
- p2.log.info(`Launching ${cmd}...
31114
- `);
31115
- const flags = skipPermissions ? ["--full-auto"] : [];
31116
- spawnSync2("codex", [...flags, ASSISTANT_COMMAND2, ...args], {
31117
- stdio: "inherit",
31118
- ...SHELL_OPTS2
31119
- });
31120
- }
31121
- function runCodexUpdate(args, skipPermissions) {
31122
- const mode = args[0] === "plugin" || args[0] === "sdk" ? args[0] : "all";
31123
- if (mode === "plugin" || mode === "all") {
31124
- const s = p2.spinner();
31125
- s.start("Upgrading bitfab marketplace plugin");
31126
- const result = spawnSync2(
31127
- "codex",
31128
- ["plugin", "marketplace", "upgrade", "bitfab"],
31129
- { stdio: "pipe", ...SHELL_OPTS2 }
31130
- );
31131
- if (result.status !== 0) {
31132
- s.stop("Marketplace upgrade failed");
31133
- throw new Error(
31134
- `codex plugin marketplace upgrade failed${result.status === null ? "" : ` with status ${result.status}`}`
31135
- );
31136
- }
31137
- const out = (result.stdout?.toString() ?? "") + (result.stderr?.toString() ?? "");
31138
- if (out.includes("already") || out.includes("up to date")) {
31139
- s.stop("Plugin already up to date");
31140
- } else {
31141
- s.stop("Plugin updated");
31142
- }
31143
- }
31144
- if (mode === "sdk" || mode === "all") {
31145
- p2.log.info(`Launching ${UPDATE_COMMAND2} sdk...
31146
- `);
31147
- const flags = skipPermissions ? ["--full-auto"] : [];
31148
- spawnSync2("codex", [...flags, UPDATE_COMMAND2, "sdk"], {
31149
- stdio: "inherit",
31150
- ...SHELL_OPTS2
31151
- });
31152
- }
31153
- }
31154
31160
  function enableCodexPlugin(configPath) {
31155
31161
  let content = "";
31156
31162
  if (fs21.existsSync(configPath)) {
@@ -31184,64 +31190,82 @@ ${desiredSection}`;
31184
31190
  function escapeRegex2(s) {
31185
31191
  return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
31186
31192
  }
31193
+ var config3 = {
31194
+ cli: CLI2,
31195
+ skipFlag: SKIP_FLAG2,
31196
+ setupCommand: SETUP_COMMAND2,
31197
+ assistantCommand: ASSISTANT_COMMAND2,
31198
+ updateCommand: UPDATE_COMMAND2,
31199
+ pullLatest: pullLatestCodexPlugin
31200
+ };
31201
+ var codexAdapter = {
31202
+ label: "Codex",
31203
+ install: runCodexInstall,
31204
+ ensureLatest: ensureLatestCodexPlugin,
31205
+ setup: (skipPermissions) => cliSetup(config3, skipPermissions),
31206
+ analyzeRepo: runCodexAnalyzeRepo,
31207
+ assistant: (args, skipPermissions) => cliAssistant(config3, args, skipPermissions),
31208
+ update: (args, skipPermissions) => cliUpdate(config3, args, skipPermissions)
31209
+ };
31187
31210
 
31188
31211
  // src/cursor.ts
31189
- import { spawn as spawn6, spawnSync as spawnSync3 } from "child_process";
31212
+ import { spawn as spawn6, spawnSync as spawnSync2 } from "child_process";
31190
31213
  import os17 from "os";
31191
- import * as p3 from "@clack/prompts";
31214
+ import * as p5 from "@clack/prompts";
31192
31215
  var REPO3 = "Project-White-Rabbit/bitfab-cursor-plugin";
31193
31216
  var ADD_PLUGIN_CMD = `/add-plugin ${REPO3}`;
31194
31217
  var SETUP_COMMAND3 = "/bitfab-setup";
31195
31218
  var ASSISTANT_COMMAND3 = "/bitfab-assistant";
31196
31219
  var UPDATE_COMMAND3 = "/bitfab-update";
31197
- var SHELL_OPTS3 = process.platform === "win32" ? { shell: true } : {};
31198
31220
  function runCursorInstall() {
31199
31221
  const copied = copyToClipboard(ADD_PLUGIN_CMD);
31200
31222
  if (copied) {
31201
- p3.log.success(`Copied to clipboard: ${ADD_PLUGIN_CMD}`);
31223
+ p5.log.success(`Copied to clipboard: ${ADD_PLUGIN_CMD}`);
31202
31224
  } else {
31203
- p3.log.warn(`Copy this command: ${ADD_PLUGIN_CMD}`);
31225
+ p5.log.warn(`Copy this command: ${ADD_PLUGIN_CMD}`);
31204
31226
  }
31205
- p3.note(
31227
+ p5.note(
31206
31228
  [
31207
31229
  `1. Run ${ADD_PLUGIN_CMD} (already in your clipboard)`,
31208
31230
  `2. Then run ${SETUP_COMMAND3}`
31209
31231
  ].join("\n"),
31210
31232
  "Finish setup in Cursor"
31211
31233
  );
31212
- p3.log.info("Opening Cursor...");
31234
+ p5.log.info("Opening Cursor...");
31213
31235
  const child = spawn6("cursor", ["."], {
31214
31236
  stdio: "ignore",
31215
31237
  detached: true,
31216
31238
  windowsHide: true,
31217
- ...SHELL_OPTS3
31239
+ ...SHELL_OPTS
31218
31240
  });
31219
31241
  child.on("error", () => {
31220
31242
  });
31221
31243
  child.unref();
31222
31244
  }
31245
+ function ensureLatestCursorPlugin() {
31246
+ }
31223
31247
  function runCursorSetup(skipPermissions) {
31224
31248
  if (skipPermissions) {
31225
- p3.log.warn("--skip-permissions is not supported for Cursor");
31249
+ p5.log.warn("--skip-permissions is not supported for Cursor");
31226
31250
  }
31227
- p3.log.info(`To complete setup, run ${SETUP_COMMAND3} in Cursor.`);
31251
+ p5.log.info(`To complete setup, run ${SETUP_COMMAND3} in Cursor.`);
31228
31252
  }
31229
31253
  function runCursorAnalyzeRepo() {
31230
- p3.log.warn(
31254
+ p5.log.warn(
31231
31255
  "Headless analyze-repo is currently supported for Claude Code only."
31232
31256
  );
31233
- p3.log.info(`To run it in Cursor, run ${SETUP_COMMAND3} analyze-repo manually.`);
31257
+ p5.log.info(`To run it in Cursor, run ${SETUP_COMMAND3} analyze-repo manually.`);
31234
31258
  }
31235
31259
  function runCursorAssistant(args, skipPermissions) {
31236
31260
  if (skipPermissions) {
31237
- p3.log.warn("--skip-permissions is not supported for Cursor");
31261
+ p5.log.warn("--skip-permissions is not supported for Cursor");
31238
31262
  }
31239
31263
  const cmd = [ASSISTANT_COMMAND3, ...args].join(" ");
31240
- p3.log.info(`To start the assistant, run ${cmd} in Cursor.`);
31264
+ p5.log.info(`To start the assistant, run ${cmd} in Cursor.`);
31241
31265
  }
31242
31266
  function runCursorUpdate(args, skipPermissions) {
31243
31267
  if (skipPermissions) {
31244
- p3.log.warn("--skip-permissions is not supported for Cursor");
31268
+ p5.log.warn("--skip-permissions is not supported for Cursor");
31245
31269
  }
31246
31270
  const mode = args[0] === "plugin" || args[0] === "sdk" ? args[0] : "all";
31247
31271
  const lines = [];
@@ -31251,14 +31275,14 @@ function runCursorUpdate(args, skipPermissions) {
31251
31275
  if (mode === "sdk" || mode === "all") {
31252
31276
  lines.push(`Run ${UPDATE_COMMAND3} sdk (updates installed SDKs)`);
31253
31277
  }
31254
- p3.note(lines.join("\n"), "Update Bitfab in Cursor");
31278
+ p5.note(lines.join("\n"), "Update Bitfab in Cursor");
31255
31279
  }
31256
31280
  function copyToClipboard(text) {
31257
31281
  const cmd = clipboardCommand();
31258
31282
  if (!cmd) {
31259
31283
  return false;
31260
31284
  }
31261
- const result = spawnSync3(cmd.bin, cmd.args, {
31285
+ const result = spawnSync2(cmd.bin, cmd.args, {
31262
31286
  input: text,
31263
31287
  stdio: ["pipe", "ignore", "ignore"]
31264
31288
  });
@@ -31276,6 +31300,15 @@ function clipboardCommand() {
31276
31300
  }
31277
31301
  return null;
31278
31302
  }
31303
+ var cursorAdapter = {
31304
+ label: "Cursor",
31305
+ install: runCursorInstall,
31306
+ ensureLatest: ensureLatestCursorPlugin,
31307
+ setup: runCursorSetup,
31308
+ analyzeRepo: runCursorAnalyzeRepo,
31309
+ assistant: runCursorAssistant,
31310
+ update: runCursorUpdate
31311
+ };
31279
31312
 
31280
31313
  // src/platform.ts
31281
31314
  var platform = {
@@ -31315,35 +31348,10 @@ async function runLoginCommand(options) {
31315
31348
 
31316
31349
  // src/init.ts
31317
31350
  var EDITORS = ["claude", "codex", "cursor"];
31318
- var EDITOR_LABEL = {
31319
- claude: "Claude Code",
31320
- codex: "Codex",
31321
- cursor: "Cursor"
31322
- };
31323
- var INSTALL_FN = {
31324
- claude: runClaudeInstall,
31325
- codex: runCodexInstall,
31326
- cursor: runCursorInstall
31327
- };
31328
- var SETUP_FN = {
31329
- claude: runClaudeSetup,
31330
- codex: runCodexSetup,
31331
- cursor: runCursorSetup
31332
- };
31333
- var ANALYZE_REPO_FN = {
31334
- claude: runClaudeAnalyzeRepo,
31335
- codex: runCodexAnalyzeRepo,
31336
- cursor: runCursorAnalyzeRepo
31337
- };
31338
- var ASSISTANT_FN = {
31339
- claude: runClaudeAssistant,
31340
- codex: runCodexAssistant,
31341
- cursor: runCursorAssistant
31342
- };
31343
- var UPDATE_FN = {
31344
- claude: runClaudeUpdate,
31345
- codex: runCodexUpdate,
31346
- cursor: runCursorUpdate
31351
+ var ADAPTERS = {
31352
+ claude: claudeAdapter,
31353
+ codex: codexAdapter,
31354
+ cursor: cursorAdapter
31347
31355
  };
31348
31356
  function detectInstalledEditors() {
31349
31357
  return EDITORS.filter((e) => isOnPath(e));
@@ -31359,18 +31367,18 @@ function isOnPath(binary) {
31359
31367
  }
31360
31368
  async function pickEditor(detected) {
31361
31369
  if (detected.length === 1) {
31362
- p4.log.info(`Detected ${EDITOR_LABEL[detected[0]]}`);
31370
+ p6.log.info(`Detected ${ADAPTERS[detected[0]].label}`);
31363
31371
  return detected[0];
31364
31372
  }
31365
- const choice = await p4.select({
31373
+ const choice = await p6.select({
31366
31374
  message: "Which editor should we set up?",
31367
31375
  options: detected.map((e) => ({
31368
31376
  value: e,
31369
- label: EDITOR_LABEL[e]
31377
+ label: ADAPTERS[e].label
31370
31378
  }))
31371
31379
  });
31372
- if (p4.isCancel(choice)) {
31373
- p4.cancel("Setup cancelled.");
31380
+ if (p6.isCancel(choice)) {
31381
+ p6.cancel("Setup cancelled.");
31374
31382
  process.exit(0);
31375
31383
  }
31376
31384
  return choice;
@@ -31379,12 +31387,12 @@ async function resolveSkipPermissions(value) {
31379
31387
  if (value !== void 0) {
31380
31388
  return value;
31381
31389
  }
31382
- const answer = await p4.confirm({
31390
+ const answer = await p6.confirm({
31383
31391
  message: "Skip permission prompts? (runs the agent autonomously)",
31384
31392
  initialValue: false
31385
31393
  });
31386
- if (p4.isCancel(answer)) {
31387
- p4.cancel("Cancelled.");
31394
+ if (p6.isCancel(answer)) {
31395
+ p6.cancel("Cancelled.");
31388
31396
  process.exit(0);
31389
31397
  }
31390
31398
  return answer;
@@ -31395,7 +31403,7 @@ async function resolveCaptureOverride(flag) {
31395
31403
  }
31396
31404
  const existing = getSessionLogConsent();
31397
31405
  if (existing !== null) {
31398
- p4.log.step(
31406
+ p6.log.step(
31399
31407
  existing ? "Session logs: enabled (saved preference)." : "Session logs: disabled (saved preference)."
31400
31408
  );
31401
31409
  return void 0;
@@ -31403,12 +31411,12 @@ async function resolveCaptureOverride(flag) {
31403
31411
  if (!process.stdin.isTTY) {
31404
31412
  return false;
31405
31413
  }
31406
- const answer = await p4.confirm({
31414
+ const answer = await p6.confirm({
31407
31415
  message: "Allow Bitfab to collect session logs? (used to diagnose issues and improve the product)",
31408
31416
  initialValue: true
31409
31417
  });
31410
- if (p4.isCancel(answer)) {
31411
- p4.cancel("Cancelled.");
31418
+ if (p6.isCancel(answer)) {
31419
+ p6.cancel("Cancelled.");
31412
31420
  process.exit(0);
31413
31421
  }
31414
31422
  setSessionLogConsent(answer);
@@ -31417,21 +31425,21 @@ async function resolveCaptureOverride(flag) {
31417
31425
  async function resolveEditor({ editor }) {
31418
31426
  const detected = detectInstalledEditors();
31419
31427
  if (detected.length === 0) {
31420
- p4.cancel(
31428
+ p6.cancel(
31421
31429
  "No supported editor found on PATH. Install Claude Code, Codex, or Cursor and try again."
31422
31430
  );
31423
31431
  process.exit(1);
31424
31432
  }
31425
31433
  if (editor) {
31426
31434
  if (!EDITORS.includes(editor)) {
31427
- p4.cancel(
31435
+ p6.cancel(
31428
31436
  `Unknown editor: ${editor}. Expected one of: ${EDITORS.join(", ")}`
31429
31437
  );
31430
31438
  process.exit(1);
31431
31439
  }
31432
31440
  if (!detected.includes(editor)) {
31433
- p4.cancel(
31434
- `${EDITOR_LABEL[editor]} is not installed ("${editor}" not found on PATH).`
31441
+ p6.cancel(
31442
+ `${ADAPTERS[editor].label} is not installed ("${editor}" not found on PATH).`
31435
31443
  );
31436
31444
  process.exit(1);
31437
31445
  }
@@ -31440,71 +31448,73 @@ async function resolveEditor({ editor }) {
31440
31448
  return pickEditor(detected);
31441
31449
  }
31442
31450
  async function runInstall(opts) {
31443
- p4.intro("bitfab");
31451
+ p6.intro("bitfab");
31444
31452
  const chosen = await resolveEditor(opts);
31445
- p4.log.step(`Installing Bitfab in ${EDITOR_LABEL[chosen]}`);
31446
- INSTALL_FN[chosen]();
31447
- p4.outro("Done!");
31453
+ p6.log.step(`Installing Bitfab in ${ADAPTERS[chosen].label}`);
31454
+ ADAPTERS[chosen].install();
31455
+ p6.outro("Done!");
31448
31456
  }
31449
31457
  async function runSetup(opts) {
31450
31458
  const chosen = await resolveEditor(opts);
31459
+ ADAPTERS[chosen].ensureLatest();
31451
31460
  const skip = await resolveSkipPermissions(opts.skipPermissions);
31452
- SETUP_FN[chosen](skip);
31461
+ ADAPTERS[chosen].setup(skip);
31453
31462
  }
31454
31463
  async function runAssistant(opts, args) {
31455
31464
  const chosen = await resolveEditor(opts);
31465
+ ADAPTERS[chosen].ensureLatest();
31456
31466
  const skip = await resolveSkipPermissions(opts.skipPermissions);
31457
- ASSISTANT_FN[chosen](args, skip);
31467
+ ADAPTERS[chosen].assistant(args, skip);
31458
31468
  }
31459
31469
  async function runUpdate2(opts, args) {
31460
31470
  const chosen = await resolveEditor(opts);
31461
31471
  const skip = await resolveSkipPermissions(opts.skipPermissions);
31462
- UPDATE_FN[chosen](args, skip);
31472
+ ADAPTERS[chosen].update(args, skip);
31463
31473
  }
31464
31474
  async function runInit(opts) {
31465
- p4.intro("bitfab");
31475
+ p6.intro("bitfab");
31466
31476
  const chosen = await resolveEditor(opts);
31467
- p4.log.step(`Setting up Bitfab in ${EDITOR_LABEL[chosen]}`);
31468
- INSTALL_FN[chosen]();
31477
+ p6.log.step(`Setting up Bitfab in ${ADAPTERS[chosen].label}`);
31478
+ ADAPTERS[chosen].install();
31469
31479
  const loggedInEmail = await checkAuth();
31470
31480
  if (loggedInEmail) {
31471
- p4.log.success(`Already logged in as ${loggedInEmail}`);
31481
+ p6.log.success(`Already logged in as ${loggedInEmail}`);
31472
31482
  } else {
31473
- p4.log.step("Signing in to Bitfab");
31483
+ p6.log.step("Signing in to Bitfab");
31474
31484
  await runLoginCommand({ exitOnComplete: false });
31475
31485
  }
31476
31486
  const skip = await resolveSkipPermissions(opts.skipPermissions);
31477
- SETUP_FN[chosen](skip);
31487
+ ADAPTERS[chosen].setup(skip);
31478
31488
  const detected = detectInstalledEditors();
31479
31489
  const others = detected.filter((e) => e !== chosen);
31480
31490
  if (others.length > 0) {
31481
- p4.note(
31491
+ p6.note(
31482
31492
  others.map((e) => `bitfab init --editor ${e}`).join("\n"),
31483
31493
  "Set up another editor"
31484
31494
  );
31485
31495
  }
31486
- p4.outro("Done!");
31496
+ p6.outro("Done!");
31487
31497
  }
31488
31498
  async function runAnalyzeRepo(opts) {
31489
- p4.intro("bitfab");
31499
+ p6.intro("bitfab");
31490
31500
  const chosen = await resolveEditor(opts);
31491
- p4.log.step(`Setting up Bitfab in ${EDITOR_LABEL[chosen]}`);
31492
- INSTALL_FN[chosen]();
31501
+ p6.log.step(`Setting up Bitfab in ${ADAPTERS[chosen].label}`);
31502
+ ADAPTERS[chosen].install();
31493
31503
  if (chosen !== "claude") {
31494
- ANALYZE_REPO_FN[chosen]();
31504
+ ADAPTERS[chosen].analyzeRepo();
31495
31505
  process.exit(1);
31496
31506
  }
31497
31507
  const loggedInEmail = await checkAuth();
31498
31508
  if (!loggedInEmail) {
31499
- p4.cancel(
31509
+ p6.cancel(
31500
31510
  "Not authenticated. Run `bitfab login` (or set BITFAB_API_KEY) before `bitfab analyze-repo` - it is non-interactive and cannot open a browser."
31501
31511
  );
31502
31512
  process.exit(1);
31503
31513
  }
31504
- p4.log.success(`Logged in as ${loggedInEmail}`);
31514
+ p6.log.success(`Logged in as ${loggedInEmail}`);
31505
31515
  const captureOverride = await resolveCaptureOverride(opts.uploadLogs);
31506
- await ANALYZE_REPO_FN[chosen](captureOverride, opts.limit);
31507
- p4.outro("Done!");
31516
+ await ADAPTERS[chosen].analyzeRepo(captureOverride, opts.limit);
31517
+ p6.outro("Done!");
31508
31518
  }
31509
31519
  async function checkAuth() {
31510
31520
  const { apiKey, serviceUrl } = getConfig();
@@ -31530,6 +31540,54 @@ function runLogoutCommand() {
31530
31540
  runLogout();
31531
31541
  }
31532
31542
 
31543
+ // src/sessionLogs.ts
31544
+ function parseSessionLogsArgs(args) {
31545
+ const [verb, value] = args;
31546
+ if (verb === void 0 || verb === "status" || verb === "get") {
31547
+ return { kind: "status" };
31548
+ }
31549
+ if (verb === "enable" || verb === "on") {
31550
+ return { kind: "set", value: true };
31551
+ }
31552
+ if (verb === "disable" || verb === "off") {
31553
+ return { kind: "set", value: false };
31554
+ }
31555
+ if (verb === "set") {
31556
+ if (value === "true") {
31557
+ return { kind: "set", value: true };
31558
+ }
31559
+ if (value === "false") {
31560
+ return { kind: "set", value: false };
31561
+ }
31562
+ throw new Error(
31563
+ `Expected "set true" or "set false", got "set ${value ?? ""}".`
31564
+ );
31565
+ }
31566
+ throw new Error(
31567
+ `Unknown session-logs command "${verb}". Expected status, enable, or disable.`
31568
+ );
31569
+ }
31570
+ function runSessionLogsCommand(args) {
31571
+ const action = parseSessionLogsArgs(args);
31572
+ if (action.kind === "status") {
31573
+ const consent = getSessionLogConsent();
31574
+ if (consent === true) {
31575
+ process.stdout.write("Session logs are enabled.\n");
31576
+ return;
31577
+ }
31578
+ if (consent === false) {
31579
+ process.stdout.write("Session logs are disabled.\n");
31580
+ return;
31581
+ }
31582
+ process.stdout.write("Session logs are not configured.\n");
31583
+ return;
31584
+ }
31585
+ setSessionLogConsent(action.value);
31586
+ process.stdout.write(
31587
+ action.value ? "Session logs enabled.\n" : "Session logs disabled.\n"
31588
+ );
31589
+ }
31590
+
31533
31591
  // src/updateCheck.ts
31534
31592
  var NPM_REGISTRY_URL = "https://registry.npmjs.org/bitfab-cli/latest";
31535
31593
  var TIMEOUT_MS = 3e3;
@@ -31581,6 +31639,7 @@ Commands:
31581
31639
  plugin-install [--editor <name>] Install the Bitfab plugin in one editor
31582
31640
  login Authenticate with Bitfab (opens browser)
31583
31641
  logout Remove stored credentials
31642
+ session-logs [status|enable|disable] Read or update session log collection
31584
31643
  setup [--editor <name>] Launch /bitfab:setup in the editor
31585
31644
  analyze-repo [--editor <name>] Headless scan: draft + upload trace plans (no prompts, no code edits)
31586
31645
  assistant [--editor <name>] [args] Launch /bitfab:assistant in the editor
@@ -31600,6 +31659,8 @@ Examples:
31600
31659
  bitfab init --editor claude Full setup for Claude Code
31601
31660
  bitfab analyze-repo Scan the repo and upload draft trace plans (headless)
31602
31661
  bitfab analyze-repo --limit 3 Scan the repo and upload at most 3 draft trace plans
31662
+ bitfab session-logs enable Enable session log collection
31663
+ bitfab session-logs disable Disable session log collection
31603
31664
  bitfab assistant investigate Investigate traces
31604
31665
  bitfab setup --skip-permissions Setup without permission prompts
31605
31666
  bitfab assistant --skip-permissions Run assistant autonomously
@@ -31684,6 +31745,11 @@ async function main() {
31684
31745
  abortUpdateCheck();
31685
31746
  return;
31686
31747
  }
31748
+ if (command === "session-logs") {
31749
+ runSessionLogsCommand(rest);
31750
+ abortUpdateCheck();
31751
+ return;
31752
+ }
31687
31753
  if (command === "setup") {
31688
31754
  await runSetup({ editor, skipPermissions });
31689
31755
  abortUpdateCheck();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bitfab-cli",
3
- "version": "0.2.166",
3
+ "version": "0.2.168",
4
4
  "description": "Install and configure the Bitfab plugin in Claude Code, Codex, or Cursor.",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",