@aiden-ade/sandbox-agent 0.1.38 → 0.1.40
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/index.cjs +228 -35
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -15717,10 +15717,107 @@ function getCodexPermissionArgs(config) {
|
|
|
15717
15717
|
const sandbox = shouldUseReadOnlyRuntimePermissions(config) ? "read-only" : "danger-full-access";
|
|
15718
15718
|
return ["--ask-for-approval", "never", "--sandbox", sandbox];
|
|
15719
15719
|
}
|
|
15720
|
+
var ERROR_SPECS = {
|
|
15721
|
+
model_mismatch: {
|
|
15722
|
+
message: "The selected model isn't available, or you don't have access to it. Pick a different model, then send your message again.",
|
|
15723
|
+
recoveryClass: "user_fixable"
|
|
15724
|
+
},
|
|
15725
|
+
auth_invalid: {
|
|
15726
|
+
message: "API key invalid or expired. Check your provider settings, then retry.",
|
|
15727
|
+
recoveryClass: "user_fixable"
|
|
15728
|
+
},
|
|
15729
|
+
not_logged_in: {
|
|
15730
|
+
message: "Not logged in to this provider. Sign in from provider settings, then retry.",
|
|
15731
|
+
recoveryClass: "user_fixable"
|
|
15732
|
+
},
|
|
15733
|
+
not_authenticated: {
|
|
15734
|
+
message: "The agent CLI isn't signed in on this runtime. Authenticate it there, then retry.",
|
|
15735
|
+
recoveryClass: "needs_env"
|
|
15736
|
+
},
|
|
15737
|
+
auth_expired: {
|
|
15738
|
+
message: "The provider connection expired. Reconnect it in Cloud settings, then restart or recreate the machine.",
|
|
15739
|
+
recoveryClass: "user_fixable"
|
|
15740
|
+
},
|
|
15741
|
+
subscription_required: {
|
|
15742
|
+
message: "This model requires a paid subscription. Switch to a supported model or upgrade your plan.",
|
|
15743
|
+
recoveryClass: "user_fixable"
|
|
15744
|
+
},
|
|
15745
|
+
quota_exceeded: {
|
|
15746
|
+
message: "API quota exceeded. Wait for it to reset or check your billing, then retry.",
|
|
15747
|
+
recoveryClass: "user_fixable"
|
|
15748
|
+
},
|
|
15749
|
+
usage_limit: {
|
|
15750
|
+
message: "Provider usage limit reached. Switch model or wait for the limit to reset, then retry.",
|
|
15751
|
+
recoveryClass: "user_fixable"
|
|
15752
|
+
},
|
|
15753
|
+
context_length: {
|
|
15754
|
+
message: "Context window exceeded \u2014 the conversation is too long. Start a new session or send a shorter message.",
|
|
15755
|
+
recoveryClass: "user_fixable"
|
|
15756
|
+
},
|
|
15757
|
+
rate_limited: {
|
|
15758
|
+
message: "Rate limited by the provider. Retrying automatically shortly.",
|
|
15759
|
+
recoveryClass: "auto_recovering"
|
|
15760
|
+
},
|
|
15761
|
+
overloaded: {
|
|
15762
|
+
message: "The provider is overloaded. Retrying automatically.",
|
|
15763
|
+
recoveryClass: "auto_recovering"
|
|
15764
|
+
},
|
|
15765
|
+
network: {
|
|
15766
|
+
message: "Network connection failed. Check your internet connection \u2014 retrying automatically.",
|
|
15767
|
+
recoveryClass: "auto_recovering"
|
|
15768
|
+
},
|
|
15769
|
+
provider_timeout: {
|
|
15770
|
+
message: "The provider timed out while continuing the turn. Send your message again; if it repeats, check network/API latency or reduce slow tool calls.",
|
|
15771
|
+
recoveryClass: "retry"
|
|
15772
|
+
},
|
|
15773
|
+
resume_failed: {
|
|
15774
|
+
message: "The previous session could not be resumed \u2014 its stored session was missing or expired. The next message starts a fresh session without earlier context.",
|
|
15775
|
+
recoveryClass: "retry"
|
|
15776
|
+
},
|
|
15777
|
+
permission_denied: {
|
|
15778
|
+
message: "Permission denied. Check file or command permissions on the runtime.",
|
|
15779
|
+
recoveryClass: "needs_env"
|
|
15780
|
+
},
|
|
15781
|
+
out_of_memory: {
|
|
15782
|
+
message: "Out of memory on the runtime. Close other work or use a larger machine, then retry.",
|
|
15783
|
+
recoveryClass: "needs_env"
|
|
15784
|
+
},
|
|
15785
|
+
provider_error: {
|
|
15786
|
+
message: "The provider returned an error. Send your message again to retry.",
|
|
15787
|
+
recoveryClass: "retry"
|
|
15788
|
+
},
|
|
15789
|
+
unknown_cli_error: {
|
|
15790
|
+
message: "The agent stopped unexpectedly. Send your message again to retry.",
|
|
15791
|
+
recoveryClass: "retry"
|
|
15792
|
+
}
|
|
15793
|
+
};
|
|
15794
|
+
function specForErrorKind(errorKind) {
|
|
15795
|
+
const spec = ERROR_SPECS[errorKind];
|
|
15796
|
+
return { message: spec.message, errorKind, recoveryClass: spec.recoveryClass };
|
|
15797
|
+
}
|
|
15720
15798
|
function isLikelyProviderAuthError(stderr) {
|
|
15721
15799
|
const lower = stderr.toLowerCase();
|
|
15722
15800
|
return lower.includes("api key") || lower.includes("api_key") || lower.includes("invalid api key") || lower.includes("api key invalid") || lower.includes("unauthorized") || lower.includes("authentication failed") || lower.includes("authentication error") || lower.includes("provider settings") || lower.includes("invalid token") || lower.includes("token expired");
|
|
15723
15801
|
}
|
|
15802
|
+
function mapProviderApiError(errorCode, apiStatus) {
|
|
15803
|
+
const code = errorCode?.trim().toLowerCase();
|
|
15804
|
+
if (code) {
|
|
15805
|
+
if (code.includes("model_not_found") || code.includes("model_not_available")) {
|
|
15806
|
+
return "model_mismatch";
|
|
15807
|
+
}
|
|
15808
|
+
if (code.includes("authentication") || code.includes("permission_error")) return "auth_invalid";
|
|
15809
|
+
if (code.includes("rate_limit")) return "rate_limited";
|
|
15810
|
+
if (code.includes("overloaded")) return "overloaded";
|
|
15811
|
+
if (code.includes("insufficient_quota") || code.includes("billing")) return "quota_exceeded";
|
|
15812
|
+
}
|
|
15813
|
+
if (typeof apiStatus === "number") {
|
|
15814
|
+
if (apiStatus === 404) return "model_mismatch";
|
|
15815
|
+
if (apiStatus === 401 || apiStatus === 403) return "auth_invalid";
|
|
15816
|
+
if (apiStatus === 429) return "rate_limited";
|
|
15817
|
+
if (apiStatus >= 500) return "overloaded";
|
|
15818
|
+
}
|
|
15819
|
+
return null;
|
|
15820
|
+
}
|
|
15724
15821
|
function normalizeCodexCliErrorMessage(message) {
|
|
15725
15822
|
const lower = message.toLowerCase();
|
|
15726
15823
|
if (lower.includes("reconnecting") && lower.includes("request timed out")) {
|
|
@@ -15731,40 +15828,80 @@ function normalizeCodexCliErrorMessage(message) {
|
|
|
15731
15828
|
}
|
|
15732
15829
|
return message;
|
|
15733
15830
|
}
|
|
15734
|
-
function
|
|
15831
|
+
function classifyCliErrorDetailed(stderr, _exitCode, opts) {
|
|
15735
15832
|
const normalizedCodexError = normalizeCodexCliErrorMessage(stderr);
|
|
15736
|
-
if (normalizedCodexError !== stderr)
|
|
15737
|
-
|
|
15738
|
-
|
|
15739
|
-
|
|
15740
|
-
|
|
15741
|
-
|
|
15742
|
-
|
|
15743
|
-
|
|
15744
|
-
|
|
15745
|
-
|
|
15746
|
-
if (
|
|
15747
|
-
return "
|
|
15748
|
-
if (
|
|
15749
|
-
|
|
15750
|
-
|
|
15751
|
-
|
|
15752
|
-
if (
|
|
15753
|
-
return "
|
|
15754
|
-
if (
|
|
15755
|
-
|
|
15756
|
-
|
|
15757
|
-
|
|
15758
|
-
|
|
15759
|
-
|
|
15760
|
-
|
|
15761
|
-
|
|
15762
|
-
|
|
15763
|
-
|
|
15764
|
-
|
|
15765
|
-
|
|
15833
|
+
if (normalizedCodexError !== stderr) {
|
|
15834
|
+
const kind = /timed out/i.test(normalizedCodexError) ? "provider_timeout" : "auth_expired";
|
|
15835
|
+
return {
|
|
15836
|
+
message: normalizedCodexError,
|
|
15837
|
+
errorKind: kind,
|
|
15838
|
+
recoveryClass: ERROR_SPECS[kind].recoveryClass
|
|
15839
|
+
};
|
|
15840
|
+
}
|
|
15841
|
+
const haystack = [stderr, ...opts?.extraSignals ?? []].join("\n").toLowerCase();
|
|
15842
|
+
const has = (...needles) => needles.some((n) => haystack.includes(n));
|
|
15843
|
+
if (has("codex cli connection expired", "reconnect openai codex"))
|
|
15844
|
+
return specForErrorKind("auth_expired");
|
|
15845
|
+
if (has("codex connection to openai timed out")) return specForErrorKind("provider_timeout");
|
|
15846
|
+
if (has("authentication required", "not authenticated"))
|
|
15847
|
+
return specForErrorKind("not_authenticated");
|
|
15848
|
+
if (has("out of usage", "increase your limit")) return specForErrorKind("usage_limit");
|
|
15849
|
+
if (has("no chat found", "chat not found", "session not found", "could not resume"))
|
|
15850
|
+
return specForErrorKind("resume_failed");
|
|
15851
|
+
if (has("rate_limit", "rate limit", "429")) return specForErrorKind("rate_limited");
|
|
15852
|
+
if (has("authentication_failed", "authentication error", "authentication failed") || isLikelyProviderAuthError(haystack))
|
|
15853
|
+
return specForErrorKind("auth_invalid");
|
|
15854
|
+
if (has(
|
|
15855
|
+
"not logged in",
|
|
15856
|
+
"login required",
|
|
15857
|
+
"please sign in",
|
|
15858
|
+
"please log in",
|
|
15859
|
+
"sign in to",
|
|
15860
|
+
"log in to",
|
|
15861
|
+
// Claude prompts the user to re-auth with the /login slash command.
|
|
15862
|
+
"run /login",
|
|
15863
|
+
"please run /login"
|
|
15864
|
+
))
|
|
15865
|
+
return specForErrorKind("not_logged_in");
|
|
15866
|
+
if (has(
|
|
15867
|
+
"model not supported",
|
|
15868
|
+
"unsupported model",
|
|
15869
|
+
"model not found",
|
|
15870
|
+
"model not available",
|
|
15871
|
+
"model is not available",
|
|
15872
|
+
"invalid model",
|
|
15873
|
+
"unknown model",
|
|
15874
|
+
"no such model",
|
|
15875
|
+
"llm not set",
|
|
15876
|
+
// Claude Code phrasings (safety net; the structured decoder catches these first).
|
|
15877
|
+
"issue with the selected model",
|
|
15878
|
+
"may not exist or you may not have access"
|
|
15879
|
+
))
|
|
15880
|
+
return specForErrorKind("model_mismatch");
|
|
15881
|
+
if (has(
|
|
15882
|
+
"subscription",
|
|
15883
|
+
"paid plan",
|
|
15884
|
+
"plan required",
|
|
15885
|
+
"upgrade your plan",
|
|
15886
|
+
"only supports free",
|
|
15887
|
+
"not available on your",
|
|
15888
|
+
"requires a paid"
|
|
15889
|
+
))
|
|
15890
|
+
return specForErrorKind("subscription_required");
|
|
15891
|
+
if (has("quota exceeded", "quota limit", "daily limit", "monthly limit", "usage limit"))
|
|
15892
|
+
return specForErrorKind("quota_exceeded");
|
|
15893
|
+
if (has("overloaded", "503", "service unavailable")) return specForErrorKind("overloaded");
|
|
15894
|
+
if (has("context_length", "too long", "max tokens", "context window"))
|
|
15895
|
+
return specForErrorKind("context_length");
|
|
15896
|
+
if (has("econnrefused", "network", "enotfound", "timeout", "etimedout"))
|
|
15897
|
+
return specForErrorKind("network");
|
|
15898
|
+
if (has("permission denied", "eacces")) return specForErrorKind("permission_denied");
|
|
15899
|
+
if (has("out of memory", "enomem")) return specForErrorKind("out_of_memory");
|
|
15766
15900
|
const raw = stderr.trim().slice(0, 200);
|
|
15767
|
-
|
|
15901
|
+
if (raw) {
|
|
15902
|
+
return { message: raw, errorKind: "unknown_cli_error", recoveryClass: "unknown" };
|
|
15903
|
+
}
|
|
15904
|
+
return specForErrorKind("unknown_cli_error");
|
|
15768
15905
|
}
|
|
15769
15906
|
function isTransientError(errorMessage) {
|
|
15770
15907
|
const lower = errorMessage.toLowerCase();
|
|
@@ -16204,13 +16341,34 @@ function createGenericCliBackend(options) {
|
|
|
16204
16341
|
};
|
|
16205
16342
|
}
|
|
16206
16343
|
const summary = state.summary.trim() || state.error?.trim() || (failed ? "Task failed" : "Task completed");
|
|
16344
|
+
let classifiedError;
|
|
16345
|
+
let classifiedErrorKind;
|
|
16346
|
+
let classifiedRecoveryClass;
|
|
16347
|
+
if (failed) {
|
|
16348
|
+
if (state.errorKind && state.error?.trim()) {
|
|
16349
|
+
classifiedError = state.error.trim();
|
|
16350
|
+
classifiedErrorKind = state.errorKind;
|
|
16351
|
+
classifiedRecoveryClass = state.recoveryClass;
|
|
16352
|
+
} else {
|
|
16353
|
+
const detailed = classifyCliErrorDetailed(
|
|
16354
|
+
state.error?.trim() || stderrText || "",
|
|
16355
|
+
exitCode,
|
|
16356
|
+
{ extraSignals: state.summary ? [state.summary] : void 0 }
|
|
16357
|
+
);
|
|
16358
|
+
classifiedError = detailed.message;
|
|
16359
|
+
classifiedErrorKind = detailed.errorKind;
|
|
16360
|
+
classifiedRecoveryClass = detailed.recoveryClass;
|
|
16361
|
+
}
|
|
16362
|
+
}
|
|
16207
16363
|
return {
|
|
16208
16364
|
success: !failed,
|
|
16209
16365
|
summary,
|
|
16210
16366
|
filesModified: [],
|
|
16211
16367
|
planFilesCreated: [],
|
|
16212
16368
|
iterations: Math.max(state.iterations, 1),
|
|
16213
|
-
error:
|
|
16369
|
+
error: classifiedError,
|
|
16370
|
+
...classifiedErrorKind ? { errorKind: classifiedErrorKind } : {},
|
|
16371
|
+
...classifiedRecoveryClass ? { recoveryClass: classifiedRecoveryClass } : {},
|
|
16214
16372
|
providerSessionId: state.runtimeSessionId,
|
|
16215
16373
|
runtimeSessionId: state.runtimeSessionId,
|
|
16216
16374
|
backendKind: options.kind,
|
|
@@ -16884,6 +17042,9 @@ function handleClaudeStructuredEvent(parsed, context, state) {
|
|
|
16884
17042
|
if (typeof parsed.session_id === "string") {
|
|
16885
17043
|
state.runtimeSessionId = parsed.session_id;
|
|
16886
17044
|
}
|
|
17045
|
+
if (typeof parsed.error === "string" && parsed.error.trim()) {
|
|
17046
|
+
state.providerErrorCode = parsed.error.trim();
|
|
17047
|
+
}
|
|
16887
17048
|
const parentToolUseId = typeof parsed.parent_tool_use_id === "string" ? parsed.parent_tool_use_id : null;
|
|
16888
17049
|
switch (type) {
|
|
16889
17050
|
case "system": {
|
|
@@ -17096,6 +17257,27 @@ function handleClaudeStructuredEvent(parsed, context, state) {
|
|
|
17096
17257
|
})
|
|
17097
17258
|
);
|
|
17098
17259
|
}
|
|
17260
|
+
const isApiError = parsed.is_error === true || parsed.terminal_reason === "api_error" || typeof parsed.api_error_status === "number";
|
|
17261
|
+
if (isApiError && !state.error) {
|
|
17262
|
+
const apiStatus = typeof parsed.api_error_status === "number" ? parsed.api_error_status : void 0;
|
|
17263
|
+
state.apiErrorStatus = apiStatus;
|
|
17264
|
+
const mappedKind = mapProviderApiError(state.providerErrorCode, apiStatus);
|
|
17265
|
+
const spec = mappedKind ? specForErrorKind(mappedKind) : specForErrorKind("provider_error");
|
|
17266
|
+
state.error = mappedKind || typeof parsed.result !== "string" || !parsed.result.trim() ? spec.message : parsed.result.trim();
|
|
17267
|
+
state.errorKind = spec.errorKind;
|
|
17268
|
+
state.recoveryClass = spec.recoveryClass;
|
|
17269
|
+
console.error(
|
|
17270
|
+
"[claude_cli] result flagged API error:",
|
|
17271
|
+
JSON.stringify({
|
|
17272
|
+
is_error: parsed.is_error,
|
|
17273
|
+
terminal_reason: parsed.terminal_reason,
|
|
17274
|
+
api_error_status: parsed.api_error_status,
|
|
17275
|
+
providerErrorCode: state.providerErrorCode,
|
|
17276
|
+
mappedKind,
|
|
17277
|
+
result: typeof parsed.result === "string" ? parsed.result.slice(0, 200) : void 0
|
|
17278
|
+
})
|
|
17279
|
+
);
|
|
17280
|
+
}
|
|
17099
17281
|
debugAskLog(
|
|
17100
17282
|
`[claude_cli] result event \u2014 pendingAskUserToolIds size=${presenter.pendingAskUserToolIds?.size ?? "undefined"}, hasOwnProp=${Object.hasOwn(presenter, "pendingAskUserToolIds")}`
|
|
17101
17283
|
);
|
|
@@ -21829,6 +22011,10 @@ var ANTIGRAVITY_MODEL_DISCOVERY_TIMEOUT_MS = 12e3;
|
|
|
21829
22011
|
var OPENCODE_ZEN_MODEL_IDS = OPENCODE_ZEN_MODELS.map((model) => model.id);
|
|
21830
22012
|
var CLAUDE_MODEL_ID_PATTERN = /claude-(?:sonnet|opus|haiku|fable)-[a-z0-9][a-z0-9-]*/g;
|
|
21831
22013
|
var CLAUDE_MODEL_ALIASES = ["sonnet", "opus", "haiku", "fable"];
|
|
22014
|
+
var CLAUDE_MODEL_QUALIFIER_SEGMENTS = /* @__PURE__ */ new Set(["fast", "thinking", "latest", "preview"]);
|
|
22015
|
+
var PROTECTED_CATALOG_MODEL_IDS = new Set(
|
|
22016
|
+
AVAILABLE_MODELS.map((model) => model.id).filter((id) => id.length > 0)
|
|
22017
|
+
);
|
|
21832
22018
|
var CATALOG_MODEL_IDS_BY_PROVIDER = Object.fromEntries(
|
|
21833
22019
|
Object.entries(PROVIDER_MODELS).map(([provider, models]) => [
|
|
21834
22020
|
provider,
|
|
@@ -21919,15 +22105,22 @@ function extractModelIdsFromLabeledList(value2) {
|
|
|
21919
22105
|
}
|
|
21920
22106
|
function isValidClaudeModelId(id) {
|
|
21921
22107
|
if (CLAUDE_MODEL_ALIASES.includes(id)) return true;
|
|
21922
|
-
|
|
22108
|
+
const match = id.match(/^claude-(sonnet|opus|haiku|fable)-([a-z0-9][a-z0-9-]*)$/);
|
|
22109
|
+
if (!match) return false;
|
|
21923
22110
|
if (id.includes(".")) return false;
|
|
21924
22111
|
if (/-\d{8}$/.test(id)) return false;
|
|
21925
22112
|
if (/-v\d+$/.test(id)) return false;
|
|
22113
|
+
for (const segment of match[2].split("-")) {
|
|
22114
|
+
if (/^\d+$/.test(segment)) continue;
|
|
22115
|
+
if (CLAUDE_MODEL_QUALIFIER_SEGMENTS.has(segment)) continue;
|
|
22116
|
+
return false;
|
|
22117
|
+
}
|
|
21926
22118
|
return true;
|
|
21927
22119
|
}
|
|
21928
22120
|
function filterClaudePrefixModelIds(ids) {
|
|
21929
22121
|
const set = new Set(ids);
|
|
21930
22122
|
return ids.filter((id) => {
|
|
22123
|
+
if (PROTECTED_CATALOG_MODEL_IDS.has(id)) return true;
|
|
21931
22124
|
for (const other of set) {
|
|
21932
22125
|
if (other !== id && other.startsWith(`${id}-`)) return false;
|
|
21933
22126
|
}
|
|
@@ -22250,7 +22443,7 @@ var RunStartGate = class {
|
|
|
22250
22443
|
};
|
|
22251
22444
|
|
|
22252
22445
|
// src/version.ts
|
|
22253
|
-
var AGENT_VERSION = "0.1.
|
|
22446
|
+
var AGENT_VERSION = "0.1.40";
|
|
22254
22447
|
|
|
22255
22448
|
// src/workspace-relocation.ts
|
|
22256
22449
|
var import_node_child_process3 = require("child_process");
|