@wrongstack/core 0.292.0 → 0.293.0
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/coordination/index.d.ts +1 -1
- package/dist/coordination/index.d.ts.map +1 -1
- package/dist/coordination/index.js +163 -39
- package/dist/coordination/index.js.map +3 -3
- package/dist/coordination/mailbox-http-router.d.ts +38 -0
- package/dist/coordination/mailbox-http-router.d.ts.map +1 -1
- package/dist/coordination/provider-status-tracker.d.ts.map +1 -1
- package/dist/core/fallback-model.d.ts.map +1 -1
- package/dist/core/fallback-profile-manager.d.ts +0 -2
- package/dist/core/fallback-profile-manager.d.ts.map +1 -1
- package/dist/core/system-prompt-builder.d.ts.map +1 -1
- package/dist/defaults/index.js +351 -318
- package/dist/defaults/index.js.map +4 -4
- package/dist/execution/compaction-core.d.ts +3 -0
- package/dist/execution/compaction-core.d.ts.map +1 -1
- package/dist/execution/compactor.d.ts +4 -0
- package/dist/execution/compactor.d.ts.map +1 -1
- package/dist/execution/index.js +141 -50
- package/dist/execution/index.js.map +4 -4
- package/dist/execution/intelligent-compactor.d.ts +5 -1
- package/dist/execution/intelligent-compactor.d.ts.map +1 -1
- package/dist/execution/one-shot-llm.d.ts.map +1 -1
- package/dist/execution/selective-compactor.d.ts +4 -0
- package/dist/execution/selective-compactor.d.ts.map +1 -1
- package/dist/goal/phase-orchestrator.d.ts +4 -0
- package/dist/goal/phase-orchestrator.d.ts.map +1 -1
- package/dist/hooks/runner.d.ts +0 -2
- package/dist/hooks/runner.d.ts.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +421 -248
- package/dist/index.js.map +4 -4
- package/dist/models/alibaba-token-plan-catalog.d.ts +85 -0
- package/dist/models/alibaba-token-plan-catalog.d.ts.map +1 -0
- package/dist/models/index.d.ts +1 -0
- package/dist/models/index.d.ts.map +1 -1
- package/dist/models/index.js +200 -15
- package/dist/models/index.js.map +4 -4
- package/dist/models/llm-selector.d.ts +4 -0
- package/dist/models/llm-selector.d.ts.map +1 -1
- package/dist/models/models-registry.d.ts +8 -0
- package/dist/models/models-registry.d.ts.map +1 -1
- package/dist/security/index.js +0 -23
- package/dist/security/index.js.map +2 -2
- package/dist/security/permission-policy.d.ts +0 -23
- package/dist/security/permission-policy.d.ts.map +1 -1
- package/dist/storage/config-loader.d.ts.map +1 -1
- package/dist/storage/index.js +6 -5
- package/dist/storage/index.js.map +2 -2
- package/dist/tools/index.js +8 -1
- package/dist/tools/index.js.map +2 -2
- package/dist/types/config.d.ts +9 -16
- package/dist/types/config.d.ts.map +1 -1
- package/dist/types/index.js +7 -4
- package/dist/types/index.js.map +2 -2
- package/dist/types/provider.d.ts.map +1 -1
- package/dist/utils/connectivity.d.ts +36 -0
- package/dist/utils/connectivity.d.ts.map +1 -0
- package/dist/utils/index.d.ts +1 -0
- package/dist/utils/index.d.ts.map +1 -1
- package/dist/utils/index.js +59 -11
- package/dist/utils/index.js.map +4 -4
- package/dist/utils/merge-models-payload.d.ts +9 -0
- package/dist/utils/merge-models-payload.d.ts.map +1 -1
- package/package.json +2 -2
package/dist/defaults/index.js
CHANGED
|
@@ -1625,15 +1625,30 @@ function deepEqual(a, b) {
|
|
|
1625
1625
|
}
|
|
1626
1626
|
|
|
1627
1627
|
// src/utils/merge-models-payload.ts
|
|
1628
|
+
var REMOVE_PROVIDERS_KEY = "_removeProviders";
|
|
1629
|
+
var REMOVE_MODELS_KEY = "_removeModels";
|
|
1628
1630
|
function mergeModelsPayload(base, overlay) {
|
|
1631
|
+
const removeProviders = Array.isArray(overlay[REMOVE_PROVIDERS_KEY]) ? overlay[REMOVE_PROVIDERS_KEY] : [];
|
|
1632
|
+
const removeModels = overlay[REMOVE_MODELS_KEY] && typeof overlay[REMOVE_MODELS_KEY] === "object" ? overlay[REMOVE_MODELS_KEY] : {};
|
|
1629
1633
|
const out = {};
|
|
1630
1634
|
for (const [id, provider] of Object.entries(base)) {
|
|
1631
1635
|
out[id] = cloneProvider(provider);
|
|
1632
1636
|
}
|
|
1633
1637
|
for (const [id, ovProvider] of Object.entries(overlay)) {
|
|
1638
|
+
if (id === REMOVE_PROVIDERS_KEY || id === REMOVE_MODELS_KEY) continue;
|
|
1634
1639
|
const existing = out[id];
|
|
1635
1640
|
out[id] = existing ? mergeProvider(existing, ovProvider) : cloneProvider(ovProvider);
|
|
1636
1641
|
}
|
|
1642
|
+
for (const providerId of removeProviders) {
|
|
1643
|
+
delete out[providerId];
|
|
1644
|
+
}
|
|
1645
|
+
for (const [providerId, modelIds] of Object.entries(removeModels)) {
|
|
1646
|
+
const provider = out[providerId];
|
|
1647
|
+
if (!provider || !provider.models) continue;
|
|
1648
|
+
for (const modelId of modelIds) {
|
|
1649
|
+
delete provider.models[modelId];
|
|
1650
|
+
}
|
|
1651
|
+
}
|
|
1637
1652
|
return out;
|
|
1638
1653
|
}
|
|
1639
1654
|
function mergeProvider(base, overlay) {
|
|
@@ -9317,7 +9332,8 @@ function hashStr(s) {
|
|
|
9317
9332
|
// src/types/provider.ts
|
|
9318
9333
|
var CONTEXT_OVERFLOW_RE = /context.length|context.window|maximum context|max.*tokens?.*exceeded|prompt is too long|too long|exceeds the context|\btokens\b.*exceed|too many tokens|reduce the length|resulted in \d+ tokens|input.{0,12}too (?:large|long)|context_length_exceeded/i;
|
|
9319
9334
|
var CONTENT_FILTER_RE = /content.(filter|policy|moderation)|safety (system|filter)/i;
|
|
9320
|
-
var QUOTA_EXHAUSTED_RE = /(?:insufficient|exhausted|depleted|exceeded|no|not enough)[-_\s]*(?:quota|credit|balance)|(?:quota|credit|balance)[-_\s]*(?:exhausted|depleted|exceeded|insufficient)|billing[_\s-]*(?:hard[_\s-]*)?limit|payment required|spending limit|plan limit/i;
|
|
9335
|
+
var QUOTA_EXHAUSTED_RE = /(?:insufficient|exhausted|depleted|exceeded|no|not enough)[-_\s]*(?:quota|credit|balance)|(?:quota|credit|balance)[-_\s]*(?:exhausted|depleted|exceeded|insufficient)|billing[_\s-]*(?:hard[_\s-]*)?limit|payment required|spending limit|plan limit|usage[-_\s]*limit[-_\s]*(?:reached|exceeded)/i;
|
|
9336
|
+
var RATE_LIMIT_EXCEEDED_RE = /rate[-_\s]*limit[-_\s]*exceeded/i;
|
|
9321
9337
|
function classifyProviderError(status, body, message) {
|
|
9322
9338
|
const type = body?.type;
|
|
9323
9339
|
const text = [message, body?.message, type, body?.raw].filter(Boolean).join("\n");
|
|
@@ -9325,6 +9341,9 @@ function classifyProviderError(status, body, message) {
|
|
|
9325
9341
|
if (status === 408) return "timeout";
|
|
9326
9342
|
if (status === 599) return "stream_hang";
|
|
9327
9343
|
if (status === 402 || QUOTA_EXHAUSTED_RE.test(text)) return "quota_exhausted";
|
|
9344
|
+
if (status === 429 && body?.message && RATE_LIMIT_EXCEEDED_RE.test(body.message)) {
|
|
9345
|
+
return "quota_exhausted";
|
|
9346
|
+
}
|
|
9328
9347
|
if (type === "rate_limit_error" || status === 429) return "rate_limit";
|
|
9329
9348
|
if (type === "overloaded_error" || status === 529) return "overloaded";
|
|
9330
9349
|
if (status >= 500) return "server";
|
|
@@ -15073,25 +15092,30 @@ var WHITESPACE_COLLAPSE_PATTERN = /\s+/g;
|
|
|
15073
15092
|
function compactionDebugEnabled() {
|
|
15074
15093
|
return process.env["NODE_ENV"] === "development" || process.env["WRONGSTACK_DEBUG"] === "1";
|
|
15075
15094
|
}
|
|
15095
|
+
var _debugLogger;
|
|
15096
|
+
function setCompactionDebugLogger(logger) {
|
|
15097
|
+
_debugLogger = logger;
|
|
15098
|
+
}
|
|
15076
15099
|
function emitCompactionMetrics(event, metrics) {
|
|
15077
15100
|
if (!compactionDebugEnabled()) return;
|
|
15078
|
-
|
|
15079
|
-
|
|
15080
|
-
|
|
15081
|
-
|
|
15082
|
-
|
|
15083
|
-
|
|
15084
|
-
|
|
15085
|
-
|
|
15086
|
-
|
|
15087
|
-
|
|
15088
|
-
|
|
15089
|
-
|
|
15090
|
-
|
|
15091
|
-
|
|
15092
|
-
|
|
15093
|
-
|
|
15094
|
-
|
|
15101
|
+
const ctx = {
|
|
15102
|
+
event,
|
|
15103
|
+
messageCount: metrics.messageCount,
|
|
15104
|
+
preserveStart: metrics.preserveStart,
|
|
15105
|
+
fastPathIterations: metrics.fastPathIterations,
|
|
15106
|
+
fastPathInnerIterations: metrics.fastPathInnerIterations,
|
|
15107
|
+
fastPathInnerPerOuter: metrics.fastPathIterations > 0 ? metrics.fastPathInnerIterations / metrics.fastPathIterations : 0,
|
|
15108
|
+
fullPassIterations: metrics.fullPassIterations,
|
|
15109
|
+
fullPassInnerIterations: metrics.fullPassInnerIterations,
|
|
15110
|
+
fullPassInnerPerOuter: metrics.fullPassIterations > 0 ? metrics.fullPassInnerIterations / metrics.fullPassIterations : 0,
|
|
15111
|
+
tokensSaved: metrics.tokensSaved,
|
|
15112
|
+
changed: metrics.changed
|
|
15113
|
+
};
|
|
15114
|
+
if (_debugLogger) {
|
|
15115
|
+
_debugLogger.debug(`compaction: ${event}`, ctx);
|
|
15116
|
+
} else {
|
|
15117
|
+
console.log(JSON.stringify({ level: "debug", ...ctx }));
|
|
15118
|
+
}
|
|
15095
15119
|
}
|
|
15096
15120
|
var estimateMessages = estimateMessageTokens;
|
|
15097
15121
|
function hasTextContent(m) {
|
|
@@ -15123,18 +15147,20 @@ function findPreserveStart(messages, preserveK) {
|
|
|
15123
15147
|
preserveStart--;
|
|
15124
15148
|
}
|
|
15125
15149
|
if (compactionDebugEnabled()) {
|
|
15126
|
-
|
|
15127
|
-
|
|
15128
|
-
|
|
15129
|
-
|
|
15130
|
-
|
|
15131
|
-
|
|
15132
|
-
|
|
15133
|
-
|
|
15134
|
-
|
|
15135
|
-
|
|
15136
|
-
|
|
15137
|
-
|
|
15150
|
+
const ctx = {
|
|
15151
|
+
event: "compaction.find_preserve_start.ended",
|
|
15152
|
+
messageCount: messages.length,
|
|
15153
|
+
preserveK,
|
|
15154
|
+
preserveStart,
|
|
15155
|
+
pairRepairIterations,
|
|
15156
|
+
pairRepairInnerIterations,
|
|
15157
|
+
pairRepairInnerPerOuter: pairRepairIterations > 0 ? pairRepairInnerIterations / pairRepairIterations : 0
|
|
15158
|
+
};
|
|
15159
|
+
if (_debugLogger) {
|
|
15160
|
+
_debugLogger.debug("compaction: find_preserve_start.ended", ctx);
|
|
15161
|
+
} else {
|
|
15162
|
+
console.log(JSON.stringify({ level: "debug", ...ctx }));
|
|
15163
|
+
}
|
|
15138
15164
|
}
|
|
15139
15165
|
return preserveStart;
|
|
15140
15166
|
}
|
|
@@ -15249,16 +15275,18 @@ function eliseOldToolResults(messages, opts) {
|
|
|
15249
15275
|
if (compactionDebugEnabled()) {
|
|
15250
15276
|
const ratio = fullPassInnerIterations / fullPassIterations;
|
|
15251
15277
|
if (ratio > 10) {
|
|
15252
|
-
|
|
15253
|
-
|
|
15254
|
-
|
|
15255
|
-
|
|
15256
|
-
|
|
15257
|
-
|
|
15258
|
-
|
|
15259
|
-
|
|
15260
|
-
})
|
|
15261
|
-
|
|
15278
|
+
const ctx = {
|
|
15279
|
+
event: "compaction.elision.regression",
|
|
15280
|
+
message: `fullPassInnerPerOuter=${ratio.toFixed(2)} exceeds threshold 10 \u2014 possible O(n\xB7m) regression`,
|
|
15281
|
+
messageCount: messages.length,
|
|
15282
|
+
fullPassIterations,
|
|
15283
|
+
fullPassInnerIterations
|
|
15284
|
+
};
|
|
15285
|
+
if (_debugLogger) {
|
|
15286
|
+
_debugLogger.error(`compaction: elision.regression \u2014 ratio ${ratio.toFixed(2)}`, ctx);
|
|
15287
|
+
} else {
|
|
15288
|
+
console.error(JSON.stringify({ level: "error", ...ctx }));
|
|
15289
|
+
}
|
|
15262
15290
|
}
|
|
15263
15291
|
}
|
|
15264
15292
|
}
|
|
@@ -16283,6 +16311,207 @@ function resolveContextWindowPolicy(config = {}, overrideMode) {
|
|
|
16283
16311
|
};
|
|
16284
16312
|
}
|
|
16285
16313
|
|
|
16314
|
+
// src/infrastructure/logger.ts
|
|
16315
|
+
import * as fsp10 from "node:fs/promises";
|
|
16316
|
+
import * as path14 from "node:path";
|
|
16317
|
+
var LEVEL_RANK2 = {
|
|
16318
|
+
error: 0,
|
|
16319
|
+
warn: 1,
|
|
16320
|
+
info: 2,
|
|
16321
|
+
debug: 3,
|
|
16322
|
+
trace: 4
|
|
16323
|
+
};
|
|
16324
|
+
var COLORS = {
|
|
16325
|
+
error: color.red,
|
|
16326
|
+
warn: color.yellow,
|
|
16327
|
+
info: color.cyan,
|
|
16328
|
+
debug: color.gray,
|
|
16329
|
+
trace: color.dim
|
|
16330
|
+
};
|
|
16331
|
+
var LOG_LEVELS = /* @__PURE__ */ new Set(["error", "warn", "info", "debug", "trace"]);
|
|
16332
|
+
var LOG_FORMATS = /* @__PURE__ */ new Set(["pretty", "json"]);
|
|
16333
|
+
var DefaultLogger = class _DefaultLogger {
|
|
16334
|
+
/** How many file writes between rotation size checks (statSync is not free). */
|
|
16335
|
+
static ROTATE_CHECK_EVERY = 100;
|
|
16336
|
+
level;
|
|
16337
|
+
file;
|
|
16338
|
+
bindings;
|
|
16339
|
+
format;
|
|
16340
|
+
stderr;
|
|
16341
|
+
maxFileBytes;
|
|
16342
|
+
writesSinceRotateCheck = 0;
|
|
16343
|
+
/**
|
|
16344
|
+
* Serialized async tail for file writes. Every appendFile (and any
|
|
16345
|
+
* chained rotation) is awaited through this promise so file I/O
|
|
16346
|
+
* never overlaps itself — preserving the per-line ordering the
|
|
16347
|
+
* sync version had, but without blocking the caller thread. Any
|
|
16348
|
+
* rejection is swallowed (`catch(() => {})`) because logging must
|
|
16349
|
+
* never crash the host.
|
|
16350
|
+
*
|
|
16351
|
+
* Children share the parent's tail: `child.tail === parent.tail`
|
|
16352
|
+
* for the lifetime of the chain. Read/write access goes through
|
|
16353
|
+
* `_tail` so that, when a child has been wired to a parent, both
|
|
16354
|
+
* `enqueueRotate` and `log` always observe the parent's current tail
|
|
16355
|
+
* rather than a stale snapshot taken at `child()` time.
|
|
16356
|
+
*/
|
|
16357
|
+
tail = Promise.resolve();
|
|
16358
|
+
parent = null;
|
|
16359
|
+
/**
|
|
16360
|
+
* Resolve the current tail. For the root logger this is the field;
|
|
16361
|
+
* for a child logger we always read through the parent so that a
|
|
16362
|
+
* child's appends land on the parent's most recent tail, and a
|
|
16363
|
+
* parent's `flush()` waits for everything the child chained.
|
|
16364
|
+
*/
|
|
16365
|
+
get _tail() {
|
|
16366
|
+
return this.parent ? this.parent._tail : this.tail;
|
|
16367
|
+
}
|
|
16368
|
+
set _tail(next) {
|
|
16369
|
+
if (this.parent) this.parent.tail = next;
|
|
16370
|
+
else this.tail = next;
|
|
16371
|
+
}
|
|
16372
|
+
constructor(opts = {}) {
|
|
16373
|
+
this.level = opts.level ?? parseLogLevel(process.env.WRONGSTACK_LOG_LEVEL);
|
|
16374
|
+
this.file = opts.file;
|
|
16375
|
+
this.bindings = opts.bindings ?? {};
|
|
16376
|
+
this.format = opts.format ?? parseLogFormat(process.env.WRONGSTACK_LOG_FORMAT);
|
|
16377
|
+
this.stderr = opts.stderr !== false;
|
|
16378
|
+
this.maxFileBytes = opts.maxFileBytes ?? 10 * 1024 * 1024;
|
|
16379
|
+
if (this.file) {
|
|
16380
|
+
const dir = path14.dirname(this.file);
|
|
16381
|
+
this._tail = this._tail.then(async () => {
|
|
16382
|
+
await fsp10.mkdir(dir, { recursive: true });
|
|
16383
|
+
}).catch(() => void 0);
|
|
16384
|
+
}
|
|
16385
|
+
}
|
|
16386
|
+
error(msg, ctx) {
|
|
16387
|
+
this.log("error", msg, ctx);
|
|
16388
|
+
}
|
|
16389
|
+
warn(msg, ctx) {
|
|
16390
|
+
this.log("warn", msg, ctx);
|
|
16391
|
+
}
|
|
16392
|
+
info(msg, ctx) {
|
|
16393
|
+
this.log("info", msg, ctx);
|
|
16394
|
+
}
|
|
16395
|
+
debug(msg, ctx) {
|
|
16396
|
+
this.log("debug", msg, ctx);
|
|
16397
|
+
}
|
|
16398
|
+
trace(msg, ctx) {
|
|
16399
|
+
this.log("trace", msg, ctx);
|
|
16400
|
+
}
|
|
16401
|
+
child(bindings) {
|
|
16402
|
+
const child = Object.create(_DefaultLogger.prototype);
|
|
16403
|
+
child.level = this.level;
|
|
16404
|
+
child.file = this.file;
|
|
16405
|
+
child.bindings = { ...this.bindings, ...bindings };
|
|
16406
|
+
child.format = this.format;
|
|
16407
|
+
child.stderr = this.stderr;
|
|
16408
|
+
child.maxFileBytes = this.maxFileBytes;
|
|
16409
|
+
child.parent = this;
|
|
16410
|
+
child.writesSinceRotateCheck = this.writesSinceRotateCheck;
|
|
16411
|
+
return child;
|
|
16412
|
+
}
|
|
16413
|
+
/**
|
|
16414
|
+
* Wait until all queued file writes (and any pending rotation) have
|
|
16415
|
+
* completed. `log()` is fire-and-forget by design — the caller never
|
|
16416
|
+
* blocks on disk — so tests, shutdown handlers, and processes that
|
|
16417
|
+
* need a deterministic "everything is on disk now" guarantee should
|
|
16418
|
+
* `await logger.flush()` before reading the file or exiting.
|
|
16419
|
+
*/
|
|
16420
|
+
flush() {
|
|
16421
|
+
return this._tail;
|
|
16422
|
+
}
|
|
16423
|
+
/**
|
|
16424
|
+
* Size-based rotation: when the file outgrows `maxFileBytes`, rename it to
|
|
16425
|
+
* `<file>.1` (dropping the previous `.1`) so the live file restarts empty.
|
|
16426
|
+
* Checked on the first write and every ROTATE_CHECK_EVERY writes after.
|
|
16427
|
+
* Best-effort: a rename can fail on Windows while another process holds
|
|
16428
|
+
* the file — the next check retries. Multiple processes appending to the
|
|
16429
|
+
* same log all run this check; whoever crosses the threshold first wins.
|
|
16430
|
+
*
|
|
16431
|
+
* Async: the rotation runs on the file-write tail (so its writes don't
|
|
16432
|
+
* interleave with the next append), and the caller never blocks on a
|
|
16433
|
+
* statSync / renameSync syscall on the hot log path.
|
|
16434
|
+
*/
|
|
16435
|
+
enqueueRotate(file) {
|
|
16436
|
+
if (this.writesSinceRotateCheck++ % _DefaultLogger.ROTATE_CHECK_EVERY !== 0) return;
|
|
16437
|
+
this._tail = this._tail.then(async () => {
|
|
16438
|
+
let st;
|
|
16439
|
+
try {
|
|
16440
|
+
st = await fsp10.stat(file);
|
|
16441
|
+
} catch {
|
|
16442
|
+
return;
|
|
16443
|
+
}
|
|
16444
|
+
if (st.size < this.maxFileBytes) return;
|
|
16445
|
+
try {
|
|
16446
|
+
await fsp10.rm(`${file}.1`, { force: true });
|
|
16447
|
+
await fsp10.rename(file, `${file}.1`);
|
|
16448
|
+
} catch {
|
|
16449
|
+
}
|
|
16450
|
+
}).catch(() => void 0);
|
|
16451
|
+
}
|
|
16452
|
+
log(level, msg, ctx) {
|
|
16453
|
+
const r = LEVEL_RANK2[level];
|
|
16454
|
+
const allowed = LEVEL_RANK2[this.level];
|
|
16455
|
+
if (r > allowed) return;
|
|
16456
|
+
const ts = (/* @__PURE__ */ new Date()).toISOString();
|
|
16457
|
+
const entry = { ts, level, msg, ...this.bindings };
|
|
16458
|
+
if (ctx !== void 0) {
|
|
16459
|
+
entry.ctx = ctx instanceof Error ? { message: ctx.message, stack: ctx.stack } : ctx;
|
|
16460
|
+
}
|
|
16461
|
+
if (this.file) {
|
|
16462
|
+
this.enqueueRotate(this.file);
|
|
16463
|
+
const line = `${JSON.stringify(entry)}
|
|
16464
|
+
`;
|
|
16465
|
+
this._tail = this._tail.then(() => fsp10.appendFile(this.file, line)).catch(() => void 0);
|
|
16466
|
+
}
|
|
16467
|
+
if (!this.stderr) return;
|
|
16468
|
+
if (this.format === "json") {
|
|
16469
|
+
writeErr(`${JSON.stringify(entry)}
|
|
16470
|
+
`);
|
|
16471
|
+
} else {
|
|
16472
|
+
const head = `${color.dim(ts)} ${COLORS[level](level.toUpperCase().padEnd(5))} ${msg}`;
|
|
16473
|
+
if (ctx !== void 0) {
|
|
16474
|
+
writeErr(`${head} ${formatCtx(ctx)}
|
|
16475
|
+
`);
|
|
16476
|
+
} else {
|
|
16477
|
+
writeErr(`${head}
|
|
16478
|
+
`);
|
|
16479
|
+
}
|
|
16480
|
+
}
|
|
16481
|
+
}
|
|
16482
|
+
};
|
|
16483
|
+
function parseLogLevel(raw) {
|
|
16484
|
+
return raw && LOG_LEVELS.has(raw) ? raw : "info";
|
|
16485
|
+
}
|
|
16486
|
+
function parseLogFormat(raw) {
|
|
16487
|
+
return raw && LOG_FORMATS.has(raw) ? raw : "pretty";
|
|
16488
|
+
}
|
|
16489
|
+
function formatCtx(ctx) {
|
|
16490
|
+
if (ctx instanceof Error) return color.dim(ctx.message);
|
|
16491
|
+
if (typeof ctx === "string") return color.dim(ctx);
|
|
16492
|
+
try {
|
|
16493
|
+
return color.dim(JSON.stringify(ctx));
|
|
16494
|
+
} catch {
|
|
16495
|
+
return color.dim(String(ctx));
|
|
16496
|
+
}
|
|
16497
|
+
}
|
|
16498
|
+
var noOpLogger = {
|
|
16499
|
+
// 'error' is the quietest level the Logger contract offers; the methods
|
|
16500
|
+
// discard everything regardless, this only matters to level checks.
|
|
16501
|
+
level: "error",
|
|
16502
|
+
error: () => {
|
|
16503
|
+
},
|
|
16504
|
+
warn: () => {
|
|
16505
|
+
},
|
|
16506
|
+
info: () => {
|
|
16507
|
+
},
|
|
16508
|
+
debug: () => {
|
|
16509
|
+
},
|
|
16510
|
+
trace: () => {
|
|
16511
|
+
},
|
|
16512
|
+
child: () => noOpLogger
|
|
16513
|
+
};
|
|
16514
|
+
|
|
16286
16515
|
// src/types/default-config.ts
|
|
16287
16516
|
var DEFAULT_TOOLS_CONFIG = Object.freeze({
|
|
16288
16517
|
defaultExecutionStrategy: "smart",
|
|
@@ -16328,10 +16557,13 @@ var HybridCompactor = class {
|
|
|
16328
16557
|
preserveK;
|
|
16329
16558
|
eliseThreshold;
|
|
16330
16559
|
smart;
|
|
16560
|
+
logger;
|
|
16331
16561
|
constructor(opts = {}) {
|
|
16332
16562
|
this.preserveK = opts.preserveK ?? 5;
|
|
16333
16563
|
this.eliseThreshold = opts.eliseThreshold ?? 2e3;
|
|
16334
16564
|
this.smart = opts.smart ?? false;
|
|
16565
|
+
this.logger = opts.logger ?? noOpLogger;
|
|
16566
|
+
setCompactionDebugLogger(this.logger);
|
|
16335
16567
|
}
|
|
16336
16568
|
async compact(ctx, opts = {}) {
|
|
16337
16569
|
const beforeTokens = estimateMessages(ctx.messages);
|
|
@@ -16669,7 +16901,7 @@ var AutonomousRunner = class {
|
|
|
16669
16901
|
};
|
|
16670
16902
|
|
|
16671
16903
|
// src/storage/goal-store.ts
|
|
16672
|
-
import * as
|
|
16904
|
+
import * as fsp11 from "node:fs/promises";
|
|
16673
16905
|
var MAX_JOURNAL_ENTRIES = 500;
|
|
16674
16906
|
function goalFilePath(projectRoot) {
|
|
16675
16907
|
return resolveWstackPaths({ projectRoot }).projectGoal;
|
|
@@ -16678,7 +16910,7 @@ async function loadGoal(filePath, events, warn) {
|
|
|
16678
16910
|
const t0 = Date.now();
|
|
16679
16911
|
let raw;
|
|
16680
16912
|
try {
|
|
16681
|
-
raw = await
|
|
16913
|
+
raw = await fsp11.readFile(filePath, "utf8");
|
|
16682
16914
|
} catch (err) {
|
|
16683
16915
|
const code = err.code;
|
|
16684
16916
|
if (code === "ENOENT") {
|
|
@@ -16867,7 +17099,7 @@ function isDesignStack(v) {
|
|
|
16867
17099
|
// src/execution/design-kit-loader.ts
|
|
16868
17100
|
import { existsSync } from "node:fs";
|
|
16869
17101
|
import * as fs4 from "node:fs/promises";
|
|
16870
|
-
import * as
|
|
17102
|
+
import * as path15 from "node:path";
|
|
16871
17103
|
import { fileURLToPath as fileURLToPath3 } from "node:url";
|
|
16872
17104
|
var KIT_FILE = "KIT.md";
|
|
16873
17105
|
var TOKENS_FILE = "tokens.json";
|
|
@@ -16980,7 +17212,7 @@ var DefaultDesignKitLoader = class {
|
|
|
16980
17212
|
}
|
|
16981
17213
|
for (const e of entries) {
|
|
16982
17214
|
if (!e.isDirectory()) continue;
|
|
16983
|
-
const kitFile =
|
|
17215
|
+
const kitFile = path15.join(dir, e.name, KIT_FILE);
|
|
16984
17216
|
try {
|
|
16985
17217
|
const raw = await fs4.readFile(kitFile, "utf8");
|
|
16986
17218
|
const fm = parseKitFrontmatter(raw);
|
|
@@ -17054,7 +17286,7 @@ var DefaultDesignKitLoader = class {
|
|
|
17054
17286
|
const m = await this.find(id);
|
|
17055
17287
|
let tokens;
|
|
17056
17288
|
if (m) {
|
|
17057
|
-
const tokensPath =
|
|
17289
|
+
const tokensPath = path15.join(path15.dirname(m.path), TOKENS_FILE);
|
|
17058
17290
|
try {
|
|
17059
17291
|
const raw = await fs4.readFile(tokensPath, "utf8");
|
|
17060
17292
|
const parsed = JSON.parse(raw);
|
|
@@ -17081,12 +17313,12 @@ var DefaultDesignKitLoader = class {
|
|
|
17081
17313
|
};
|
|
17082
17314
|
function resolveBundledDesignKitsDir() {
|
|
17083
17315
|
try {
|
|
17084
|
-
const here =
|
|
17316
|
+
const here = path15.dirname(fileURLToPath3(import.meta.url));
|
|
17085
17317
|
const candidates = [
|
|
17086
|
-
|
|
17087
|
-
|
|
17088
|
-
|
|
17089
|
-
|
|
17318
|
+
path15.join(here, "design-kits"),
|
|
17319
|
+
path15.join(here, "..", "design-kits"),
|
|
17320
|
+
path15.join(here, "..", "..", "design-kits"),
|
|
17321
|
+
path15.join(here, "..", "..", "..", "design-kits")
|
|
17090
17322
|
];
|
|
17091
17323
|
for (const c of candidates) {
|
|
17092
17324
|
if (existsSync(c)) return c;
|
|
@@ -17115,10 +17347,10 @@ function _resetDesignKitLoaderMemo() {
|
|
|
17115
17347
|
// src/execution/design-project-store.ts
|
|
17116
17348
|
import { existsSync as existsSync2 } from "node:fs";
|
|
17117
17349
|
import * as fs5 from "node:fs/promises";
|
|
17118
|
-
import * as
|
|
17350
|
+
import * as path16 from "node:path";
|
|
17119
17351
|
var DESIGN_DIR = ".design";
|
|
17120
17352
|
function designProjectDir(projectRoot) {
|
|
17121
|
-
return
|
|
17353
|
+
return path16.join(projectRoot, DESIGN_DIR);
|
|
17122
17354
|
}
|
|
17123
17355
|
var RULE_FILES = ["rules.md", "RULES.md", "design.md"];
|
|
17124
17356
|
var rulesCache = /* @__PURE__ */ new Map();
|
|
@@ -17127,7 +17359,7 @@ async function loadProjectDesignRules(projectRoot) {
|
|
|
17127
17359
|
let rules;
|
|
17128
17360
|
for (const name of RULE_FILES) {
|
|
17129
17361
|
try {
|
|
17130
|
-
const txt = await fs5.readFile(
|
|
17362
|
+
const txt = await fs5.readFile(path16.join(designProjectDir(projectRoot), name), "utf8");
|
|
17131
17363
|
if (txt.trim()) {
|
|
17132
17364
|
rules = txt.trim();
|
|
17133
17365
|
break;
|
|
@@ -17148,7 +17380,7 @@ function parseOverrides(value) {
|
|
|
17148
17380
|
}
|
|
17149
17381
|
async function loadActiveKit(projectRoot) {
|
|
17150
17382
|
try {
|
|
17151
|
-
const raw = await fs5.readFile(
|
|
17383
|
+
const raw = await fs5.readFile(path16.join(designProjectDir(projectRoot), "active.json"), "utf8");
|
|
17152
17384
|
const parsed = JSON.parse(raw);
|
|
17153
17385
|
if (parsed && typeof parsed.kit === "string") {
|
|
17154
17386
|
return {
|
|
@@ -17182,7 +17414,7 @@ function applyTokenOverrides(tokens, overrides) {
|
|
|
17182
17414
|
async function ensureDesignDir(projectRoot) {
|
|
17183
17415
|
const dir = designProjectDir(projectRoot);
|
|
17184
17416
|
await fs5.mkdir(dir, { recursive: true });
|
|
17185
|
-
const gi =
|
|
17417
|
+
const gi = path16.join(dir, ".gitignore");
|
|
17186
17418
|
if (!existsSync2(gi)) {
|
|
17187
17419
|
try {
|
|
17188
17420
|
await fs5.writeFile(gi, "*\n");
|
|
@@ -17196,11 +17428,11 @@ async function recordKitChoice(projectRoot, kit, stack, source, isoTime, overrid
|
|
|
17196
17428
|
const dir = await ensureDesignDir(projectRoot);
|
|
17197
17429
|
const record = { kit, stack: stack ?? null };
|
|
17198
17430
|
if (overrides && Object.keys(overrides).length > 0) record.overrides = overrides;
|
|
17199
|
-
await fs5.writeFile(
|
|
17431
|
+
await fs5.writeFile(path16.join(dir, "active.json"), `${JSON.stringify(record, null, 2)}
|
|
17200
17432
|
`);
|
|
17201
17433
|
const line = `- ${isoTime} \xB7 kit=${kit}${stack ? ` stack=${stack}` : ""} \xB7 via=${source}
|
|
17202
17434
|
`;
|
|
17203
|
-
await fs5.appendFile(
|
|
17435
|
+
await fs5.appendFile(path16.join(dir, "decisions.md"), line);
|
|
17204
17436
|
} catch {
|
|
17205
17437
|
}
|
|
17206
17438
|
}
|
|
@@ -17216,11 +17448,11 @@ async function recordOverrides(projectRoot, patch, isoTime) {
|
|
|
17216
17448
|
const dir = await ensureDesignDir(projectRoot);
|
|
17217
17449
|
const record = { kit: active.kit, stack: active.stack ?? null };
|
|
17218
17450
|
if (Object.keys(merged).length > 0) record.overrides = merged;
|
|
17219
|
-
await fs5.writeFile(
|
|
17451
|
+
await fs5.writeFile(path16.join(dir, "active.json"), `${JSON.stringify(record, null, 2)}
|
|
17220
17452
|
`);
|
|
17221
17453
|
const keys = Object.keys(patch).join(",");
|
|
17222
17454
|
await fs5.appendFile(
|
|
17223
|
-
|
|
17455
|
+
path16.join(dir, "decisions.md"),
|
|
17224
17456
|
`- ${isoTime} \xB7 kit=${active.kit} \xB7 override=${keys} \xB7 via=set
|
|
17225
17457
|
`
|
|
17226
17458
|
);
|
|
@@ -17230,7 +17462,7 @@ async function recordOverrides(projectRoot, patch, isoTime) {
|
|
|
17230
17462
|
}
|
|
17231
17463
|
async function clearPersistedActiveKit(projectRoot) {
|
|
17232
17464
|
try {
|
|
17233
|
-
await fs5.rm(
|
|
17465
|
+
await fs5.rm(path16.join(designProjectDir(projectRoot), "active.json"), { force: true });
|
|
17234
17466
|
} catch {
|
|
17235
17467
|
}
|
|
17236
17468
|
}
|
|
@@ -19014,6 +19246,7 @@ var IntelligentCompactor = class {
|
|
|
19014
19246
|
summarizerPrompt;
|
|
19015
19247
|
summarizerModel;
|
|
19016
19248
|
oneShotOrchestrator;
|
|
19249
|
+
logger;
|
|
19017
19250
|
constructor(opts) {
|
|
19018
19251
|
this.provider = opts.provider;
|
|
19019
19252
|
this.warnThreshold = opts.warnThreshold ?? 0.5;
|
|
@@ -19025,6 +19258,8 @@ var IntelligentCompactor = class {
|
|
|
19025
19258
|
this.summarizerPrompt = opts.summarizerPrompt ?? readBundledInstructionText("llm/intelligent-compactor-summarizer.md");
|
|
19026
19259
|
this.summarizerModel = opts.summarizerModel;
|
|
19027
19260
|
this.oneShotOrchestrator = opts.oneShotOrchestrator;
|
|
19261
|
+
this.logger = opts.logger ?? noOpLogger;
|
|
19262
|
+
setCompactionDebugLogger(this.logger);
|
|
19028
19263
|
}
|
|
19029
19264
|
async compact(ctx, opts = {}) {
|
|
19030
19265
|
const beforeTokens = estimateMessages(ctx.messages);
|
|
@@ -20418,11 +20653,13 @@ var LLMSelector = class {
|
|
|
20418
20653
|
systemPrompt;
|
|
20419
20654
|
maxOutputTokens;
|
|
20420
20655
|
oneShotOrchestrator;
|
|
20656
|
+
logger;
|
|
20421
20657
|
constructor(opts) {
|
|
20422
20658
|
this.provider = opts.provider;
|
|
20423
20659
|
this.model = opts.model ?? "unknown";
|
|
20660
|
+
this.logger = opts.logger ?? noOpLogger;
|
|
20424
20661
|
if (this.model === "unknown" && (process.env["NODE_ENV"] === "development" || process.env["WRONGSTACK_DEBUG"] === "1")) {
|
|
20425
|
-
|
|
20662
|
+
this.logger.warn(
|
|
20426
20663
|
"[LLMSelector] model not set \u2014 selector will use the provider default. Set `model` explicitly in LLMSelectorOptions to silence this warning."
|
|
20427
20664
|
);
|
|
20428
20665
|
}
|
|
@@ -20472,14 +20709,9 @@ IMPORTANT: Total conversation (${totalTokens} tokens) exceeds budget (${effectiv
|
|
|
20472
20709
|
}
|
|
20473
20710
|
} catch (err) {
|
|
20474
20711
|
if (err instanceof Error) {
|
|
20475
|
-
|
|
20476
|
-
|
|
20477
|
-
|
|
20478
|
-
event: "llm_selector.call_failed",
|
|
20479
|
-
message: `selector call failed, using recency fallback: ${err.message}`,
|
|
20480
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
20481
|
-
})
|
|
20482
|
-
);
|
|
20712
|
+
this.logger.warn(`selector call failed, using recency fallback: ${err.message}`, {
|
|
20713
|
+
event: "llm_selector.call_failed"
|
|
20714
|
+
});
|
|
20483
20715
|
}
|
|
20484
20716
|
return this.fallbackSelect(messages, effectiveBudget);
|
|
20485
20717
|
} finally {
|
|
@@ -20586,6 +20818,7 @@ var SelectiveCompactor = class {
|
|
|
20586
20818
|
eliseThreshold;
|
|
20587
20819
|
summarizerModel;
|
|
20588
20820
|
summarizerPrompt;
|
|
20821
|
+
logger;
|
|
20589
20822
|
constructor(opts) {
|
|
20590
20823
|
this.provider = opts.provider;
|
|
20591
20824
|
this.selector = opts.selector ?? new LLMSelector({ provider: opts.provider, model: opts.selectorModel, maxOutputTokens: opts.selectorMaxOutputTokens });
|
|
@@ -20596,8 +20829,10 @@ var SelectiveCompactor = class {
|
|
|
20596
20829
|
this.preserveK = opts.preserveK ?? 4;
|
|
20597
20830
|
this.eliseThreshold = opts.eliseThreshold ?? 300;
|
|
20598
20831
|
this.summarizerModel = opts.summarizerModel ?? opts.selectorModel;
|
|
20832
|
+
this.logger = opts.logger ?? noOpLogger;
|
|
20833
|
+
setCompactionDebugLogger(this.logger);
|
|
20599
20834
|
if (this.summarizerModel === void 0 && (process.env["NODE_ENV"] === "development" || process.env["WRONGSTACK_DEBUG"] === "1")) {
|
|
20600
|
-
|
|
20835
|
+
this.logger.warn(
|
|
20601
20836
|
"[SelectiveCompactor] summarizerModel not set \u2014 will fall back to ctx.model at summarize time. Set `summarizerModel` explicitly to silence this warning."
|
|
20602
20837
|
);
|
|
20603
20838
|
}
|
|
@@ -20826,7 +21061,7 @@ Summarize the following message range:`;
|
|
|
20826
21061
|
|
|
20827
21062
|
// src/execution/skill-loader.ts
|
|
20828
21063
|
import * as fs6 from "node:fs/promises";
|
|
20829
|
-
import * as
|
|
21064
|
+
import * as path17 from "node:path";
|
|
20830
21065
|
|
|
20831
21066
|
// src/skills/foreign-sources.ts
|
|
20832
21067
|
var FOREIGN_SKILL_TOOLS = [
|
|
@@ -20976,7 +21211,7 @@ async function entryIsDirectory(dir, entry) {
|
|
|
20976
21211
|
if (entry.isDirectory()) return true;
|
|
20977
21212
|
if (entry.isSymbolicLink()) {
|
|
20978
21213
|
try {
|
|
20979
|
-
return (await fs6.stat(
|
|
21214
|
+
return (await fs6.stat(path17.join(dir, entry.name))).isDirectory();
|
|
20980
21215
|
} catch {
|
|
20981
21216
|
return false;
|
|
20982
21217
|
}
|
|
@@ -20997,7 +21232,7 @@ var DefaultSkillLoader = class {
|
|
|
20997
21232
|
for (const tool of FOREIGN_SKILL_TOOLS) {
|
|
20998
21233
|
if (!foreignIds.includes(tool.id)) continue;
|
|
20999
21234
|
dirs.push({
|
|
21000
|
-
dir:
|
|
21235
|
+
dir: path17.join(root, "." + tool.id, tool.subdir),
|
|
21001
21236
|
source: "foreign",
|
|
21002
21237
|
originTool: tool.id
|
|
21003
21238
|
});
|
|
@@ -21024,7 +21259,7 @@ var DefaultSkillLoader = class {
|
|
|
21024
21259
|
);
|
|
21025
21260
|
for (const e of entries) {
|
|
21026
21261
|
if (!await entryIsDirectory(dir, e)) continue;
|
|
21027
|
-
const skillFile =
|
|
21262
|
+
const skillFile = path17.join(dir, e.name, "SKILL.md");
|
|
21028
21263
|
try {
|
|
21029
21264
|
const raw = await fs6.readFile(skillFile, "utf8");
|
|
21030
21265
|
const fm = parseSkillFrontmatter(raw);
|
|
@@ -21108,7 +21343,7 @@ var DefaultSkillLoader = class {
|
|
|
21108
21343
|
if (cached !== void 0) return cached;
|
|
21109
21344
|
const m = await this.find(name);
|
|
21110
21345
|
if (!m) throw new Error(`Skill "${name}" not found`);
|
|
21111
|
-
const savePath =
|
|
21346
|
+
const savePath = path17.join(path17.dirname(m.path), "SKILL.save.md");
|
|
21112
21347
|
let result;
|
|
21113
21348
|
try {
|
|
21114
21349
|
result = await fs6.readFile(savePath, "utf8");
|
|
@@ -21142,11 +21377,11 @@ function parseDescriptionFromText(desc) {
|
|
|
21142
21377
|
|
|
21143
21378
|
// src/execution/prompt-loader.ts
|
|
21144
21379
|
import * as fs8 from "node:fs/promises";
|
|
21145
|
-
import * as
|
|
21380
|
+
import * as path19 from "node:path";
|
|
21146
21381
|
|
|
21147
21382
|
// src/storage/prompt-store.ts
|
|
21148
21383
|
import * as fs7 from "node:fs/promises";
|
|
21149
|
-
import * as
|
|
21384
|
+
import * as path18 from "node:path";
|
|
21150
21385
|
var SCHEMA_VERSION = 2;
|
|
21151
21386
|
function migratePromptEntry(raw) {
|
|
21152
21387
|
if (!raw || typeof raw !== "object") return null;
|
|
@@ -21212,7 +21447,7 @@ var DefaultPromptStore = class {
|
|
|
21212
21447
|
if (!file.endsWith(".json")) continue;
|
|
21213
21448
|
try {
|
|
21214
21449
|
const raw = JSON.parse(
|
|
21215
|
-
await fs7.readFile(
|
|
21450
|
+
await fs7.readFile(path18.join(this.dir, file), "utf8")
|
|
21216
21451
|
);
|
|
21217
21452
|
const migrated = migratePromptEntry(raw.entry);
|
|
21218
21453
|
if (migrated) entries.push(migrated);
|
|
@@ -21226,7 +21461,7 @@ var DefaultPromptStore = class {
|
|
|
21226
21461
|
);
|
|
21227
21462
|
}
|
|
21228
21463
|
async get(id) {
|
|
21229
|
-
const file =
|
|
21464
|
+
const file = path18.join(this.dir, `${id}.json`);
|
|
21230
21465
|
try {
|
|
21231
21466
|
const raw = JSON.parse(await fs7.readFile(file, "utf8"));
|
|
21232
21467
|
return migratePromptEntry(raw.entry);
|
|
@@ -21236,12 +21471,12 @@ var DefaultPromptStore = class {
|
|
|
21236
21471
|
}
|
|
21237
21472
|
async save(entry) {
|
|
21238
21473
|
await ensureDir(this.dir);
|
|
21239
|
-
const file =
|
|
21474
|
+
const file = path18.join(this.dir, `${entry.id}.json`);
|
|
21240
21475
|
const raw = { version: SCHEMA_VERSION, entry };
|
|
21241
21476
|
await atomicWrite(file, JSON.stringify(raw, null, 2));
|
|
21242
21477
|
}
|
|
21243
21478
|
async delete(id) {
|
|
21244
|
-
const file =
|
|
21479
|
+
const file = path18.join(this.dir, `${id}.json`);
|
|
21245
21480
|
try {
|
|
21246
21481
|
await fs7.unlink(file);
|
|
21247
21482
|
return true;
|
|
@@ -21330,7 +21565,7 @@ var DefaultPromptLoader = class {
|
|
|
21330
21565
|
constructor(opts) {
|
|
21331
21566
|
this.projectStore = typeof opts.paths.inProjectPrompts === "string" ? new DefaultPromptStore(opts.paths.inProjectPrompts) : void 0;
|
|
21332
21567
|
this.userStore = typeof opts.paths.globalPrompts === "string" ? new DefaultPromptStore(opts.paths.globalPrompts) : void 0;
|
|
21333
|
-
this.builtinDir = opts.bundledDir ?
|
|
21568
|
+
this.builtinDir = opts.bundledDir ? path19.join(opts.bundledDir, "prompts") : void 0;
|
|
21334
21569
|
}
|
|
21335
21570
|
async list() {
|
|
21336
21571
|
if (this.cache) return this.cache;
|
|
@@ -21462,7 +21697,7 @@ async function walkJson(dir) {
|
|
|
21462
21697
|
return out;
|
|
21463
21698
|
}
|
|
21464
21699
|
for (const e of entries) {
|
|
21465
|
-
const full =
|
|
21700
|
+
const full = path19.join(dir, e.name);
|
|
21466
21701
|
if (e.isDirectory()) {
|
|
21467
21702
|
out.push(...await walkJson(full));
|
|
21468
21703
|
} else if (e.name.endsWith(".json") && e.name !== "index.json" && e.name !== "schema.json") {
|
|
@@ -21661,11 +21896,11 @@ function runWithProcessTelemetry(context, run) {
|
|
|
21661
21896
|
// src/execution/tool-executor.ts
|
|
21662
21897
|
import { isDeepStrictEqual } from "node:util";
|
|
21663
21898
|
import * as fs9 from "node:fs/promises";
|
|
21664
|
-
import * as
|
|
21899
|
+
import * as path21 from "node:path";
|
|
21665
21900
|
|
|
21666
21901
|
// src/security/kanban-boundary.ts
|
|
21667
21902
|
import { realpath as realpath3 } from "node:fs/promises";
|
|
21668
|
-
import * as
|
|
21903
|
+
import * as path20 from "node:path";
|
|
21669
21904
|
import {
|
|
21670
21905
|
evaluateKanbanBoundaryOpaque,
|
|
21671
21906
|
evaluateKanbanBoundaryPath,
|
|
@@ -21740,10 +21975,10 @@ function resolveKanbanIdentity(ctx) {
|
|
|
21740
21975
|
async function extractCandidatePaths(toolName, input, ctx) {
|
|
21741
21976
|
if (toolName === "patch" && typeof input["patch"] === "string") {
|
|
21742
21977
|
const directoryInput = stringValue(input["directory"]) ?? ctx.workingDir;
|
|
21743
|
-
const directory =
|
|
21978
|
+
const directory = path20.isAbsolute(directoryInput) ? directoryInput : path20.resolve(ctx.workingDir, directoryInput);
|
|
21744
21979
|
const strip = Math.max(1, numericValue(input["strip"]) ?? 1);
|
|
21745
21980
|
const targets = extractPatchTargets(input["patch"], strip).map(
|
|
21746
|
-
(target) => relativeToProject(
|
|
21981
|
+
(target) => relativeToProject(path20.resolve(directory, target), ctx.projectRoot)
|
|
21747
21982
|
);
|
|
21748
21983
|
return Promise.all(targets.map((target) => canonicalizeCandidatePath(target, ctx)));
|
|
21749
21984
|
}
|
|
@@ -21753,7 +21988,7 @@ async function extractCandidatePaths(toolName, input, ctx) {
|
|
|
21753
21988
|
collectPathValues(input, values, pathKeys);
|
|
21754
21989
|
if (toolName === "scaffold" && typeof input["name"] === "string") {
|
|
21755
21990
|
const cwd = stringValue(input["cwd"]) ?? ctx.workingDir;
|
|
21756
|
-
values.push(
|
|
21991
|
+
values.push(path20.join(cwd, input["name"]));
|
|
21757
21992
|
}
|
|
21758
21993
|
const candidates = [
|
|
21759
21994
|
...new Set(values.flatMap(splitPathList).map((value) => resolveInputPath(value, ctx)))
|
|
@@ -21761,21 +21996,21 @@ async function extractCandidatePaths(toolName, input, ctx) {
|
|
|
21761
21996
|
return Promise.all(candidates.map((candidate) => canonicalizeCandidatePath(candidate, ctx)));
|
|
21762
21997
|
}
|
|
21763
21998
|
async function canonicalizeCandidatePath(candidate, ctx) {
|
|
21764
|
-
if (
|
|
21765
|
-
const absolute =
|
|
21999
|
+
if (path20.isAbsolute(candidate)) return candidate;
|
|
22000
|
+
const absolute = path20.resolve(ctx.projectRoot, candidate);
|
|
21766
22001
|
const canonicalRoot = await realpath3(ctx.projectRoot).catch(() => ctx.projectRoot);
|
|
21767
22002
|
let probe = absolute;
|
|
21768
22003
|
const missingSegments = [];
|
|
21769
22004
|
while (true) {
|
|
21770
22005
|
try {
|
|
21771
|
-
const canonical =
|
|
22006
|
+
const canonical = path20.join(await realpath3(probe), ...missingSegments);
|
|
21772
22007
|
return relativeToProject(canonical, canonicalRoot);
|
|
21773
22008
|
} catch (cause) {
|
|
21774
22009
|
const code = cause.code;
|
|
21775
22010
|
if (code !== "ENOENT" && code !== "ENOTDIR") return absolute;
|
|
21776
|
-
const parent =
|
|
22011
|
+
const parent = path20.dirname(probe);
|
|
21777
22012
|
if (parent === probe) return absolute;
|
|
21778
|
-
missingSegments.unshift(
|
|
22013
|
+
missingSegments.unshift(path20.basename(probe));
|
|
21779
22014
|
probe = parent;
|
|
21780
22015
|
}
|
|
21781
22016
|
}
|
|
@@ -21798,12 +22033,12 @@ function splitPathList(value) {
|
|
|
21798
22033
|
return value.split(",").map((item) => item.trim()).filter(Boolean);
|
|
21799
22034
|
}
|
|
21800
22035
|
function resolveInputPath(value, ctx) {
|
|
21801
|
-
const absolute =
|
|
22036
|
+
const absolute = path20.isAbsolute(value) ? value : path20.resolve(ctx.workingDir, value);
|
|
21802
22037
|
return relativeToProject(absolute, ctx.projectRoot);
|
|
21803
22038
|
}
|
|
21804
22039
|
function relativeToProject(absolute, projectRoot) {
|
|
21805
|
-
const relative6 =
|
|
21806
|
-
return relative6.startsWith("../") ||
|
|
22040
|
+
const relative6 = path20.relative(projectRoot, absolute).replace(/\\/g, "/");
|
|
22041
|
+
return relative6.startsWith("../") || path20.isAbsolute(relative6) ? absolute : relative6 || ".";
|
|
21807
22042
|
}
|
|
21808
22043
|
function extractPatchTargets(patchText, strip) {
|
|
21809
22044
|
const targets = [];
|
|
@@ -22147,7 +22382,7 @@ ${errorDetails}`,
|
|
|
22147
22382
|
const inputPath = use.input && typeof use.input === "object" ? use.input.path : void 0;
|
|
22148
22383
|
const caps = tool.capabilities ?? [];
|
|
22149
22384
|
const hasFileCapability = caps.includes("fs.read") || caps.includes("fs.write");
|
|
22150
|
-
const absPath = hasFileCapability && typeof inputPath === "string" ?
|
|
22385
|
+
const absPath = hasFileCapability && typeof inputPath === "string" ? path21.isAbsolute(inputPath) ? inputPath : path21.resolve(ctx.projectRoot, inputPath) : void 0;
|
|
22151
22386
|
let writeTargetExisted;
|
|
22152
22387
|
if (tool.name === "write" && caps.includes("fs.write") && absPath) {
|
|
22153
22388
|
writeTargetExisted = await fs9.stat(absPath).then(
|
|
@@ -22739,11 +22974,11 @@ async function maybePersistLargeToolOutput(toolName, content, budget) {
|
|
|
22739
22974
|
return content;
|
|
22740
22975
|
}
|
|
22741
22976
|
try {
|
|
22742
|
-
const dir =
|
|
22977
|
+
const dir = path21.join(wstackGlobalRoot(), "tool-output");
|
|
22743
22978
|
await fs9.mkdir(dir, { recursive: true });
|
|
22744
22979
|
const safeTool = toolName.replace(/[^a-zA-Z0-9._-]+/g, "_").slice(0, 40) || "tool";
|
|
22745
22980
|
const stamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
22746
|
-
const filePath =
|
|
22981
|
+
const filePath = path21.join(dir, `${stamp}-${safeTool}-${randomUUID11()}.log`);
|
|
22747
22982
|
await fs9.writeFile(filePath, content, "utf8");
|
|
22748
22983
|
const marker = `[full tool output: ${bytes} bytes at ${filePath}; read/grep that file selectively instead of re-running or requesting more output]`;
|
|
22749
22984
|
const fixedBytes = Buffer.byteLength(marker + TOOL_OUTPUT_ARTIFACT_OMISSION, "utf8");
|
|
@@ -23062,191 +23297,6 @@ function createContextManagerTool(opts = {}) {
|
|
|
23062
23297
|
}
|
|
23063
23298
|
var contextManagerTool = createContextManagerTool();
|
|
23064
23299
|
|
|
23065
|
-
// src/infrastructure/logger.ts
|
|
23066
|
-
import * as fsp11 from "node:fs/promises";
|
|
23067
|
-
import * as path21 from "node:path";
|
|
23068
|
-
var LEVEL_RANK2 = {
|
|
23069
|
-
error: 0,
|
|
23070
|
-
warn: 1,
|
|
23071
|
-
info: 2,
|
|
23072
|
-
debug: 3,
|
|
23073
|
-
trace: 4
|
|
23074
|
-
};
|
|
23075
|
-
var COLORS = {
|
|
23076
|
-
error: color.red,
|
|
23077
|
-
warn: color.yellow,
|
|
23078
|
-
info: color.cyan,
|
|
23079
|
-
debug: color.gray,
|
|
23080
|
-
trace: color.dim
|
|
23081
|
-
};
|
|
23082
|
-
var LOG_LEVELS = /* @__PURE__ */ new Set(["error", "warn", "info", "debug", "trace"]);
|
|
23083
|
-
var LOG_FORMATS = /* @__PURE__ */ new Set(["pretty", "json"]);
|
|
23084
|
-
var DefaultLogger = class _DefaultLogger {
|
|
23085
|
-
/** How many file writes between rotation size checks (statSync is not free). */
|
|
23086
|
-
static ROTATE_CHECK_EVERY = 100;
|
|
23087
|
-
level;
|
|
23088
|
-
file;
|
|
23089
|
-
bindings;
|
|
23090
|
-
format;
|
|
23091
|
-
stderr;
|
|
23092
|
-
maxFileBytes;
|
|
23093
|
-
writesSinceRotateCheck = 0;
|
|
23094
|
-
/**
|
|
23095
|
-
* Serialized async tail for file writes. Every appendFile (and any
|
|
23096
|
-
* chained rotation) is awaited through this promise so file I/O
|
|
23097
|
-
* never overlaps itself — preserving the per-line ordering the
|
|
23098
|
-
* sync version had, but without blocking the caller thread. Any
|
|
23099
|
-
* rejection is swallowed (`catch(() => {})`) because logging must
|
|
23100
|
-
* never crash the host.
|
|
23101
|
-
*
|
|
23102
|
-
* Children share the parent's tail: `child.tail === parent.tail`
|
|
23103
|
-
* for the lifetime of the chain. Read/write access goes through
|
|
23104
|
-
* `_tail` so that, when a child has been wired to a parent, both
|
|
23105
|
-
* `enqueueRotate` and `log` always observe the parent's current tail
|
|
23106
|
-
* rather than a stale snapshot taken at `child()` time.
|
|
23107
|
-
*/
|
|
23108
|
-
tail = Promise.resolve();
|
|
23109
|
-
parent = null;
|
|
23110
|
-
/**
|
|
23111
|
-
* Resolve the current tail. For the root logger this is the field;
|
|
23112
|
-
* for a child logger we always read through the parent so that a
|
|
23113
|
-
* child's appends land on the parent's most recent tail, and a
|
|
23114
|
-
* parent's `flush()` waits for everything the child chained.
|
|
23115
|
-
*/
|
|
23116
|
-
get _tail() {
|
|
23117
|
-
return this.parent ? this.parent._tail : this.tail;
|
|
23118
|
-
}
|
|
23119
|
-
set _tail(next) {
|
|
23120
|
-
if (this.parent) this.parent.tail = next;
|
|
23121
|
-
else this.tail = next;
|
|
23122
|
-
}
|
|
23123
|
-
constructor(opts = {}) {
|
|
23124
|
-
this.level = opts.level ?? parseLogLevel(process.env.WRONGSTACK_LOG_LEVEL);
|
|
23125
|
-
this.file = opts.file;
|
|
23126
|
-
this.bindings = opts.bindings ?? {};
|
|
23127
|
-
this.format = opts.format ?? parseLogFormat(process.env.WRONGSTACK_LOG_FORMAT);
|
|
23128
|
-
this.stderr = opts.stderr !== false;
|
|
23129
|
-
this.maxFileBytes = opts.maxFileBytes ?? 10 * 1024 * 1024;
|
|
23130
|
-
if (this.file) {
|
|
23131
|
-
const dir = path21.dirname(this.file);
|
|
23132
|
-
this._tail = this._tail.then(async () => {
|
|
23133
|
-
await fsp11.mkdir(dir, { recursive: true });
|
|
23134
|
-
}).catch(() => void 0);
|
|
23135
|
-
}
|
|
23136
|
-
}
|
|
23137
|
-
error(msg, ctx) {
|
|
23138
|
-
this.log("error", msg, ctx);
|
|
23139
|
-
}
|
|
23140
|
-
warn(msg, ctx) {
|
|
23141
|
-
this.log("warn", msg, ctx);
|
|
23142
|
-
}
|
|
23143
|
-
info(msg, ctx) {
|
|
23144
|
-
this.log("info", msg, ctx);
|
|
23145
|
-
}
|
|
23146
|
-
debug(msg, ctx) {
|
|
23147
|
-
this.log("debug", msg, ctx);
|
|
23148
|
-
}
|
|
23149
|
-
trace(msg, ctx) {
|
|
23150
|
-
this.log("trace", msg, ctx);
|
|
23151
|
-
}
|
|
23152
|
-
child(bindings) {
|
|
23153
|
-
const child = Object.create(_DefaultLogger.prototype);
|
|
23154
|
-
child.level = this.level;
|
|
23155
|
-
child.file = this.file;
|
|
23156
|
-
child.bindings = { ...this.bindings, ...bindings };
|
|
23157
|
-
child.format = this.format;
|
|
23158
|
-
child.stderr = this.stderr;
|
|
23159
|
-
child.maxFileBytes = this.maxFileBytes;
|
|
23160
|
-
child.parent = this;
|
|
23161
|
-
child.writesSinceRotateCheck = this.writesSinceRotateCheck;
|
|
23162
|
-
return child;
|
|
23163
|
-
}
|
|
23164
|
-
/**
|
|
23165
|
-
* Wait until all queued file writes (and any pending rotation) have
|
|
23166
|
-
* completed. `log()` is fire-and-forget by design — the caller never
|
|
23167
|
-
* blocks on disk — so tests, shutdown handlers, and processes that
|
|
23168
|
-
* need a deterministic "everything is on disk now" guarantee should
|
|
23169
|
-
* `await logger.flush()` before reading the file or exiting.
|
|
23170
|
-
*/
|
|
23171
|
-
flush() {
|
|
23172
|
-
return this._tail;
|
|
23173
|
-
}
|
|
23174
|
-
/**
|
|
23175
|
-
* Size-based rotation: when the file outgrows `maxFileBytes`, rename it to
|
|
23176
|
-
* `<file>.1` (dropping the previous `.1`) so the live file restarts empty.
|
|
23177
|
-
* Checked on the first write and every ROTATE_CHECK_EVERY writes after.
|
|
23178
|
-
* Best-effort: a rename can fail on Windows while another process holds
|
|
23179
|
-
* the file — the next check retries. Multiple processes appending to the
|
|
23180
|
-
* same log all run this check; whoever crosses the threshold first wins.
|
|
23181
|
-
*
|
|
23182
|
-
* Async: the rotation runs on the file-write tail (so its writes don't
|
|
23183
|
-
* interleave with the next append), and the caller never blocks on a
|
|
23184
|
-
* statSync / renameSync syscall on the hot log path.
|
|
23185
|
-
*/
|
|
23186
|
-
enqueueRotate(file) {
|
|
23187
|
-
if (this.writesSinceRotateCheck++ % _DefaultLogger.ROTATE_CHECK_EVERY !== 0) return;
|
|
23188
|
-
this._tail = this._tail.then(async () => {
|
|
23189
|
-
let st;
|
|
23190
|
-
try {
|
|
23191
|
-
st = await fsp11.stat(file);
|
|
23192
|
-
} catch {
|
|
23193
|
-
return;
|
|
23194
|
-
}
|
|
23195
|
-
if (st.size < this.maxFileBytes) return;
|
|
23196
|
-
try {
|
|
23197
|
-
await fsp11.rm(`${file}.1`, { force: true });
|
|
23198
|
-
await fsp11.rename(file, `${file}.1`);
|
|
23199
|
-
} catch {
|
|
23200
|
-
}
|
|
23201
|
-
}).catch(() => void 0);
|
|
23202
|
-
}
|
|
23203
|
-
log(level, msg, ctx) {
|
|
23204
|
-
const r = LEVEL_RANK2[level];
|
|
23205
|
-
const allowed = LEVEL_RANK2[this.level];
|
|
23206
|
-
if (r > allowed) return;
|
|
23207
|
-
const ts = (/* @__PURE__ */ new Date()).toISOString();
|
|
23208
|
-
const entry = { ts, level, msg, ...this.bindings };
|
|
23209
|
-
if (ctx !== void 0) {
|
|
23210
|
-
entry.ctx = ctx instanceof Error ? { message: ctx.message, stack: ctx.stack } : ctx;
|
|
23211
|
-
}
|
|
23212
|
-
if (this.file) {
|
|
23213
|
-
this.enqueueRotate(this.file);
|
|
23214
|
-
const line = `${JSON.stringify(entry)}
|
|
23215
|
-
`;
|
|
23216
|
-
this._tail = this._tail.then(() => fsp11.appendFile(this.file, line)).catch(() => void 0);
|
|
23217
|
-
}
|
|
23218
|
-
if (!this.stderr) return;
|
|
23219
|
-
if (this.format === "json") {
|
|
23220
|
-
writeErr(`${JSON.stringify(entry)}
|
|
23221
|
-
`);
|
|
23222
|
-
} else {
|
|
23223
|
-
const head = `${color.dim(ts)} ${COLORS[level](level.toUpperCase().padEnd(5))} ${msg}`;
|
|
23224
|
-
if (ctx !== void 0) {
|
|
23225
|
-
writeErr(`${head} ${formatCtx(ctx)}
|
|
23226
|
-
`);
|
|
23227
|
-
} else {
|
|
23228
|
-
writeErr(`${head}
|
|
23229
|
-
`);
|
|
23230
|
-
}
|
|
23231
|
-
}
|
|
23232
|
-
}
|
|
23233
|
-
};
|
|
23234
|
-
function parseLogLevel(raw) {
|
|
23235
|
-
return raw && LOG_LEVELS.has(raw) ? raw : "info";
|
|
23236
|
-
}
|
|
23237
|
-
function parseLogFormat(raw) {
|
|
23238
|
-
return raw && LOG_FORMATS.has(raw) ? raw : "pretty";
|
|
23239
|
-
}
|
|
23240
|
-
function formatCtx(ctx) {
|
|
23241
|
-
if (ctx instanceof Error) return color.dim(ctx.message);
|
|
23242
|
-
if (typeof ctx === "string") return color.dim(ctx);
|
|
23243
|
-
try {
|
|
23244
|
-
return color.dim(JSON.stringify(ctx));
|
|
23245
|
-
} catch {
|
|
23246
|
-
return color.dim(String(ctx));
|
|
23247
|
-
}
|
|
23248
|
-
}
|
|
23249
|
-
|
|
23250
23300
|
// src/infrastructure/mcp-servers.ts
|
|
23251
23301
|
var filesystemServer = () => ({
|
|
23252
23302
|
name: "filesystem",
|
|
@@ -23825,6 +23875,7 @@ var DefaultModelsRegistry = class {
|
|
|
23825
23875
|
overlayUrl;
|
|
23826
23876
|
overlayFile;
|
|
23827
23877
|
overlayCacheFile;
|
|
23878
|
+
logger;
|
|
23828
23879
|
constructor(opts) {
|
|
23829
23880
|
this.cacheFile = opts.cacheFile;
|
|
23830
23881
|
this.url = opts.url ?? process.env[ENV_URL_KEY] ?? DEFAULT_URL;
|
|
@@ -23838,6 +23889,7 @@ var DefaultModelsRegistry = class {
|
|
|
23838
23889
|
this.overlayUrl = opts.overlayUrl;
|
|
23839
23890
|
this.overlayFile = opts.overlayFile;
|
|
23840
23891
|
this.overlayCacheFile = opts.overlayCacheFile ?? (opts.overlayUrl ? path24.join(path24.dirname(opts.cacheFile), "models-overlay-cache.json") : void 0);
|
|
23892
|
+
this.logger = opts.logger ?? noOpLogger;
|
|
23841
23893
|
}
|
|
23842
23894
|
async load(opts = {}) {
|
|
23843
23895
|
if (this.payload && !opts.force) return this.payload;
|
|
@@ -23886,16 +23938,18 @@ var DefaultModelsRegistry = class {
|
|
|
23886
23938
|
if (cached && this.isWithinMaxStaleAge(cached.fetchedAt)) {
|
|
23887
23939
|
this.fetchedAt = new Date(cached.fetchedAt);
|
|
23888
23940
|
const ageSeconds = Math.floor((Date.now() - this.fetchedAt.getTime()) / 1e3);
|
|
23889
|
-
|
|
23890
|
-
`ModelsRegistry: models.dev unavailable (${toErrorMessage(err)}); using stale cache from ${formatAge(ageSeconds)} ago. Run \`wstack models refresh\` to retry
|
|
23941
|
+
this.logger.warn(
|
|
23942
|
+
`ModelsRegistry: models.dev unavailable (${toErrorMessage(err)}); using stale cache from ${formatAge(ageSeconds)} ago. Run \`wstack models refresh\` to retry.`,
|
|
23943
|
+
{ event: "models_registry.stale_cache_fallback" }
|
|
23891
23944
|
);
|
|
23892
23945
|
return cached.payload;
|
|
23893
23946
|
}
|
|
23894
23947
|
if (overlayAvailable) {
|
|
23895
|
-
|
|
23948
|
+
this.logger.warn(
|
|
23896
23949
|
`ModelsRegistry: models.dev unavailable (${toErrorMessage(
|
|
23897
23950
|
err
|
|
23898
|
-
)}); serving curated overlay only
|
|
23951
|
+
)}); serving curated overlay only.`,
|
|
23952
|
+
{ event: "models_registry.overlay_only_fallback" }
|
|
23899
23953
|
);
|
|
23900
23954
|
return {};
|
|
23901
23955
|
}
|
|
@@ -23991,8 +24045,9 @@ var DefaultModelsRegistry = class {
|
|
|
23991
24045
|
const cached = await this.readCacheAt(this.overlayCacheFile);
|
|
23992
24046
|
if (cached && this.isWithinMaxStaleAge(cached.fetchedAt)) {
|
|
23993
24047
|
const ageSeconds = Math.floor((Date.now() - new Date(cached.fetchedAt).getTime()) / 1e3);
|
|
23994
|
-
|
|
23995
|
-
`ModelsRegistry: overlay unavailable; using stale overlay from ${formatAge(ageSeconds)} ago
|
|
24048
|
+
this.logger.warn(
|
|
24049
|
+
`ModelsRegistry: overlay unavailable; using stale overlay from ${formatAge(ageSeconds)} ago.`,
|
|
24050
|
+
{ event: "models_registry.overlay_stale_fallback", ageSeconds }
|
|
23996
24051
|
);
|
|
23997
24052
|
return cached.payload;
|
|
23998
24053
|
}
|
|
@@ -25145,9 +25200,6 @@ var DefaultPermissionPolicy = class {
|
|
|
25145
25200
|
loaded = false;
|
|
25146
25201
|
trustFile;
|
|
25147
25202
|
yolo;
|
|
25148
|
-
yoloDestructive;
|
|
25149
|
-
/** Deprecated compatibility flag; no longer gates YOLO calls. */
|
|
25150
|
-
confirmDestructive;
|
|
25151
25203
|
/**
|
|
25152
25204
|
* Session-scoped "soft deny" map. When the user presses 'n' (block once),
|
|
25153
25205
|
* the tool+pattern is added here. If the LLM retries in the same session,
|
|
@@ -25200,8 +25252,6 @@ var DefaultPermissionPolicy = class {
|
|
|
25200
25252
|
constructor(opts) {
|
|
25201
25253
|
this.trustFile = opts.trustFile;
|
|
25202
25254
|
this.yolo = opts.yolo ?? false;
|
|
25203
|
-
this.yoloDestructive = opts.yoloDestructive ?? opts.forceAllYolo ?? false;
|
|
25204
|
-
this.confirmDestructive = opts.confirmDestructive ?? false;
|
|
25205
25255
|
this.promptDelegate = opts.promptDelegate;
|
|
25206
25256
|
}
|
|
25207
25257
|
/**
|
|
@@ -25222,24 +25272,6 @@ var DefaultPermissionPolicy = class {
|
|
|
25222
25272
|
getYolo() {
|
|
25223
25273
|
return this.yolo;
|
|
25224
25274
|
}
|
|
25225
|
-
/** Toggle the destructive YOLO override at runtime. */
|
|
25226
|
-
setYoloDestructive(enabled) {
|
|
25227
|
-
if (this.yoloDestructive !== enabled) this._evalCache.clear();
|
|
25228
|
-
this.yoloDestructive = enabled;
|
|
25229
|
-
}
|
|
25230
|
-
/** Check whether the destructive YOLO override is active. */
|
|
25231
|
-
getYoloDestructive() {
|
|
25232
|
-
return this.yoloDestructive;
|
|
25233
|
-
}
|
|
25234
|
-
/** Toggle deprecated destructive confirmation compatibility flag. */
|
|
25235
|
-
setConfirmDestructive(enabled) {
|
|
25236
|
-
if (this.confirmDestructive !== enabled) this._evalCache.clear();
|
|
25237
|
-
this.confirmDestructive = enabled;
|
|
25238
|
-
}
|
|
25239
|
-
/** Check deprecated destructive confirmation compatibility flag. */
|
|
25240
|
-
getConfirmDestructive() {
|
|
25241
|
-
return this.confirmDestructive;
|
|
25242
|
-
}
|
|
25243
25275
|
/** Read-only diagnostics for policy inspector/editor surfaces. */
|
|
25244
25276
|
getPolicyDiagnostics() {
|
|
25245
25277
|
return this.policyDiagnostics.map((diagnostic) => ({ ...diagnostic }));
|
|
@@ -26540,9 +26572,10 @@ var BEHAVIOR_DEFAULTS = {
|
|
|
26540
26572
|
prompts: true,
|
|
26541
26573
|
// 'auto' → resolveTokenSavingTier picks a concrete tier from the model's
|
|
26542
26574
|
// context window ONCE per session (cache-safe): lean prompt on small
|
|
26543
|
-
// windows (<32k medium, <
|
|
26544
|
-
// a big fraction;
|
|
26545
|
-
//
|
|
26575
|
+
// windows (<32k medium, <128k light) where the fixed identity+tool prose
|
|
26576
|
+
// is a big fraction; minimal trimming on >=128k so modern large-window
|
|
26577
|
+
// models still get cost savings without capability loss. Explicit tiers
|
|
26578
|
+
// are respected verbatim.
|
|
26546
26579
|
tokenSavingMode: "auto",
|
|
26547
26580
|
allowOutsideProjectRoot: true
|
|
26548
26581
|
},
|
|
@@ -26610,7 +26643,7 @@ var BEHAVIOR_DEFAULTS = {
|
|
|
26610
26643
|
// Mirrored from the top-level yolo default so the autonomy subsystem
|
|
26611
26644
|
// (which reads autonomy.yolo) stays consistent with config.yolo.
|
|
26612
26645
|
yolo: false,
|
|
26613
|
-
|
|
26646
|
+
fleetChatVerbosity: "off",
|
|
26614
26647
|
chime: false,
|
|
26615
26648
|
confirmExit: true,
|
|
26616
26649
|
mouseMode: false,
|
|
@@ -26628,7 +26661,7 @@ var BEHAVIOR_DEFAULTS = {
|
|
|
26628
26661
|
// silently omitted, and surfaced as a per-request warning. Users who
|
|
26629
26662
|
// want a specific effort can opt in via `/settings` or the WebUI panel.
|
|
26630
26663
|
reasoning: { mode: "auto" },
|
|
26631
|
-
cache: {}
|
|
26664
|
+
cache: { ttl: "1h" }
|
|
26632
26665
|
}
|
|
26633
26666
|
};
|
|
26634
26667
|
function isPlainRecord(value) {
|