@vibe80/vibe80 0.1.7 → 0.1.8

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/bin/vibe80.js CHANGED
@@ -19,6 +19,9 @@ const defaultEnv = {
19
19
  };
20
20
  const deploymentMode = process.env.DEPLOYMENT_MODE || defaultEnv.DEPLOYMENT_MODE;
21
21
  const serverPort = process.env.PORT || "5179";
22
+ const cliArgs = process.argv.slice(2);
23
+ const enableCodexFromCli = cliArgs.includes("--codex");
24
+ const enableClaudeFromCli = cliArgs.includes("--claude");
22
25
 
23
26
  const spawnProcess = (cmd, args, label, extraEnv = {}) => {
24
27
  const child = spawn(cmd, args, {
@@ -127,11 +130,21 @@ const shutdown = (code = 0) => {
127
130
 
128
131
  const startServer = () => {
129
132
  unlinkMonoAuthUrlFile();
133
+ const monoProviderEnv = {};
134
+ if (enableCodexFromCli) {
135
+ monoProviderEnv.VIBE80_MONO_ENABLE_CODEX = "true";
136
+ }
137
+ if (enableClaudeFromCli) {
138
+ monoProviderEnv.VIBE80_MONO_ENABLE_CLAUDE = "true";
139
+ }
130
140
  server = spawnProcess(
131
141
  process.execPath,
132
142
  ["server/src/index.js"],
133
143
  "server",
134
- { VIBE80_MONO_AUTH_URL_FILE: monoAuthUrlFile }
144
+ {
145
+ VIBE80_MONO_AUTH_URL_FILE: monoAuthUrlFile,
146
+ ...monoProviderEnv,
147
+ }
135
148
  );
136
149
  void maybeOpenMonoAuthUrl();
137
150
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vibe80/vibe80",
3
- "version": "0.1.7",
3
+ "version": "0.1.8",
4
4
  "private": false,
5
5
  "workspaces": [
6
6
  "server",
@@ -48,7 +48,7 @@ export class ClaudeCliClient extends EventEmitter {
48
48
  this.tmpDir = tmpDir || null;
49
49
  this.sessionId = sessionId || null;
50
50
  this.worktreeId = worktreeId || "main";
51
- this.ready = false;
51
+ this.ready = true;
52
52
  this.threadId = threadId || null;
53
53
  this.pendingForkFromThreadId = forkFromThreadId || null;
54
54
  this.modelInfo = null;
@@ -77,7 +77,6 @@ export class ClaudeCliClient extends EventEmitter {
77
77
  return;
78
78
  }
79
79
  this.activeProcess = null;
80
- this.ready = false;
81
80
  const exitPromise = new Promise((resolve) => {
82
81
  proc.once("exit", resolve);
83
82
  proc.once("close", resolve);
@@ -223,6 +222,7 @@ export class ClaudeCliClient extends EventEmitter {
223
222
  cwd: isMonoUser ? this.cwd : undefined,
224
223
  });
225
224
  this.activeProcess = proc;
225
+ this.ready = false;
226
226
 
227
227
  proc.stdout.setEncoding("utf8");
228
228
  proc.stdout.on("data", (chunk) => {
@@ -264,6 +264,7 @@ export class ClaudeCliClient extends EventEmitter {
264
264
  if (this.activeProcess === proc) {
265
265
  this.activeProcess = null;
266
266
  }
267
+ this.ready = true;
267
268
  this.#flushLogBuffer("OUT", "stdoutLogBuffer");
268
269
  this.#flushLogBuffer("ERR", "stderrLogBuffer");
269
270
  this.providerLogger?.close?.();
@@ -662,9 +662,20 @@ wss.on("connection", (socket, req) => {
662
662
  return;
663
663
  }
664
664
  const isMainWorktree = worktreeId === "main";
665
- const client = isMainWorktree
665
+ let client = isMainWorktree
666
666
  ? getActiveClient(session)
667
667
  : runtime.worktreeClients.get(worktreeId);
668
+ if (isMainWorktree && !client) {
669
+ const provider = session.activeProvider === "claude" ? "claude" : "codex";
670
+ client = await getOrCreateClient(session, provider);
671
+ if (!client.listenerCount("ready")) {
672
+ if (provider === "claude") {
673
+ attachClaudeEvents(sessionId, client, provider);
674
+ } else {
675
+ attachClientEvents(sessionId, client, provider);
676
+ }
677
+ }
678
+ }
668
679
  if (!client?.ready) {
669
680
  const label = isMainWorktree
670
681
  ? getProviderLabel(session)
@@ -1146,6 +1157,20 @@ wss.on("connection", (socket, req) => {
1146
1157
  });
1147
1158
  });
1148
1159
  }
1160
+ } else if (session.activeProvider === "claude") {
1161
+ const client = await getOrCreateClient(session, "claude");
1162
+ if (!client.listenerCount("ready")) {
1163
+ attachClaudeEvents(sessionId, client, "claude");
1164
+ }
1165
+ if (!client.ready && !client.activeProcess) {
1166
+ client.start().catch((error) => {
1167
+ console.error("Failed to restart Claude CLI:", error);
1168
+ broadcastToSession(sessionId, {
1169
+ type: "error",
1170
+ message: "Claude CLI failed to start.",
1171
+ });
1172
+ });
1173
+ }
1149
1174
  }
1150
1175
 
1151
1176
  authenticated = true;
@@ -430,9 +430,20 @@ export default function worktreeRoutes(deps) {
430
430
 
431
431
  const isMainWorktree = worktreeId === "main";
432
432
  const runtime = getSessionRuntime(sessionId);
433
- const client = isMainWorktree
433
+ let client = isMainWorktree
434
434
  ? getActiveClient(session)
435
435
  : runtime?.worktreeClients?.get(worktreeId);
436
+ if (isMainWorktree && !client) {
437
+ const provider = session.activeProvider === "claude" ? "claude" : "codex";
438
+ client = await getOrCreateClient(session, provider);
439
+ if (!client.listenerCount("ready")) {
440
+ if (provider === "claude") {
441
+ attachClaudeEvents(sessionId, client, provider);
442
+ } else {
443
+ attachClientEvents(sessionId, client, provider);
444
+ }
445
+ }
446
+ }
436
447
  if (!client?.ready) {
437
448
  const label = isMainWorktree
438
449
  ? worktree.provider === "claude"
@@ -765,14 +765,12 @@ export const ensureDefaultMonoWorkspace = async () => {
765
765
  return;
766
766
  }
767
767
  const workspaceId = "default";
768
+ const enabledProviders = getMonoEnabledProvidersFromEnv();
768
769
  await ensureWorkspaceDirs(workspaceId);
769
770
  const ids = await getWorkspaceUserIds(workspaceId);
770
771
  const existing = await storage.getWorkspace(workspaceId);
771
772
  if (!existing) {
772
- const providers = {
773
- codex: { enabled: true, auth: null },
774
- claude: { enabled: true, auth: null },
775
- };
773
+ const providers = applyMonoEnabledProviders({}, enabledProviders);
776
774
  await persistWorkspaceRecord({
777
775
  workspaceId,
778
776
  providers,
@@ -781,12 +779,69 @@ export const ensureDefaultMonoWorkspace = async () => {
781
779
  existing: null,
782
780
  });
783
781
  await appendAuditLog(workspaceId, "workspace_created");
782
+ return;
784
783
  }
784
+ const providers = applyMonoEnabledProviders(existing.providers || {}, enabledProviders);
785
+ await persistWorkspaceRecord({
786
+ workspaceId,
787
+ providers,
788
+ ids,
789
+ existing,
790
+ });
791
+ await appendAuditLog(workspaceId, "workspace_providers_activation_updated", {
792
+ codexEnabled: providers.codex?.enabled ?? false,
793
+ claudeEnabled: providers.claude?.enabled ?? false,
794
+ });
785
795
  };
786
796
 
787
797
  const readEnvValue = (name) =>
788
798
  typeof process.env[name] === "string" ? process.env[name].trim() : "";
789
799
 
800
+ const parseMonoEnableEnv = (name) => {
801
+ const raw = process.env[name];
802
+ if (typeof raw !== "string") {
803
+ return false;
804
+ }
805
+ const value = raw.trim().toLowerCase();
806
+ if (["1", "true", "yes", "on"].includes(value)) {
807
+ return true;
808
+ }
809
+ if (["0", "false", "no", "off", ""].includes(value)) {
810
+ return false;
811
+ }
812
+ throw new Error(
813
+ `Invalid ${name} value \"${raw}\". Use one of: true/false, 1/0, yes/no, on/off.`
814
+ );
815
+ };
816
+
817
+ const getMonoEnabledProvidersFromEnv = () => {
818
+ const codexEnabled = parseMonoEnableEnv("VIBE80_MONO_ENABLE_CODEX");
819
+ const claudeEnabled = parseMonoEnableEnv("VIBE80_MONO_ENABLE_CLAUDE");
820
+ if (!codexEnabled && !claudeEnabled) {
821
+ throw new Error(
822
+ "In mono_user mode, enable at least one provider via --codex/--claude or VIBE80_MONO_ENABLE_CODEX/VIBE80_MONO_ENABLE_CLAUDE."
823
+ );
824
+ }
825
+ return { codexEnabled, claudeEnabled };
826
+ };
827
+
828
+ const applyMonoEnabledProviders = (providers = {}, enabledConfig) => {
829
+ const { codexEnabled, claudeEnabled } = enabledConfig;
830
+ const codexPrev = providers?.codex && typeof providers.codex === "object" ? providers.codex : {};
831
+ const claudePrev = providers?.claude && typeof providers.claude === "object" ? providers.claude : {};
832
+ return {
833
+ ...providers,
834
+ codex: {
835
+ enabled: Boolean(codexEnabled),
836
+ auth: codexPrev.auth || null,
837
+ },
838
+ claude: {
839
+ enabled: Boolean(claudeEnabled),
840
+ auth: claudePrev.auth || null,
841
+ },
842
+ };
843
+ };
844
+
790
845
  const buildMonoUserProviderOverridesFromEnv = () => {
791
846
  const codexApiKey = readEnvValue("CODEX_API_KEY");
792
847
  const codexAuthJsonB64Raw = process.env.CODEX_AUTH_JSON_B64;
@@ -814,7 +869,6 @@ const buildMonoUserProviderOverridesFromEnv = () => {
814
869
  const decoded = decodeBase64(codexAuthJsonB64);
815
870
  validateCodexAuthJson(decoded);
816
871
  overrides.codex = {
817
- enabled: true,
818
872
  auth: { type: "auth_json_b64", value: codexAuthJsonB64 },
819
873
  };
820
874
  } catch {
@@ -825,7 +879,6 @@ const buildMonoUserProviderOverridesFromEnv = () => {
825
879
  }
826
880
  } else if (codexApiKey) {
827
881
  overrides.codex = {
828
- enabled: true,
829
882
  auth: { type: "api_key", value: codexApiKey },
830
883
  };
831
884
  }
@@ -842,13 +895,11 @@ const buildMonoUserProviderOverridesFromEnv = () => {
842
895
  );
843
896
  } else {
844
897
  overrides.claude = {
845
- enabled: true,
846
898
  auth: { type: "setup_token", value: claudeSetupToken },
847
899
  };
848
900
  }
849
901
  } else if (claudeApiKey) {
850
902
  overrides.claude = {
851
- enabled: true,
852
903
  auth: { type: "api_key", value: claudeApiKey },
853
904
  };
854
905
  }
@@ -869,7 +920,25 @@ export const applyMonoUserProviderOverridesFromEnv = async () => {
869
920
  if (!existing) {
870
921
  return;
871
922
  }
872
- const mergedProviders = mergeProvidersForUpdate(existing.providers || {}, overrides);
923
+ const activationConfig = getMonoEnabledProvidersFromEnv();
924
+ const mergedProviders = mergeProvidersForUpdate(existing.providers || {}, {
925
+ ...(overrides.codex
926
+ ? {
927
+ codex: {
928
+ enabled: activationConfig.codexEnabled,
929
+ auth: overrides.codex.auth,
930
+ },
931
+ }
932
+ : {}),
933
+ ...(overrides.claude
934
+ ? {
935
+ claude: {
936
+ enabled: activationConfig.claudeEnabled,
937
+ auth: overrides.claude.auth,
938
+ },
939
+ }
940
+ : {}),
941
+ });
873
942
  const ids = await getWorkspaceUserIds(workspaceId);
874
943
  await writeWorkspaceProviderAuth(workspaceId, mergedProviders);
875
944
  await persistWorkspaceRecord({
@@ -891,13 +960,18 @@ export const createWorkspace = async (providers) => {
891
960
  if (isMonoUser) {
892
961
  const workspaceId = "default";
893
962
  await ensureWorkspaceDirs(workspaceId);
963
+ const enabledProviders = getMonoEnabledProvidersFromEnv();
894
964
  const secret = "default";
895
965
  const ids = await getWorkspaceUserIds(workspaceId);
896
966
  const existing = await storage.getWorkspace(workspaceId);
897
- await writeWorkspaceProviderAuth(workspaceId, providers);
967
+ const providersWithActivation = applyMonoEnabledProviders(
968
+ providers || existing?.providers || {},
969
+ enabledProviders
970
+ );
971
+ await writeWorkspaceProviderAuth(workspaceId, providersWithActivation);
898
972
  await persistWorkspaceRecord({
899
973
  workspaceId,
900
- providers,
974
+ providers: providersWithActivation,
901
975
  ids,
902
976
  workspaceSecretHash: hashWorkspaceSecret(secret),
903
977
  existing,