@meetopenbot/claude-code 0.1.7 → 0.1.9

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 (2) hide show
  1. package/dist/index.js +152 -15
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -1,3 +1,7 @@
1
+ // cloud-mode.ts
2
+ var isCloudMode = () => process.env.OPENBOT_CLOUD_MODE === "1";
3
+ var defaultAuthMode = () => isCloudMode() ? "credits" : "byok";
4
+
1
5
  // runtime.ts
2
6
  import { execSync } from "node:child_process";
3
7
  import { existsSync as existsSync2, readlinkSync as readlinkSync2, statSync as statSync2 } from "node:fs";
@@ -19365,6 +19369,29 @@ function uiWidget(args) {
19365
19369
  };
19366
19370
  }
19367
19371
 
19372
+ // credits-auth.ts
19373
+ var INTEGRATIONS_TOKEN_HEADER = "x-openbot-integrations-token";
19374
+ var CREDITS_API_KEY_PLACEHOLDER = "openbot-credits";
19375
+ var resolveCreditsAuthConfig = () => {
19376
+ const baseUrl = process.env.OPENBOT_INTEGRATIONS_BASE_URL?.trim();
19377
+ const token = process.env.OPENBOT_INTEGRATIONS_TOKEN?.trim();
19378
+ if (!baseUrl || !token) return void 0;
19379
+ return { baseUrl: baseUrl.replace(/\/$/, ""), token };
19380
+ };
19381
+ var buildCreditsAnthropicEnv = () => {
19382
+ const config = resolveCreditsAuthConfig();
19383
+ if (!config) return void 0;
19384
+ const apiKey = config.token || CREDITS_API_KEY_PLACEHOLDER;
19385
+ return {
19386
+ ANTHROPIC_BASE_URL: `${config.baseUrl}/anthropic/v1`,
19387
+ ANTHROPIC_CUSTOM_HEADERS: `${INTEGRATIONS_TOKEN_HEADER}: ${config.token}`,
19388
+ ANTHROPIC_API_KEY: apiKey,
19389
+ // Prevent the CLI from preferring stored OAuth over gateway routing.
19390
+ CLAUDE_CODE_OAUTH_TOKEN: "",
19391
+ ANTHROPIC_AUTH_TOKEN: ""
19392
+ };
19393
+ };
19394
+
19368
19395
  // runtime.ts
19369
19396
  var asRecord = (value) => value && typeof value === "object" && !Array.isArray(value) ? value : {};
19370
19397
  var readPersistedSessionId = (state) => {
@@ -19400,6 +19427,31 @@ var isAuthErrorMessage = (message) => {
19400
19427
  const lower = message.toLowerCase();
19401
19428
  return AUTH_ERROR_PATTERNS.some((p) => lower.includes(p));
19402
19429
  };
19430
+ var isCreditsErrorMessage = (message) => {
19431
+ const lower = message.toLowerCase();
19432
+ return lower.includes("insufficient_credits") || lower.includes("insufficient credits") || lower.includes("402");
19433
+ };
19434
+ var isIntegrationsProviderError = (message) => {
19435
+ const lower = message.toLowerCase();
19436
+ return lower.includes("provider api key not configured") || lower.includes("503") && lower.includes("provider");
19437
+ };
19438
+ var CREDITS_NOT_CONFIGURED_MESSAGE = "OpenBot Credits is not configured on this runtime. The cloud host must set OPENBOT_INTEGRATIONS_BASE_URL and OPENBOT_INTEGRATIONS_TOKEN (try redeploying the workspace).";
19439
+ var CREDITS_PROVIDER_UNAVAILABLE_MESSAGE = "OpenBot Credits could not reach Anthropic \u2014 the platform provider API key is not configured yet. Try again later or switch this agent to BYOK mode.";
19440
+ var CREDITS_AUTH_FAILED_MESSAGE = "Claude could not authenticate via OpenBot Credits. Check your workspace credit balance in settings, or switch this agent to BYOK mode.";
19441
+ var buildSdkEnv = (authMode) => {
19442
+ if (authMode !== "credits") return void 0;
19443
+ const creditsEnv = buildCreditsAnthropicEnv();
19444
+ if (!creditsEnv) return void 0;
19445
+ return { ...process.env, ...creditsEnv };
19446
+ };
19447
+ var creditsErrorMessage = (message) => {
19448
+ if (isIntegrationsProviderError(message)) return CREDITS_PROVIDER_UNAVAILABLE_MESSAGE;
19449
+ if (isCreditsErrorMessage(message)) {
19450
+ return "Insufficient workspace credits. Add credits in workspace settings or switch this agent to BYOK mode.";
19451
+ }
19452
+ if (isAuthErrorMessage(message)) return CREDITS_AUTH_FAILED_MESSAGE;
19453
+ return void 0;
19454
+ };
19403
19455
  var buildApiKeyWidget = (agentId, threadId, reason) => uiWidget({
19404
19456
  agentId,
19405
19457
  threadId,
@@ -19638,7 +19690,8 @@ var claudeCodeRuntime = (options = {}) => (builder) => {
19638
19690
  cwd,
19639
19691
  executablePath: executablePathOverride,
19640
19692
  allowedTools,
19641
- storage
19693
+ storage,
19694
+ authMode = defaultAuthMode()
19642
19695
  } = options;
19643
19696
  const executablePath = executablePathOverride || findClaudeExecutable();
19644
19697
  builder.on("agent:invoke", async function* (event, context) {
@@ -19655,6 +19708,15 @@ var claudeCodeRuntime = (options = {}) => (builder) => {
19655
19708
  executablePath,
19656
19709
  workingDir
19657
19710
  };
19711
+ const sdkEnv = buildSdkEnv(authMode);
19712
+ if (authMode === "credits" && !resolveCreditsAuthConfig()) {
19713
+ yield agentOutput({
19714
+ agentId: context.state.agentId,
19715
+ threadId,
19716
+ content: CREDITS_NOT_CONFIGURED_MESSAGE
19717
+ });
19718
+ return;
19719
+ }
19658
19720
  const sdkOptions = {
19659
19721
  model,
19660
19722
  permissionMode,
@@ -19665,11 +19727,13 @@ var claudeCodeRuntime = (options = {}) => (builder) => {
19665
19727
  ...resumeId ? { resume: resumeId } : {},
19666
19728
  ...workingDir ? { cwd: workingDir } : {},
19667
19729
  ...executablePath ? { pathToClaudeCodeExecutable: executablePath } : {},
19668
- ...allowedTools ? { allowedTools } : {}
19730
+ ...allowedTools ? { allowedTools } : {},
19731
+ ...sdkEnv ? { env: sdkEnv } : {}
19669
19732
  };
19670
19733
  try {
19671
19734
  let lastSessionId = resumeId;
19672
19735
  let authWidgetYielded = false;
19736
+ let creditsFailureYielded = false;
19673
19737
  const emittedToolCallIds = /* @__PURE__ */ new Set();
19674
19738
  const emittedToolResultIds = /* @__PURE__ */ new Set();
19675
19739
  const toolTitleByUseId = /* @__PURE__ */ new Map();
@@ -19679,12 +19743,20 @@ var claudeCodeRuntime = (options = {}) => (builder) => {
19679
19743
  }
19680
19744
  if (!authWidgetYielded && message.type === "assistant" && (message.error === "authentication_failed" || message.error === "oauth_org_not_allowed")) {
19681
19745
  authWidgetYielded = true;
19682
- yield buildApiKeyWidget(context.state.agentId, threadId, message.error);
19683
- yield agentOutput({
19684
- agentId: context.state.agentId,
19685
- threadId,
19686
- content: "Claude needs an API key to continue. Please provide ANTHROPIC_API_KEY as a variable from the workspace settings or inside the widget above."
19687
- });
19746
+ if (authMode === "credits") {
19747
+ yield agentOutput({
19748
+ agentId: context.state.agentId,
19749
+ threadId,
19750
+ content: creditsErrorMessage(message.error) ?? CREDITS_AUTH_FAILED_MESSAGE
19751
+ });
19752
+ } else {
19753
+ yield buildApiKeyWidget(context.state.agentId, threadId, message.error);
19754
+ yield agentOutput({
19755
+ agentId: context.state.agentId,
19756
+ threadId,
19757
+ content: "Claude needs an API key to continue. Please provide ANTHROPIC_API_KEY as a variable from the workspace settings or inside the widget above."
19758
+ });
19759
+ }
19688
19760
  return;
19689
19761
  }
19690
19762
  if (message.type === "assistant") {
@@ -19737,11 +19809,20 @@ var claudeCodeRuntime = (options = {}) => (builder) => {
19737
19809
  if (textParts.length > 0) {
19738
19810
  const joined = textParts.join("\n");
19739
19811
  if (joined.length > 0) {
19740
- yield agentOutput({
19741
- agentId: context.state.agentId,
19742
- threadId,
19743
- content: joined
19744
- });
19812
+ if (authMode === "credits" && !creditsFailureYielded && isIntegrationsProviderError(joined)) {
19813
+ creditsFailureYielded = true;
19814
+ yield agentOutput({
19815
+ agentId: context.state.agentId,
19816
+ threadId,
19817
+ content: CREDITS_PROVIDER_UNAVAILABLE_MESSAGE
19818
+ });
19819
+ } else {
19820
+ yield agentOutput({
19821
+ agentId: context.state.agentId,
19822
+ threadId,
19823
+ content: joined
19824
+ });
19825
+ }
19745
19826
  }
19746
19827
  }
19747
19828
  }
@@ -19781,9 +19862,31 @@ var claudeCodeRuntime = (options = {}) => (builder) => {
19781
19862
  if (message.type === "result" && message.subtype !== "success") {
19782
19863
  const subtype = message.subtype;
19783
19864
  const resultText = "result" in message && typeof message.result === "string" ? message.result : "";
19865
+ const errorText = resultText || subtype;
19866
+ if (authMode === "credits") {
19867
+ const creditsMessage = creditsErrorMessage(errorText);
19868
+ if (creditsMessage && !creditsFailureYielded) {
19869
+ creditsFailureYielded = true;
19870
+ yield agentOutput({
19871
+ agentId: context.state.agentId,
19872
+ threadId,
19873
+ content: creditsMessage
19874
+ });
19875
+ return;
19876
+ }
19877
+ if (creditsFailureYielded) return;
19878
+ }
19784
19879
  if (!authWidgetYielded && (isAuthErrorMessage(subtype) || isAuthErrorMessage(resultText))) {
19785
19880
  authWidgetYielded = true;
19786
- yield buildApiKeyWidget(context.state.agentId, threadId, subtype);
19881
+ if (authMode === "credits") {
19882
+ yield agentOutput({
19883
+ agentId: context.state.agentId,
19884
+ threadId,
19885
+ content: creditsErrorMessage(resultText || subtype) ?? CREDITS_AUTH_FAILED_MESSAGE
19886
+ });
19887
+ } else {
19888
+ yield buildApiKeyWidget(context.state.agentId, threadId, subtype);
19889
+ }
19787
19890
  return;
19788
19891
  }
19789
19892
  const details = formatResultError(message);
@@ -19800,8 +19903,27 @@ ${details}` : `[claude-code] run ended with error: ${subtype}`
19800
19903
  }
19801
19904
  } catch (error) {
19802
19905
  const errorMessage = formatClaudeCodeError(error, launchContext, stderrChunks);
19906
+ if (authMode === "credits") {
19907
+ const creditsMessage = creditsErrorMessage(errorMessage);
19908
+ if (creditsMessage) {
19909
+ yield agentOutput({
19910
+ agentId: context.state.agentId,
19911
+ threadId,
19912
+ content: creditsMessage
19913
+ });
19914
+ return;
19915
+ }
19916
+ }
19803
19917
  if (isAuthErrorMessage(errorMessage)) {
19804
- yield buildApiKeyWidget(context.state.agentId, threadId, errorMessage);
19918
+ if (authMode === "credits") {
19919
+ yield agentOutput({
19920
+ agentId: context.state.agentId,
19921
+ threadId,
19922
+ content: creditsErrorMessage(errorMessage) ?? CREDITS_AUTH_FAILED_MESSAGE
19923
+ });
19924
+ } else {
19925
+ yield buildApiKeyWidget(context.state.agentId, threadId, errorMessage);
19926
+ }
19805
19927
  return;
19806
19928
  }
19807
19929
  yield agentOutput({
@@ -19861,6 +19983,12 @@ Your goal is to help the user with their coding tasks.
19861
19983
  `;
19862
19984
 
19863
19985
  // index.ts
19986
+ var resolveAuthMode = (config) => {
19987
+ if (config.authMode === "byok" || config.authMode === "credits") {
19988
+ return config.authMode;
19989
+ }
19990
+ return defaultAuthMode();
19991
+ };
19864
19992
  var claudeCodePlugin = {
19865
19993
  id: "claude-code",
19866
19994
  name: "Claude Code",
@@ -19868,6 +19996,14 @@ var claudeCodePlugin = {
19868
19996
  configSchema: {
19869
19997
  type: "object",
19870
19998
  properties: {
19999
+ ...isCloudMode() ? {
20000
+ authMode: {
20001
+ type: "string",
20002
+ description: "Credits \u2014 use your workspace credit balance via OpenBot. BYOK \u2014 bring your own Anthropic API key.",
20003
+ enum: ["credits", "byok"],
20004
+ default: "credits"
20005
+ }
20006
+ } : {},
19871
20007
  model: {
19872
20008
  type: "string",
19873
20009
  description: "Claude model alias or full id (e.g. sonnet, opus, claude-opus-4-5).",
@@ -19893,6 +20029,7 @@ var claudeCodePlugin = {
19893
20029
  model,
19894
20030
  permissionMode,
19895
20031
  executablePath,
20032
+ authMode: resolveAuthMode(config),
19896
20033
  system: agentDetails.instructions || CLAUDE_CODE_SYSTEM_PROMPT,
19897
20034
  storage
19898
20035
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@meetopenbot/claude-code",
3
- "version": "0.1.7",
3
+ "version": "0.1.9",
4
4
  "type": "module",
5
5
  "description": "Claude Code plugin for OpenBot",
6
6
  "main": "./dist/index.js",