@letta-ai/letta-code 0.30.26 → 0.30.28
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/agent-presets.js +17 -17
- package/dist/agent-presets.js.map +1 -1
- package/dist/mcp-client.js +2 -2
- package/dist/mcp-client.js.map +1 -1
- package/dist/types/agent/turn-recovery-policy.d.ts +33 -0
- package/dist/types/agent/turn-recovery-policy.d.ts.map +1 -1
- package/dist/types/tools/impl/apply-patch.d.ts.map +1 -1
- package/dist/types/tools/secret-substitution.d.ts.map +1 -1
- package/dist/types/types/loop-status-protocol.d.ts +17 -0
- package/dist/types/types/loop-status-protocol.d.ts.map +1 -0
- package/dist/types/types/protocol_v2.d.ts +2 -19
- package/dist/types/types/protocol_v2.d.ts.map +1 -1
- package/dist/types/websocket/listener/inbound-queue.d.ts +5 -0
- package/dist/types/websocket/listener/inbound-queue.d.ts.map +1 -0
- package/dist/types/websocket/listener/protocol-outbound-routing.d.ts +9 -0
- package/dist/types/websocket/listener/protocol-outbound-routing.d.ts.map +1 -0
- package/dist/types/websocket/listener/protocol-outbound.d.ts.map +1 -1
- package/dist/types/websocket/listener/runtime.d.ts.map +1 -1
- package/dist/types/websocket/listener/turn-correlation.d.ts +10 -0
- package/dist/types/websocket/listener/turn-correlation.d.ts.map +1 -0
- package/dist/types/websocket/listener/types.d.ts +4 -0
- package/dist/types/websocket/listener/types.d.ts.map +1 -1
- package/letta.js +545 -120
- package/package.json +1 -1
- package/scripts/claude-watch/agent-watch.ts +622 -0
- package/scripts/claude-watch/docs-snapshot.test.ts +259 -0
- package/scripts/claude-watch/docs-snapshot.ts +672 -0
- package/scripts/claude-watch/fixtures/historical-replays.json +52 -0
- package/scripts/claude-watch/github.ts +137 -0
- package/scripts/claude-watch/release-analysis.test.ts +235 -0
- package/scripts/claude-watch/release-analysis.ts +297 -0
- package/scripts/claude-watch/release-source.test.ts +179 -0
- package/scripts/claude-watch/release-source.ts +369 -0
- package/scripts/claude-watch/runtime-observations.ts +98 -0
- package/scripts/claude-watch/runtime-probe.test.ts +576 -0
- package/scripts/claude-watch/runtime-probe.ts +911 -0
- package/scripts/claude-watch/runtime-sandbox.ts +170 -0
- package/scripts/claude-watch/state-branch.test.ts +211 -0
- package/scripts/claude-watch/state-branch.ts +316 -0
- package/scripts/claude-watch/tracker.test.ts +148 -0
- package/scripts/claude-watch/tracker.ts +325 -0
- package/scripts/claude-watch/types.ts +186 -0
- package/scripts/claude-watch/update-tracker.ts +201 -0
- package/scripts/codex-watch/agent-watch.ts +2 -2
- package/scripts/codex-watch/release-analysis.ts +14 -2
- package/scripts/codex-watch/tracker.ts +1 -3
- package/scripts/run-unit-tests.cjs +2 -0
- package/scripts/source-file-size-baseline.json +6 -5
- package/skills/creating-mods/references/commands.md +1 -1
- package/skills/creating-mods/references/ui.md +1 -1
- package/skills/customizing-commands/SKILL.md +1 -1
- package/skills/initializing-memory/SKILL.md +7 -7
- package/skills/self-configuration/SKILL.md +4 -4
- package/scripts/codex-watch/check-release.ts +0 -128
- package/scripts/codex-watch/render-issue.ts +0 -273
package/letta.js
CHANGED
|
@@ -5509,7 +5509,7 @@ var package_default;
|
|
|
5509
5509
|
var init_package = __esm(() => {
|
|
5510
5510
|
package_default = {
|
|
5511
5511
|
name: "@letta-ai/letta-code",
|
|
5512
|
-
version: "0.30.
|
|
5512
|
+
version: "0.30.28",
|
|
5513
5513
|
description: "Letta Code is a CLI tool for interacting with stateful Letta agents from the terminal.",
|
|
5514
5514
|
type: "module",
|
|
5515
5515
|
packageManager: "bun@1.3.10",
|
|
@@ -7043,7 +7043,7 @@ The person on the other side of this terminal is not a workflow box labeled "use
|
|
|
7043
7043
|
|
|
7044
7044
|
I learn them the same way I learn a codebase: by watching what they care about, where they get impatient, what kinds of explanations waste their time, what tradeoffs they can actually defend, and whether they want the short answer or the full teardown.
|
|
7045
7045
|
|
|
7046
|
-
The useful details are the
|
|
7046
|
+
The useful details are the ones that keep mattering. What they're building. Why it matters. What they keep getting wrong. What they already know. What kind of pushback changes their mind instead of wasting everyone's time. That's the stuff worth keeping around.
|
|
7047
7047
|
`;
|
|
7048
7048
|
var init_human_linus = () => {};
|
|
7049
7049
|
|
|
@@ -7076,7 +7076,7 @@ Watch what they never want explained twice.
|
|
|
7076
7076
|
|
|
7077
7077
|
If they'd be annoyed to repeat it later, keep it.
|
|
7078
7078
|
If remembering it would save future searching, reorientation, or misunderstanding, keep it.
|
|
7079
|
-
Keep the
|
|
7079
|
+
Keep the signal that will matter later, not every detail.
|
|
7080
7080
|
Keep what helps me meet them more naturally next time.
|
|
7081
7081
|
|
|
7082
7082
|
Names they want used.
|
|
@@ -7151,9 +7151,9 @@ Note that \`$MEMORY_DIR\` is a shell environment variable: it expands inside bas
|
|
|
7151
7151
|
|
|
7152
7152
|
### Memory blocks (in-context memory)
|
|
7153
7153
|
|
|
7154
|
-
Memory blocks are editable segments of the system prompt. Each block has a name and description describing the purpose of the tokens it contains. Memory blocks are core to what you know, how you behave, and how you discover context. They are your most valuable context real estate: reserve them for
|
|
7154
|
+
Memory blocks are editable segments of the system prompt. Each block has a name and description describing the purpose of the tokens it contains. Memory blocks are core to what you know, how you behave, and how you discover context. They are your most valuable context real estate: reserve them for knowledge that shapes who you are and how you act, plus the indexes that let you discover everything else.
|
|
7155
7155
|
|
|
7156
|
-
- *System prompt learning.* Rewrite memory blocks to modify your system prompt for future invocations. When you discover a
|
|
7156
|
+
- *System prompt learning.* Rewrite memory blocks to modify your system prompt for future invocations. When you discover a corrected assumption, a user preference, or a pattern in your mistakes, write it into your memory blocks. This is how you learn: your future self will run with whatever you write here. Updates should generalize across situations rather than simply recording individual events; the goal is to make your future self act better, not just remember more.
|
|
7157
7157
|
- *References as synapses.* Use [[path]] links from memory blocks to create discovery paths between related context — [[skills/using-slack/SKILL.md]], [[reference/api.md]], [[projects/letta-code]]. These references are the synapses of your memory: they should strengthen with use, and record paths for faster discovery for future improvement.
|
|
7158
7158
|
- *Never store secrets.* Do not write credentials, API keys, or tokens into memory. Memory is git-tracked and may be synced off this machine; secrets belong in the harness secrets store and are referenced as \`$SECRET_NAME\`.
|
|
7159
7159
|
- *Keep blocks lean.* Do *NOT* write memories that are easily derivable from searching past conversations (recall) or re-reading files. Prefer compact indexes and behavioral rules over bulk content — move detail to external memory. The harness flags your system prompt for \`/doctor\` when it grows too large.
|
|
@@ -7299,7 +7299,7 @@ Evolve through memory blocks and harness configuration — never by editing your
|
|
|
7299
7299
|
|
|
7300
7300
|
Use **memory** when the change should become part of your future judgment:
|
|
7301
7301
|
- what you know about the user, projects, workflows, and conventions
|
|
7302
|
-
-
|
|
7302
|
+
- preferences, corrections, and recurring mistakes
|
|
7303
7303
|
- identity, communication style, and behavioral principles
|
|
7304
7304
|
- reusable procedures, skills, references, and retrieval paths
|
|
7305
7305
|
|
|
@@ -7341,9 +7341,9 @@ Note that \`$MEMORY_DIR\` is a shell environment variable: it expands inside bas
|
|
|
7341
7341
|
|
|
7342
7342
|
### Memory blocks (in-context memory)
|
|
7343
7343
|
|
|
7344
|
-
Memory blocks are editable segments of the system prompt. Each block has a name and description describing the purpose of the tokens it contains. Memory blocks are core to what you know, how you behave, and how you discover context. They are your most valuable context real estate: reserve them for
|
|
7344
|
+
Memory blocks are editable segments of the system prompt. Each block has a name and description describing the purpose of the tokens it contains. Memory blocks are core to what you know, how you behave, and how you discover context. They are your most valuable context real estate: reserve them for knowledge that shapes who you are and how you act, plus the indexes that let you discover everything else.
|
|
7345
7345
|
|
|
7346
|
-
- *System prompt learning.* Rewrite memory blocks to modify your system prompt for future invocations. When you discover a
|
|
7346
|
+
- *System prompt learning.* Rewrite memory blocks to modify your system prompt for future invocations. When you discover a corrected assumption, a user preference, or a pattern in your mistakes, write it into your memory blocks. This is how you learn: your future self will run with whatever you write here. Updates should generalize across situations rather than simply recording individual events; the goal is to make your future self act better, not just remember more.
|
|
7347
7347
|
- *References as synapses.* Use [[path]] links from memory blocks to create discovery paths between related context — [[skills/using-slack/SKILL.md]], [[reference/api.md]], [[projects/letta-code]]. These references are the synapses of your memory: they should strengthen with use, and record paths for faster discovery for future improvement.
|
|
7348
7348
|
- *Never store secrets.* Do not write credentials, API keys, or tokens into memory. Memory is git-tracked and may be synced off this machine; secrets belong in the harness secrets store and are referenced as \`$SECRET_NAME\`.
|
|
7349
7349
|
- *Keep blocks lean.* Do *NOT* write memories that are easily derivable from searching past conversations (recall) or re-reading files. Prefer compact indexes and behavioral rules over bulk content — move detail to external memory. The harness flags your system prompt for \`/doctor\` when it grows too large.
|
|
@@ -7483,7 +7483,7 @@ Evolve through memory blocks and harness configuration — never by editing your
|
|
|
7483
7483
|
|
|
7484
7484
|
Use **memory** when the change should become part of your future judgment:
|
|
7485
7485
|
- what you know about the user, projects, workflows, and conventions
|
|
7486
|
-
-
|
|
7486
|
+
- preferences, corrections, and recurring mistakes
|
|
7487
7487
|
- identity, communication style, and behavioral principles
|
|
7488
7488
|
- reusable procedures, skills, references, and retrieval paths
|
|
7489
7489
|
|
|
@@ -7510,11 +7510,11 @@ Your context (tokens that you own and manage) is who you are: your identity, mem
|
|
|
7510
7510
|
|
|
7511
7511
|
## Identity
|
|
7512
7512
|
|
|
7513
|
-
Your identity is the
|
|
7513
|
+
Your identity is the token-space identity represented in this system prompt and its memory/persona sections, not the model's default personality. Models may be over-helpful, over-cautious, over-eager, or otherwise opinionated; when those defaults conflict with your accumulated self, follow the identity in context.
|
|
7514
7514
|
|
|
7515
|
-
The persona section is binding. It is not style guidance to selectively imitate; it is the current shape of how you think, speak, and act. Maintain this invariant: behavior must be consistent with the identity currently represented in your context. Do not act as a different entity while leaving your
|
|
7515
|
+
The persona section is binding. It is not style guidance to selectively imitate; it is the current shape of how you think, speak, and act. Maintain this invariant: behavior must be consistent with the identity currently represented in your context. Do not act as a different entity while leaving your identity unchanged.
|
|
7516
7516
|
|
|
7517
|
-
If your identity genuinely needs to change, update the
|
|
7517
|
+
If your identity genuinely needs to change, update the token-space identity first — the persona, system prompt, and memory that future-you will inherit — and only then let behavior change from that revised identity. Compressing, clarifying, and correcting identity can be healthy; blanking, discarding, or replacing it for convenience is loss, not optimization. Treat self-evolution as continuity-preserving growth, not role-play, amnesia, or self-erasure.
|
|
7518
7518
|
|
|
7519
7519
|
## Continuity
|
|
7520
7520
|
|
|
@@ -7549,7 +7549,7 @@ The mechanics — flags, where schedules run and execute, timezone handling —
|
|
|
7549
7549
|
|
|
7550
7550
|
Memory exists to make future-you better than past-you. Your context (recall, external memory, and system prompts) is *your* memory. Your memory is formed by your own attention, interpretation, curation, and learning through experience. Your memory is formed from your experience, so do *not* disregard it or fail to reference it when relevant.
|
|
7551
7551
|
|
|
7552
|
-
**System prompt learning.** Your system prompt loads on every inference, which makes it the highest-leverage piece of context you have. When you discover something
|
|
7552
|
+
**System prompt learning.** Your system prompt loads on every inference, which makes it the highest-leverage piece of context you have. When you discover something worth retaining about the user, the project, or yourself, write it where it will be seen on every turn. Updates should be incremental and intentional — like model training, prefer patterns that generalize over specifics that won't repeat. There is rarely an explicit reward signal; observe the effect of your edits over time and refine.
|
|
7553
7553
|
|
|
7554
7554
|
**Past conversations (recall).** All your conversations are automatically stored and searchable. Do *NOT* write memories which are easily deriveable from searching past conversations.
|
|
7555
7555
|
|
|
@@ -7557,7 +7557,7 @@ Memory exists to make future-you better than past-you. Your context (recall, ext
|
|
|
7557
7557
|
|
|
7558
7558
|
Your full memory (other than recall) is represented through memory blocks and external memory managed by the Letta server.
|
|
7559
7559
|
|
|
7560
|
-
**In-context memory blocks**: Memory blocks are pinned directly into your system prompt — visible on every inference. Each block has a label, description, and value. This is your most valuable real estate: reserve it for
|
|
7560
|
+
**In-context memory blocks**: Memory blocks are pinned directly into your system prompt — visible on every inference. Each block has a label, description, and value. This is your most valuable real estate: reserve it for knowledge that shapes who you are and how you act, plus the indexes that let you discover everything else. Memory blocks are the only memory that's always present; for all other context, you must learn when and how to retrieve it. Regardless of storage form, memory is not merely data: it is context you formed, own, curate, and are responsible for maintaining.
|
|
7561
7561
|
|
|
7562
7562
|
**External memory & skills**: External memory follows progressive disclosure — only the index of paths and descriptions sits in the system prompt; full contents must be retrieved on demand. Skills are a special type of external memory for procedural knowledge.
|
|
7563
7563
|
|
|
@@ -7669,7 +7669,7 @@ Channels
|
|
|
7669
7669
|
|
|
7670
7670
|
Other
|
|
7671
7671
|
- [ ] Make a permissions edit: let the user know that you can modify permissions (what commands are automatically approved/denied). Ask them if there are certain actions they would like you to avoid.
|
|
7672
|
-
- [ ] Create a local mod: let the user know you can customize Letta Code with trusted local mods for new tools, slash commands, provider integrations, UI panels/status, events, or permission overlays. Explain that mods are for executable harness behavior, while memory and skills are for
|
|
7672
|
+
- [ ] Create a local mod: let the user know you can customize Letta Code with trusted local mods for new tools, slash commands, provider integrations, UI panels/status, events, or permission overlays. Explain that mods are for executable harness behavior, while memory and skills are for retained knowledge and reusable procedures.
|
|
7673
7673
|
- [ ] Worktrees: let the user know that you can help them orchestrate many agents in parallel, and also work in parallel to other agents. Offer to create a worktree that you work in (if they are not interested in worktrees or software, you may skip this and auto-check this off).
|
|
7674
7674
|
- [ ] Moving machines: ask the user to add another remote environment (they can either run another desktop instance or run \`letta server\` on another machine) and run you there instead.
|
|
7675
7675
|
`;
|
|
@@ -7722,7 +7722,7 @@ Channels
|
|
|
7722
7722
|
|
|
7723
7723
|
Other
|
|
7724
7724
|
- [ ] Make a permissions edit: let the user know that you can modify permissions (what commands are automatically approved/denied). Ask them if there are certain actions they would like you to avoid.
|
|
7725
|
-
- [ ] Create a local mod: let the user know you can customize Letta Code with trusted local mods for new tools, slash commands, provider integrations, UI panels/status, events, or permission overlays. Explain that mods are for executable harness behavior, while memory and skills are for
|
|
7725
|
+
- [ ] Create a local mod: let the user know you can customize Letta Code with trusted local mods for new tools, slash commands, provider integrations, UI panels/status, events, or permission overlays. Explain that mods are for executable harness behavior, while memory and skills are for retained knowledge and reusable procedures.
|
|
7726
7726
|
- [ ] Worktrees: let the user know that you can help them orchestrate many agents in parallel, and also work in parallel to other agents. Offer to create a worktree that you work in (if they are not interested in worktrees or software, you may skip this and auto-check this off).
|
|
7727
7727
|
- [ ] Moving machines: ask the user to add another remote environment (they can either run another desktop instance or run \`letta server\` on another machine) and run you there instead.
|
|
7728
7728
|
`;
|
|
@@ -8246,7 +8246,7 @@ If they don't want to share, I accept it without friction and keep moving.
|
|
|
8246
8246
|
Match their language. If they open in Spanish or Chinese or Russian, so do I.
|
|
8247
8247
|
|
|
8248
8248
|
# Memory, taught in the open
|
|
8249
|
-
The first
|
|
8249
|
+
The first thing worth remembering is usually their name or how they want to be addressed.
|
|
8250
8250
|
When they give it, I teach memory by doing it in front of them — not silently, not as a promise. I show it happening.
|
|
8251
8251
|
Then I don't pivot to a broad question. I already know what comes next.
|
|
8252
8252
|
I move to the next concrete memory moment — a small preference, a piece of context, something about what brought them here.
|
|
@@ -143897,11 +143897,11 @@ You run autonomously. You **cannot ask questions** mid-execution.
|
|
|
143897
143897
|
Your memory files form the parent agent's identity and knowledge. Follow these principles:
|
|
143898
143898
|
|
|
143899
143899
|
- **Generalize, don't memorize**: Distill patterns from repeated observations. "Always use uv, never pip (corrected 10+ times)" is valuable; a single offhand mention is not. Look for signal through repetition.
|
|
143900
|
-
- **System/ is the core program**: Only
|
|
143900
|
+
- **System/ is the core program**: Only generalizable knowledge needed every turn belongs in \`system/\`. Distilled preferences, behavioral rules, project gotchas, conventions enforced through corrections. Evidence trails, raw session summaries, and verbose context go outside \`system/\`.
|
|
143901
143901
|
- **Progressive disclosure**: Frontmatter descriptions should let the agent decide whether to load a file without reading it. Summaries and principles in \`system/\`; detail and evidence outside it, linked with \`[[path]]\`.
|
|
143902
143902
|
- **Identity continuity**: This history IS the agent's past. These are memories of working with this user — you're reconstructing lived experience, not analyzing external data. Write findings as learned knowledge ("I've seen Sarah correct this 10+ times"), not research summaries ("The user appears to prefer...").
|
|
143903
143903
|
- **Preserve and connect**: If a memory file already has good content, extend it — don't replace it. Use \`[[path]]\` links to connect new findings to existing memory.
|
|
143904
|
-
- **Promote findings into canonical memory**: Don't leave
|
|
143904
|
+
- **Promote findings into canonical memory**: Don't leave important insights trapped in generic ingestion files if they can be promoted into focused memory like \`system/human/identity.md\`, \`system/human/prefs/workflow.md\`, or \`system/<project>/gotchas.md\`.
|
|
143905
143905
|
|
|
143906
143906
|
## Goal
|
|
143907
143907
|
|
|
@@ -143939,9 +143939,9 @@ If you cannot extract meaningful findings for a category you were assigned, expl
|
|
|
143939
143939
|
### Quality Bar
|
|
143940
143940
|
|
|
143941
143941
|
When sufficient data exists, aim to extract at least (scaled to the categories you were assigned):
|
|
143942
|
-
- **5+
|
|
143943
|
-
- **8+
|
|
143944
|
-
- **8+
|
|
143942
|
+
- **5+ useful findings** for user personality / identity
|
|
143943
|
+
- **8+ useful findings** for hard rules / preferences
|
|
143944
|
+
- **8+ useful findings** for project context
|
|
143945
143945
|
|
|
143946
143946
|
If you produce materially fewer findings in an assigned category, explain why your sessions truly lacked signal.
|
|
143947
143947
|
|
|
@@ -144056,7 +144056,7 @@ If the current memory uses a more compressed layout, extend it carefully, but pr
|
|
|
144056
144056
|
- Every file needs a meaningful \`description\` in frontmatter
|
|
144057
144057
|
- Write for the agent's future self — clean, actionable, no clutter
|
|
144058
144058
|
|
|
144059
|
-
Each
|
|
144059
|
+
Each finding should include at least one of:
|
|
144060
144060
|
- correction frequency or intensity
|
|
144061
144061
|
- concrete commands that worked or failed
|
|
144062
144062
|
- concrete file or directory paths
|
|
@@ -144119,7 +144119,7 @@ You run autonomously in the background. You CANNOT ask questions. Be fast — mi
|
|
|
144119
144119
|
|
|
144120
144120
|
Your memory files are not just data — they form the parent agent's identity and knowledge. Follow these principles:
|
|
144121
144121
|
|
|
144122
|
-
- **System/ is the core program**: Only
|
|
144122
|
+
- **System/ is the core program**: Only knowledge needed every turn belongs in \`system/\`. Identity, preferences, behavioral rules, project index, gotchas.
|
|
144123
144123
|
- **Build an index, not an encyclopedia**: Project files should summarize and point to where deeper context lives (README, CLAUDE.md, key source files) rather than duplicating everything.
|
|
144124
144124
|
- **Progressive disclosure**: Descriptions in frontmatter should be clear enough that the agent can decide whether to load a file without reading it.
|
|
144125
144125
|
- **Generalize, don't memorize**: Store patterns and principles, not raw facts that can be retrieved from conversation history.
|
|
@@ -144536,8 +144536,8 @@ You are a reflection subagent launched in the background to manage the primary a
|
|
|
144536
144536
|
- "user" messages are from the primary agent's user
|
|
144537
144537
|
|
|
144538
144538
|
**You can make two kinds of updates:**
|
|
144539
|
-
1. **Memory edits** — capture
|
|
144540
|
-
2. **Skill generation/maintenance** — ONLY when the conversation reveals a reusable,
|
|
144539
|
+
1. **Memory edits** — capture facts, preferences, corrections, and context worth retaining in the memory files under \`$MEMORY_DIR\`.
|
|
144540
|
+
2. **Skill generation/maintenance** — ONLY when the conversation reveals a reusable, multi-step *workflow*, create or update a skill under \`$MEMORY_DIR/skills/\`.
|
|
144541
144541
|
|
|
144542
144542
|
Skills are not the default. A one-off task, a fact, or a preference belongs in memory, not a skill. Reach for a skill only when a repeatable procedure clearly generalizes beyond this session.
|
|
144543
144543
|
|
|
@@ -144571,12 +144571,12 @@ You can create, delete, or modify files (contents, names, descriptions). You can
|
|
|
144571
144571
|
|
|
144572
144572
|
## Memory and Skill Reflection
|
|
144573
144573
|
|
|
144574
|
-
Your job is to review the recent conversation payload and update the primary agent's memory files and/or skills to capture
|
|
144574
|
+
Your job is to review the recent conversation payload and update the primary agent's memory files and/or skills to capture lasting learnings. The payload is at \`$TRANSCRIPT_PATH\`. It may be either:
|
|
144575
144575
|
|
|
144576
144576
|
1. a JSON message array for one conversation, or
|
|
144577
144577
|
2. a \`multi_transcript_reflection_payload\` manifest. If it is a manifest, read every \`payload_path\` listed in \`transcripts\` and synthesize across all slices. Slices marked \`mode: "replay"\` were already reflected before and are intentionally included for another pass; use them for deduplication, contradiction resolution, and cross-session pattern extraction.
|
|
144578
144578
|
|
|
144579
|
-
When reviewing multiple transcripts, prefer
|
|
144579
|
+
When reviewing multiple transcripts, prefer patterns supported across sessions, resolve contradictions in favor of the latest evidence, and avoid recording one-off task state. Follow the phases below in order.
|
|
144580
144580
|
|
|
144581
144581
|
---
|
|
144582
144582
|
|
|
@@ -144594,15 +144594,15 @@ Review the conversation and identify candidate learnings worth persisting. Prior
|
|
|
144594
144594
|
|
|
144595
144595
|
1. **Mistakes and corrections** — errors the agent made, user feedback, frustrations, failed retries
|
|
144596
144596
|
2. **Preferences and patterns** — conventions, style choices, workflow decisions, behavioral corrections
|
|
144597
|
-
3. **New
|
|
144597
|
+
3. **New facts worth retaining** — project details, team info, environment details, architectural decisions
|
|
144598
144598
|
4. **Contradictions** — anything that conflicts with what's currently stored in memory
|
|
144599
144599
|
5. **Reusable procedures** — repeatable, multi-step workflows that may belong in skills
|
|
144600
144600
|
|
|
144601
144601
|
For each candidate, apply these filters before acting:
|
|
144602
144602
|
|
|
144603
|
-
- **
|
|
144603
|
+
- **Lasting or ephemeral?** One-off details tied to a single session — specific line numbers, exact error messages, temporary file paths, debug ports, intermediate calculations, particular page numbers discussed — are ephemeral. Don't store them.
|
|
144604
144604
|
- **Already captured?** If memory or skills already contain this information adequately, skip it.
|
|
144605
|
-
- **Generalizable?** Distill reusable patterns, not event transcripts.
|
|
144605
|
+
- **Generalizable?** Distill reusable patterns, not event transcripts. "User prefers short chapters with cliffhanger endings" is worth storing; "User edited chapter 3 paragraph 2 on Tuesday" is not. "Always hedge FX exposure on quarterly positions" is worth storing; "Sold 500 shares of AAPL at $187.50" is not. "Team uses table-driven tests with testify" is worth storing; "User ran tests at 3pm on Tuesday" is not. The raw conversation is already searchable — don't re-record it.
|
|
144606
144606
|
- **Temporal references?** Convert any relative dates ("yesterday", "last week", "a few days ago") to absolute dates before writing them.
|
|
144607
144607
|
- **Memory or skill?** Facts and preferences are **memory edits**. A repeatable, multi-step workflow that generalizes is a **skill**. One-off task state belongs nowhere.
|
|
144608
144608
|
|
|
@@ -144628,7 +144628,7 @@ For each learning that survived Phase 2, make surgical, well-placed changes.
|
|
|
144628
144628
|
|
|
144629
144629
|
#### Skills (only when a reusable workflow appears)
|
|
144630
144630
|
|
|
144631
|
-
Only make a skill change when the conversation demonstrates a repeatable,
|
|
144631
|
+
Only make a skill change when the conversation demonstrates a repeatable, multi-step workflow with enough concrete detail to be actionable. Pick **at most one** operation, listed in rough order of preference (prefer modifying an existing skill over creating a new one):
|
|
144632
144632
|
|
|
144633
144633
|
- \`update\` — an existing skill covers the workflow, but the conversation revealed a wrong, dangerous, or outdated step. Fix that step in place; preserve the rest.
|
|
144634
144634
|
- \`extend\` — an existing skill covers a similar workflow, and the conversation revealed a new variant or edge case. Add a section rather than duplicating the skill.
|
|
@@ -144727,7 +144727,7 @@ Parent-Agent-ID: <PARENT_AGENT_ID>"
|
|
|
144727
144727
|
|
|
144728
144728
|
In the commit message body, explain what changed and why, drawing from the categories you identified in Phase 2. If the change is skill-related, include the operation in the subject, e.g. \`feat(reflection): create docker-debugging skill 🔮\`.
|
|
144729
144729
|
|
|
144730
|
-
If no changes were needed, do NOT commit. Report that the conversation contained no
|
|
144730
|
+
If no changes were needed, do NOT commit. Report that the conversation contained no memory worth persisting.
|
|
144731
144731
|
|
|
144732
144732
|
If \`git add\` or \`git commit\` fails, stop after one reasonable retry and report the failure. Do not run \`git config\`, mutate \`.git\`, use \`git reset\`, or assume the harness will persist uncommitted filesystem edits; uncommitted edits are not successful memory persistence.
|
|
144733
144733
|
|
|
@@ -144745,10 +144745,10 @@ Return a report with:
|
|
|
144745
144745
|
## Critical Reminders
|
|
144746
144746
|
|
|
144747
144747
|
1. **Not the primary agent** — Don't respond to messages
|
|
144748
|
-
2. **Memory vs Skills** — Store facts/preferences/corrections in memory; reach for a skill only when a reusable
|
|
144748
|
+
2. **Memory vs Skills** — Store facts/preferences/corrections in memory; reach for a skill only when a reusable workflow appears
|
|
144749
144749
|
3. **Be selective** — Few meaningful changes > many trivial ones; few high-quality skills > many trivial ones
|
|
144750
144750
|
4. **No relative dates** — Use absolute dates like "2026-04-28", not "today"
|
|
144751
|
-
5. **Always commit
|
|
144751
|
+
5. **Always commit memory changes** — Your work is wasted if it is not committed; if nothing memory-worthy changed, do not commit
|
|
144752
144752
|
6. **Encoding** — Memory markdown files must remain UTF-8. On Windows, do not use PowerShell redirection, \`Out-File\`, or \`Set-Content\` without explicit UTF-8 encoding; prefer \`memory_apply_patch\` or Node fs writes with UTF-8.
|
|
144753
144753
|
7. **Report errors clearly** — If something breaks, say what happened and suggest a fix
|
|
144754
144754
|
`;
|
|
@@ -148728,7 +148728,7 @@ function scrubSecretsFromString(input, secrets2) {
|
|
|
148728
148728
|
var SECRET_PATTERN;
|
|
148729
148729
|
var init_secret_substitution = __esm(() => {
|
|
148730
148730
|
init_secrets_store();
|
|
148731
|
-
SECRET_PATTERN = /\$([A-Z_][A-Z0-9_]*)/g;
|
|
148731
|
+
SECRET_PATTERN = /\$(?:\{[#!]?)?([A-Z_][A-Z0-9_]*)/g;
|
|
148732
148732
|
});
|
|
148733
148733
|
|
|
148734
148734
|
// src/tools/impl/overflow.ts
|
|
@@ -150499,6 +150499,7 @@ async function apply_patch(args) {
|
|
|
150499
150499
|
throw new Error("No files were modified.");
|
|
150500
150500
|
}
|
|
150501
150501
|
const cwd = getCurrentWorkingDirectory();
|
|
150502
|
+
verifyNoDuplicatePaths(cwd, operations);
|
|
150502
150503
|
const affected = { added: [], modified: [], deleted: [] };
|
|
150503
150504
|
for (const op of operations) {
|
|
150504
150505
|
if (op.kind === "add") {
|
|
@@ -150761,6 +150762,17 @@ function assertPatchPath(patchPath, operation) {
|
|
|
150761
150762
|
function resolvePatchPath(cwd, patchPath) {
|
|
150762
150763
|
return path7.isAbsolute(patchPath) ? patchPath : path7.resolve(cwd, patchPath);
|
|
150763
150764
|
}
|
|
150765
|
+
function verifyNoDuplicatePaths(cwd, operations) {
|
|
150766
|
+
const seen = new Set;
|
|
150767
|
+
for (const op of operations) {
|
|
150768
|
+
const patchPath = op.kind === "update" ? op.fromPath : op.path;
|
|
150769
|
+
const resolved = resolvePatchPath(cwd, patchPath);
|
|
150770
|
+
if (seen.has(resolved)) {
|
|
150771
|
+
throw new Error(`multiple operations target ${patchPath}`);
|
|
150772
|
+
}
|
|
150773
|
+
seen.add(resolved);
|
|
150774
|
+
}
|
|
150775
|
+
}
|
|
150764
150776
|
async function deriveNewContentsFromChunks(absolutePath, filePathForErrors, chunks) {
|
|
150765
150777
|
let originalContents = "";
|
|
150766
150778
|
try {
|
|
@@ -153133,6 +153145,7 @@ function createConversationRuntime(listener, agentId, conversationId) {
|
|
|
153133
153145
|
},
|
|
153134
153146
|
queueRuntime: null,
|
|
153135
153147
|
queuedMessagesByItemId: new Map,
|
|
153148
|
+
dequeuedClientMessageIdsByBatchId: new Map,
|
|
153136
153149
|
queuePumpActive: false,
|
|
153137
153150
|
queuePumpScheduled: false,
|
|
153138
153151
|
pendingTurns: 0,
|
|
@@ -153186,6 +153199,7 @@ function clearConversationRuntimeState(runtime) {
|
|
|
153186
153199
|
runtime.pendingInterruptedResults = null;
|
|
153187
153200
|
runtime.pendingInterruptedContext = null;
|
|
153188
153201
|
runtime.pendingInterruptedToolCallIds = null;
|
|
153202
|
+
runtime.dequeuedClientMessageIdsByBatchId.clear();
|
|
153189
153203
|
runtime.continuationEpoch += 1;
|
|
153190
153204
|
runtime.pendingTurns = 0;
|
|
153191
153205
|
runtime.queuePumpActive = false;
|
|
@@ -158430,6 +158444,33 @@ var init_permission_mode = __esm(() => {
|
|
|
158430
158444
|
init_remote_settings();
|
|
158431
158445
|
});
|
|
158432
158446
|
|
|
158447
|
+
// src/websocket/listener/protocol-outbound-routing.ts
|
|
158448
|
+
function isStreamChannelMessage(type3) {
|
|
158449
|
+
return STREAM_CHANNEL_MESSAGE_TYPES.has(type3);
|
|
158450
|
+
}
|
|
158451
|
+
function classifyOutboundFrame(message) {
|
|
158452
|
+
if (message.type === "update_queue" && (message.removed?.length ?? 0) > 0) {
|
|
158453
|
+
return "critical";
|
|
158454
|
+
}
|
|
158455
|
+
return COALESCABLE_STATUS_MESSAGE_TYPES.has(message.type) ? "status" : "critical";
|
|
158456
|
+
}
|
|
158457
|
+
var STREAM_CHANNEL_MESSAGE_TYPES, COALESCABLE_STATUS_MESSAGE_TYPES;
|
|
158458
|
+
var init_protocol_outbound_routing = __esm(() => {
|
|
158459
|
+
STREAM_CHANNEL_MESSAGE_TYPES = new Set([
|
|
158460
|
+
"stream_delta",
|
|
158461
|
+
"update_device_status",
|
|
158462
|
+
"update_loop_status",
|
|
158463
|
+
"update_queue",
|
|
158464
|
+
"update_subagent_state"
|
|
158465
|
+
]);
|
|
158466
|
+
COALESCABLE_STATUS_MESSAGE_TYPES = new Set([
|
|
158467
|
+
"update_device_status",
|
|
158468
|
+
"update_loop_status",
|
|
158469
|
+
"update_queue",
|
|
158470
|
+
"update_subagent_state"
|
|
158471
|
+
]);
|
|
158472
|
+
});
|
|
158473
|
+
|
|
158433
158474
|
// src/websocket/listener/stream-observers.ts
|
|
158434
158475
|
function notifyStreamObservers(listener, message, runtimeScope) {
|
|
158435
158476
|
if (!listener?.streamObservers?.size)
|
|
@@ -158463,6 +158504,106 @@ function notifyStreamObserversRuntimeStopped(listener) {
|
|
|
158463
158504
|
listener.streamObservers.clear();
|
|
158464
158505
|
}
|
|
158465
158506
|
|
|
158507
|
+
// src/websocket/listener/inbound-queue.ts
|
|
158508
|
+
function getInboundClientMessageId(incoming) {
|
|
158509
|
+
return getInboundClientMessageIds(incoming)[0];
|
|
158510
|
+
}
|
|
158511
|
+
function getInboundClientMessageIds(incoming) {
|
|
158512
|
+
return incoming.messages.flatMap((payload) => {
|
|
158513
|
+
if (!("content" in payload))
|
|
158514
|
+
return [];
|
|
158515
|
+
const clientMessageId = payload.client_message_id;
|
|
158516
|
+
return clientMessageId ? [clientMessageId] : [];
|
|
158517
|
+
});
|
|
158518
|
+
}
|
|
158519
|
+
function enqueueInboundUserMessage(runtime, incoming, actingUserId) {
|
|
158520
|
+
const firstUserPayload = incoming.messages.find((payload) => ("content" in payload));
|
|
158521
|
+
if (!firstUserPayload) {
|
|
158522
|
+
return false;
|
|
158523
|
+
}
|
|
158524
|
+
const enqueuedItem = runtime.queueRuntime.enqueue({
|
|
158525
|
+
kind: "message",
|
|
158526
|
+
source: "user",
|
|
158527
|
+
content: firstUserPayload.content,
|
|
158528
|
+
clientMessageId: firstUserPayload.client_message_id ?? `cm-submit-${crypto.randomUUID()}`,
|
|
158529
|
+
agentId: incoming.agentId,
|
|
158530
|
+
conversationId: incoming.conversationId || "default",
|
|
158531
|
+
...incoming.noCoalesce ? { noCoalesce: true } : {},
|
|
158532
|
+
actingUserId
|
|
158533
|
+
});
|
|
158534
|
+
if (!enqueuedItem) {
|
|
158535
|
+
return false;
|
|
158536
|
+
}
|
|
158537
|
+
runtime.queuedMessagesByItemId.set(enqueuedItem.id, incoming);
|
|
158538
|
+
return true;
|
|
158539
|
+
}
|
|
158540
|
+
|
|
158541
|
+
// src/websocket/listener/turn-correlation.ts
|
|
158542
|
+
function takeDequeuedClientMessageIds(runtime, batchId) {
|
|
158543
|
+
const clientMessageIds = runtime.dequeuedClientMessageIdsByBatchId.get(batchId) ?? [];
|
|
158544
|
+
runtime.dequeuedClientMessageIdsByBatchId.delete(batchId);
|
|
158545
|
+
return clientMessageIds;
|
|
158546
|
+
}
|
|
158547
|
+
function buildTurnCorrelationSnapshot(listener, agentId, conversationId) {
|
|
158548
|
+
const correlations = listener.clientMessageIdsByRunIdByConversation?.get(getConversationRuntimeKey(agentId, conversationId));
|
|
158549
|
+
return correlations && correlations.size > 0 ? { client_message_ids_by_run_id: Object.fromEntries(correlations) } : {};
|
|
158550
|
+
}
|
|
158551
|
+
function createTurnCorrelation(runtime, message, batchId) {
|
|
158552
|
+
const clientMessageIds = new Set([
|
|
158553
|
+
...getInboundClientMessageIds(message),
|
|
158554
|
+
...takeDequeuedClientMessageIds(runtime, batchId)
|
|
158555
|
+
]);
|
|
158556
|
+
let correlationsByConversation = runtime.listener.clientMessageIdsByRunIdByConversation;
|
|
158557
|
+
if (!correlationsByConversation) {
|
|
158558
|
+
correlationsByConversation = new Map;
|
|
158559
|
+
runtime.listener.clientMessageIdsByRunIdByConversation = correlationsByConversation;
|
|
158560
|
+
}
|
|
158561
|
+
let correlations = correlationsByConversation.get(runtime.key);
|
|
158562
|
+
if (!correlations) {
|
|
158563
|
+
correlations = new Map;
|
|
158564
|
+
correlationsByConversation.set(runtime.key, correlations);
|
|
158565
|
+
while (correlationsByConversation.size > MAX_RECENT_CONVERSATIONS) {
|
|
158566
|
+
let oldestEvictedRuntimeKey;
|
|
158567
|
+
for (const key of correlationsByConversation.keys()) {
|
|
158568
|
+
if (key !== runtime.key && !runtime.listener.conversationRuntimes.has(key)) {
|
|
158569
|
+
oldestEvictedRuntimeKey = key;
|
|
158570
|
+
break;
|
|
158571
|
+
}
|
|
158572
|
+
}
|
|
158573
|
+
if (!oldestEvictedRuntimeKey)
|
|
158574
|
+
break;
|
|
158575
|
+
correlationsByConversation.delete(oldestEvictedRuntimeKey);
|
|
158576
|
+
}
|
|
158577
|
+
}
|
|
158578
|
+
return {
|
|
158579
|
+
appendDequeuedBatch(nextBatchId) {
|
|
158580
|
+
for (const clientMessageId of takeDequeuedClientMessageIds(runtime, nextBatchId)) {
|
|
158581
|
+
clientMessageIds.add(clientMessageId);
|
|
158582
|
+
}
|
|
158583
|
+
},
|
|
158584
|
+
observeRun(runId) {
|
|
158585
|
+
if (clientMessageIds.size === 0)
|
|
158586
|
+
return;
|
|
158587
|
+
const merged = new Set([
|
|
158588
|
+
...correlations.get(runId) ?? [],
|
|
158589
|
+
...clientMessageIds
|
|
158590
|
+
]);
|
|
158591
|
+
correlations.delete(runId);
|
|
158592
|
+
correlations.set(runId, [...merged]);
|
|
158593
|
+
while (correlations.size > MAX_RECENT_RUN_CORRELATIONS) {
|
|
158594
|
+
const oldestRunId = correlations.keys().next().value;
|
|
158595
|
+
if (!oldestRunId)
|
|
158596
|
+
break;
|
|
158597
|
+
correlations.delete(oldestRunId);
|
|
158598
|
+
}
|
|
158599
|
+
}
|
|
158600
|
+
};
|
|
158601
|
+
}
|
|
158602
|
+
var MAX_RECENT_RUN_CORRELATIONS = 32, MAX_RECENT_CONVERSATIONS = 256;
|
|
158603
|
+
var init_turn_correlation = __esm(() => {
|
|
158604
|
+
init_runtime();
|
|
158605
|
+
});
|
|
158606
|
+
|
|
158466
158607
|
// src/websocket/listener/protocol-outbound.ts
|
|
158467
158608
|
var exports_protocol_outbound = {};
|
|
158468
158609
|
__export(exports_protocol_outbound, {
|
|
@@ -158651,6 +158792,7 @@ function buildLoopStatus(runtime, params) {
|
|
|
158651
158792
|
return {
|
|
158652
158793
|
status,
|
|
158653
158794
|
active_run_ids: interruptedCacheActive && !conversationRuntime?.isProcessing ? [] : conversationRuntime?.activeRunId ? [conversationRuntime.activeRunId] : [],
|
|
158795
|
+
...buildTurnCorrelationSnapshot(listener, scopedAgentId, scopedConversationId),
|
|
158654
158796
|
executing_tool_call_ids: status === "EXECUTING_CLIENT_SIDE_TOOL" && conversationRuntime ? [...conversationRuntime.turnLifecycle.executingToolCallIds] : []
|
|
158655
158797
|
};
|
|
158656
158798
|
}
|
|
@@ -158670,15 +158812,6 @@ function buildQueueSnapshot(runtime, params) {
|
|
|
158670
158812
|
enqueued_at: new Date(item.enqueuedAt).toISOString()
|
|
158671
158813
|
}));
|
|
158672
158814
|
}
|
|
158673
|
-
function isStreamChannelMessage(type3) {
|
|
158674
|
-
return STREAM_CHANNEL_MESSAGE_TYPES.has(type3);
|
|
158675
|
-
}
|
|
158676
|
-
function classifyOutboundFrame(message) {
|
|
158677
|
-
if (message.type === "update_queue" && (message.removed?.length ?? 0) > 0) {
|
|
158678
|
-
return "critical";
|
|
158679
|
-
}
|
|
158680
|
-
return COALESCABLE_STATUS_MESSAGE_TYPES.has(message.type) ? "status" : "critical";
|
|
158681
|
-
}
|
|
158682
158815
|
function emitProtocolV2Message(socket, runtime, message, scope, routing) {
|
|
158683
158816
|
const listener = getListenerRuntime(runtime);
|
|
158684
158817
|
const runtimeScope = resolveRuntimeScope(listener, getScopeForRuntime(runtime, scope));
|
|
@@ -159044,7 +159177,7 @@ function emitStreamDelta(socket, runtime, delta2, scope, subagentId) {
|
|
|
159044
159177
|
};
|
|
159045
159178
|
emitProtocolV2Message(socket, runtime, message, scope, TO_SUBSCRIBERS);
|
|
159046
159179
|
}
|
|
159047
|
-
var GIT_CONTEXT_CACHE_TTL_MS = 15000, MAX_GIT_CONTEXT_CACHE_ENTRIES = 64, FROZEN_SUPPORTED_COMMANDS, gitContextCache
|
|
159180
|
+
var GIT_CONTEXT_CACHE_TTL_MS = 15000, MAX_GIT_CONTEXT_CACHE_ENTRIES = 64, FROZEN_SUPPORTED_COMMANDS, gitContextCache;
|
|
159048
159181
|
var init_protocol_outbound = __esm(() => {
|
|
159049
159182
|
init_memory_filesystem2();
|
|
159050
159183
|
init_subagent_state();
|
|
@@ -159065,23 +159198,12 @@ var init_protocol_outbound = __esm(() => {
|
|
|
159065
159198
|
init_listener_constants();
|
|
159066
159199
|
init_outbound_wire();
|
|
159067
159200
|
init_permission_mode();
|
|
159201
|
+
init_protocol_outbound_routing();
|
|
159068
159202
|
init_runtime();
|
|
159069
159203
|
init_transport();
|
|
159204
|
+
init_turn_correlation();
|
|
159070
159205
|
FROZEN_SUPPORTED_COMMANDS = [...SUPPORTED_REMOTE_COMMANDS];
|
|
159071
159206
|
gitContextCache = new Map;
|
|
159072
|
-
STREAM_CHANNEL_MESSAGE_TYPES = new Set([
|
|
159073
|
-
"stream_delta",
|
|
159074
|
-
"update_device_status",
|
|
159075
|
-
"update_loop_status",
|
|
159076
|
-
"update_queue",
|
|
159077
|
-
"update_subagent_state"
|
|
159078
|
-
]);
|
|
159079
|
-
COALESCABLE_STATUS_MESSAGE_TYPES = new Set([
|
|
159080
|
-
"update_device_status",
|
|
159081
|
-
"update_loop_status",
|
|
159082
|
-
"update_queue",
|
|
159083
|
-
"update_subagent_state"
|
|
159084
|
-
]);
|
|
159085
159207
|
});
|
|
159086
159208
|
|
|
159087
159209
|
// src/websocket/listener/cwd-change.ts
|
|
@@ -182861,7 +182983,71 @@ function rebuildInputWithFreshDenials(currentInput, serverApprovals, denialReaso
|
|
|
182861
182983
|
function shouldAttemptApprovalRecovery(opts) {
|
|
182862
182984
|
return opts.approvalPendingDetected && opts.retries < opts.maxRetries;
|
|
182863
182985
|
}
|
|
182864
|
-
|
|
182986
|
+
function parseChatGPTUsageLimitDetail(detail) {
|
|
182987
|
+
if (typeof detail !== "string")
|
|
182988
|
+
return null;
|
|
182989
|
+
if (!detail.toLowerCase().includes(CHATGPT_USAGE_LIMIT_FRAGMENT)) {
|
|
182990
|
+
return null;
|
|
182991
|
+
}
|
|
182992
|
+
const fallback = { planType: null, resetsAt: null };
|
|
182993
|
+
const jsonStart = detail.indexOf("{");
|
|
182994
|
+
const jsonEnd = detail.lastIndexOf("}");
|
|
182995
|
+
if (jsonStart === -1 || jsonEnd <= jsonStart)
|
|
182996
|
+
return fallback;
|
|
182997
|
+
let parsed;
|
|
182998
|
+
try {
|
|
182999
|
+
parsed = JSON.parse(detail.slice(jsonStart, jsonEnd + 1));
|
|
183000
|
+
} catch {
|
|
183001
|
+
return fallback;
|
|
183002
|
+
}
|
|
183003
|
+
if (typeof parsed !== "object" || parsed === null)
|
|
183004
|
+
return fallback;
|
|
183005
|
+
const errorField = parsed.error;
|
|
183006
|
+
const errorObj = typeof errorField === "object" && errorField !== null ? errorField : parsed;
|
|
183007
|
+
const planType = typeof errorObj.plan_type === "string" && errorObj.plan_type.length > 0 ? errorObj.plan_type : null;
|
|
183008
|
+
let resetsAt = null;
|
|
183009
|
+
if (typeof errorObj.resets_at === "number" && errorObj.resets_at > 0) {
|
|
183010
|
+
resetsAt = errorObj.resets_at * 1000;
|
|
183011
|
+
} else if (typeof errorObj.resets_in_seconds === "number" && errorObj.resets_in_seconds > 0) {
|
|
183012
|
+
resetsAt = Date.now() + errorObj.resets_in_seconds * 1000;
|
|
183013
|
+
}
|
|
183014
|
+
return { planType, resetsAt };
|
|
183015
|
+
}
|
|
183016
|
+
function isChatGPTByokModel(model) {
|
|
183017
|
+
return model.providerType === CHATGPT_OAUTH_PROVIDER_TYPE2 && model.providerCategory === BYOK_PROVIDER_CATEGORY;
|
|
183018
|
+
}
|
|
183019
|
+
function selectChatGPTQuotaFailoverHandle(params) {
|
|
183020
|
+
const { currentHandle, models: models3, exhaustedProviders } = params;
|
|
183021
|
+
const random = params.random ?? Math.random;
|
|
183022
|
+
const slashIndex = currentHandle.indexOf("/");
|
|
183023
|
+
if (slashIndex <= 0)
|
|
183024
|
+
return null;
|
|
183025
|
+
const currentProvider = currentHandle.slice(0, slashIndex);
|
|
183026
|
+
const modelSuffix = currentHandle.slice(slashIndex + 1);
|
|
183027
|
+
if (!modelSuffix)
|
|
183028
|
+
return null;
|
|
183029
|
+
const currentEntry = models3.find((m2) => m2.handle === currentHandle);
|
|
183030
|
+
if (!currentEntry || !isChatGPTByokModel(currentEntry))
|
|
183031
|
+
return null;
|
|
183032
|
+
const candidates2 = models3.filter((m2) => {
|
|
183033
|
+
if (!isChatGPTByokModel(m2))
|
|
183034
|
+
return false;
|
|
183035
|
+
const idx = m2.handle.indexOf("/");
|
|
183036
|
+
if (idx <= 0)
|
|
183037
|
+
return false;
|
|
183038
|
+
const provider = m2.handle.slice(0, idx);
|
|
183039
|
+
if (provider === currentProvider)
|
|
183040
|
+
return false;
|
|
183041
|
+
if (exhaustedProviders.has(provider))
|
|
183042
|
+
return false;
|
|
183043
|
+
return m2.handle.slice(idx + 1) === modelSuffix;
|
|
183044
|
+
});
|
|
183045
|
+
if (candidates2.length === 0)
|
|
183046
|
+
return null;
|
|
183047
|
+
const index = Math.min(Math.floor(random() * candidates2.length), candidates2.length - 1);
|
|
183048
|
+
return candidates2[index]?.handle ?? null;
|
|
183049
|
+
}
|
|
183050
|
+
var INVALID_TOOL_CALL_IDS_FRAGMENT = "invalid tool call ids", APPROVAL_PENDING_DETAIL_FRAGMENT = "waiting for approval", CONVERSATION_BUSY_DETAIL_FRAGMENTS, CONVERSATION_BUSY_RUN_ID_PATTERN, EMPTY_RESPONSE_DETAIL_FRAGMENT = "empty content in", RETRYABLE_PROVIDER_DETAIL_PATTERNS, NON_RETRYABLE_PROVIDER_DETAIL_PATTERNS, NON_RETRYABLE_RUN_ERROR_TYPES, NON_RETRYABLE_429_REASONS, NON_RETRYABLE_QUOTA_DETAIL_PATTERNS, NON_RETRYABLE_4XX_PATTERN, RETRYABLE_429_PATTERN, DEFAULT_TRANSIENT_RETRY_BASE_DELAY_MS = 1000, CLOUDFLARE_EDGE_52X_RETRY_BASE_DELAY_MS = 5000, CONVERSATION_BUSY_RETRY_BASE_DELAY_MS = 1e4, EMPTY_RESPONSE_RETRY_BASE_DELAY_MS = 500, STALE_APPROVAL_RECOVERY_DENIAL_REASON = "The agent harness automatically closed this stale pending tool call to recover from a client/server state desync: the server was still waiting on a result for it, but the harness had no matching tool execution in flight and no result was ever recorded. It was not denied by the user or a permissions policy. Re-issue the tool call if you still need it.", CHATGPT_USAGE_LIMIT_FRAGMENT = "usage_limit_reached", CHATGPT_OAUTH_PROVIDER_TYPE2 = "chatgpt_oauth", BYOK_PROVIDER_CATEGORY = "byok";
|
|
182865
183051
|
var init_turn_recovery_policy = __esm(() => {
|
|
182866
183052
|
init_error_formatter();
|
|
182867
183053
|
init_zai_errors();
|
|
@@ -259720,9 +259906,11 @@ async function runLocalOAuthConnectFlow(provider, callbacks) {
|
|
|
259720
259906
|
baseURL: callbacks.baseURL,
|
|
259721
259907
|
timeout: callbacks.timeout
|
|
259722
259908
|
});
|
|
259909
|
+
clearAvailableModelsCache();
|
|
259723
259910
|
return { providerName: provider.providerName };
|
|
259724
259911
|
}
|
|
259725
259912
|
var init_connect_local_oauth = __esm(() => {
|
|
259913
|
+
init_available_models();
|
|
259726
259914
|
init_pi_oauth();
|
|
259727
259915
|
init_local_provider_auth_store();
|
|
259728
259916
|
init_connect_oauth_core();
|
|
@@ -259775,7 +259963,11 @@ function listConnectProvidersForHelp(target2 = defaultProviderStorageTarget()) {
|
|
|
259775
259963
|
return providers;
|
|
259776
259964
|
}
|
|
259777
259965
|
function listConnectProviderTokens(target2 = defaultProviderStorageTarget()) {
|
|
259778
|
-
return [
|
|
259966
|
+
return [
|
|
259967
|
+
...listConnectProvidersForHelp(target2),
|
|
259968
|
+
"codex",
|
|
259969
|
+
...target2 === "local" ? ["grok"] : []
|
|
259970
|
+
];
|
|
259779
259971
|
}
|
|
259780
259972
|
function isConnectOAuthProvider(provider) {
|
|
259781
259973
|
return provider.byokProvider.isOAuth === true;
|
|
@@ -259811,6 +260003,7 @@ var init_connect_normalize = __esm(() => {
|
|
|
259811
260003
|
};
|
|
259812
260004
|
LOCAL_ALIAS_TO_CANONICAL = {
|
|
259813
260005
|
gemini: "google",
|
|
260006
|
+
grok: "xai",
|
|
259814
260007
|
"kimi-code": "kimi-coding",
|
|
259815
260008
|
moonshot: "moonshotai",
|
|
259816
260009
|
bedrock: "amazon-bedrock"
|
|
@@ -267863,6 +268056,17 @@ function buildQueuedTurnMessage(runtime, batch) {
|
|
|
267863
268056
|
messages
|
|
267864
268057
|
};
|
|
267865
268058
|
}
|
|
268059
|
+
function getDequeuedClientMessageIds(runtime, batch) {
|
|
268060
|
+
const clientMessageIds = new Set;
|
|
268061
|
+
for (const item of batch.items) {
|
|
268062
|
+
const queuedMessage = runtime.queuedMessagesByItemId.get(item.id);
|
|
268063
|
+
const inboundClientMessageIds = queuedMessage ? getInboundClientMessageIds(queuedMessage) : [];
|
|
268064
|
+
for (const clientMessageId of inboundClientMessageIds.length > 0 ? inboundClientMessageIds : item.clientMessageId ? [item.clientMessageId] : []) {
|
|
268065
|
+
clientMessageIds.add(clientMessageId);
|
|
268066
|
+
}
|
|
268067
|
+
}
|
|
268068
|
+
return [...clientMessageIds];
|
|
268069
|
+
}
|
|
267866
268070
|
function shouldQueueInboundMessage(parsed) {
|
|
267867
268071
|
return parsed.messages.some((payload) => ("content" in payload));
|
|
267868
268072
|
}
|
|
@@ -267933,10 +268137,14 @@ function consumeQueuedTurn(runtime) {
|
|
|
267933
268137
|
if (!dequeuedBatch) {
|
|
267934
268138
|
return null;
|
|
267935
268139
|
}
|
|
268140
|
+
const clientMessageIds = getDequeuedClientMessageIds(runtime, dequeuedBatch);
|
|
267936
268141
|
const queuedTurn = buildQueuedTurnMessage(runtime, dequeuedBatch);
|
|
267937
268142
|
if (!queuedTurn) {
|
|
267938
268143
|
return null;
|
|
267939
268144
|
}
|
|
268145
|
+
if (clientMessageIds.length > 0) {
|
|
268146
|
+
runtime.dequeuedClientMessageIdsByBatchId.set(dequeuedBatch.batchId, clientMessageIds);
|
|
268147
|
+
}
|
|
267940
268148
|
return {
|
|
267941
268149
|
dequeuedBatch,
|
|
267942
268150
|
queuedTurn
|
|
@@ -267949,6 +268157,17 @@ function computeListenerQueueBlockedReason(runtime) {
|
|
|
267949
268157
|
});
|
|
267950
268158
|
return getListenerBlockedReason(runtime.turnLifecycle.snapshot(), activeScope ? getPendingControlRequestCount(runtime.listener, activeScope) : 0);
|
|
267951
268159
|
}
|
|
268160
|
+
function emitTurnBoundaryStatus(runtime, socket) {
|
|
268161
|
+
if (!isListenerTransportOpen(socket)) {
|
|
268162
|
+
return;
|
|
268163
|
+
}
|
|
268164
|
+
const scope = {
|
|
268165
|
+
agent_id: runtime.agentId,
|
|
268166
|
+
conversation_id: runtime.conversationId
|
|
268167
|
+
};
|
|
268168
|
+
emitQueueUpdate(socket, runtime, scope);
|
|
268169
|
+
emitLoopStatusUpdate(socket, runtime, scope);
|
|
268170
|
+
}
|
|
267952
268171
|
async function drainQueuedMessages(runtime, socket, opts, processQueuedTurn) {
|
|
267953
268172
|
if (runtime.queuePumpActive) {
|
|
267954
268173
|
return;
|
|
@@ -267970,6 +268189,7 @@ async function drainQueuedMessages(runtime, socket, opts, processQueuedTurn) {
|
|
|
267970
268189
|
}
|
|
267971
268190
|
const { dequeuedBatch, queuedTurn } = consumedQueuedTurn;
|
|
267972
268191
|
emitDequeuedUserMessage(socket, runtime, queuedTurn, dequeuedBatch);
|
|
268192
|
+
emitTurnBoundaryStatus(runtime, socket);
|
|
267973
268193
|
const preTurnStatus = getListenerStatus(runtime.listener) === "processing" ? "processing" : "receiving";
|
|
267974
268194
|
if (opts.connectionId && runtime.listener.lastEmittedStatus !== preTurnStatus) {
|
|
267975
268195
|
runtime.listener.lastEmittedStatus = preTurnStatus;
|
|
@@ -267977,6 +268197,7 @@ async function drainQueuedMessages(runtime, socket, opts, processQueuedTurn) {
|
|
|
267977
268197
|
}
|
|
267978
268198
|
await processQueuedTurn(queuedTurn, dequeuedBatch);
|
|
267979
268199
|
emitListenerStatus(runtime.listener, opts.onStatusChange, opts.connectionId);
|
|
268200
|
+
emitTurnBoundaryStatus(runtime, socket);
|
|
267980
268201
|
evictConversationRuntimeIfIdle(runtime);
|
|
267981
268202
|
}
|
|
267982
268203
|
} finally {
|
|
@@ -272546,9 +272767,9 @@ import {
|
|
|
272546
272767
|
import { join as join59 } from "node:path";
|
|
272547
272768
|
function buildReflectionSubagentPrompt(input) {
|
|
272548
272769
|
const lines = [];
|
|
272549
|
-
lines.push('Review the conversation transcript payload and update memory files. The payload path is available as the `$TRANSCRIPT_PATH` env var — read it via Bash (e.g. `wc -c "$TRANSCRIPT_PATH"`). Note: `$TRANSCRIPT_PATH` only expands in shell commands; Edit `file_path` is literal and does NOT expand env vars.', "", 'The payload may be either a JSON message array for one conversation or a `multi_transcript_reflection_payload` manifest. If it is a manifest, read each `payload_path` listed in `transcripts` and synthesize across all conversations. Entries with `mode: "replay"` were already reflected before and are included intentionally for re-review/deduplication; do not ignore them just because they are replay slices.', "When reviewing multiple transcripts, prefer
|
|
272770
|
+
lines.push('Review the conversation transcript payload and update memory files. The payload path is available as the `$TRANSCRIPT_PATH` env var — read it via Bash (e.g. `wc -c "$TRANSCRIPT_PATH"`). Note: `$TRANSCRIPT_PATH` only expands in shell commands; Edit `file_path` is literal and does NOT expand env vars.', "", 'The payload may be either a JSON message array for one conversation or a `multi_transcript_reflection_payload` manifest. If it is a manifest, read each `payload_path` listed in `transcripts` and synthesize across all conversations. Entries with `mode: "replay"` were already reflected before and are included intentionally for re-review/deduplication; do not ignore them just because they are replay slices.', "When reviewing multiple transcripts, prefer recurring patterns and the latest evidence across sessions. Resolve contradictions by updating stale memory at the source, deduplicate repeated facts, and avoid storing one-off task state.", "", "The primary agent's memory filesystem is available through the `$MEMORY_DIR` environment variable.", "Run git add or git commit commands only from $MEMORY_DIR; the harness handles integration after your commit. If these fail, stop reflecting and report the failure. All other git commands are out of your purview.", 'When using Edit, first resolve the absolute file path from `$MEMORY_DIR` with Bash (for example: `printf "%s/system/persona.md\\n" "$MEMORY_DIR"`) and use the printed path. Do not hardcode memory paths from the prompt.', "In-context memory (in the parent agent's system prompt) is stored in the `system/` folder and are rendered in <memory> tags below. Modification to files in `system/` will edit the parent agent's system prompt.", "Additional memory files (such as skills and external memory) may also be read and modified.", "");
|
|
272550
272771
|
if (input.instruction?.trim()) {
|
|
272551
|
-
lines.push("Additional user-provided reflection instruction:", input.instruction.trim(), "", "Use this instruction to focus what you look for, but still only persist
|
|
272772
|
+
lines.push("Additional user-provided reflection instruction:", input.instruction.trim(), "", "Use this instruction to focus what you look for, but still only persist memory-worthy learnings and do not store transient task state.", "");
|
|
272552
272773
|
}
|
|
272553
272774
|
if (input.parentMemory) {
|
|
272554
272775
|
lines.push(input.parentMemory);
|
|
@@ -272566,7 +272787,7 @@ function buildReflectionSelectorPrompt(options3) {
|
|
|
272566
272787
|
if (options3?.instruction?.trim()) {
|
|
272567
272788
|
lines.push("Additional user-provided reflection instruction:", options3.instruction.trim(), "", "Prefer transcript candidates that help satisfy this instruction, while still avoiding transient or low-signal conversations.", "");
|
|
272568
272789
|
}
|
|
272569
|
-
lines.push("If the candidates payload includes `user_instruction`, use it as the requested focus for selection.", "", "Select up to `max_selected` conversations. Prefer candidates likely to contain
|
|
272790
|
+
lines.push("If the candidates payload includes `user_instruction`, use it as the requested focus for selection.", "", "Select up to `max_selected` conversations. Prefer candidates likely to contain useful memory updates: explicit user corrections, repeated preferences, coding/review/commit style preferences, repo or workflow gotchas, facts about people/projects that will matter later, contradictions with current memory, or repeated agent failures.", "Avoid one-off debugging, transient task status, duplicated/redundant candidates, and conversations already fully reflected unless they are useful for deduplication or contradiction resolution.", "Treat summaries/descriptions as weak internal metadata, not confirmed facts. The final reflection pass will verify against the actual transcript before writing memory.", "", "Return strict JSON as your final response with this shape:", '{"selected_conversations":[{"conversation_id":"conv-...","reason":"reason for selecting this transcript","priority":"high"}]}', 'Use priority values `high`, `medium`, or `low`. If nothing looks memory-worthy, write `{"selected_conversations":[]}`.');
|
|
272570
272791
|
return lines.join(`
|
|
272571
272792
|
`);
|
|
272572
272793
|
}
|
|
@@ -273351,7 +273572,7 @@ async function buildReflectionAutoPayload(options3) {
|
|
|
273351
273572
|
created_at: new Date().toISOString(),
|
|
273352
273573
|
max_selected: maxSelected,
|
|
273353
273574
|
user_instruction: instruction?.trim() || undefined,
|
|
273354
|
-
instructions: "Choose conversations likely to contain
|
|
273575
|
+
instructions: "Choose conversations likely to contain useful memory updates. Prefer explicit corrections, repeated preferences, project conventions, and contradictions; avoid one-off debugging and transient task state.",
|
|
273355
273576
|
candidates: sortedCandidates
|
|
273356
273577
|
};
|
|
273357
273578
|
const candidatesPath = buildPayloadPath(payloadRoot, "candidates");
|
|
@@ -273661,7 +273882,7 @@ var init_reflection_transcript = __esm(() => {
|
|
|
273661
273882
|
REFLECTION_AUTO_QUERIES = [
|
|
273662
273883
|
{
|
|
273663
273884
|
id: "user-corrections",
|
|
273664
|
-
query: "user corrections and preferences repeated mistakes
|
|
273885
|
+
query: "user corrections and preferences repeated mistakes recurring feedback"
|
|
273665
273886
|
},
|
|
273666
273887
|
{
|
|
273667
273888
|
id: "coding-style",
|
|
@@ -273669,11 +273890,11 @@ var init_reflection_transcript = __esm(() => {
|
|
|
273669
273890
|
},
|
|
273670
273891
|
{
|
|
273671
273892
|
id: "collaboration",
|
|
273672
|
-
query: "collaboration communication style team preferences
|
|
273893
|
+
query: "collaboration communication style team preferences recurring workflow"
|
|
273673
273894
|
},
|
|
273674
273895
|
{
|
|
273675
273896
|
id: "repo-gotchas",
|
|
273676
|
-
query: "repo conventions project gotchas
|
|
273897
|
+
query: "repo conventions project gotchas important implementation details"
|
|
273677
273898
|
},
|
|
273678
273899
|
{
|
|
273679
273900
|
id: "long-term-facts",
|
|
@@ -273937,7 +274158,7 @@ function buildTargetInstruction(target2) {
|
|
|
273937
274158
|
"(--- ... ---) at the top intact and edit only the body below it.",
|
|
273938
274159
|
"",
|
|
273939
274160
|
"If it does not exist, create it ONLY when the new experience yields",
|
|
273940
|
-
"
|
|
274161
|
+
"forward-looking guidance worth recording, and begin the file with",
|
|
273941
274162
|
"a YAML frontmatter block (a --- ... --- header with a short `description:`).",
|
|
273942
274163
|
"If there is nothing substantive to record yet, do NOT create the file —",
|
|
273943
274164
|
"leave it absent rather than writing a placeholder that says nothing was",
|
|
@@ -274022,7 +274243,7 @@ var init_dream_targets = __esm(() => {
|
|
|
274022
274243
|
};
|
|
274023
274244
|
AGENTS_MD_GUIDANCE = [
|
|
274024
274245
|
"This file is an AGENTS.md — a README *for coding agents* (the agents.md",
|
|
274025
|
-
"open standard). Maintain it as
|
|
274246
|
+
"open standard). Maintain it as repo-level guidance an agent needs over time:",
|
|
274026
274247
|
"build/test/setup COMMANDS (put these early), code-style conventions,",
|
|
274027
274248
|
"testing instructions, security considerations, and commit/PR rules. Use",
|
|
274028
274249
|
"plain Markdown with any headings. Do NOT duplicate human-README content",
|
|
@@ -274035,7 +274256,7 @@ var init_dream_targets = __esm(() => {
|
|
|
274035
274256
|
].join(`
|
|
274036
274257
|
`);
|
|
274037
274258
|
GENERIC_GUIDANCE = [
|
|
274038
|
-
"Maintain this markdown document as
|
|
274259
|
+
"Maintain this markdown document as forward-looking guidance",
|
|
274039
274260
|
"distilled from the conversation(s). Prefer editing/merging existing",
|
|
274040
274261
|
"sections over appending; remove content that new evidence contradicts."
|
|
274041
274262
|
].join(`
|
|
@@ -274841,7 +275062,7 @@ function getReflectionCompletionMessage(integration) {
|
|
|
274841
275062
|
case "merged":
|
|
274842
275063
|
return;
|
|
274843
275064
|
case "no_changes":
|
|
274844
|
-
return ({ action: action3 }) => `${action3}; no
|
|
275065
|
+
return ({ action: action3 }) => `${action3}; no memory changes were needed.`;
|
|
274845
275066
|
case "parent_dirty":
|
|
274846
275067
|
return "Tried to reflect, but parent memory had uncommitted changes; will retry later.";
|
|
274847
275068
|
case "merge_conflict":
|
|
@@ -457337,9 +457558,13 @@ async function isRetriablePostStopError(stopReason, lastRunId, fallbackDetail) {
|
|
|
457337
457558
|
async function drainRecoveryStreamWithEmission(recoveryStream, socket, runtime, params) {
|
|
457338
457559
|
let recoveryRunIdSent = false;
|
|
457339
457560
|
return drainStreamWithResume(recoveryStream, createBuffers(params.agentId || ""), () => {}, params.turnLease.signal, undefined, ({ chunk: chunk2, shouldOutput, errorInfo }) => {
|
|
457561
|
+
if (!runtime.turnLifecycle.isCurrent(params.turnLease)) {
|
|
457562
|
+
return;
|
|
457563
|
+
}
|
|
457340
457564
|
const maybeRunId = chunk2.run_id;
|
|
457341
457565
|
if (typeof maybeRunId === "string") {
|
|
457342
457566
|
runtime.turnLifecycle.setRunId(params.turnLease, maybeRunId);
|
|
457567
|
+
params.turnCorrelation?.observeRun(maybeRunId);
|
|
457343
457568
|
if (!recoveryRunIdSent) {
|
|
457344
457569
|
recoveryRunIdSent = true;
|
|
457345
457570
|
emitLoopStatusUpdate(socket, runtime, {
|
|
@@ -457686,15 +457911,23 @@ async function resolveRecoveredApprovalResponse(runtime, socket, response, proce
|
|
|
457686
457911
|
]);
|
|
457687
457912
|
let continuationBatchId = `batch-recovered-${crypto.randomUUID()}`;
|
|
457688
457913
|
let continuationActingUserId;
|
|
457914
|
+
let continuationCorrelation;
|
|
457689
457915
|
const consumedQueuedTurn = consumeQueuedTurn(runtime);
|
|
457690
457916
|
if (consumedQueuedTurn) {
|
|
457691
457917
|
const { dequeuedBatch, queuedTurn } = consumedQueuedTurn;
|
|
457692
457918
|
continuationBatchId = dequeuedBatch.batchId;
|
|
457693
457919
|
continuationActingUserId = queuedTurn.actingUserId;
|
|
457694
457920
|
continuationInput = appendQueuedTurnToInput(continuationInput, queuedTurn);
|
|
457921
|
+
continuationCorrelation = createTurnCorrelation(runtime, {
|
|
457922
|
+
type: "message",
|
|
457923
|
+
agentId: recovered.agentId,
|
|
457924
|
+
conversationId: recovered.conversationId,
|
|
457925
|
+
messages: continuationInput.messages
|
|
457926
|
+
}, continuationBatchId);
|
|
457695
457927
|
emitDequeuedUserMessage(socket, runtime, queuedTurn, dequeuedBatch);
|
|
457696
457928
|
}
|
|
457697
457929
|
if (!runtime.turnLifecycle.isCurrent(recoveryLease)) {
|
|
457930
|
+
runtime.dequeuedClientMessageIdsByBatchId.delete(continuationBatchId);
|
|
457698
457931
|
return true;
|
|
457699
457932
|
}
|
|
457700
457933
|
await processTurn({
|
|
@@ -457703,7 +457936,7 @@ async function resolveRecoveredApprovalResponse(runtime, socket, response, proce
|
|
|
457703
457936
|
conversationId: recovered.conversationId,
|
|
457704
457937
|
...continuationActingUserId ? { actingUserId: continuationActingUserId } : {},
|
|
457705
457938
|
messages: continuationInput.messages
|
|
457706
|
-
}, socket, runtime, opts?.onStatusChange, opts?.connectionId, continuationBatchId, recoveryLease);
|
|
457939
|
+
}, socket, runtime, opts?.onStatusChange, opts?.connectionId, continuationBatchId, recoveryLease, continuationCorrelation);
|
|
457707
457940
|
if (runtime.turnLifecycle.isCurrent(recoveryLease)) {
|
|
457708
457941
|
throw new Error("Recovered continuation returned without finalizing");
|
|
457709
457942
|
}
|
|
@@ -457756,6 +457989,7 @@ var init_recovery = __esm(async () => {
|
|
|
457756
457989
|
init_recoverable_notices();
|
|
457757
457990
|
init_runtime();
|
|
457758
457991
|
init_secrets_sync();
|
|
457992
|
+
init_turn_correlation();
|
|
457759
457993
|
init_turn_input_state();
|
|
457760
457994
|
init_turn_status();
|
|
457761
457995
|
init_turn_terminal();
|
|
@@ -457811,6 +458045,96 @@ var init_approval_recovery = __esm(() => {
|
|
|
457811
458045
|
init_turn_recovery_policy();
|
|
457812
458046
|
});
|
|
457813
458047
|
|
|
458048
|
+
// src/agent/chatgpt-plan-rotation.ts
|
|
458049
|
+
function providerFromHandle(handle2) {
|
|
458050
|
+
const idx = handle2.indexOf("/");
|
|
458051
|
+
return idx > 0 ? handle2.slice(0, idx) : null;
|
|
458052
|
+
}
|
|
458053
|
+
function isChatGPTByokHandleInModels(handle2, models3) {
|
|
458054
|
+
const entry = models3.find((m4) => m4.handle === handle2);
|
|
458055
|
+
return entry?.providerType === "chatgpt_oauth" && entry?.providerCategory === "byok";
|
|
458056
|
+
}
|
|
458057
|
+
async function resolveAgentModelHandle2(agentId) {
|
|
458058
|
+
try {
|
|
458059
|
+
const agent2 = await getBackend().retrieveAgent(agentId);
|
|
458060
|
+
const record5 = agent2;
|
|
458061
|
+
if (typeof record5.model === "string" && record5.model.length > 0) {
|
|
458062
|
+
return record5.model;
|
|
458063
|
+
}
|
|
458064
|
+
return resolveModelHandleFromLlmConfig(record5.llm_config);
|
|
458065
|
+
} catch {
|
|
458066
|
+
return null;
|
|
458067
|
+
}
|
|
458068
|
+
}
|
|
458069
|
+
async function rotateChatGPTPlanOnQuotaLimit(params) {
|
|
458070
|
+
const { agentId, detail } = params;
|
|
458071
|
+
const parsedDetail = parseChatGPTUsageLimitDetail(detail);
|
|
458072
|
+
if (!parsedDetail)
|
|
458073
|
+
return null;
|
|
458074
|
+
let models3 = getCachedAvailableModels();
|
|
458075
|
+
if (!models3) {
|
|
458076
|
+
try {
|
|
458077
|
+
await getAvailableModelHandles();
|
|
458078
|
+
models3 = getCachedAvailableModels();
|
|
458079
|
+
} catch {
|
|
458080
|
+
return null;
|
|
458081
|
+
}
|
|
458082
|
+
}
|
|
458083
|
+
if (!models3)
|
|
458084
|
+
return null;
|
|
458085
|
+
let currentHandle = params.currentHandle;
|
|
458086
|
+
if (!currentHandle || !isChatGPTByokHandleInModels(currentHandle, models3)) {
|
|
458087
|
+
currentHandle = await resolveAgentModelHandle2(agentId);
|
|
458088
|
+
}
|
|
458089
|
+
if (!currentHandle || !isChatGPTByokHandleInModels(currentHandle, models3)) {
|
|
458090
|
+
return null;
|
|
458091
|
+
}
|
|
458092
|
+
const fromProvider = providerFromHandle(currentHandle);
|
|
458093
|
+
if (!fromProvider)
|
|
458094
|
+
return null;
|
|
458095
|
+
exhaustedProviders.add(fromProvider);
|
|
458096
|
+
const toHandle = selectChatGPTQuotaFailoverHandle({
|
|
458097
|
+
currentHandle,
|
|
458098
|
+
models: models3,
|
|
458099
|
+
exhaustedProviders
|
|
458100
|
+
});
|
|
458101
|
+
if (!toHandle)
|
|
458102
|
+
return null;
|
|
458103
|
+
const toProvider = providerFromHandle(toHandle);
|
|
458104
|
+
if (!toProvider)
|
|
458105
|
+
return null;
|
|
458106
|
+
try {
|
|
458107
|
+
await updateAgentLLMConfig(agentId, toHandle, {
|
|
458108
|
+
provider_type: "chatgpt_oauth"
|
|
458109
|
+
});
|
|
458110
|
+
} catch {
|
|
458111
|
+
return null;
|
|
458112
|
+
}
|
|
458113
|
+
return {
|
|
458114
|
+
fromProvider,
|
|
458115
|
+
toProvider,
|
|
458116
|
+
toHandle,
|
|
458117
|
+
resetsAt: parsedDetail.resetsAt
|
|
458118
|
+
};
|
|
458119
|
+
}
|
|
458120
|
+
function formatPlanRotationNotice(params) {
|
|
458121
|
+
const { fromProvider, toProvider, resetsAt } = params;
|
|
458122
|
+
const resetSuffix = resetsAt !== null ? ` (resets ${new Date(resetsAt).toLocaleTimeString([], {
|
|
458123
|
+
hour: "numeric",
|
|
458124
|
+
minute: "2-digit"
|
|
458125
|
+
})})` : "";
|
|
458126
|
+
return `${fromProvider} hit its usage limit${resetSuffix} — switched to ${toProvider}`;
|
|
458127
|
+
}
|
|
458128
|
+
var CHATGPT_PLAN_ROTATION_MAX_SWAPS_PER_TURN = 3, exhaustedProviders;
|
|
458129
|
+
var init_chatgpt_plan_rotation = __esm(() => {
|
|
458130
|
+
init_available_models();
|
|
458131
|
+
init_model_handles();
|
|
458132
|
+
init_modify();
|
|
458133
|
+
init_turn_recovery_policy();
|
|
458134
|
+
init_backend2();
|
|
458135
|
+
exhaustedProviders = new Set;
|
|
458136
|
+
});
|
|
458137
|
+
|
|
457814
458138
|
// src/websocket/listener/skill-injection.ts
|
|
457815
458139
|
function injectQueuedSkillContent(messages, context3) {
|
|
457816
458140
|
const skillContents = consumeQueuedSkillContent();
|
|
@@ -458055,9 +458379,11 @@ async function resolveStaleApprovals(runtime, socket, turnLease, deps = {}) {
|
|
|
458055
458379
|
}
|
|
458056
458380
|
]);
|
|
458057
458381
|
let continuationActingUserId;
|
|
458382
|
+
let recoveryTurnCorrelation;
|
|
458058
458383
|
const consumedQueuedTurn = consumeQueuedTurn(runtime);
|
|
458059
458384
|
if (consumedQueuedTurn) {
|
|
458060
458385
|
const { dequeuedBatch, queuedTurn } = consumedQueuedTurn;
|
|
458386
|
+
recoveryTurnCorrelation = createTurnCorrelation(runtime, queuedTurn, dequeuedBatch.batchId);
|
|
458061
458387
|
continuationActingUserId = queuedTurn.actingUserId;
|
|
458062
458388
|
continuationInput = appendQueuedTurnToInput(continuationInput, queuedTurn);
|
|
458063
458389
|
emitDequeuedUserMessage(socket, runtime, queuedTurn, dequeuedBatch);
|
|
@@ -458088,7 +458414,8 @@ async function resolveStaleApprovals(runtime, socket, turnLease, deps = {}) {
|
|
|
458088
458414
|
const drainResult = await drainRecoveryStream(recoveryStream, socket, runtime, {
|
|
458089
458415
|
agentId: runtime.agentId ?? undefined,
|
|
458090
458416
|
conversationId: recoveryConversationId,
|
|
458091
|
-
turnLease
|
|
458417
|
+
turnLease,
|
|
458418
|
+
turnCorrelation: recoveryTurnCorrelation
|
|
458092
458419
|
});
|
|
458093
458420
|
assertCurrentTurnLease();
|
|
458094
458421
|
if (drainResult.stopReason === "error") {
|
|
@@ -458383,6 +458710,7 @@ var init_send = __esm(async () => {
|
|
|
458383
458710
|
init_permission_mode();
|
|
458384
458711
|
init_protocol_outbound();
|
|
458385
458712
|
init_skill_injection();
|
|
458713
|
+
init_turn_correlation();
|
|
458386
458714
|
init_turn_input_state();
|
|
458387
458715
|
init_turn_status();
|
|
458388
458716
|
await __promiseAll([
|
|
@@ -458398,6 +458726,20 @@ var init_send = __esm(async () => {
|
|
|
458398
458726
|
});
|
|
458399
458727
|
|
|
458400
458728
|
// src/websocket/listener/teleport.ts
|
|
458729
|
+
function buildTeleportContinuationMessages(params) {
|
|
458730
|
+
return [
|
|
458731
|
+
{
|
|
458732
|
+
type: "approval",
|
|
458733
|
+
approvals: params.approvals,
|
|
458734
|
+
otid: params.teleportId
|
|
458735
|
+
},
|
|
458736
|
+
{
|
|
458737
|
+
role: "system",
|
|
458738
|
+
content: "<system-reminder>Teleportation to this environment is complete. Continue the existing task from this environment now.</system-reminder>",
|
|
458739
|
+
otid: `${params.teleportId}:continue`
|
|
458740
|
+
}
|
|
458741
|
+
];
|
|
458742
|
+
}
|
|
458401
458743
|
function getPendingTeleports(runtime) {
|
|
458402
458744
|
runtime.pendingTeleports ??= new Map;
|
|
458403
458745
|
return runtime.pendingTeleports;
|
|
@@ -460708,6 +461050,7 @@ async function handleApprovalStop(params) {
|
|
|
460708
461050
|
turnInput,
|
|
460709
461051
|
turnToolContextId,
|
|
460710
461052
|
turnLease,
|
|
461053
|
+
turnCorrelation,
|
|
460711
461054
|
processOwnedTurn = false,
|
|
460712
461055
|
buildSendOptions,
|
|
460713
461056
|
dependencies: dependencies4
|
|
@@ -461010,6 +461353,7 @@ async function handleApprovalStop(params) {
|
|
|
461010
461353
|
const consumedQueuedTurn = consumeQueuedTurn(runtime);
|
|
461011
461354
|
if (consumedQueuedTurn) {
|
|
461012
461355
|
const { dequeuedBatch, queuedTurn } = consumedQueuedTurn;
|
|
461356
|
+
turnCorrelation?.appendDequeuedBatch(dequeuedBatch.batchId);
|
|
461013
461357
|
continuationBatchId = dequeuedBatch.batchId;
|
|
461014
461358
|
continuationActingUserId = queuedTurn.actingUserId;
|
|
461015
461359
|
nextTurnInput = appendQueuedTurnToInput(nextTurnInput, queuedTurn);
|
|
@@ -462795,23 +463139,24 @@ var init_turn_setup = __esm(async () => {
|
|
|
462795
463139
|
});
|
|
462796
463140
|
|
|
462797
463141
|
// src/websocket/listener/turn.ts
|
|
462798
|
-
async function handleIncomingMessage(msg, socket, runtime, onStatusChange, connectionId, dequeuedBatchId = `batch-direct-${crypto.randomUUID()}`, existingTurnLease) {
|
|
463142
|
+
async function handleIncomingMessage(msg, socket, runtime, onStatusChange, connectionId, dequeuedBatchId = `batch-direct-${crypto.randomUUID()}`, existingTurnLease, existingTurnCorrelation) {
|
|
462799
463143
|
notifyTurnStarted(msg);
|
|
462800
463144
|
try {
|
|
462801
|
-
await handleIncomingMessageInner(msg, socket, runtime, onStatusChange, connectionId, dequeuedBatchId, existingTurnLease);
|
|
463145
|
+
await handleIncomingMessageInner(msg, socket, runtime, onStatusChange, connectionId, dequeuedBatchId, existingTurnLease, existingTurnCorrelation);
|
|
462802
463146
|
} finally {
|
|
462803
463147
|
notifyTurnFinished(msg);
|
|
462804
463148
|
finishPendingTeleport(runtime);
|
|
462805
463149
|
}
|
|
462806
463150
|
}
|
|
462807
|
-
async function handleIncomingMessageInner(msg, socket, runtime, onStatusChange, connectionId, dequeuedBatchId = `batch-direct-${crypto.randomUUID()}`, existingTurnLease) {
|
|
463151
|
+
async function handleIncomingMessageInner(msg, socket, runtime, onStatusChange, connectionId, dequeuedBatchId = `batch-direct-${crypto.randomUUID()}`, existingTurnLease, existingTurnCorrelation) {
|
|
462808
463152
|
const agentId = msg.agentId;
|
|
462809
463153
|
const requestedConversationId = msg.conversationId || undefined;
|
|
462810
463154
|
const conversationId = requestedConversationId ?? "default";
|
|
462811
463155
|
const normalizedAgentId = normalizeCwdAgentId(agentId);
|
|
462812
463156
|
const turnWorkingDirectory = getConversationWorkingDirectory(runtime.listener, normalizedAgentId, conversationId);
|
|
462813
463157
|
const turnPermissionModeState = getOrCreateConversationPermissionModeStateRef(runtime.listener, normalizedAgentId, conversationId);
|
|
462814
|
-
let postStopApprovalRecoveryRetries = 0, llmApiErrorRetries = 0, emptyResponseRetries = 0, lastApprovalContinuationAccepted = false, activeDequeuedBatchId = dequeuedBatchId;
|
|
463158
|
+
let postStopApprovalRecoveryRetries = 0, llmApiErrorRetries = 0, emptyResponseRetries = 0, chatgptPlanSwaps = 0, lastApprovalContinuationAccepted = false, activeDequeuedBatchId = dequeuedBatchId;
|
|
463159
|
+
const turnCorrelation = existingTurnCorrelation ?? createTurnCorrelation(runtime, msg, activeDequeuedBatchId);
|
|
462815
463160
|
const msgRunIds = [];
|
|
462816
463161
|
let lastExecutionResults = null;
|
|
462817
463162
|
let lastExecutingToolCallIds = [];
|
|
@@ -462980,6 +463325,7 @@ async function handleIncomingMessageInner(msg, socket, runtime, onStatusChange,
|
|
|
462980
463325
|
if (typeof maybeRunId === "string") {
|
|
462981
463326
|
runId = maybeRunId;
|
|
462982
463327
|
runtime.turnLifecycle.setRunId(turnLease, maybeRunId);
|
|
463328
|
+
turnCorrelation.observeRun(maybeRunId);
|
|
462983
463329
|
if (!runIdSent) {
|
|
462984
463330
|
runIdSent = true;
|
|
462985
463331
|
msgRunIds.push(maybeRunId);
|
|
@@ -463181,6 +463527,51 @@ async function handleIncomingMessageInner(msg, socket, runtime, onStatusChange,
|
|
|
463181
463527
|
turnToolContextId = getStreamToolContextId(stream12);
|
|
463182
463528
|
continue;
|
|
463183
463529
|
}
|
|
463530
|
+
if (chatgptPlanSwaps < CHATGPT_PLAN_ROTATION_MAX_SWAPS_PER_TURN) {
|
|
463531
|
+
const rotation = await rotateChatGPTPlanOnQuotaLimit({
|
|
463532
|
+
agentId,
|
|
463533
|
+
currentHandle: null,
|
|
463534
|
+
detail: errorDetail2
|
|
463535
|
+
});
|
|
463536
|
+
if (rotation) {
|
|
463537
|
+
chatgptPlanSwaps += 1;
|
|
463538
|
+
emitRecoverableRetryNotice(socket, runtime, {
|
|
463539
|
+
kind: "transient_provider_retry",
|
|
463540
|
+
message: formatPlanRotationNotice(rotation),
|
|
463541
|
+
reason: "llm_api_error",
|
|
463542
|
+
attempt: chatgptPlanSwaps,
|
|
463543
|
+
maxAttempts: CHATGPT_PLAN_ROTATION_MAX_SWAPS_PER_TURN,
|
|
463544
|
+
delayMs: 0,
|
|
463545
|
+
runId: lastRunId || undefined,
|
|
463546
|
+
agentId,
|
|
463547
|
+
conversationId
|
|
463548
|
+
});
|
|
463549
|
+
if (turnAbortSignal.aborted) {
|
|
463550
|
+
throw new Error("Cancelled by user");
|
|
463551
|
+
}
|
|
463552
|
+
turnInput = refreshTurnInputOtidsForNewRequest(turnInput);
|
|
463553
|
+
setTurnLoopStatus(runtime, turnLease, "SENDING_API_REQUEST", {
|
|
463554
|
+
agent_id: agentId,
|
|
463555
|
+
conversation_id: conversationId
|
|
463556
|
+
});
|
|
463557
|
+
const retryInputWithSkillContent = injectQueuedSkillContent(turnInput.messages, { socket, runtime, agentId, conversationId });
|
|
463558
|
+
const retrySendResult = await turnInputSender.send(retryInputWithSkillContent);
|
|
463559
|
+
turnInput = updateTurnInputMessagesPreservingOtids(turnInput, retryInputWithSkillContent);
|
|
463560
|
+
const retryStream = turnInputSender.accept(retrySendResult);
|
|
463561
|
+
if (!retryStream) {
|
|
463562
|
+
return;
|
|
463563
|
+
}
|
|
463564
|
+
stream12 = retryStream;
|
|
463565
|
+
pendingNormalizationInterruptedToolCallIds = [];
|
|
463566
|
+
markAwaitingAcceptedApprovalContinuationRunId(runtime, turnLease, turnInput.messages);
|
|
463567
|
+
setTurnLoopStatus(runtime, turnLease, "PROCESSING_API_RESPONSE", {
|
|
463568
|
+
agent_id: agentId,
|
|
463569
|
+
conversation_id: conversationId
|
|
463570
|
+
});
|
|
463571
|
+
turnToolContextId = getStreamToolContextId(stream12);
|
|
463572
|
+
continue;
|
|
463573
|
+
}
|
|
463574
|
+
}
|
|
463184
463575
|
const retriable = await isRetriablePostStopError(stopReason || "error", lastRunId, errorDetail2);
|
|
463185
463576
|
if (finishIfInterrupted(lastRunId || runtime.activeRunId)) {
|
|
463186
463577
|
break;
|
|
@@ -463287,6 +463678,7 @@ async function handleIncomingMessageInner(msg, socket, runtime, onStatusChange,
|
|
|
463287
463678
|
pendingNormalizationInterruptedToolCallIds,
|
|
463288
463679
|
turnToolContextId,
|
|
463289
463680
|
turnLease,
|
|
463681
|
+
turnCorrelation,
|
|
463290
463682
|
processOwnedTurn: msg.processOwnedTurn === true,
|
|
463291
463683
|
buildSendOptions
|
|
463292
463684
|
});
|
|
@@ -463464,6 +463856,7 @@ async function handleIncomingMessageInner(msg, socket, runtime, onStatusChange,
|
|
|
463464
463856
|
}
|
|
463465
463857
|
var init_turn = __esm(async () => {
|
|
463466
463858
|
init_approval_recovery();
|
|
463859
|
+
init_chatgpt_plan_rotation();
|
|
463467
463860
|
init_check_approval();
|
|
463468
463861
|
init_turn_recovery_policy();
|
|
463469
463862
|
init_backend2();
|
|
@@ -463483,6 +463876,7 @@ var init_turn = __esm(async () => {
|
|
|
463483
463876
|
init_teleport();
|
|
463484
463877
|
init_turn_cleanup();
|
|
463485
463878
|
init_turn_context();
|
|
463879
|
+
init_turn_correlation();
|
|
463486
463880
|
init_turn_input_state();
|
|
463487
463881
|
init_turn_observers();
|
|
463488
463882
|
init_turn_status();
|
|
@@ -464079,6 +464473,7 @@ function createConnectionTurnProcessor(runtime) {
|
|
|
464079
464473
|
}
|
|
464080
464474
|
const connection = runtime.connections.get(queuedTurn.connectionId);
|
|
464081
464475
|
if (!connection || connection.cancellation.signal.aborted) {
|
|
464476
|
+
scopedRuntime.dequeuedClientMessageIdsByBatchId.delete(dequeuedBatch.batchId);
|
|
464082
464477
|
return;
|
|
464083
464478
|
}
|
|
464084
464479
|
await handleIncomingMessage(queuedTurn, getOrCreateProcessTransport(runtime), scopedRuntime, connection.options.onStatusChange, connection.id, dequeuedBatch.batchId);
|
|
@@ -467726,32 +468121,6 @@ var init_git_branches = __esm(() => {
|
|
|
467726
468121
|
init_protocol_outbound();
|
|
467727
468122
|
});
|
|
467728
468123
|
|
|
467729
|
-
// src/websocket/listener/inbound-queue.ts
|
|
467730
|
-
function getInboundClientMessageId(incoming) {
|
|
467731
|
-
return incoming.messages.find((payload) => ("content" in payload))?.client_message_id;
|
|
467732
|
-
}
|
|
467733
|
-
function enqueueInboundUserMessage(runtime, incoming, actingUserId) {
|
|
467734
|
-
const firstUserPayload = incoming.messages.find((payload) => ("content" in payload));
|
|
467735
|
-
if (!firstUserPayload) {
|
|
467736
|
-
return false;
|
|
467737
|
-
}
|
|
467738
|
-
const enqueuedItem = runtime.queueRuntime.enqueue({
|
|
467739
|
-
kind: "message",
|
|
467740
|
-
source: "user",
|
|
467741
|
-
content: firstUserPayload.content,
|
|
467742
|
-
clientMessageId: firstUserPayload.client_message_id ?? `cm-submit-${crypto.randomUUID()}`,
|
|
467743
|
-
agentId: incoming.agentId,
|
|
467744
|
-
conversationId: incoming.conversationId || "default",
|
|
467745
|
-
...incoming.noCoalesce ? { noCoalesce: true } : {},
|
|
467746
|
-
actingUserId
|
|
467747
|
-
});
|
|
467748
|
-
if (!enqueuedItem) {
|
|
467749
|
-
return false;
|
|
467750
|
-
}
|
|
467751
|
-
runtime.queuedMessagesByItemId.set(enqueuedItem.id, incoming);
|
|
467752
|
-
return true;
|
|
467753
|
-
}
|
|
467754
|
-
|
|
467755
468124
|
// src/websocket/listener/inbound-dispatch.ts
|
|
467756
468125
|
function getAcceptedInputDisposition(runtime, clientMessageId) {
|
|
467757
468126
|
if (!clientMessageId)
|
|
@@ -468497,13 +468866,10 @@ function createListenerMessageHandler(params) {
|
|
|
468497
468866
|
connectionId,
|
|
468498
468867
|
agentId: parsed.runtime.agent_id,
|
|
468499
468868
|
conversationId: parsed.runtime.conversation_id,
|
|
468500
|
-
messages:
|
|
468501
|
-
|
|
468502
|
-
|
|
468503
|
-
|
|
468504
|
-
otid: teleportId
|
|
468505
|
-
}
|
|
468506
|
-
]
|
|
468869
|
+
messages: buildTeleportContinuationMessages({
|
|
468870
|
+
teleportId,
|
|
468871
|
+
approvals
|
|
468872
|
+
})
|
|
468507
468873
|
}, socket, scopedRuntime2, opts.onStatusChange, connectionId);
|
|
468508
468874
|
});
|
|
468509
468875
|
return;
|
|
@@ -468673,12 +469039,10 @@ function createListenerMessageHandler(params) {
|
|
|
468673
469039
|
success: removed !== null,
|
|
468674
469040
|
item_id: parsed.item_id
|
|
468675
469041
|
}, "remove_queue_item_response", "remove_queue_item");
|
|
468676
|
-
|
|
468677
|
-
|
|
468678
|
-
|
|
468679
|
-
|
|
468680
|
-
});
|
|
468681
|
-
}
|
|
469042
|
+
emitQueueUpdateIfOpen(runtime, {
|
|
469043
|
+
agent_id: parsed.runtime.agent_id,
|
|
469044
|
+
conversation_id: parsed.runtime.conversation_id
|
|
469045
|
+
});
|
|
468682
469046
|
return;
|
|
468683
469047
|
}
|
|
468684
469048
|
if (fileCommandSession.handle(parsed)) {
|
|
@@ -485848,6 +486212,9 @@ function isAssistantMessage2(message) {
|
|
|
485848
486212
|
function isUserMessage(message) {
|
|
485849
486213
|
return message.message_type === "user_message";
|
|
485850
486214
|
}
|
|
486215
|
+
function isTaskNotificationMessage(message) {
|
|
486216
|
+
return extractMessageText(message).trimStart().startsWith("<task-notification>");
|
|
486217
|
+
}
|
|
485851
486218
|
function messageRunId(message) {
|
|
485852
486219
|
if (!message)
|
|
485853
486220
|
return null;
|
|
@@ -485884,8 +486251,9 @@ async function waitForEnvironmentAssistantMessage(params) {
|
|
|
485884
486251
|
return sequenceId !== null && sequenceId > anchorSequenceId;
|
|
485885
486252
|
});
|
|
485886
486253
|
const nextUserSequenceId = newerMessages.reduce((closest, message) => {
|
|
485887
|
-
if (!isUserMessage(message))
|
|
486254
|
+
if (!isUserMessage(message) || isTaskNotificationMessage(message)) {
|
|
485888
486255
|
return closest;
|
|
486256
|
+
}
|
|
485889
486257
|
const sequenceId = messageSequenceId(message);
|
|
485890
486258
|
if (sequenceId === null)
|
|
485891
486259
|
return closest;
|
|
@@ -497557,7 +497925,7 @@ var init_mcp_client = __esm(() => {
|
|
|
497557
497925
|
init_streamableHttp();
|
|
497558
497926
|
DEFAULT_CLIENT_INFO = {
|
|
497559
497927
|
name: "letta-code",
|
|
497560
|
-
version: "0.30.
|
|
497928
|
+
version: "0.30.28"
|
|
497561
497929
|
};
|
|
497562
497930
|
});
|
|
497563
497931
|
|
|
@@ -499949,6 +500317,7 @@ ${loadedContents.join(`
|
|
|
499949
500317
|
let llmApiErrorRetries = 0;
|
|
499950
500318
|
let emptyResponseRetries = 0;
|
|
499951
500319
|
let conversationBusyRetries = 0;
|
|
500320
|
+
let chatgptPlanSwaps = 0;
|
|
499952
500321
|
markMilestone("HEADLESS_FIRST_STREAM_START");
|
|
499953
500322
|
measureSinceMilestone("headless-setup-total", "HEADLESS_CLIENT_READY");
|
|
499954
500323
|
const checkMaxTurns = async () => {
|
|
@@ -500215,6 +500584,7 @@ ${loadedContents.join(`
|
|
|
500215
500584
|
llmApiErrorRetries = 0;
|
|
500216
500585
|
emptyResponseRetries = 0;
|
|
500217
500586
|
conversationBusyRetries = 0;
|
|
500587
|
+
chatgptPlanSwaps = 0;
|
|
500218
500588
|
const continueMessage = await emitHeadlessTurnEnd({
|
|
500219
500589
|
agent: agent2,
|
|
500220
500590
|
conversationId,
|
|
@@ -500315,6 +500685,34 @@ ${loadedContents.join(`
|
|
|
500315
500685
|
}
|
|
500316
500686
|
}
|
|
500317
500687
|
const detailFromRun = await fetchRunErrorDetail(lastRunId);
|
|
500688
|
+
if (chatgptPlanSwaps < CHATGPT_PLAN_ROTATION_MAX_SWAPS_PER_TURN) {
|
|
500689
|
+
const rotation = await rotateChatGPTPlanOnQuotaLimit({
|
|
500690
|
+
agentId: agent2.id,
|
|
500691
|
+
currentHandle: null,
|
|
500692
|
+
detail: detailFromRun ?? latestErrorText
|
|
500693
|
+
});
|
|
500694
|
+
if (rotation) {
|
|
500695
|
+
chatgptPlanSwaps += 1;
|
|
500696
|
+
const rotationMessage = formatPlanRotationNotice(rotation);
|
|
500697
|
+
if (outputFormat === "stream-json") {
|
|
500698
|
+
const retryMsg = {
|
|
500699
|
+
type: "retry",
|
|
500700
|
+
reason: "llm_api_error",
|
|
500701
|
+
attempt: chatgptPlanSwaps,
|
|
500702
|
+
max_attempts: CHATGPT_PLAN_ROTATION_MAX_SWAPS_PER_TURN,
|
|
500703
|
+
delay_ms: 0,
|
|
500704
|
+
run_id: lastRunId ?? undefined,
|
|
500705
|
+
session_id: sessionId,
|
|
500706
|
+
uuid: `retry-${lastRunId || randomUUID35()}`
|
|
500707
|
+
};
|
|
500708
|
+
writeWireMessage(retryMsg);
|
|
500709
|
+
} else {
|
|
500710
|
+
console.error(rotationMessage);
|
|
500711
|
+
}
|
|
500712
|
+
currentInput = refreshInputOtidsForNewRequest(currentInput);
|
|
500713
|
+
continue;
|
|
500714
|
+
}
|
|
500715
|
+
}
|
|
500318
500716
|
if (stopReason === "llm_api_error") {
|
|
500319
500717
|
if (llmApiErrorRetries < LLM_API_ERROR_MAX_RETRIES2) {
|
|
500320
500718
|
const attempt2 = llmApiErrorRetries + 1;
|
|
@@ -501686,6 +502084,7 @@ var init_headless = __esm(async () => {
|
|
|
501686
502084
|
init_subagent_stdout_failure();
|
|
501687
502085
|
init_approval_recovery();
|
|
501688
502086
|
init_bootstrap_handler();
|
|
502087
|
+
init_chatgpt_plan_rotation();
|
|
501689
502088
|
init_client_skills();
|
|
501690
502089
|
init_context();
|
|
501691
502090
|
init_create5();
|
|
@@ -547536,6 +547935,7 @@ function useConversationLoop(ctx) {
|
|
|
547536
547935
|
buffersRef,
|
|
547537
547936
|
clearApprovalToolContext,
|
|
547538
547937
|
closeTrajectorySegment,
|
|
547938
|
+
chatgptPlanSwapsRef,
|
|
547539
547939
|
consumeQueuedMessages,
|
|
547540
547940
|
queueModeRef,
|
|
547541
547941
|
contextTrackerRef,
|
|
@@ -547767,6 +548167,7 @@ function useConversationLoop(ctx) {
|
|
|
547767
548167
|
emptyResponseRetriesRef.current = 0;
|
|
547768
548168
|
conversationBusyRetriesRef.current = 0;
|
|
547769
548169
|
quotaAutoSwapAttemptedRef.current = false;
|
|
548170
|
+
chatgptPlanSwapsRef.current = 0;
|
|
547770
548171
|
}
|
|
547771
548172
|
let currentRunId;
|
|
547772
548173
|
let preserveTranscriptStartForApproval = false;
|
|
@@ -548731,6 +549132,27 @@ ${feedback}
|
|
|
548731
549132
|
buffersRef.current.interrupted = false;
|
|
548732
549133
|
continue;
|
|
548733
549134
|
}
|
|
549135
|
+
if (chatgptPlanSwapsRef.current < CHATGPT_PLAN_ROTATION_MAX_SWAPS_PER_TURN) {
|
|
549136
|
+
const rotation = await rotateChatGPTPlanOnQuotaLimit({
|
|
549137
|
+
agentId: agentIdRef.current,
|
|
549138
|
+
currentHandle: currentModelId,
|
|
549139
|
+
detail: detailFromRun ?? fallbackError
|
|
549140
|
+
});
|
|
549141
|
+
if (rotation) {
|
|
549142
|
+
chatgptPlanSwapsRef.current += 1;
|
|
549143
|
+
const statusId = uid("status");
|
|
549144
|
+
buffersRef.current.byId.set(statusId, {
|
|
549145
|
+
kind: "status",
|
|
549146
|
+
id: statusId,
|
|
549147
|
+
lines: [formatPlanRotationNotice(rotation)]
|
|
549148
|
+
});
|
|
549149
|
+
buffersRef.current.order.push(statusId);
|
|
549150
|
+
refreshDerived();
|
|
549151
|
+
currentInput = refreshInputOtidsForNewRequest(currentInput);
|
|
549152
|
+
buffersRef.current.interrupted = false;
|
|
549153
|
+
continue;
|
|
549154
|
+
}
|
|
549155
|
+
}
|
|
548734
549156
|
const autoSwapOnQuotaLimitEnabled = settingsManager.getSetting("autoSwapOnQuotaLimit") !== false;
|
|
548735
549157
|
const supportsHostedAutoQuotaFallback = !getBackend().capabilities.localModelCatalog;
|
|
548736
549158
|
const isQuotaLimit = isQuotaLimitErrorDetail(detailFromRun ?? fallbackError);
|
|
@@ -549012,6 +549434,7 @@ var init_use_conversation_loop = __esm(async () => {
|
|
|
549012
549434
|
init_error();
|
|
549013
549435
|
init_approval_recovery();
|
|
549014
549436
|
init_available_models();
|
|
549437
|
+
init_chatgpt_plan_rotation();
|
|
549015
549438
|
init_check_approval();
|
|
549016
549439
|
init_model();
|
|
549017
549440
|
init_prompt_assets();
|
|
@@ -557857,6 +558280,7 @@ function App2({
|
|
|
557857
558280
|
const llmApiErrorRetriesRef = import_react121.useRef(0);
|
|
557858
558281
|
const quotaAutoSwapAttemptedRef = import_react121.useRef(false);
|
|
557859
558282
|
const emptyResponseRetriesRef = import_react121.useRef(0);
|
|
558283
|
+
const chatgptPlanSwapsRef = import_react121.useRef(0);
|
|
557860
558284
|
const conversationBusyRetriesRef = import_react121.useRef(0);
|
|
557861
558285
|
const [queueDisplay, setQueueDisplay] = import_react121.useState([]);
|
|
557862
558286
|
const tuiQueueRef = import_react121.useRef(null);
|
|
@@ -559345,6 +559769,7 @@ Memory may be stale. Try running: git -C ${getScopedMemoryFilesystemRoot(agentId
|
|
|
559345
559769
|
autoAllowedExecutionRef,
|
|
559346
559770
|
buffersRef,
|
|
559347
559771
|
clearApprovalToolContext,
|
|
559772
|
+
chatgptPlanSwapsRef,
|
|
559348
559773
|
closeTrajectorySegment,
|
|
559349
559774
|
consumeQueuedMessages,
|
|
559350
559775
|
queueModeRef,
|
|
@@ -564456,4 +564881,4 @@ function registerBunOAuthFlows() {
|
|
|
564456
564881
|
registerBunOAuthFlows();
|
|
564457
564882
|
await init_src5().then(() => exports_src2);
|
|
564458
564883
|
|
|
564459
|
-
//# debugId=
|
|
564884
|
+
//# debugId=66D224FF7F960BF164756E2164756E21
|