trantor 0.18.65 → 0.18.67
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/.claude-plugin/plugin.json +1 -1
- package/bin/crew-runner.mjs +23 -5
- package/hooks/lib/handoff.mjs +14 -24
- package/package.json +1 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "trantor",
|
|
3
|
-
"version": "0.18.
|
|
3
|
+
"version": "0.18.67",
|
|
4
4
|
"description": "Trantor — the hub-world for AI agent crews: live message bus, presence, project Kanban/flow board + crew orchestration for independent AI coding agents (Claude, Codex, Gemini, Kimi, DeepSeek)",
|
|
5
5
|
"mcpServers": {
|
|
6
6
|
"relay": {
|
package/bin/crew-runner.mjs
CHANGED
|
@@ -1014,14 +1014,32 @@ async function loadLessons() {
|
|
|
1014
1014
|
// #5683: every prompt section is capped (bin/crew-payload.mjs) and the payload has ONE hard total
|
|
1015
1015
|
// cap; below the caps the composition is byte-identical to the old concatenation.
|
|
1016
1016
|
function composedTurn({ base = "", wakeText = "", ctxText = "", againText = "", tailText = "", rulesText = "", lessons = null }) {
|
|
1017
|
+
// STABLE FIRST, VOLATILE LAST — this order is a COST decision, not a stylistic one (#8199).
|
|
1018
|
+
// Every provider we send this to caches on an exact prefix match from token 0: DeepSeek's docs say
|
|
1019
|
+
// "only requests with identical prefixes (starting from the 0th token) will be considered
|
|
1020
|
+
// duplicates, and partial matches in the middle of the input will not trigger a cache hit", and a
|
|
1021
|
+
// hit bills at roughly a tenth of a miss. This array used to open with `base` and then the
|
|
1022
|
+
// per-turn WAKE, with the big unchanging blocks (RULES, lessons) buried at the end. On an ordinary
|
|
1023
|
+
// turn `base` is empty — the sha rides inside `again` — so token 0 was the wake text itself, which
|
|
1024
|
+
// is different every turn by definition. No cache could ever hit, and ~4,800 tokens of identical preamble were re-bought at full rate per turn,
|
|
1025
|
+
// on every foreign-CLI seat: dsh, codex, kimi and every opencode/BYOM seat. The state path had
|
|
1026
|
+
// known this for weeks — lib/state/assemble.mjs: "the bytes before STATE_DELIM are the caller's
|
|
1027
|
+
// preamble and NOTHING else, or prefix caching never engages" — and it was never carried across.
|
|
1028
|
+
//
|
|
1029
|
+
// Reading order improves with it rather than suffering: rules and lessons are the standing brief,
|
|
1030
|
+
// then context and history, and the ASK lands last, which is what #7063 found a work order wants.
|
|
1031
|
+
//
|
|
1032
|
+
// The `order` field is UNRELATED to this and deliberately unchanged: it ranks what gets trimmed
|
|
1033
|
+
// when the payload busts its total cap, and wake is trimmed last there because losing the
|
|
1034
|
+
// instruction is worse than losing the cache on that one turn.
|
|
1017
1035
|
const built = composePrompt([
|
|
1018
|
-
{ name: "base", text: base },
|
|
1019
|
-
{ name: "wake", text: wakeText, trim: "truncate", order: 4 },
|
|
1020
|
-
{ name: "ctx", text: ctxText, trim: "drop", order: 1 },
|
|
1021
|
-
{ name: "again", text: againText },
|
|
1022
|
-
{ name: "tail", text: tailText },
|
|
1023
1036
|
{ name: "rules", text: rulesText, trim: "drop", order: 3 },
|
|
1024
1037
|
{ name: "lessons", text: lessons?.text || "", trim: "drop", order: 2 },
|
|
1038
|
+
{ name: "ctx", text: ctxText, trim: "drop", order: 1 },
|
|
1039
|
+
{ name: "tail", text: tailText },
|
|
1040
|
+
{ name: "again", text: againText },
|
|
1041
|
+
{ name: "base", text: base },
|
|
1042
|
+
{ name: "wake", text: wakeText, trim: "truncate", order: 4 },
|
|
1025
1043
|
]);
|
|
1026
1044
|
const parts = built.sections.filter(s => s.chars).map(s => `${s.name} ${s.chars.toLocaleString("en-US")}c`).join(" · ");
|
|
1027
1045
|
const lessonsNote = lessons && lessons.total ? ` (lessons ${lessons.kept}/${lessons.total})` : "";
|
package/hooks/lib/handoff.mjs
CHANGED
|
@@ -751,33 +751,23 @@ export function maybeSpawn(projectDir, conf = readConfig(), handoffFile = "", de
|
|
|
751
751
|
try {
|
|
752
752
|
if (_platform !== "darwin") return false;
|
|
753
753
|
if (_env.TRANTOR_NO_HANDOFF_SPAWN === "1") return false;
|
|
754
|
-
// #8089
|
|
755
|
-
//
|
|
756
|
-
//
|
|
757
|
-
//
|
|
758
|
-
//
|
|
759
|
-
//
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
}
|
|
766
|
-
const ok = _spawnPane(projectDir, handoffFile, paneId);
|
|
767
|
-
_log(`[trantor] herdr pane ${paneId}: ${ok ? "baton driver spawned — it replaces this pane in place" : "baton driver FAILED to spawn — no successor"}\n`);
|
|
768
|
-
return ok;
|
|
754
|
+
// #8089 REVERTED 2026-09-19, and the revert is the point. A pane session gets NO Terminal
|
|
755
|
+
// window AND no baton driver from here: the APP owns the replacement. app handoff_now runs
|
|
756
|
+
// `trantor handoff --write-only`, waits for the record (including the armed-mid-turn case it
|
|
757
|
+
// explicitly handles), then does its OWN idle gate, kill and reopen (#6081, #5509). Making this
|
|
758
|
+
// spawn a pane baton put a SECOND driver on the same pane, racing the app's — which broke the
|
|
759
|
+
// chat handoff button and the skill, both of which had been working. The stranding this was
|
|
760
|
+
// meant to fix is real but lives in the SKILL path, where no app driver exists; fixing it here
|
|
761
|
+
// cannot tell the two flows apart, so it must be fixed where the flows are distinguishable.
|
|
762
|
+
if (_pane(_env)) {
|
|
763
|
+
_log(`[trantor] session lives in herdr pane ${_pane(_env)} — no Terminal window and no baton driver from here; the app (or the skill path) owns the replacement\n`);
|
|
764
|
+
return false;
|
|
769
765
|
}
|
|
770
766
|
if (conf.autoHandoffPrompt === false) return false;
|
|
771
767
|
if (_hasPane(basename(projectDir))) {
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
_log(`[trantor] orch pane hosts ${basename(projectDir)} but no handoff file was given — no successor opened\n`);
|
|
776
|
-
return false;
|
|
777
|
-
}
|
|
778
|
-
const ok = _spawnPane(projectDir, handoffFile);
|
|
779
|
-
_log(`[trantor] orch pane hosts ${basename(projectDir)}: ${ok ? "baton driver spawned — it replaces the pane in place" : "baton driver FAILED to spawn — no successor"}\n`);
|
|
780
|
-
return ok;
|
|
768
|
+
_log(`[trantor] orch pane hosts ${basename(projectDir)} — no Terminal window; the app or the skill path claims the handoff
|
|
769
|
+
`);
|
|
770
|
+
return false;
|
|
781
771
|
}
|
|
782
772
|
const script = join(HERE, "..", "..", "bin", "handoff-prompt.sh");
|
|
783
773
|
if (!existsSync(script)) { _log(`[trantor] handoff-prompt.sh missing\n`); return false; }
|