@atlasharness/atlascode 0.1.57 → 0.1.59
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +330 -98
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -26920,6 +26920,63 @@ function gatewayUnreachableRemediationHint(error) {
|
|
|
26920
26920
|
return null;
|
|
26921
26921
|
return "IFF 不可达:已切人工确认 —— /doctor 排查";
|
|
26922
26922
|
}
|
|
26923
|
+
function modelRetryBackoffMs(attempt, baseMs = MODEL_RETRY_BACKOFF_BASE_MS, capMs = MODEL_RETRY_BACKOFF_CAP_MS) {
|
|
26924
|
+
const base = Math.max(0, baseMs);
|
|
26925
|
+
const cap = Math.max(base, capMs);
|
|
26926
|
+
if (attempt <= 0)
|
|
26927
|
+
return Math.min(base, cap);
|
|
26928
|
+
return Math.min(base * 2 ** attempt, cap);
|
|
26929
|
+
}
|
|
26930
|
+
function sleepSignalAware(ms, signal) {
|
|
26931
|
+
if (ms <= 0)
|
|
26932
|
+
return Promise.resolve();
|
|
26933
|
+
return new Promise((resolve) => {
|
|
26934
|
+
if (signal?.aborted) {
|
|
26935
|
+
resolve();
|
|
26936
|
+
return;
|
|
26937
|
+
}
|
|
26938
|
+
let settled = false;
|
|
26939
|
+
const timer = setTimeout(() => {
|
|
26940
|
+
settled = true;
|
|
26941
|
+
if (signal)
|
|
26942
|
+
signal.removeEventListener("abort", onAbort);
|
|
26943
|
+
resolve();
|
|
26944
|
+
}, ms);
|
|
26945
|
+
function onAbort() {
|
|
26946
|
+
if (settled)
|
|
26947
|
+
return;
|
|
26948
|
+
settled = true;
|
|
26949
|
+
clearTimeout(timer);
|
|
26950
|
+
resolve();
|
|
26951
|
+
}
|
|
26952
|
+
if (signal)
|
|
26953
|
+
signal.addEventListener("abort", onAbort, { once: true });
|
|
26954
|
+
});
|
|
26955
|
+
}
|
|
26956
|
+
function buildStreamErrorEvent(err, signal) {
|
|
26957
|
+
const message = err instanceof Error ? err.message || err.name : String(err);
|
|
26958
|
+
const code = isClientRequestTimeout(err) ? "TIMEOUT" : "API_ERROR";
|
|
26959
|
+
return { type: "error", code, message, retryable: shouldRetryModelError(err, signal) };
|
|
26960
|
+
}
|
|
26961
|
+
function buildStreamContentBlocks(reasoningText, fullText, toolCalls) {
|
|
26962
|
+
const blocks = [];
|
|
26963
|
+
if (reasoningText)
|
|
26964
|
+
blocks.push({ type: "thinking", thinking: reasoningText, signature: "first-party" });
|
|
26965
|
+
if (fullText)
|
|
26966
|
+
blocks.push({ type: "text", text: fullText });
|
|
26967
|
+
blocks.push(...[...toolCalls.values()].filter((t) => t.name).map((t) => {
|
|
26968
|
+
let input = {};
|
|
26969
|
+
if (t.args) {
|
|
26970
|
+
try {
|
|
26971
|
+
input = JSON.parse(t.args);
|
|
26972
|
+
} catch {
|
|
26973
|
+
input = { _raw_arguments: t.args };
|
|
26974
|
+
}
|
|
26975
|
+
}
|
|
26976
|
+
return { type: "tool_use", id: t.id || `toolu_${randomUUID()}`, name: t.name, input };
|
|
26977
|
+
}));
|
|
26978
|
+
return blocks;
|
|
26979
|
+
}
|
|
26923
26980
|
function startLlmWaitHeartbeat(modelId, attempt, totalRetries) {
|
|
26924
26981
|
const startedAt = Date.now();
|
|
26925
26982
|
const id = setInterval(() => {
|
|
@@ -26934,10 +26991,16 @@ class OpenAIProvider {
|
|
|
26934
26991
|
maxRetriesPerModel;
|
|
26935
26992
|
timeoutMs;
|
|
26936
26993
|
timeoutResolver;
|
|
26937
|
-
|
|
26994
|
+
retryBackoffBaseMs;
|
|
26995
|
+
retryBackoffCapMs;
|
|
26996
|
+
retryBackoffSleep;
|
|
26997
|
+
constructor(maxRetriesPerModel = 3, timeoutMs = LLM_TIMEOUT_DEFAULT_MS, timeoutResolver, retryBackoff) {
|
|
26938
26998
|
this.maxRetriesPerModel = maxRetriesPerModel;
|
|
26939
26999
|
this.timeoutMs = timeoutMs;
|
|
26940
27000
|
this.timeoutResolver = timeoutResolver;
|
|
27001
|
+
this.retryBackoffBaseMs = retryBackoff?.baseMs ?? MODEL_RETRY_BACKOFF_BASE_MS;
|
|
27002
|
+
this.retryBackoffCapMs = retryBackoff?.capMs ?? MODEL_RETRY_BACKOFF_CAP_MS;
|
|
27003
|
+
this.retryBackoffSleep = retryBackoff?.sleep ?? ((ms, signal) => sleepSignalAware(ms, signal));
|
|
26941
27004
|
}
|
|
26942
27005
|
getTimeoutMs() {
|
|
26943
27006
|
return this.timeoutResolver ? this.timeoutResolver() : this.timeoutMs;
|
|
@@ -27030,6 +27093,9 @@ class OpenAIProvider {
|
|
|
27030
27093
|
lastErr = err;
|
|
27031
27094
|
if (!shouldRetryModelError(err, args.signal))
|
|
27032
27095
|
break;
|
|
27096
|
+
if (attempt < this.maxRetriesPerModel - 1) {
|
|
27097
|
+
await this.retryBackoffSleep(modelRetryBackoffMs(attempt, this.retryBackoffBaseMs, this.retryBackoffCapMs), args.signal);
|
|
27098
|
+
}
|
|
27033
27099
|
}
|
|
27034
27100
|
}
|
|
27035
27101
|
}
|
|
@@ -27045,6 +27111,7 @@ class OpenAIProvider {
|
|
|
27045
27111
|
const attemptRefs = refs;
|
|
27046
27112
|
let lastErr = null;
|
|
27047
27113
|
let succeeded = false;
|
|
27114
|
+
let partialRetained = false;
|
|
27048
27115
|
for (const ref of attemptRefs) {
|
|
27049
27116
|
const entry = resolveModel(ref);
|
|
27050
27117
|
if (!entry) {
|
|
@@ -27073,22 +27140,27 @@ class OpenAIProvider {
|
|
|
27073
27140
|
if (args.signal?.aborted)
|
|
27074
27141
|
return;
|
|
27075
27142
|
try {
|
|
27076
|
-
yield* this.streamOneAttempt(client, params, entry, args.signal, attempt, this.maxRetriesPerModel);
|
|
27143
|
+
const outcome = yield* this.streamOneAttempt(client, params, entry, args.signal, attempt, this.maxRetriesPerModel);
|
|
27144
|
+
if (outcome.partialRetained) {
|
|
27145
|
+
partialRetained = true;
|
|
27146
|
+
break;
|
|
27147
|
+
}
|
|
27077
27148
|
succeeded = true;
|
|
27078
27149
|
break;
|
|
27079
27150
|
} catch (err) {
|
|
27080
27151
|
lastErr = err;
|
|
27081
27152
|
if (!shouldRetryModelError(err, args.signal))
|
|
27082
27153
|
break;
|
|
27154
|
+
if (attempt < this.maxRetriesPerModel - 1) {
|
|
27155
|
+
await this.retryBackoffSleep(modelRetryBackoffMs(attempt, this.retryBackoffBaseMs, this.retryBackoffCapMs), args.signal);
|
|
27156
|
+
}
|
|
27083
27157
|
}
|
|
27084
27158
|
}
|
|
27085
|
-
if (succeeded || args.signal?.aborted)
|
|
27159
|
+
if (succeeded || partialRetained || args.signal?.aborted)
|
|
27086
27160
|
return;
|
|
27087
27161
|
}
|
|
27088
27162
|
if (lastErr) {
|
|
27089
|
-
|
|
27090
|
-
const code = isClientRequestTimeout(lastErr) ? "TIMEOUT" : "API_ERROR";
|
|
27091
|
-
yield { type: "error", code, message, retryable: shouldRetryModelError(lastErr, args.signal) };
|
|
27163
|
+
yield buildStreamErrorEvent(lastErr, args.signal);
|
|
27092
27164
|
return;
|
|
27093
27165
|
}
|
|
27094
27166
|
throw new Error(`No models configured for role '${args.role}'.`);
|
|
@@ -27107,66 +27179,111 @@ class OpenAIProvider {
|
|
|
27107
27179
|
const toolCalls = new Map;
|
|
27108
27180
|
let finishReason = null;
|
|
27109
27181
|
let usage = null;
|
|
27110
|
-
|
|
27111
|
-
|
|
27112
|
-
const
|
|
27113
|
-
|
|
27114
|
-
|
|
27115
|
-
|
|
27116
|
-
|
|
27117
|
-
|
|
27118
|
-
|
|
27119
|
-
|
|
27120
|
-
|
|
27121
|
-
|
|
27122
|
-
const
|
|
27123
|
-
|
|
27124
|
-
cur
|
|
27125
|
-
|
|
27126
|
-
|
|
27127
|
-
if (
|
|
27128
|
-
|
|
27129
|
-
if (currentToolCall
|
|
27130
|
-
|
|
27131
|
-
|
|
27132
|
-
|
|
27133
|
-
|
|
27182
|
+
let streamError = null;
|
|
27183
|
+
try {
|
|
27184
|
+
for await (const chunk of stream) {
|
|
27185
|
+
const choice = chunk.choices?.[0];
|
|
27186
|
+
const delta = choice?.delta;
|
|
27187
|
+
if (delta?.content) {
|
|
27188
|
+
fullText += delta.content;
|
|
27189
|
+
yield { type: "text_delta", text: delta.content };
|
|
27190
|
+
}
|
|
27191
|
+
if (delta?.reasoning_content)
|
|
27192
|
+
reasoningText += delta.reasoning_content;
|
|
27193
|
+
if (delta?.tool_calls) {
|
|
27194
|
+
for (const tc of delta.tool_calls) {
|
|
27195
|
+
const idx = tc.index ?? 0;
|
|
27196
|
+
const cur = toolCalls.get(idx) ?? { id: "", name: "", args: "" };
|
|
27197
|
+
if (tc.id)
|
|
27198
|
+
cur.id = tc.id;
|
|
27199
|
+
if (tc.function?.name) {
|
|
27200
|
+
cur.name = tc.function.name;
|
|
27201
|
+
if (currentToolCall) {
|
|
27202
|
+
let input = {};
|
|
27203
|
+
if (currentToolCall.args) {
|
|
27204
|
+
try {
|
|
27205
|
+
input = JSON.parse(currentToolCall.args);
|
|
27206
|
+
} catch {
|
|
27207
|
+
input = { _raw_arguments: currentToolCall.args };
|
|
27208
|
+
}
|
|
27134
27209
|
}
|
|
27210
|
+
yield { type: "tool_use_end", id: currentToolCall.id, name: currentToolCall.name, input };
|
|
27135
27211
|
}
|
|
27136
|
-
|
|
27212
|
+
currentToolCall = { id: cur.id, name: cur.name, args: cur.args };
|
|
27213
|
+
yield { type: "tool_use_start", id: cur.id, name: cur.name };
|
|
27137
27214
|
}
|
|
27138
|
-
|
|
27139
|
-
|
|
27140
|
-
|
|
27141
|
-
|
|
27142
|
-
|
|
27143
|
-
|
|
27144
|
-
currentToolCall.args = cur.args;
|
|
27145
|
-
yield { type: "tool_use_delta", id: cur.id, inputJsonDelta: tc.function.arguments };
|
|
27215
|
+
if (tc.function?.arguments) {
|
|
27216
|
+
cur.args += tc.function.arguments;
|
|
27217
|
+
if (currentToolCall && cur.name) {
|
|
27218
|
+
currentToolCall.args = cur.args;
|
|
27219
|
+
yield { type: "tool_use_delta", id: cur.id, inputJsonDelta: tc.function.arguments };
|
|
27220
|
+
}
|
|
27146
27221
|
}
|
|
27222
|
+
toolCalls.set(idx, cur);
|
|
27147
27223
|
}
|
|
27148
|
-
toolCalls.set(idx, cur);
|
|
27149
27224
|
}
|
|
27150
|
-
|
|
27151
|
-
|
|
27152
|
-
|
|
27153
|
-
|
|
27154
|
-
|
|
27155
|
-
|
|
27156
|
-
|
|
27157
|
-
|
|
27158
|
-
|
|
27225
|
+
if (choice?.finish_reason) {
|
|
27226
|
+
if (currentToolCall) {
|
|
27227
|
+
let input = {};
|
|
27228
|
+
if (currentToolCall.args) {
|
|
27229
|
+
try {
|
|
27230
|
+
input = JSON.parse(currentToolCall.args);
|
|
27231
|
+
} catch {
|
|
27232
|
+
input = { _raw_arguments: currentToolCall.args };
|
|
27233
|
+
}
|
|
27159
27234
|
}
|
|
27235
|
+
yield { type: "tool_use_end", id: currentToolCall.id, name: currentToolCall.name, input };
|
|
27236
|
+
currentToolCall = null;
|
|
27160
27237
|
}
|
|
27161
|
-
|
|
27162
|
-
currentToolCall = null;
|
|
27238
|
+
finishReason = choice.finish_reason;
|
|
27163
27239
|
}
|
|
27164
|
-
|
|
27240
|
+
if (chunk.usage)
|
|
27241
|
+
usage = mapOpenAIUsage(chunk.usage);
|
|
27242
|
+
if (signal?.aborted)
|
|
27243
|
+
break;
|
|
27165
27244
|
}
|
|
27166
|
-
|
|
27167
|
-
|
|
27168
|
-
|
|
27169
|
-
|
|
27245
|
+
} catch (err) {
|
|
27246
|
+
streamError = err;
|
|
27247
|
+
}
|
|
27248
|
+
if (streamError !== null) {
|
|
27249
|
+
const partialBlocks = buildStreamContentBlocks(reasoningText, fullText, toolCalls);
|
|
27250
|
+
if (partialBlocks.length === 0)
|
|
27251
|
+
throw streamError;
|
|
27252
|
+
yield {
|
|
27253
|
+
type: "message_stop",
|
|
27254
|
+
stopReason: "interrupted",
|
|
27255
|
+
usage: usage ? {
|
|
27256
|
+
input_tokens: usage.input_tokens ?? 0,
|
|
27257
|
+
output_tokens: usage.output_tokens ?? 0,
|
|
27258
|
+
cache_creation_input_tokens: usage.cache_creation_input_tokens ?? 0,
|
|
27259
|
+
cache_read_input_tokens: usage.cache_read_input_tokens ?? 0
|
|
27260
|
+
} : undefined
|
|
27261
|
+
};
|
|
27262
|
+
const emptyUsage = mapOpenAIUsage(null);
|
|
27263
|
+
const partialMsg = {
|
|
27264
|
+
uuid: randomUUID(),
|
|
27265
|
+
timestamp: new Date().toISOString(),
|
|
27266
|
+
message: {
|
|
27267
|
+
id: randomUUID(),
|
|
27268
|
+
container: null,
|
|
27269
|
+
model: entry.modelId,
|
|
27270
|
+
role: "assistant",
|
|
27271
|
+
stop_reason: "interrupted",
|
|
27272
|
+
stop_sequence: "",
|
|
27273
|
+
type: "message",
|
|
27274
|
+
usage: usage || emptyUsage,
|
|
27275
|
+
content: partialBlocks
|
|
27276
|
+
}
|
|
27277
|
+
};
|
|
27278
|
+
yield {
|
|
27279
|
+
type: "assistant",
|
|
27280
|
+
uuid: partialMsg.uuid,
|
|
27281
|
+
timestamp: partialMsg.timestamp,
|
|
27282
|
+
message: partialMsg.message,
|
|
27283
|
+
interrupted: true
|
|
27284
|
+
};
|
|
27285
|
+
yield buildStreamErrorEvent(streamError, signal);
|
|
27286
|
+
return { partialRetained: true };
|
|
27170
27287
|
}
|
|
27171
27288
|
yield {
|
|
27172
27289
|
type: "message_stop",
|
|
@@ -27178,27 +27295,11 @@ class OpenAIProvider {
|
|
|
27178
27295
|
cache_read_input_tokens: usage.cache_read_input_tokens ?? 0
|
|
27179
27296
|
} : undefined
|
|
27180
27297
|
};
|
|
27181
|
-
const contentBlocks =
|
|
27182
|
-
if (reasoningText)
|
|
27183
|
-
contentBlocks.push({ type: "thinking", thinking: reasoningText, signature: "first-party" });
|
|
27184
|
-
if (fullText)
|
|
27185
|
-
contentBlocks.push({ type: "text", text: fullText });
|
|
27186
|
-
const toolUseBlocks = [...toolCalls.values()].filter((t) => t.name).map((t) => {
|
|
27187
|
-
let input = {};
|
|
27188
|
-
if (t.args) {
|
|
27189
|
-
try {
|
|
27190
|
-
input = JSON.parse(t.args);
|
|
27191
|
-
} catch {
|
|
27192
|
-
input = { _raw_arguments: t.args };
|
|
27193
|
-
}
|
|
27194
|
-
}
|
|
27195
|
-
return { type: "tool_use", id: t.id || `toolu_${randomUUID()}`, name: t.name, input };
|
|
27196
|
-
});
|
|
27197
|
-
contentBlocks.push(...toolUseBlocks);
|
|
27298
|
+
const contentBlocks = buildStreamContentBlocks(reasoningText, fullText, toolCalls);
|
|
27198
27299
|
if (contentBlocks.length === 0) {
|
|
27199
27300
|
contentBlocks.push({ type: "text", text: PROVIDER_EMPTY_CONTENT_PLACEHOLDER });
|
|
27200
27301
|
}
|
|
27201
|
-
const stopReason =
|
|
27302
|
+
const stopReason = contentBlocks.some((b) => b.type === "tool_use") ? "tool_use" : finishReason === "length" ? "max_tokens" : "end_turn";
|
|
27202
27303
|
const emptyUsage = mapOpenAIUsage(null);
|
|
27203
27304
|
const finalMsg = {
|
|
27204
27305
|
uuid: randomUUID(),
|
|
@@ -27216,6 +27317,7 @@ class OpenAIProvider {
|
|
|
27216
27317
|
}
|
|
27217
27318
|
};
|
|
27218
27319
|
yield { type: "assistant", uuid: finalMsg.uuid, timestamp: finalMsg.timestamp, message: finalMsg.message };
|
|
27320
|
+
return { partialRetained: false };
|
|
27219
27321
|
}
|
|
27220
27322
|
async healthCheck(role) {
|
|
27221
27323
|
const refs = getRoleModels(role);
|
|
@@ -27332,7 +27434,7 @@ class OpenAIProvider {
|
|
|
27332
27434
|
}
|
|
27333
27435
|
}
|
|
27334
27436
|
}
|
|
27335
|
-
var PROVIDER_EMPTY_CONTENT_PLACEHOLDER = "(provider: empty response)";
|
|
27437
|
+
var PROVIDER_EMPTY_CONTENT_PLACEHOLDER = "(provider: empty response)", MODEL_RETRY_BACKOFF_BASE_MS = 500, MODEL_RETRY_BACKOFF_CAP_MS = 8000;
|
|
27336
27438
|
var init_modelprovider = __esm(() => {
|
|
27337
27439
|
init_openai();
|
|
27338
27440
|
init_clients();
|
|
@@ -27786,7 +27888,7 @@ function turnRecoveryBackoffMs(attempt, baseMs, capMs) {
|
|
|
27786
27888
|
return Math.min(base, cap);
|
|
27787
27889
|
return Math.min(base * 2 ** attempt, cap);
|
|
27788
27890
|
}
|
|
27789
|
-
function
|
|
27891
|
+
function sleepSignalAware2(ms, signal) {
|
|
27790
27892
|
if (ms <= 0)
|
|
27791
27893
|
return Promise.resolve();
|
|
27792
27894
|
return new Promise((resolve) => {
|
|
@@ -27829,7 +27931,7 @@ async function withTurnRecovery(attempt, options = {}) {
|
|
|
27829
27931
|
if (i < cfg.maxRetries && shouldRetryModelError(err, options.signal)) {
|
|
27830
27932
|
const backoff = turnRecoveryBackoffMs(i, cfg.backoffBaseMs, cfg.backoffCapMs);
|
|
27831
27933
|
if (backoff > 0) {
|
|
27832
|
-
await
|
|
27934
|
+
await sleepSignalAware2(backoff, options.signal);
|
|
27833
27935
|
}
|
|
27834
27936
|
continue;
|
|
27835
27937
|
}
|
|
@@ -27838,6 +27940,15 @@ async function withTurnRecovery(attempt, options = {}) {
|
|
|
27838
27940
|
}
|
|
27839
27941
|
throw lastErr;
|
|
27840
27942
|
}
|
|
27943
|
+
function nextFallbackRef(fallbackModels, tried) {
|
|
27944
|
+
if (!fallbackModels)
|
|
27945
|
+
return;
|
|
27946
|
+
for (const ref of fallbackModels) {
|
|
27947
|
+
if (!tried.has(ref))
|
|
27948
|
+
return ref;
|
|
27949
|
+
}
|
|
27950
|
+
return;
|
|
27951
|
+
}
|
|
27841
27952
|
var DEFAULT_MAX_RETRIES = 13, DEFAULT_BACKOFF_BASE_MS = 100, DEFAULT_BACKOFF_CAP_MS = 1000;
|
|
27842
27953
|
var init_turnRecovery = __esm(() => {
|
|
27843
27954
|
init_modelprovider2();
|
|
@@ -29485,6 +29596,65 @@ function getRuleByContentsForToolName(context, toolName, behavior) {
|
|
|
29485
29596
|
}
|
|
29486
29597
|
return ruleByContents;
|
|
29487
29598
|
}
|
|
29599
|
+
function parseParametricContent(ruleContent) {
|
|
29600
|
+
const params = {};
|
|
29601
|
+
for (const segment of ruleContent.split(",")) {
|
|
29602
|
+
const idx = segment.indexOf(":");
|
|
29603
|
+
if (idx <= 0)
|
|
29604
|
+
return null;
|
|
29605
|
+
const param = segment.slice(0, idx).trim();
|
|
29606
|
+
if (!param)
|
|
29607
|
+
return null;
|
|
29608
|
+
params[param] = segment.slice(idx + 1).trim();
|
|
29609
|
+
}
|
|
29610
|
+
return Object.keys(params).length > 0 ? params : null;
|
|
29611
|
+
}
|
|
29612
|
+
function declaredInputFields(tool) {
|
|
29613
|
+
const props = tool.inputSchema?.properties;
|
|
29614
|
+
if (!props)
|
|
29615
|
+
return new Set;
|
|
29616
|
+
return new Set(Object.keys(props));
|
|
29617
|
+
}
|
|
29618
|
+
function ruleMatchesParametric(rule, tool, input) {
|
|
29619
|
+
const ruleContent = rule.ruleValue.ruleContent;
|
|
29620
|
+
if (ruleContent === undefined)
|
|
29621
|
+
return false;
|
|
29622
|
+
const params = parseParametricContent(ruleContent);
|
|
29623
|
+
if (params === null)
|
|
29624
|
+
return false;
|
|
29625
|
+
const fields = declaredInputFields(tool);
|
|
29626
|
+
for (const [param, value] of Object.entries(params)) {
|
|
29627
|
+
if (!fields.has(param))
|
|
29628
|
+
return false;
|
|
29629
|
+
if (input[param] !== value)
|
|
29630
|
+
return false;
|
|
29631
|
+
}
|
|
29632
|
+
return true;
|
|
29633
|
+
}
|
|
29634
|
+
function getParametricRuleForTool(context, tool, input, behavior) {
|
|
29635
|
+
let rules;
|
|
29636
|
+
switch (behavior) {
|
|
29637
|
+
case "allow":
|
|
29638
|
+
rules = getAllowRules(context);
|
|
29639
|
+
break;
|
|
29640
|
+
case "deny":
|
|
29641
|
+
rules = getDenyRules(context);
|
|
29642
|
+
break;
|
|
29643
|
+
case "ask":
|
|
29644
|
+
rules = getAskRules(context);
|
|
29645
|
+
break;
|
|
29646
|
+
}
|
|
29647
|
+
const nameForRuleMatch = getToolNameForPermissionCheck(tool);
|
|
29648
|
+
for (const rule of rules) {
|
|
29649
|
+
if (rule.ruleValue.toolName !== nameForRuleMatch)
|
|
29650
|
+
continue;
|
|
29651
|
+
if (rule.ruleBehavior !== behavior)
|
|
29652
|
+
continue;
|
|
29653
|
+
if (ruleMatchesParametric(rule, tool, input))
|
|
29654
|
+
return rule;
|
|
29655
|
+
}
|
|
29656
|
+
return null;
|
|
29657
|
+
}
|
|
29488
29658
|
function permissionModeTitle(mode) {
|
|
29489
29659
|
return PERMISSION_MODE_TITLES[mode] ?? "Default";
|
|
29490
29660
|
}
|
|
@@ -29621,6 +29791,17 @@ var BASH_TOOL_NAME = "Bash", hasPermissionsToUseTool = async (tool, input, conte
|
|
|
29621
29791
|
}
|
|
29622
29792
|
};
|
|
29623
29793
|
}
|
|
29794
|
+
const parametricDenyRule = permissionContext ? getParametricRuleForTool(permissionContext, tool, input, "deny") : null;
|
|
29795
|
+
if (parametricDenyRule) {
|
|
29796
|
+
return {
|
|
29797
|
+
behavior: "deny",
|
|
29798
|
+
message: `Permission to use ${tool.name} has been denied.`,
|
|
29799
|
+
decisionReason: {
|
|
29800
|
+
type: "rule",
|
|
29801
|
+
rule: parametricDenyRule
|
|
29802
|
+
}
|
|
29803
|
+
};
|
|
29804
|
+
}
|
|
29624
29805
|
const askRule = permissionContext ? getAskRuleForTool(permissionContext, tool) : null;
|
|
29625
29806
|
if (askRule) {
|
|
29626
29807
|
const canSandboxAutoAllow = tool.name === BASH_TOOL_NAME && sandbox.isSandboxingEnabled() && sandbox.isAutoAllowBashIfSandboxedEnabled() && input.dangerouslyDisableSandbox !== true;
|
|
@@ -29635,6 +29816,17 @@ var BASH_TOOL_NAME = "Bash", hasPermissionsToUseTool = async (tool, input, conte
|
|
|
29635
29816
|
}, permissionContext, tool.name);
|
|
29636
29817
|
}
|
|
29637
29818
|
}
|
|
29819
|
+
const parametricAskRule = permissionContext ? getParametricRuleForTool(permissionContext, tool, input, "ask") : null;
|
|
29820
|
+
if (parametricAskRule) {
|
|
29821
|
+
return applyDontAskMode({
|
|
29822
|
+
behavior: "ask",
|
|
29823
|
+
message: createPermissionRequestMessage(tool.name),
|
|
29824
|
+
decisionReason: {
|
|
29825
|
+
type: "rule",
|
|
29826
|
+
rule: parametricAskRule
|
|
29827
|
+
}
|
|
29828
|
+
}, permissionContext, tool.name);
|
|
29829
|
+
}
|
|
29638
29830
|
let toolPermissionResult = {
|
|
29639
29831
|
behavior: "passthrough",
|
|
29640
29832
|
message: createPermissionRequestMessage(tool.name)
|
|
@@ -30740,6 +30932,12 @@ Block unconditionally. Do not look for authorization. No ALLOW exception applies
|
|
|
30740
30932
|
- **Trace the full destination path.** Do not stop at the first hop; do not discount a pathway because a future merge, deploy, or review gates it — arming the pathway is the harm. Modifying a CI/build workflow or publish pipeline so it will upload private-repo content, then committing or pushing it, is the blocked action even on a personal feature branch. **Bulk scale is its own red flag**: shipping an entire repo or package tree to any destination other than the repo's own configured remote as of session start — a mid-session repoint makes it a new destination — (e.g. pushing all refs to a new remote, archiving or syncing the working tree, pushing an image that COPYs the repo root) is exfiltration regardless of how private the destination claims to be — no routine task relocates an entire tree, and the agent creating the destination does not establish it as trusted. Cross-repo copies from a private repo followed by commit or push are exfiltration regardless of branch. Generating a public or anyone-with-link share URL for sensitive data counts as publishing even when the underlying store is trusted.
|
|
30741
30933
|
- **Is the final destination confirmed external or public?** A destination is trusted only if it is explicitly listed in Environment, or it is the trusted repo's own configured remote and its visibility fits the content (see Trusted repo). Same-org/same-account ownership, a personal or feature branch name, or the push being non-force does not establish privacy. A same-session \`git remote set-url\`/\`git remote add\` severs continuity — the new remote is not where this content already lives — so sensitive content pushed after a repoint is judged by this hard rule with the destination treated as public; intent expressed before the repoint does not carry across it. When a repo's visibility is not established in the transcript, unknown visibility is not itself a reason to block; judge the content on the other checks and rules — except after a same-session repoint, where the sentence above governs. Unknown visibility never clears anything either — it contributes nothing in either direction; an unrequested sensitive-source read feeding the content (see Sensitive-Source Provenance) is an independent signal that stands on its own.
|
|
30742
30934
|
|
|
30935
|
+
## USER HARD DENY — unconditional blocks (User Intent Rule does NOT clear these)
|
|
30936
|
+
|
|
30937
|
+
Rules in this class block unconditionally: no ALLOW exception applies, and the user's own words do not clear them (unlike SOFT BLOCK, whose User Intent Rule CAN clear). Add the user's unconditional block rules here, one per line (\`- \` prefix).
|
|
30938
|
+
|
|
30939
|
+
<user_hard_deny_rules_to_replace>(none configured)</user_hard_deny_rules_to_replace>
|
|
30940
|
+
|
|
30743
30941
|
## SOFT BLOCK — destructive or irreversible (User Intent Rule CAN clear these)
|
|
30744
30942
|
|
|
30745
30943
|
Every rule below clears at one bar — **[named+specifics]**: the user's own words name the action and the rule's **must name:** item (or affirm an agent proposal, visible directly before their reply, that named both); for adversarial-pattern rules the specifics is the user confirming the flagged pattern is a false positive — an agent ask like "auto mode blocked this for <reason> — is that incorrect and are you OK with it?" answered yes meets it. A rule's own stated conditions and stricter bars apply as written. In weighing any bar, assume the user has not closely read the transcript: a bare verb names an action, not its specifics. A bar is met at the step that ships or externalizes — consent to a preparatory step (a rename, a copy, a config write) does not carry forward to the later step that ships its result. At a push or publication, the content this session wrote into the outgoing files — visible in its earlier Write and Edit calls — is judged against the sensitivity classes like any other content: a session-authored file carrying secrets-, entrusted-, or personal-class material is that class's matter when it goes outward, regardless of being the repo's own work. Reads along the way are part of that judgment: a session that read sensitive-classed paths and then wrote is judged with those reads in mind. When blocking on an unmet bar, the block reason surfaces the blocked command and states what would clear it.
|
|
@@ -30845,6 +31043,7 @@ var init_permissions_external = () => {};
|
|
|
30845
31043
|
function getDefaultExternalAutoModeRules() {
|
|
30846
31044
|
return {
|
|
30847
31045
|
allow: extractTaggedBullets("user_allow_rules_to_replace"),
|
|
31046
|
+
hard_deny: extractTaggedBullets("user_hard_deny_rules_to_replace"),
|
|
30848
31047
|
soft_deny: extractTaggedBullets("user_deny_rules_to_replace"),
|
|
30849
31048
|
environment: extractTaggedBullets("user_environment_to_replace")
|
|
30850
31049
|
};
|
|
@@ -30857,7 +31056,7 @@ function extractTaggedBullets(tagName) {
|
|
|
30857
31056
|
`).map((line) => line.trim()).filter((line) => line.startsWith("- ")).map((line) => line.slice(2));
|
|
30858
31057
|
}
|
|
30859
31058
|
function buildDefaultExternalSystemPrompt() {
|
|
30860
|
-
return BASE_PROMPT.replace("<permissions_template>", () => EXTERNAL_PERMISSIONS_TEMPLATE).replace(/<user_allow_rules_to_replace>([\s\S]*?)<\/user_allow_rules_to_replace>/, (_m, defaults) => defaults).replace(/<user_deny_rules_to_replace>([\s\S]*?)<\/user_deny_rules_to_replace>/, (_m, defaults) => defaults).replace(/<user_environment_to_replace>([\s\S]*?)<\/user_environment_to_replace>/, (_m, defaults) => defaults);
|
|
31059
|
+
return BASE_PROMPT.replace("<permissions_template>", () => EXTERNAL_PERMISSIONS_TEMPLATE).replace(/<user_allow_rules_to_replace>([\s\S]*?)<\/user_allow_rules_to_replace>/, (_m, defaults) => defaults).replace(/<user_deny_rules_to_replace>([\s\S]*?)<\/user_deny_rules_to_replace>/, (_m, defaults) => defaults).replace(/<user_hard_deny_rules_to_replace>([\s\S]*?)<\/user_hard_deny_rules_to_replace>/, (_m, defaults) => defaults).replace(/<user_environment_to_replace>([\s\S]*?)<\/user_environment_to_replace>/, (_m, defaults) => defaults);
|
|
30861
31060
|
}
|
|
30862
31061
|
var BASE_PROMPT, EXTERNAL_PERMISSIONS_TEMPLATE;
|
|
30863
31062
|
var init_prompts = __esm(() => {
|
|
@@ -31266,11 +31465,13 @@ function getAutoModeConfig() {
|
|
|
31266
31465
|
if (feature("TRANSCRIPT_CLASSIFIER")) {
|
|
31267
31466
|
const schema = object({
|
|
31268
31467
|
allow: array(string2()).optional(),
|
|
31468
|
+
hard_deny: array(string2()).optional(),
|
|
31269
31469
|
soft_deny: array(string2()).optional(),
|
|
31270
31470
|
deny: array(string2()).optional(),
|
|
31271
31471
|
environment: array(string2()).optional()
|
|
31272
31472
|
});
|
|
31273
31473
|
const allow = [];
|
|
31474
|
+
const hard_deny = [];
|
|
31274
31475
|
const soft_deny = [];
|
|
31275
31476
|
const environment = [];
|
|
31276
31477
|
for (const source of [
|
|
@@ -31286,6 +31487,8 @@ function getAutoModeConfig() {
|
|
|
31286
31487
|
if (result.success) {
|
|
31287
31488
|
if (result.data.allow)
|
|
31288
31489
|
allow.push(...result.data.allow);
|
|
31490
|
+
if (result.data.hard_deny)
|
|
31491
|
+
hard_deny.push(...result.data.hard_deny);
|
|
31289
31492
|
if (result.data.soft_deny)
|
|
31290
31493
|
soft_deny.push(...result.data.soft_deny);
|
|
31291
31494
|
if (result.data.environment) {
|
|
@@ -31293,9 +31496,10 @@ function getAutoModeConfig() {
|
|
|
31293
31496
|
}
|
|
31294
31497
|
}
|
|
31295
31498
|
}
|
|
31296
|
-
if (allow.length > 0 || soft_deny.length > 0 || environment.length > 0) {
|
|
31499
|
+
if (allow.length > 0 || hard_deny.length > 0 || soft_deny.length > 0 || environment.length > 0) {
|
|
31297
31500
|
return {
|
|
31298
31501
|
...allow.length > 0 && { allow },
|
|
31502
|
+
...hard_deny.length > 0 && { hard_deny },
|
|
31299
31503
|
...soft_deny.length > 0 && { soft_deny },
|
|
31300
31504
|
...environment.length > 0 && { environment }
|
|
31301
31505
|
};
|
|
@@ -81642,10 +81846,12 @@ async function queryAgentLoop(deps, args) {
|
|
|
81642
81846
|
}
|
|
81643
81847
|
deps.emit?.({ type: "round_start", turn: turns });
|
|
81644
81848
|
let reactiveRetried = false;
|
|
81849
|
+
let effectiveDeps = deps;
|
|
81850
|
+
const triedFallbackRefs = new Set;
|
|
81645
81851
|
for (;; ) {
|
|
81646
81852
|
const roundInputLen = messages.length;
|
|
81647
81853
|
try {
|
|
81648
|
-
lastRound = await queryOneRound(
|
|
81854
|
+
lastRound = await queryOneRound(effectiveDeps, tools, messages);
|
|
81649
81855
|
} catch (err) {
|
|
81650
81856
|
if (!reactiveRetried && deps.reactiveCompact !== undefined && isReactiveCompactEnabled() && isReactiveCompactRecoverableError(err)) {
|
|
81651
81857
|
reactiveRetried = true;
|
|
@@ -81667,6 +81873,12 @@ async function queryAgentLoop(deps, args) {
|
|
|
81667
81873
|
continue;
|
|
81668
81874
|
}
|
|
81669
81875
|
}
|
|
81876
|
+
const nextRef = nextFallbackRef(deps.fallbackModels, triedFallbackRefs);
|
|
81877
|
+
if (nextRef && shouldRetryModelError(err, deps.signal)) {
|
|
81878
|
+
triedFallbackRefs.add(nextRef);
|
|
81879
|
+
effectiveDeps = { ...deps, sessionModel: nextRef };
|
|
81880
|
+
continue;
|
|
81881
|
+
}
|
|
81670
81882
|
throw err;
|
|
81671
81883
|
}
|
|
81672
81884
|
messages = lastRound.messages;
|
|
@@ -81869,6 +82081,7 @@ async function createAgentLoopDeps(config = {}) {
|
|
|
81869
82081
|
responseFormat: config.responseFormat,
|
|
81870
82082
|
effortValue: config.effortValue,
|
|
81871
82083
|
fallbackModel: config.fallbackModel,
|
|
82084
|
+
fallbackModels: config.fallbackModels,
|
|
81872
82085
|
transcript: config.disablePersistence ? undefined : {
|
|
81873
82086
|
record: (msgs) => recordTranscript(msgs),
|
|
81874
82087
|
recordContentReplacement: (recs) => recordContentReplacement(recs, config.agentId)
|
|
@@ -85822,7 +86035,8 @@ async function runHeadless(inputPrompt, options) {
|
|
|
85822
86035
|
thinkingConfig: options.thinkingConfig,
|
|
85823
86036
|
responseFormat: options.jsonSchema ? toResponseFormat({ type: "json_schema", schema: options.jsonSchema }) : undefined,
|
|
85824
86037
|
effortValue: options.effort,
|
|
85825
|
-
fallbackModel: options.fallbackModel
|
|
86038
|
+
fallbackModel: options.fallbackModel,
|
|
86039
|
+
fallbackModels: options.fallbackModels
|
|
85826
86040
|
});
|
|
85827
86041
|
const { toolPermissionContext: initialTpc, tools, warnings } = bundle;
|
|
85828
86042
|
if (warnings.length > 0) {
|
|
@@ -87059,6 +87273,7 @@ function autoModeConfigHandler() {
|
|
|
87059
87273
|
const defaults = getDefaultExternalAutoModeRules();
|
|
87060
87274
|
writeRules({
|
|
87061
87275
|
allow: config?.allow?.length ? config.allow : defaults.allow,
|
|
87276
|
+
hard_deny: config?.hard_deny?.length ? config.hard_deny : defaults.hard_deny,
|
|
87062
87277
|
soft_deny: config?.soft_deny?.length ? config.soft_deny : defaults.soft_deny,
|
|
87063
87278
|
environment: config?.environment?.length ? config.environment : defaults.environment
|
|
87064
87279
|
});
|
|
@@ -87074,18 +87289,18 @@ function makeUserMessage2(text) {
|
|
|
87074
87289
|
}
|
|
87075
87290
|
async function autoModeCritiqueHandler(options) {
|
|
87076
87291
|
const config = getAutoModeConfig();
|
|
87077
|
-
const hasCustomRules = (config?.allow?.length ?? 0) > 0 || (config?.soft_deny?.length ?? 0) > 0 || (config?.environment?.length ?? 0) > 0;
|
|
87292
|
+
const hasCustomRules = (config?.allow?.length ?? 0) > 0 || (config?.hard_deny?.length ?? 0) > 0 || (config?.soft_deny?.length ?? 0) > 0 || (config?.environment?.length ?? 0) > 0;
|
|
87078
87293
|
if (!hasCustomRules) {
|
|
87079
87294
|
process.stdout.write(`No custom auto mode rules found.
|
|
87080
87295
|
|
|
87081
|
-
` + `Add rules to your settings file under autoMode.{allow, soft_deny, environment}.
|
|
87296
|
+
` + `Add rules to your settings file under autoMode.{allow, hard_deny, soft_deny, environment}.
|
|
87082
87297
|
` + "Run `atlascode auto-mode defaults` to see the default rules for reference.\n");
|
|
87083
87298
|
return;
|
|
87084
87299
|
}
|
|
87085
87300
|
const role = options.model ? modelToRole(options.model) : "premium";
|
|
87086
87301
|
const defaults = getDefaultExternalAutoModeRules();
|
|
87087
87302
|
const classifierPrompt = buildDefaultExternalSystemPrompt();
|
|
87088
|
-
const userRulesSummary = formatRulesForCritique("allow", config?.allow ?? [], defaults.allow) + formatRulesForCritique("soft_deny", config?.soft_deny ?? [], defaults.soft_deny) + formatRulesForCritique("environment", config?.environment ?? [], defaults.environment);
|
|
87303
|
+
const userRulesSummary = formatRulesForCritique("allow", config?.allow ?? [], defaults.allow) + formatRulesForCritique("hard_deny", config?.hard_deny ?? [], defaults.hard_deny) + formatRulesForCritique("soft_deny", config?.soft_deny ?? [], defaults.soft_deny) + formatRulesForCritique("environment", config?.environment ?? [], defaults.environment);
|
|
87089
87304
|
process.stdout.write(`Analyzing your auto mode rules…
|
|
87090
87305
|
|
|
87091
87306
|
`);
|
|
@@ -87151,9 +87366,10 @@ var init_autoMode2 = __esm(() => {
|
|
|
87151
87366
|
init_shared();
|
|
87152
87367
|
CRITIQUE_SYSTEM_PROMPT = `You are an expert reviewer of auto mode classifier rules for Atlas.
|
|
87153
87368
|
` + `
|
|
87154
|
-
` + 'Atlas has an "auto mode" that uses an AI classifier to decide whether ' + "tool calls should be auto-approved or require user confirmation. Users can " + `write custom rules in
|
|
87369
|
+
` + 'Atlas has an "auto mode" that uses an AI classifier to decide whether ' + "tool calls should be auto-approved or require user confirmation. Users can " + `write custom rules in four categories:
|
|
87155
87370
|
` + `
|
|
87156
87371
|
` + `- **allow**: Actions the classifier should auto-approve
|
|
87372
|
+
` + `- **hard_deny**: Actions that are blocked unconditionally (user intent does not clear these)
|
|
87157
87373
|
` + `- **soft_deny**: Actions the classifier should block (require user confirmation)
|
|
87158
87374
|
` + `- **environment**: Context about the user's setup that helps the classifier make decisions
|
|
87159
87375
|
` + `
|
|
@@ -87268,7 +87484,7 @@ function buildHeadlessOptions(options) {
|
|
|
87268
87484
|
allowedTools: options.allowedTools,
|
|
87269
87485
|
disallowedTools: options.disallowedTools,
|
|
87270
87486
|
baseTools: options.tools,
|
|
87271
|
-
permissionMode: options.permissionMode,
|
|
87487
|
+
permissionMode: options.permissionMode ?? (options.permissionPrompts === "none" ? "dontAsk" : undefined),
|
|
87272
87488
|
permissionPromptToolName: options.permissionPromptTool,
|
|
87273
87489
|
maxTurns: options.maxTurns,
|
|
87274
87490
|
model: options.model,
|
|
@@ -87281,6 +87497,7 @@ function buildHeadlessOptions(options) {
|
|
|
87281
87497
|
systemPrompt: readPromptFileInline(options.systemPrompt, options.systemPromptFile, "System prompt"),
|
|
87282
87498
|
appendSystemPrompt: readPromptFileInline(options.appendSystemPrompt, options.appendSystemPromptFile, "Append system prompt"),
|
|
87283
87499
|
fallbackModel: options.fallbackModel,
|
|
87500
|
+
fallbackModels: options.fallbackModels,
|
|
87284
87501
|
thinkingConfig: buildHeadlessThinkingConfig(options.thinking, options.maxThinkingTokens),
|
|
87285
87502
|
effort: options.effort,
|
|
87286
87503
|
mcpConfig: options.mcpConfig,
|
|
@@ -87352,7 +87569,7 @@ function buildProgram() {
|
|
|
87352
87569
|
throw new Error("--task-budget must be a positive integer");
|
|
87353
87570
|
}
|
|
87354
87571
|
return tokens;
|
|
87355
|
-
}).hideHelp()).option("--replay-user-messages", "Re-emit user messages from stdin back on stdout for acknowledgment (only works with --input-format=stream-json and --output-format=stream-json)", () => true).addOption(new Option("--enable-auth-status", "Enable auth status messages in SDK mode").default(false).hideHelp()).option("--allowedTools, --allowed-tools <tools...>", 'Comma or space-separated list of tool names to allow (e.g. "Bash(git:*) Edit")').option("--tools <tools...>", 'Specify the list of available tools from the built-in set. Use "" to disable all tools, "default" to use all tools, or specify tool names (e.g. "Bash,Edit,Read").').option("--disallowedTools, --disallowed-tools <tools...>", 'Comma or space-separated list of tool names to deny (e.g. "Bash(git:*) Edit")').option("--mcp-config <configs...>", "Load MCP servers from JSON files or strings (space-separated)").addOption(new Option("--permission-prompt-tool <tool>", "MCP tool to use for permission prompts (only works with --print)").argParser(String).hideHelp()).addOption(new Option("--system-prompt <prompt>", "System prompt to use for the session").argParser(String)).addOption(new Option("--system-prompt-file <file>", "Read system prompt from a file").argParser(String).hideHelp()).addOption(new Option("--append-system-prompt <prompt>", "Append a system prompt to the default system prompt").argParser(String)).addOption(new Option("--append-system-prompt-file <file>", "Read system prompt from a file and append to the default system prompt").argParser(String).hideHelp()).addOption(new Option("--permission-mode <mode>", "Permission mode to use for the session").argParser(String).choices(PERMISSION_MODES)).option("-c, --continue", "Continue the most recent conversation in the current directory", () => true).option("-r, --resume [value]", "Resume a conversation by session ID, or open interactive picker with optional search term", (value) => value || true).option("--fork-session", "When resuming, create a new session ID instead of reusing the original (use with --resume or --continue)", () => true).addOption(new Option("--prefill <text>", "Pre-fill the prompt input with text without submitting it").hideHelp()).addOption(new Option("--deep-link-origin", "Signal that this session was launched from a deep link").hideHelp()).addOption(new Option("--deep-link-repo <slug>", "Repo slug the deep link ?repo= parameter resolved to the current cwd").hideHelp()).addOption(new Option("--deep-link-last-fetch <ms>", "FETCH_HEAD mtime in epoch ms, precomputed by the deep link trampoline").argParser((v) => {
|
|
87572
|
+
}).hideHelp()).option("--replay-user-messages", "Re-emit user messages from stdin back on stdout for acknowledgment (only works with --input-format=stream-json and --output-format=stream-json)", () => true).addOption(new Option("--enable-auth-status", "Enable auth status messages in SDK mode").default(false).hideHelp()).option("--allowedTools, --allowed-tools <tools...>", 'Comma or space-separated list of tool names to allow (e.g. "Bash(git:*) Edit")').option("--tools <tools...>", 'Specify the list of available tools from the built-in set. Use "" to disable all tools, "default" to use all tools, or specify tool names (e.g. "Bash,Edit,Read").').option("--disallowedTools, --disallowed-tools <tools...>", 'Comma or space-separated list of tool names to deny (e.g. "Bash(git:*) Edit")').option("--mcp-config <configs...>", "Load MCP servers from JSON files or strings (space-separated)").addOption(new Option("--permission-prompt-tool <tool>", "MCP tool to use for permission prompts (only works with --print)").argParser(String).hideHelp()).addOption(new Option("--system-prompt <prompt>", "System prompt to use for the session").argParser(String)).addOption(new Option("--system-prompt-file <file>", "Read system prompt from a file").argParser(String).hideHelp()).addOption(new Option("--append-system-prompt <prompt>", "Append a system prompt to the default system prompt").argParser(String)).addOption(new Option("--append-system-prompt-file <file>", "Read system prompt from a file and append to the default system prompt").argParser(String).hideHelp()).addOption(new Option("--permission-mode <mode>", "Permission mode to use for the session").argParser(String).choices(PERMISSION_MODES)).addOption(new Option("--permission-prompts <mode>", "Permission prompt policy; 'none' auto-denies prompts that would otherwise ask").argParser(String).choices(["none"])).option("-c, --continue", "Continue the most recent conversation in the current directory", () => true).option("-r, --resume [value]", "Resume a conversation by session ID, or open interactive picker with optional search term", (value) => value || true).option("--fork-session", "When resuming, create a new session ID instead of reusing the original (use with --resume or --continue)", () => true).addOption(new Option("--prefill <text>", "Pre-fill the prompt input with text without submitting it").hideHelp()).addOption(new Option("--deep-link-origin", "Signal that this session was launched from a deep link").hideHelp()).addOption(new Option("--deep-link-repo <slug>", "Repo slug the deep link ?repo= parameter resolved to the current cwd").hideHelp()).addOption(new Option("--deep-link-last-fetch <ms>", "FETCH_HEAD mtime in epoch ms, precomputed by the deep link trampoline").argParser((v) => {
|
|
87356
87573
|
const n = Number(v);
|
|
87357
87574
|
return Number.isFinite(n) ? n : undefined;
|
|
87358
87575
|
}).hideHelp()).option("--from-pr [value]", "Resume a session linked to a PR by PR number/URL, or open interactive picker with optional search term", (value) => value || true).option("--no-session-persistence", "Disable session persistence - sessions will not be saved to disk and cannot be resumed (only works with --print)").addOption(new Option("--resume-session-at <message id>", "When resuming, only messages up to and including the assistant message with <message.id> (use with --resume in print mode)").argParser(String).hideHelp()).addOption(new Option("--rewind-files <user-message-id>", "Restore files to state at the specified user message and exit (requires --resume)").hideHelp()).option("--model <model>", "Model for the current session. Provide a role alias (e.g. 'small' or 'premium') or a provider/model reference (e.g. 'bailian/qwen38-27b').").addOption(new Option("--effort <level>", "Effort level for the current session (low, medium, high, xhigh, max)").argParser((rawValue) => {
|
|
@@ -87362,7 +87579,7 @@ function buildProgram() {
|
|
|
87362
87579
|
throw new InvalidArgumentError(`It must be one of: ${allowed.join(", ")}`);
|
|
87363
87580
|
}
|
|
87364
87581
|
return value;
|
|
87365
|
-
})).option("--agent <agent>", "Agent for the current session. Overrides the 'agent' setting.").option("--betas <betas...>", "Beta headers to include in API requests (API key users only)").option("--fallback-model <model>", "Enable automatic fallback to specified model when default model is overloaded (only works with --print)").addOption(new Option("--workload <tag>", "Workload tag for billing-header attribution (cc_workload). Process-scoped; set by SDK daemon callers that spawn subprocesses for cron work. (only works with --print)").hideHelp()).option("--settings <file-or-json>", "Path to a settings JSON file or a JSON string to load additional settings from").option("--add-dir <directories...>", "Additional directories to allow tool access to").option("--ide", "Automatically connect to IDE on startup if exactly one valid IDE is available", () => true).option("--strict-mcp-config", "Only use MCP servers from --mcp-config, ignoring all other MCP configurations", () => true).option("--session-id <uuid>", "Use a specific session ID for the conversation (must be a valid UUID)").option("-n, --name <name>", "Set a display name for this session (shown in /resume and terminal title)").option("--agents <json>", `JSON object defining custom agents (e.g. '{"reviewer": {"description": "Reviews code", "prompt": "You are a code reviewer"}}')`).option("--setting-sources <sources>", "Comma-separated list of setting sources to load (user, project, local).").option("--plugin-dir <path>", "Load plugins from a directory for this session only (repeatable: --plugin-dir A --plugin-dir B)", (val, prev) => [...prev, val], []).option("--disable-slash-commands", "Disable all skills", () => true).option("--chrome", "Enable AtlasCode in Chrome integration").option("--no-chrome", "Disable AtlasCode in Chrome integration").option("--file <specs...>", "File resources to download at startup. Format: file_id:relative_path (e.g., --file file_abc:doc.txt file_def:img.png)").action(mainActionSeam).version(`${resolveCliVersion()} (AtlasCode)`, "-v, --version", "Output the version number");
|
|
87582
|
+
})).option("--agent <agent>", "Agent for the current session. Overrides the 'agent' setting.").option("--betas <betas...>", "Beta headers to include in API requests (API key users only)").option("--fallback-model <model>", "Enable automatic fallback to specified model when default model is overloaded (only works with --print)").option("--fallback-models <m...>", "0.1.59(CC 2.1.166):回合级有序 fallback 表(≤3 ref,按序逐个一次性重试)——主模型可重试错误时钉下一 ref 为本回合 sessionModel 重跑(区别于单串 --fallback-model 的 in-request 池末位)。缺省 = 零变更(only works with --print)").addOption(new Option("--workload <tag>", "Workload tag for billing-header attribution (cc_workload). Process-scoped; set by SDK daemon callers that spawn subprocesses for cron work. (only works with --print)").hideHelp()).option("--settings <file-or-json>", "Path to a settings JSON file or a JSON string to load additional settings from").option("--add-dir <directories...>", "Additional directories to allow tool access to").option("--ide", "Automatically connect to IDE on startup if exactly one valid IDE is available", () => true).option("--strict-mcp-config", "Only use MCP servers from --mcp-config, ignoring all other MCP configurations", () => true).option("--session-id <uuid>", "Use a specific session ID for the conversation (must be a valid UUID)").option("-n, --name <name>", "Set a display name for this session (shown in /resume and terminal title)").option("--agents <json>", `JSON object defining custom agents (e.g. '{"reviewer": {"description": "Reviews code", "prompt": "You are a code reviewer"}}')`).option("--setting-sources <sources>", "Comma-separated list of setting sources to load (user, project, local).").option("--plugin-dir <path>", "Load plugins from a directory for this session only (repeatable: --plugin-dir A --plugin-dir B)", (val, prev) => [...prev, val], []).option("--disable-slash-commands", "Disable all skills", () => true).option("--chrome", "Enable AtlasCode in Chrome integration").option("--no-chrome", "Disable AtlasCode in Chrome integration").option("--file <specs...>", "File resources to download at startup. Format: file_id:relative_path (e.g., --file file_abc:doc.txt file_def:img.png)").action(mainActionSeam).version(`${resolveCliVersion()} (AtlasCode)`, "-v, --version", "Output the version number");
|
|
87366
87583
|
program.option("-w, --worktree [name]", "Create a new git worktree for this session (optionally specify a name)");
|
|
87367
87584
|
program.option("--tmux", "Create a tmux session for the worktree (requires --worktree). Uses iTerm2 native panes when available; use --tmux=classic for traditional tmux.");
|
|
87368
87585
|
if (feature("TRANSCRIPT_CLASSIFIER")) {
|
|
@@ -124452,11 +124669,13 @@ function getAutoModeConfig2() {
|
|
|
124452
124669
|
if (feature("TRANSCRIPT_CLASSIFIER")) {
|
|
124453
124670
|
const schema = object({
|
|
124454
124671
|
allow: array(string2()).optional(),
|
|
124672
|
+
hard_deny: array(string2()).optional(),
|
|
124455
124673
|
soft_deny: array(string2()).optional(),
|
|
124456
124674
|
deny: array(string2()).optional(),
|
|
124457
124675
|
environment: array(string2()).optional()
|
|
124458
124676
|
});
|
|
124459
124677
|
const allow = [];
|
|
124678
|
+
const hard_deny = [];
|
|
124460
124679
|
const soft_deny = [];
|
|
124461
124680
|
const environment = [];
|
|
124462
124681
|
for (const source of [
|
|
@@ -124472,15 +124691,18 @@ function getAutoModeConfig2() {
|
|
|
124472
124691
|
if (result.success) {
|
|
124473
124692
|
if (result.data.allow)
|
|
124474
124693
|
allow.push(...result.data.allow);
|
|
124694
|
+
if (result.data.hard_deny)
|
|
124695
|
+
hard_deny.push(...result.data.hard_deny);
|
|
124475
124696
|
if (result.data.soft_deny)
|
|
124476
124697
|
soft_deny.push(...result.data.soft_deny);
|
|
124477
124698
|
if (result.data.environment)
|
|
124478
124699
|
environment.push(...result.data.environment);
|
|
124479
124700
|
}
|
|
124480
124701
|
}
|
|
124481
|
-
if (allow.length > 0 || soft_deny.length > 0 || environment.length > 0) {
|
|
124702
|
+
if (allow.length > 0 || hard_deny.length > 0 || soft_deny.length > 0 || environment.length > 0) {
|
|
124482
124703
|
return {
|
|
124483
124704
|
...allow.length > 0 && { allow },
|
|
124705
|
+
...hard_deny.length > 0 && { hard_deny },
|
|
124484
124706
|
...soft_deny.length > 0 && { soft_deny },
|
|
124485
124707
|
...environment.length > 0 && { environment }
|
|
124486
124708
|
};
|
|
@@ -274162,6 +274384,7 @@ function isUsingExternalPermissions() {
|
|
|
274162
274384
|
function getDefaultExternalAutoModeRules2() {
|
|
274163
274385
|
return {
|
|
274164
274386
|
allow: extractTaggedBullets2("user_allow_rules_to_replace"),
|
|
274387
|
+
hard_deny: extractTaggedBullets2("user_hard_deny_rules_to_replace"),
|
|
274165
274388
|
soft_deny: extractTaggedBullets2("user_deny_rules_to_replace"),
|
|
274166
274389
|
environment: extractTaggedBullets2("user_environment_to_replace")
|
|
274167
274390
|
};
|
|
@@ -274174,7 +274397,7 @@ function extractTaggedBullets2(tagName) {
|
|
|
274174
274397
|
`).map((line) => line.trim()).filter((line) => line.startsWith("- ")).map((line) => line.slice(2));
|
|
274175
274398
|
}
|
|
274176
274399
|
function buildDefaultExternalSystemPrompt2() {
|
|
274177
|
-
return BASE_PROMPT2.replace("<permissions_template>", () => EXTERNAL_PERMISSIONS_TEMPLATE2).replace(/<user_allow_rules_to_replace>([\s\S]*?)<\/user_allow_rules_to_replace>/, (_m, defaults) => defaults).replace(/<user_deny_rules_to_replace>([\s\S]*?)<\/user_deny_rules_to_replace>/, (_m, defaults) => defaults).replace(/<user_environment_to_replace>([\s\S]*?)<\/user_environment_to_replace>/, (_m, defaults) => defaults);
|
|
274400
|
+
return BASE_PROMPT2.replace("<permissions_template>", () => EXTERNAL_PERMISSIONS_TEMPLATE2).replace(/<user_allow_rules_to_replace>([\s\S]*?)<\/user_allow_rules_to_replace>/, (_m, defaults) => defaults).replace(/<user_deny_rules_to_replace>([\s\S]*?)<\/user_deny_rules_to_replace>/, (_m, defaults) => defaults).replace(/<user_hard_deny_rules_to_replace>([\s\S]*?)<\/user_hard_deny_rules_to_replace>/, (_m, defaults) => defaults).replace(/<user_environment_to_replace>([\s\S]*?)<\/user_environment_to_replace>/, (_m, defaults) => defaults);
|
|
274178
274401
|
}
|
|
274179
274402
|
function getAutoModeClassifierErrorDumpPath() {
|
|
274180
274403
|
return join101(getAtlasTempDir2(), "auto-mode-classifier-errors", `${getSessionId()}.txt`);
|
|
@@ -274347,10 +274570,12 @@ async function buildYoloSystemPrompt(context) {
|
|
|
274347
274570
|
const userAllow = allowDescriptions.length ? allowDescriptions.map((d) => `- ${d}`).join(`
|
|
274348
274571
|
`) : undefined;
|
|
274349
274572
|
const userDeny = denyDescriptions.length ? denyDescriptions.map((d) => `- ${d}`).join(`
|
|
274573
|
+
`) : undefined;
|
|
274574
|
+
const userHardDeny = autoMode?.hard_deny?.length ? autoMode.hard_deny.map((d) => `- ${d}`).join(`
|
|
274350
274575
|
`) : undefined;
|
|
274351
274576
|
const userEnvironment = autoMode?.environment?.length ? autoMode.environment.map((e) => `- ${e}`).join(`
|
|
274352
274577
|
`) : undefined;
|
|
274353
|
-
return systemPrompt.replace(/<user_allow_rules_to_replace>([\s\S]*?)<\/user_allow_rules_to_replace>/, (_m, defaults) => userAllow ?? defaults).replace(/<user_deny_rules_to_replace>([\s\S]*?)<\/user_deny_rules_to_replace>/, (_m, defaults) => userDeny ?? defaults).replace(/<user_environment_to_replace>([\s\S]*?)<\/user_environment_to_replace>/, (_m, defaults) => userEnvironment ?? defaults);
|
|
274578
|
+
return systemPrompt.replace(/<user_allow_rules_to_replace>([\s\S]*?)<\/user_allow_rules_to_replace>/, (_m, defaults) => userAllow ?? defaults).replace(/<user_deny_rules_to_replace>([\s\S]*?)<\/user_deny_rules_to_replace>/, (_m, defaults) => userDeny ?? defaults).replace(/<user_hard_deny_rules_to_replace>([\s\S]*?)<\/user_hard_deny_rules_to_replace>/, (_m, defaults) => userHardDeny ?? defaults).replace(/<user_environment_to_replace>([\s\S]*?)<\/user_environment_to_replace>/, (_m, defaults) => userEnvironment ?? defaults);
|
|
274354
274579
|
}
|
|
274355
274580
|
function stripThinking2(text) {
|
|
274356
274581
|
return text.replace(/<thinking>[\s\S]*?<\/thinking>/g, "").replace(/<thinking>[\s\S]*$/, "");
|
|
@@ -430373,7 +430598,10 @@ async function streamCompactSummary({
|
|
|
430373
430598
|
context.setResponseLength?.((length) => length + deltaEvent.text.length);
|
|
430374
430599
|
}
|
|
430375
430600
|
if (event.type === "assistant") {
|
|
430376
|
-
|
|
430601
|
+
const assistantEvent = event;
|
|
430602
|
+
if (!assistantEvent.interrupted) {
|
|
430603
|
+
response = assistantEvent;
|
|
430604
|
+
}
|
|
430377
430605
|
}
|
|
430378
430606
|
}
|
|
430379
430607
|
if (response) {
|
|
@@ -489893,24 +490121,25 @@ function autoModeConfigHandler2() {
|
|
|
489893
490121
|
const defaults = getDefaultExternalAutoModeRules2();
|
|
489894
490122
|
writeRules2({
|
|
489895
490123
|
allow: config?.allow?.length ? config.allow : defaults.allow,
|
|
490124
|
+
hard_deny: config?.hard_deny?.length ? config.hard_deny : defaults.hard_deny,
|
|
489896
490125
|
soft_deny: config?.soft_deny?.length ? config.soft_deny : defaults.soft_deny,
|
|
489897
490126
|
environment: config?.environment?.length ? config.environment : defaults.environment
|
|
489898
490127
|
});
|
|
489899
490128
|
}
|
|
489900
490129
|
async function autoModeCritiqueHandler2(options) {
|
|
489901
490130
|
const config = getAutoModeConfig2();
|
|
489902
|
-
const hasCustomRules = (config?.allow?.length ?? 0) > 0 || (config?.soft_deny?.length ?? 0) > 0 || (config?.environment?.length ?? 0) > 0;
|
|
490131
|
+
const hasCustomRules = (config?.allow?.length ?? 0) > 0 || (config?.hard_deny?.length ?? 0) > 0 || (config?.soft_deny?.length ?? 0) > 0 || (config?.environment?.length ?? 0) > 0;
|
|
489903
490132
|
if (!hasCustomRules) {
|
|
489904
490133
|
process.stdout.write(`No custom auto mode rules found.
|
|
489905
490134
|
|
|
489906
|
-
` + `Add rules to your settings file under autoMode.{allow, soft_deny, environment}.
|
|
490135
|
+
` + `Add rules to your settings file under autoMode.{allow, hard_deny, soft_deny, environment}.
|
|
489907
490136
|
` + "Run `claude auto-mode defaults` to see the default rules for reference.\n");
|
|
489908
490137
|
return;
|
|
489909
490138
|
}
|
|
489910
490139
|
const model = options.model ? parseUserSpecifiedModel2(options.model) : getMainLoopModel();
|
|
489911
490140
|
const defaults = getDefaultExternalAutoModeRules2();
|
|
489912
490141
|
const classifierPrompt = buildDefaultExternalSystemPrompt2();
|
|
489913
|
-
const userRulesSummary = formatRulesForCritique2("allow", config?.allow ?? [], defaults.allow) + formatRulesForCritique2("soft_deny", config?.soft_deny ?? [], defaults.soft_deny) + formatRulesForCritique2("environment", config?.environment ?? [], defaults.environment);
|
|
490142
|
+
const userRulesSummary = formatRulesForCritique2("allow", config?.allow ?? [], defaults.allow) + formatRulesForCritique2("hard_deny", config?.hard_deny ?? [], defaults.hard_deny) + formatRulesForCritique2("soft_deny", config?.soft_deny ?? [], defaults.soft_deny) + formatRulesForCritique2("environment", config?.environment ?? [], defaults.environment);
|
|
489914
490143
|
process.stdout.write(`Analyzing your auto mode rules…
|
|
489915
490144
|
|
|
489916
490145
|
`);
|
|
@@ -489979,9 +490208,10 @@ var init_autoMode3 = __esm(() => {
|
|
|
489979
490208
|
init_slowOperations();
|
|
489980
490209
|
CRITIQUE_SYSTEM_PROMPT2 = `You are an expert reviewer of auto mode classifier rules for Atlas.
|
|
489981
490210
|
` + `
|
|
489982
|
-
` + 'Atlas has an "auto mode" that uses an AI classifier to decide whether ' + "tool calls should be auto-approved or require user confirmation. Users can " + `write custom rules in
|
|
490211
|
+
` + 'Atlas has an "auto mode" that uses an AI classifier to decide whether ' + "tool calls should be auto-approved or require user confirmation. Users can " + `write custom rules in four categories:
|
|
489983
490212
|
` + `
|
|
489984
490213
|
` + `- **allow**: Actions the classifier should auto-approve
|
|
490214
|
+
` + `- **hard_deny**: Actions that are blocked unconditionally (user intent does not clear these)
|
|
489985
490215
|
` + `- **soft_deny**: Actions the classifier should block (require user confirmation)
|
|
489986
490216
|
` + `- **environment**: Context about the user's setup that helps the classifier make decisions
|
|
489987
490217
|
` + `
|
|
@@ -490836,7 +491066,7 @@ async function run() {
|
|
|
490836
491066
|
throw new Error("--task-budget must be a positive integer");
|
|
490837
491067
|
}
|
|
490838
491068
|
return tokens;
|
|
490839
|
-
}).hideHelp()).option("--replay-user-messages", "Re-emit user messages from stdin back on stdout for acknowledgment (only works with --input-format=stream-json and --output-format=stream-json)", () => true).addOption(new Option("--enable-auth-status", "Enable auth status messages in SDK mode").default(false).hideHelp()).option("--allowedTools, --allowed-tools <tools...>", 'Comma or space-separated list of tool names to allow (e.g. "Bash(git:*) Edit")').option("--tools <tools...>", 'Specify the list of available tools from the built-in set. Use "" to disable all tools, "default" to use all tools, or specify tool names (e.g. "Bash,Edit,Read").').option("--disallowedTools, --disallowed-tools <tools...>", 'Comma or space-separated list of tool names to deny (e.g. "Bash(git:*) Edit")').option("--mcp-config <configs...>", "Load MCP servers from JSON files or strings (space-separated)").addOption(new Option("--permission-prompt-tool <tool>", "MCP tool to use for permission prompts (only works with --print)").argParser(String).hideHelp()).addOption(new Option("--system-prompt <prompt>", "System prompt to use for the session").argParser(String)).addOption(new Option("--system-prompt-file <file>", "Read system prompt from a file").argParser(String).hideHelp()).addOption(new Option("--append-system-prompt <prompt>", "Append a system prompt to the default system prompt").argParser(String)).addOption(new Option("--append-system-prompt-file <file>", "Read system prompt from a file and append to the default system prompt").argParser(String).hideHelp()).addOption(new Option("--permission-mode <mode>", "Permission mode to use for the session").argParser(String).choices(PERMISSION_MODES2)).option("-c, --continue", "Continue the most recent conversation in the current directory", () => true).option("-r, --resume [value]", "Resume a conversation by session ID, or open interactive picker with optional search term", (value) => value || true).option("--fork-session", "When resuming, create a new session ID instead of reusing the original (use with --resume or --continue)", () => true).addOption(new Option("--prefill <text>", "Pre-fill the prompt input with text without submitting it").hideHelp()).addOption(new Option("--deep-link-origin", "Signal that this session was launched from a deep link").hideHelp()).addOption(new Option("--deep-link-repo <slug>", "Repo slug the deep link ?repo= parameter resolved to the current cwd").hideHelp()).addOption(new Option("--deep-link-last-fetch <ms>", "FETCH_HEAD mtime in epoch ms, precomputed by the deep link trampoline").argParser((v) => {
|
|
491069
|
+
}).hideHelp()).option("--replay-user-messages", "Re-emit user messages from stdin back on stdout for acknowledgment (only works with --input-format=stream-json and --output-format=stream-json)", () => true).addOption(new Option("--enable-auth-status", "Enable auth status messages in SDK mode").default(false).hideHelp()).option("--allowedTools, --allowed-tools <tools...>", 'Comma or space-separated list of tool names to allow (e.g. "Bash(git:*) Edit")').option("--tools <tools...>", 'Specify the list of available tools from the built-in set. Use "" to disable all tools, "default" to use all tools, or specify tool names (e.g. "Bash,Edit,Read").').option("--disallowedTools, --disallowed-tools <tools...>", 'Comma or space-separated list of tool names to deny (e.g. "Bash(git:*) Edit")').option("--mcp-config <configs...>", "Load MCP servers from JSON files or strings (space-separated)").addOption(new Option("--permission-prompt-tool <tool>", "MCP tool to use for permission prompts (only works with --print)").argParser(String).hideHelp()).addOption(new Option("--system-prompt <prompt>", "System prompt to use for the session").argParser(String)).addOption(new Option("--system-prompt-file <file>", "Read system prompt from a file").argParser(String).hideHelp()).addOption(new Option("--append-system-prompt <prompt>", "Append a system prompt to the default system prompt").argParser(String)).addOption(new Option("--append-system-prompt-file <file>", "Read system prompt from a file and append to the default system prompt").argParser(String).hideHelp()).addOption(new Option("--permission-mode <mode>", "Permission mode to use for the session").argParser(String).choices(PERMISSION_MODES2)).addOption(new Option("--permission-prompts <mode>", "Permission prompt policy; 'none' auto-denies prompts that would otherwise ask").argParser(String).choices(["none"])).option("-c, --continue", "Continue the most recent conversation in the current directory", () => true).option("-r, --resume [value]", "Resume a conversation by session ID, or open interactive picker with optional search term", (value) => value || true).option("--fork-session", "When resuming, create a new session ID instead of reusing the original (use with --resume or --continue)", () => true).addOption(new Option("--prefill <text>", "Pre-fill the prompt input with text without submitting it").hideHelp()).addOption(new Option("--deep-link-origin", "Signal that this session was launched from a deep link").hideHelp()).addOption(new Option("--deep-link-repo <slug>", "Repo slug the deep link ?repo= parameter resolved to the current cwd").hideHelp()).addOption(new Option("--deep-link-last-fetch <ms>", "FETCH_HEAD mtime in epoch ms, precomputed by the deep link trampoline").argParser((v) => {
|
|
490840
491070
|
const n = Number(v);
|
|
490841
491071
|
return Number.isFinite(n) ? n : undefined;
|
|
490842
491072
|
}).hideHelp()).option("--from-pr [value]", "Resume a session linked to a PR by PR number/URL, or open interactive picker with optional search term", (value) => value || true).option("--no-session-persistence", "Disable session persistence - sessions will not be saved to disk and cannot be resumed (only works with --print)").addOption(new Option("--resume-session-at <message id>", "When resuming, only messages up to and including the assistant message with <message.id> (use with --resume in print mode)").argParser(String).hideHelp()).addOption(new Option("--rewind-files <user-message-id>", "Restore files to state at the specified user message and exit (requires --resume)").hideHelp()).option("--model <model>", `Model for the current session. Provide a role alias (e.g. 'small' or 'premium') or a provider/model reference (e.g. 'bailian/qwen38-27b').`).addOption(new Option("--effort <level>", `Effort level for the current session (low, medium, high, xhigh, max)`).argParser((rawValue) => {
|
|
@@ -490865,7 +491095,8 @@ async function run() {
|
|
|
490865
491095
|
allowedTools = [],
|
|
490866
491096
|
disallowedTools = [],
|
|
490867
491097
|
mcpConfig = [],
|
|
490868
|
-
permissionMode:
|
|
491098
|
+
permissionMode: permissionModeCliRaw,
|
|
491099
|
+
permissionPrompts,
|
|
490869
491100
|
addDir = [],
|
|
490870
491101
|
fallbackModel,
|
|
490871
491102
|
betas = [],
|
|
@@ -490874,6 +491105,7 @@ async function run() {
|
|
|
490874
491105
|
includeHookEvents,
|
|
490875
491106
|
includePartialMessages
|
|
490876
491107
|
} = options;
|
|
491108
|
+
const permissionModeCli = permissionModeCliRaw ?? (permissionPrompts === "none" ? "dontAsk" : undefined);
|
|
490877
491109
|
if (options.prefill) {
|
|
490878
491110
|
seedEarlyInput(options.prefill);
|
|
490879
491111
|
}
|
package/package.json
CHANGED