@mindstudio-ai/remy 0.1.312 → 0.1.313
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/headless.d.ts +3 -2
- package/dist/headless.js +96 -45
- package/dist/index.js +98 -47
- package/package.json +1 -1
package/dist/headless.d.ts
CHANGED
|
@@ -122,8 +122,9 @@ declare class HeadlessSession {
|
|
|
122
122
|
/** Apply queued tool block updates to state.messages. Safe to call any time. */
|
|
123
123
|
private applyPendingBlockUpdates;
|
|
124
124
|
/**
|
|
125
|
-
* Forced compaction gate. If lastContextSize exceeds the
|
|
126
|
-
*
|
|
125
|
+
* Forced compaction gate. If lastContextSize exceeds the upcoming turn's
|
|
126
|
+
* model threshold (per-model — see ModelContextLimits in models/surfaces),
|
|
127
|
+
* compact before letting the turn run. Coalesces with any in-flight
|
|
127
128
|
* compaction (e.g., one already started by /compact or a tool call). No
|
|
128
129
|
* timeout — compaction takes as long as it takes.
|
|
129
130
|
*
|
package/dist/headless.js
CHANGED
|
@@ -486,37 +486,59 @@ var MODEL_SURFACES = {
|
|
|
486
486
|
userPickable: false
|
|
487
487
|
}
|
|
488
488
|
};
|
|
489
|
+
var DEFAULT_SUGGEST_COMPACT_AT = 3e5;
|
|
490
|
+
var TEXT_MODELS = {
|
|
491
|
+
// Anthropic 1M-context, flat-priced.
|
|
492
|
+
"claude-5-opus": { forceCompactAt: 85e4 },
|
|
493
|
+
"claude-4-8-opus": { forceCompactAt: 85e4 },
|
|
494
|
+
"claude-4-7-opus": { forceCompactAt: 85e4 },
|
|
495
|
+
// Anthropic 1M-context with 2x long-context pricing above 200K input.
|
|
496
|
+
"claude-4-6-opus": { forceCompactAt: 85e4, suggestCompactAt: 18e4 },
|
|
497
|
+
"claude-4-6-sonnet": { forceCompactAt: 85e4, suggestCompactAt: 18e4 },
|
|
498
|
+
"claude-fable-5": { forceCompactAt: 85e4 },
|
|
499
|
+
"claude-fable-5-1": { forceCompactAt: 85e4 },
|
|
500
|
+
"claude-5-sonnet": { forceCompactAt: 85e4 },
|
|
501
|
+
// OpenAI gpt-5.5/5.6: ~1M window, but the usable input ceiling under
|
|
502
|
+
// `truncation: 'auto'` is ~794K (output + reasoning reserve), and all
|
|
503
|
+
// rates double above 272K input.
|
|
504
|
+
"gpt-5.5": { forceCompactAt: 6e5, suggestCompactAt: 25e4 },
|
|
505
|
+
"gpt-5.6-sol": { forceCompactAt: 6e5, suggestCompactAt: 25e4 },
|
|
506
|
+
"gpt-5.6-terra": { forceCompactAt: 6e5, suggestCompactAt: 25e4 },
|
|
507
|
+
"gpt-5.6-luna": { forceCompactAt: 6e5, suggestCompactAt: 25e4 },
|
|
508
|
+
// Google ~1M-context; only 3.1-pro is tiered (higher rates above 200K).
|
|
509
|
+
"gemini-3-pro": { forceCompactAt: 85e4 },
|
|
510
|
+
"gemini-3.1-pro": { forceCompactAt: 85e4, suggestCompactAt: 18e4 },
|
|
511
|
+
"gemini-3-flash": { forceCompactAt: 85e4 },
|
|
512
|
+
"gemini-3.5-flash": { forceCompactAt: 85e4 },
|
|
513
|
+
"gemini-3.7-flash": { forceCompactAt: 85e4 },
|
|
514
|
+
// 256K window; its 200K pricing tier sits above the gate, so no nudge.
|
|
515
|
+
"grok-build-0.1": { forceCompactAt: 18e4 },
|
|
516
|
+
"grok-4.5": { forceCompactAt: 4e5 },
|
|
517
|
+
// 500K window
|
|
518
|
+
"grok-4.6": { forceCompactAt: 4e5 },
|
|
519
|
+
// 500K window
|
|
520
|
+
"glm-5.2": { forceCompactAt: 85e4 },
|
|
521
|
+
"muse-spark-1.1": { forceCompactAt: 85e4 },
|
|
522
|
+
"kimi-k2-7-code": { forceCompactAt: 2e5 },
|
|
523
|
+
// 262K window
|
|
524
|
+
"kimi-k3": { forceCompactAt: 85e4 },
|
|
525
|
+
"deepseek-v4-flash-0731": { forceCompactAt: 85e4 },
|
|
526
|
+
"qwen3.8-2.4t-a95b-deepinfra": { forceCompactAt: 2e5 },
|
|
527
|
+
// 262K window
|
|
528
|
+
"qwen3.8-27b-deepinfra": { forceCompactAt: 2e5 },
|
|
529
|
+
// 262K window
|
|
530
|
+
"minimax-m3": { forceCompactAt: 42e4 }
|
|
531
|
+
// 524K window
|
|
532
|
+
};
|
|
533
|
+
var DEFAULT_CONTEXT_LIMITS = { forceCompactAt: 85e4 };
|
|
534
|
+
function getContextLimits(modelId) {
|
|
535
|
+
return TEXT_MODELS[modelId] ?? DEFAULT_CONTEXT_LIMITS;
|
|
536
|
+
}
|
|
537
|
+
function getSuggestCompactAt(modelId) {
|
|
538
|
+
return getContextLimits(modelId).suggestCompactAt ?? DEFAULT_SUGGEST_COMPACT_AT;
|
|
539
|
+
}
|
|
489
540
|
var ALLOWED_MODELS_BY_TYPE = {
|
|
490
|
-
text:
|
|
491
|
-
"claude-5-opus",
|
|
492
|
-
"claude-4-8-opus",
|
|
493
|
-
"claude-4-7-opus",
|
|
494
|
-
"claude-4-6-opus",
|
|
495
|
-
"claude-4-6-sonnet",
|
|
496
|
-
"claude-fable-5",
|
|
497
|
-
"claude-fable-5-1",
|
|
498
|
-
"claude-5-sonnet",
|
|
499
|
-
"gpt-5.5",
|
|
500
|
-
"gpt-5.6-sol",
|
|
501
|
-
"gpt-5.6-terra",
|
|
502
|
-
"gpt-5.6-luna",
|
|
503
|
-
"gemini-3-pro",
|
|
504
|
-
"gemini-3.1-pro",
|
|
505
|
-
"gemini-3-flash",
|
|
506
|
-
"gemini-3.5-flash",
|
|
507
|
-
"gemini-3.7-flash",
|
|
508
|
-
"grok-build-0.1",
|
|
509
|
-
"grok-4.5",
|
|
510
|
-
"grok-4.6",
|
|
511
|
-
"glm-5.2",
|
|
512
|
-
"muse-spark-1.1",
|
|
513
|
-
"kimi-k2-7-code",
|
|
514
|
-
"kimi-k3",
|
|
515
|
-
"deepseek-v4-flash-0731",
|
|
516
|
-
"qwen3.8-2.4t-a95b-deepinfra",
|
|
517
|
-
"qwen3.8-27b-deepinfra",
|
|
518
|
-
"minimax-m3"
|
|
519
|
-
]
|
|
541
|
+
text: Object.keys(TEXT_MODELS)
|
|
520
542
|
// vision: undefined — unconstrained
|
|
521
543
|
// image_generation: undefined — unconstrained
|
|
522
544
|
};
|
|
@@ -559,6 +581,11 @@ function getEffectiveModelSurfaces() {
|
|
|
559
581
|
function resolveModel(surfaceId, models, fallback) {
|
|
560
582
|
return models?.[surfaceId] ?? fallback ?? orgDefaultModels[surfaceId] ?? MODEL_SURFACES[surfaceId].default;
|
|
561
583
|
}
|
|
584
|
+
function resolveParentModel(models, fallback, buildModel) {
|
|
585
|
+
const override = buildModel ? filterModelPicks({ parent: buildModel }).parent : void 0;
|
|
586
|
+
const baseline = resolveModel("parent", models, fallback);
|
|
587
|
+
return { baseline, effective: override ?? baseline };
|
|
588
|
+
}
|
|
562
589
|
|
|
563
590
|
// src/orgContext.ts
|
|
564
591
|
var log3 = createLogger("orgContext");
|
|
@@ -8616,6 +8643,12 @@ function classify(line, matches) {
|
|
|
8616
8643
|
tailClean = SEPARATORS_ONLY.test(gap);
|
|
8617
8644
|
}
|
|
8618
8645
|
}
|
|
8646
|
+
function chipCase(label) {
|
|
8647
|
+
if (label.startsWith("`")) {
|
|
8648
|
+
return label;
|
|
8649
|
+
}
|
|
8650
|
+
return label.charAt(0).toUpperCase() + label.slice(1);
|
|
8651
|
+
}
|
|
8619
8652
|
function parseSuggestions(raw) {
|
|
8620
8653
|
if (!raw.includes(SUGGEST_MARKER)) {
|
|
8621
8654
|
return { text: raw, suggestions: [] };
|
|
@@ -8645,7 +8678,7 @@ function parseSuggestions(raw) {
|
|
|
8645
8678
|
const key = `${m.label}::${m.message}`;
|
|
8646
8679
|
if (!seen.has(key)) {
|
|
8647
8680
|
seen.add(key);
|
|
8648
|
-
suggestions.push({ label: m.label, message: m.message });
|
|
8681
|
+
suggestions.push({ label: chipCase(m.label), message: m.message });
|
|
8649
8682
|
}
|
|
8650
8683
|
}
|
|
8651
8684
|
let rebuilt = "";
|
|
@@ -8745,10 +8778,12 @@ async function runTurn(params) {
|
|
|
8745
8778
|
onBackgroundComplete
|
|
8746
8779
|
} = params;
|
|
8747
8780
|
const tools2 = getToolDefinitions();
|
|
8748
|
-
const
|
|
8749
|
-
|
|
8750
|
-
|
|
8751
|
-
|
|
8781
|
+
const { baseline, effective: parentModel } = resolveParentModel(
|
|
8782
|
+
state.models,
|
|
8783
|
+
model,
|
|
8784
|
+
buildModel
|
|
8785
|
+
);
|
|
8786
|
+
const modelOverride = parentModel !== baseline ? { from: baseline } : void 0;
|
|
8752
8787
|
const totalAttachments = entries.reduce(
|
|
8753
8788
|
(n, e) => n + (e.attachments?.length ?? 0),
|
|
8754
8789
|
0
|
|
@@ -8756,7 +8791,7 @@ async function runTurn(params) {
|
|
|
8756
8791
|
log15.info("Turn started", {
|
|
8757
8792
|
requestId,
|
|
8758
8793
|
model,
|
|
8759
|
-
buildModel:
|
|
8794
|
+
buildModel: modelOverride ? parentModel : void 0,
|
|
8760
8795
|
toolCount: tools2.length,
|
|
8761
8796
|
...entries.length > 1 && { entryCount: entries.length },
|
|
8762
8797
|
...totalAttachments > 0 && { attachmentCount: totalAttachments }
|
|
@@ -9591,12 +9626,13 @@ function loadPassiveResults() {
|
|
|
9591
9626
|
}
|
|
9592
9627
|
return [];
|
|
9593
9628
|
}
|
|
9594
|
-
function writeStats(stats, queue, passiveResults) {
|
|
9629
|
+
function writeStats(stats, queue, passiveResults, suggestCompactAt) {
|
|
9595
9630
|
try {
|
|
9596
9631
|
writeFileAtomicSync(
|
|
9597
9632
|
STATS_FILE,
|
|
9598
9633
|
JSON.stringify({
|
|
9599
9634
|
...stats,
|
|
9635
|
+
suggestCompactAt,
|
|
9600
9636
|
queue,
|
|
9601
9637
|
passiveResults
|
|
9602
9638
|
})
|
|
@@ -9798,7 +9834,6 @@ var USER_FACING_TOOLS = /* @__PURE__ */ new Set([
|
|
|
9798
9834
|
"confirmDestructiveAction",
|
|
9799
9835
|
"presentPublishPlan"
|
|
9800
9836
|
]);
|
|
9801
|
-
var FORCED_COMPACTION_THRESHOLD_TOKENS = 85e4;
|
|
9802
9837
|
var HeadlessSession = class {
|
|
9803
9838
|
// Configuration
|
|
9804
9839
|
opts;
|
|
@@ -10071,7 +10106,15 @@ var HeadlessSession = class {
|
|
|
10071
10106
|
/** Persist sessionStats + queue snapshot + passive pen to .remy-stats.json. */
|
|
10072
10107
|
persistStats() {
|
|
10073
10108
|
this.sessionStats.updatedAt = Date.now();
|
|
10074
|
-
|
|
10109
|
+
const suggestCompactAt = getSuggestCompactAt(
|
|
10110
|
+
resolveParentModel(this.state.models, this.opts.model).effective
|
|
10111
|
+
);
|
|
10112
|
+
writeStats(
|
|
10113
|
+
this.sessionStats,
|
|
10114
|
+
this.queue.snapshot(),
|
|
10115
|
+
this.passivePen,
|
|
10116
|
+
suggestCompactAt
|
|
10117
|
+
);
|
|
10075
10118
|
}
|
|
10076
10119
|
//////////////////////////////////////////////////////////////////////////////
|
|
10077
10120
|
// Background completions (tool-block mutation; message delivery via queue)
|
|
@@ -10101,8 +10144,9 @@ var HeadlessSession = class {
|
|
|
10101
10144
|
saveSession(this.state);
|
|
10102
10145
|
}
|
|
10103
10146
|
/**
|
|
10104
|
-
* Forced compaction gate. If lastContextSize exceeds the
|
|
10105
|
-
*
|
|
10147
|
+
* Forced compaction gate. If lastContextSize exceeds the upcoming turn's
|
|
10148
|
+
* model threshold (per-model — see ModelContextLimits in models/surfaces),
|
|
10149
|
+
* compact before letting the turn run. Coalesces with any in-flight
|
|
10106
10150
|
* compaction (e.g., one already started by /compact or a tool call). No
|
|
10107
10151
|
* timeout — compaction takes as long as it takes.
|
|
10108
10152
|
*
|
|
@@ -10113,13 +10157,15 @@ var HeadlessSession = class {
|
|
|
10113
10157
|
* On compaction failure we don't bail — the turn proceeds and surfaces any
|
|
10114
10158
|
* downstream overflow through the existing "prompt is too long" path.
|
|
10115
10159
|
*/
|
|
10116
|
-
async runForcedCompactionIfNeeded(requestId) {
|
|
10117
|
-
|
|
10160
|
+
async runForcedCompactionIfNeeded(requestId, parentModel) {
|
|
10161
|
+
const threshold = getContextLimits(parentModel).forceCompactAt;
|
|
10162
|
+
if (this.sessionStats.lastContextSize <= threshold) {
|
|
10118
10163
|
return;
|
|
10119
10164
|
}
|
|
10120
10165
|
log17.info("Forced compaction gate triggered", {
|
|
10121
10166
|
contextSize: this.sessionStats.lastContextSize,
|
|
10122
|
-
threshold
|
|
10167
|
+
threshold,
|
|
10168
|
+
model: parentModel,
|
|
10123
10169
|
requestId
|
|
10124
10170
|
});
|
|
10125
10171
|
try {
|
|
@@ -10601,7 +10647,12 @@ var HeadlessSession = class {
|
|
|
10601
10647
|
}
|
|
10602
10648
|
return steered;
|
|
10603
10649
|
};
|
|
10604
|
-
|
|
10650
|
+
const parentModel = resolveParentModel(
|
|
10651
|
+
this.state.models,
|
|
10652
|
+
this.opts.model,
|
|
10653
|
+
params.buildModel
|
|
10654
|
+
).effective;
|
|
10655
|
+
await this.runForcedCompactionIfNeeded(requestId, parentModel);
|
|
10605
10656
|
try {
|
|
10606
10657
|
await runTurn({
|
|
10607
10658
|
state: this.state,
|
package/dist/index.js
CHANGED
|
@@ -2111,6 +2111,12 @@ var init_compaction = __esm({
|
|
|
2111
2111
|
});
|
|
2112
2112
|
|
|
2113
2113
|
// src/models/surfaces.ts
|
|
2114
|
+
function getContextLimits(modelId) {
|
|
2115
|
+
return TEXT_MODELS[modelId] ?? DEFAULT_CONTEXT_LIMITS;
|
|
2116
|
+
}
|
|
2117
|
+
function getSuggestCompactAt(modelId) {
|
|
2118
|
+
return getContextLimits(modelId).suggestCompactAt ?? DEFAULT_SUGGEST_COMPACT_AT;
|
|
2119
|
+
}
|
|
2114
2120
|
function setOrgDefaultModels(models) {
|
|
2115
2121
|
orgDefaultModels = models;
|
|
2116
2122
|
}
|
|
@@ -2149,7 +2155,12 @@ function getEffectiveModelSurfaces() {
|
|
|
2149
2155
|
function resolveModel(surfaceId, models, fallback) {
|
|
2150
2156
|
return models?.[surfaceId] ?? fallback ?? orgDefaultModels[surfaceId] ?? MODEL_SURFACES[surfaceId].default;
|
|
2151
2157
|
}
|
|
2152
|
-
|
|
2158
|
+
function resolveParentModel(models, fallback, buildModel) {
|
|
2159
|
+
const override = buildModel ? filterModelPicks({ parent: buildModel }).parent : void 0;
|
|
2160
|
+
const baseline = resolveModel("parent", models, fallback);
|
|
2161
|
+
return { baseline, effective: override ?? baseline };
|
|
2162
|
+
}
|
|
2163
|
+
var MODEL_SURFACES, DEFAULT_SUGGEST_COMPACT_AT, TEXT_MODELS, DEFAULT_CONTEXT_LIMITS, ALLOWED_MODELS_BY_TYPE, orgDefaultModels;
|
|
2153
2164
|
var init_surfaces = __esm({
|
|
2154
2165
|
"src/models/surfaces.ts"() {
|
|
2155
2166
|
"use strict";
|
|
@@ -2241,37 +2252,53 @@ var init_surfaces = __esm({
|
|
|
2241
2252
|
userPickable: false
|
|
2242
2253
|
}
|
|
2243
2254
|
};
|
|
2255
|
+
DEFAULT_SUGGEST_COMPACT_AT = 3e5;
|
|
2256
|
+
TEXT_MODELS = {
|
|
2257
|
+
// Anthropic 1M-context, flat-priced.
|
|
2258
|
+
"claude-5-opus": { forceCompactAt: 85e4 },
|
|
2259
|
+
"claude-4-8-opus": { forceCompactAt: 85e4 },
|
|
2260
|
+
"claude-4-7-opus": { forceCompactAt: 85e4 },
|
|
2261
|
+
// Anthropic 1M-context with 2x long-context pricing above 200K input.
|
|
2262
|
+
"claude-4-6-opus": { forceCompactAt: 85e4, suggestCompactAt: 18e4 },
|
|
2263
|
+
"claude-4-6-sonnet": { forceCompactAt: 85e4, suggestCompactAt: 18e4 },
|
|
2264
|
+
"claude-fable-5": { forceCompactAt: 85e4 },
|
|
2265
|
+
"claude-fable-5-1": { forceCompactAt: 85e4 },
|
|
2266
|
+
"claude-5-sonnet": { forceCompactAt: 85e4 },
|
|
2267
|
+
// OpenAI gpt-5.5/5.6: ~1M window, but the usable input ceiling under
|
|
2268
|
+
// `truncation: 'auto'` is ~794K (output + reasoning reserve), and all
|
|
2269
|
+
// rates double above 272K input.
|
|
2270
|
+
"gpt-5.5": { forceCompactAt: 6e5, suggestCompactAt: 25e4 },
|
|
2271
|
+
"gpt-5.6-sol": { forceCompactAt: 6e5, suggestCompactAt: 25e4 },
|
|
2272
|
+
"gpt-5.6-terra": { forceCompactAt: 6e5, suggestCompactAt: 25e4 },
|
|
2273
|
+
"gpt-5.6-luna": { forceCompactAt: 6e5, suggestCompactAt: 25e4 },
|
|
2274
|
+
// Google ~1M-context; only 3.1-pro is tiered (higher rates above 200K).
|
|
2275
|
+
"gemini-3-pro": { forceCompactAt: 85e4 },
|
|
2276
|
+
"gemini-3.1-pro": { forceCompactAt: 85e4, suggestCompactAt: 18e4 },
|
|
2277
|
+
"gemini-3-flash": { forceCompactAt: 85e4 },
|
|
2278
|
+
"gemini-3.5-flash": { forceCompactAt: 85e4 },
|
|
2279
|
+
"gemini-3.7-flash": { forceCompactAt: 85e4 },
|
|
2280
|
+
// 256K window; its 200K pricing tier sits above the gate, so no nudge.
|
|
2281
|
+
"grok-build-0.1": { forceCompactAt: 18e4 },
|
|
2282
|
+
"grok-4.5": { forceCompactAt: 4e5 },
|
|
2283
|
+
// 500K window
|
|
2284
|
+
"grok-4.6": { forceCompactAt: 4e5 },
|
|
2285
|
+
// 500K window
|
|
2286
|
+
"glm-5.2": { forceCompactAt: 85e4 },
|
|
2287
|
+
"muse-spark-1.1": { forceCompactAt: 85e4 },
|
|
2288
|
+
"kimi-k2-7-code": { forceCompactAt: 2e5 },
|
|
2289
|
+
// 262K window
|
|
2290
|
+
"kimi-k3": { forceCompactAt: 85e4 },
|
|
2291
|
+
"deepseek-v4-flash-0731": { forceCompactAt: 85e4 },
|
|
2292
|
+
"qwen3.8-2.4t-a95b-deepinfra": { forceCompactAt: 2e5 },
|
|
2293
|
+
// 262K window
|
|
2294
|
+
"qwen3.8-27b-deepinfra": { forceCompactAt: 2e5 },
|
|
2295
|
+
// 262K window
|
|
2296
|
+
"minimax-m3": { forceCompactAt: 42e4 }
|
|
2297
|
+
// 524K window
|
|
2298
|
+
};
|
|
2299
|
+
DEFAULT_CONTEXT_LIMITS = { forceCompactAt: 85e4 };
|
|
2244
2300
|
ALLOWED_MODELS_BY_TYPE = {
|
|
2245
|
-
text:
|
|
2246
|
-
"claude-5-opus",
|
|
2247
|
-
"claude-4-8-opus",
|
|
2248
|
-
"claude-4-7-opus",
|
|
2249
|
-
"claude-4-6-opus",
|
|
2250
|
-
"claude-4-6-sonnet",
|
|
2251
|
-
"claude-fable-5",
|
|
2252
|
-
"claude-fable-5-1",
|
|
2253
|
-
"claude-5-sonnet",
|
|
2254
|
-
"gpt-5.5",
|
|
2255
|
-
"gpt-5.6-sol",
|
|
2256
|
-
"gpt-5.6-terra",
|
|
2257
|
-
"gpt-5.6-luna",
|
|
2258
|
-
"gemini-3-pro",
|
|
2259
|
-
"gemini-3.1-pro",
|
|
2260
|
-
"gemini-3-flash",
|
|
2261
|
-
"gemini-3.5-flash",
|
|
2262
|
-
"gemini-3.7-flash",
|
|
2263
|
-
"grok-build-0.1",
|
|
2264
|
-
"grok-4.5",
|
|
2265
|
-
"grok-4.6",
|
|
2266
|
-
"glm-5.2",
|
|
2267
|
-
"muse-spark-1.1",
|
|
2268
|
-
"kimi-k2-7-code",
|
|
2269
|
-
"kimi-k3",
|
|
2270
|
-
"deepseek-v4-flash-0731",
|
|
2271
|
-
"qwen3.8-2.4t-a95b-deepinfra",
|
|
2272
|
-
"qwen3.8-27b-deepinfra",
|
|
2273
|
-
"minimax-m3"
|
|
2274
|
-
]
|
|
2301
|
+
text: Object.keys(TEXT_MODELS)
|
|
2275
2302
|
// vision: undefined — unconstrained
|
|
2276
2303
|
// image_generation: undefined — unconstrained
|
|
2277
2304
|
};
|
|
@@ -8921,6 +8948,12 @@ function classify(line, matches) {
|
|
|
8921
8948
|
tailClean = SEPARATORS_ONLY.test(gap);
|
|
8922
8949
|
}
|
|
8923
8950
|
}
|
|
8951
|
+
function chipCase(label) {
|
|
8952
|
+
if (label.startsWith("`")) {
|
|
8953
|
+
return label;
|
|
8954
|
+
}
|
|
8955
|
+
return label.charAt(0).toUpperCase() + label.slice(1);
|
|
8956
|
+
}
|
|
8924
8957
|
function parseSuggestions(raw) {
|
|
8925
8958
|
if (!raw.includes(SUGGEST_MARKER)) {
|
|
8926
8959
|
return { text: raw, suggestions: [] };
|
|
@@ -8950,7 +8983,7 @@ function parseSuggestions(raw) {
|
|
|
8950
8983
|
const key = `${m.label}::${m.message}`;
|
|
8951
8984
|
if (!seen.has(key)) {
|
|
8952
8985
|
seen.add(key);
|
|
8953
|
-
suggestions.push({ label: m.label, message: m.message });
|
|
8986
|
+
suggestions.push({ label: chipCase(m.label), message: m.message });
|
|
8954
8987
|
}
|
|
8955
8988
|
}
|
|
8956
8989
|
let rebuilt = "";
|
|
@@ -9401,10 +9434,12 @@ async function runTurn(params) {
|
|
|
9401
9434
|
onBackgroundComplete
|
|
9402
9435
|
} = params;
|
|
9403
9436
|
const tools2 = getToolDefinitions();
|
|
9404
|
-
const
|
|
9405
|
-
|
|
9406
|
-
|
|
9407
|
-
|
|
9437
|
+
const { baseline, effective: parentModel } = resolveParentModel(
|
|
9438
|
+
state.models,
|
|
9439
|
+
model,
|
|
9440
|
+
buildModel
|
|
9441
|
+
);
|
|
9442
|
+
const modelOverride = parentModel !== baseline ? { from: baseline } : void 0;
|
|
9408
9443
|
const totalAttachments = entries.reduce(
|
|
9409
9444
|
(n, e) => n + (e.attachments?.length ?? 0),
|
|
9410
9445
|
0
|
|
@@ -9412,7 +9447,7 @@ async function runTurn(params) {
|
|
|
9412
9447
|
log14.info("Turn started", {
|
|
9413
9448
|
requestId,
|
|
9414
9449
|
model,
|
|
9415
|
-
buildModel:
|
|
9450
|
+
buildModel: modelOverride ? parentModel : void 0,
|
|
9416
9451
|
toolCount: tools2.length,
|
|
9417
9452
|
...entries.length > 1 && { entryCount: entries.length },
|
|
9418
9453
|
...totalAttachments > 0 && { attachmentCount: totalAttachments }
|
|
@@ -10551,12 +10586,13 @@ function loadPassiveResults() {
|
|
|
10551
10586
|
}
|
|
10552
10587
|
return [];
|
|
10553
10588
|
}
|
|
10554
|
-
function writeStats(stats, queue, passiveResults) {
|
|
10589
|
+
function writeStats(stats, queue, passiveResults, suggestCompactAt) {
|
|
10555
10590
|
try {
|
|
10556
10591
|
writeFileAtomicSync(
|
|
10557
10592
|
STATS_FILE,
|
|
10558
10593
|
JSON.stringify({
|
|
10559
10594
|
...stats,
|
|
10595
|
+
suggestCompactAt,
|
|
10560
10596
|
queue,
|
|
10561
10597
|
passiveResults
|
|
10562
10598
|
})
|
|
@@ -10767,7 +10803,7 @@ var headless_exports = {};
|
|
|
10767
10803
|
__export(headless_exports, {
|
|
10768
10804
|
HeadlessSession: () => HeadlessSession
|
|
10769
10805
|
});
|
|
10770
|
-
var log17, EXTERNAL_TOOL_TIMEOUT_MS, LONG_RUNNING_TOOLS, LONG_RUNNING_TOOL_TIMEOUT_MS, USER_FACING_TOOLS,
|
|
10806
|
+
var log17, EXTERNAL_TOOL_TIMEOUT_MS, LONG_RUNNING_TOOLS, LONG_RUNNING_TOOL_TIMEOUT_MS, USER_FACING_TOOLS, HeadlessSession;
|
|
10771
10807
|
var init_headless = __esm({
|
|
10772
10808
|
"src/headless/index.ts"() {
|
|
10773
10809
|
"use strict";
|
|
@@ -10798,7 +10834,6 @@ var init_headless = __esm({
|
|
|
10798
10834
|
"confirmDestructiveAction",
|
|
10799
10835
|
"presentPublishPlan"
|
|
10800
10836
|
]);
|
|
10801
|
-
FORCED_COMPACTION_THRESHOLD_TOKENS = 85e4;
|
|
10802
10837
|
HeadlessSession = class {
|
|
10803
10838
|
// Configuration
|
|
10804
10839
|
opts;
|
|
@@ -11071,7 +11106,15 @@ var init_headless = __esm({
|
|
|
11071
11106
|
/** Persist sessionStats + queue snapshot + passive pen to .remy-stats.json. */
|
|
11072
11107
|
persistStats() {
|
|
11073
11108
|
this.sessionStats.updatedAt = Date.now();
|
|
11074
|
-
|
|
11109
|
+
const suggestCompactAt = getSuggestCompactAt(
|
|
11110
|
+
resolveParentModel(this.state.models, this.opts.model).effective
|
|
11111
|
+
);
|
|
11112
|
+
writeStats(
|
|
11113
|
+
this.sessionStats,
|
|
11114
|
+
this.queue.snapshot(),
|
|
11115
|
+
this.passivePen,
|
|
11116
|
+
suggestCompactAt
|
|
11117
|
+
);
|
|
11075
11118
|
}
|
|
11076
11119
|
//////////////////////////////////////////////////////////////////////////////
|
|
11077
11120
|
// Background completions (tool-block mutation; message delivery via queue)
|
|
@@ -11101,8 +11144,9 @@ var init_headless = __esm({
|
|
|
11101
11144
|
saveSession(this.state);
|
|
11102
11145
|
}
|
|
11103
11146
|
/**
|
|
11104
|
-
* Forced compaction gate. If lastContextSize exceeds the
|
|
11105
|
-
*
|
|
11147
|
+
* Forced compaction gate. If lastContextSize exceeds the upcoming turn's
|
|
11148
|
+
* model threshold (per-model — see ModelContextLimits in models/surfaces),
|
|
11149
|
+
* compact before letting the turn run. Coalesces with any in-flight
|
|
11106
11150
|
* compaction (e.g., one already started by /compact or a tool call). No
|
|
11107
11151
|
* timeout — compaction takes as long as it takes.
|
|
11108
11152
|
*
|
|
@@ -11113,13 +11157,15 @@ var init_headless = __esm({
|
|
|
11113
11157
|
* On compaction failure we don't bail — the turn proceeds and surfaces any
|
|
11114
11158
|
* downstream overflow through the existing "prompt is too long" path.
|
|
11115
11159
|
*/
|
|
11116
|
-
async runForcedCompactionIfNeeded(requestId) {
|
|
11117
|
-
|
|
11160
|
+
async runForcedCompactionIfNeeded(requestId, parentModel) {
|
|
11161
|
+
const threshold = getContextLimits(parentModel).forceCompactAt;
|
|
11162
|
+
if (this.sessionStats.lastContextSize <= threshold) {
|
|
11118
11163
|
return;
|
|
11119
11164
|
}
|
|
11120
11165
|
log17.info("Forced compaction gate triggered", {
|
|
11121
11166
|
contextSize: this.sessionStats.lastContextSize,
|
|
11122
|
-
threshold
|
|
11167
|
+
threshold,
|
|
11168
|
+
model: parentModel,
|
|
11123
11169
|
requestId
|
|
11124
11170
|
});
|
|
11125
11171
|
try {
|
|
@@ -11601,7 +11647,12 @@ var init_headless = __esm({
|
|
|
11601
11647
|
}
|
|
11602
11648
|
return steered;
|
|
11603
11649
|
};
|
|
11604
|
-
|
|
11650
|
+
const parentModel = resolveParentModel(
|
|
11651
|
+
this.state.models,
|
|
11652
|
+
this.opts.model,
|
|
11653
|
+
params.buildModel
|
|
11654
|
+
).effective;
|
|
11655
|
+
await this.runForcedCompactionIfNeeded(requestId, parentModel);
|
|
11605
11656
|
try {
|
|
11606
11657
|
await runTurn({
|
|
11607
11658
|
state: this.state,
|