@dreb/coding-agent 2.60.0 → 2.61.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (34) hide show
  1. package/README.md +3 -3
  2. package/dist/core/agent-session.d.ts +49 -7
  3. package/dist/core/agent-session.d.ts.map +1 -1
  4. package/dist/core/agent-session.js +136 -28
  5. package/dist/core/agent-session.js.map +1 -1
  6. package/dist/core/model-registry.d.ts +4 -0
  7. package/dist/core/model-registry.d.ts.map +1 -1
  8. package/dist/core/model-registry.js +74 -3
  9. package/dist/core/model-registry.js.map +1 -1
  10. package/dist/core/settings-manager.d.ts +1 -4
  11. package/dist/core/settings-manager.d.ts.map +1 -1
  12. package/dist/core/settings-manager.js.map +1 -1
  13. package/dist/modes/interactive/components/user-message-selector.d.ts +7 -2
  14. package/dist/modes/interactive/components/user-message-selector.d.ts.map +1 -1
  15. package/dist/modes/interactive/components/user-message-selector.js +19 -12
  16. package/dist/modes/interactive/components/user-message-selector.js.map +1 -1
  17. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  18. package/dist/modes/interactive/interactive-mode.js +27 -12
  19. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  20. package/dist/modes/rpc/rpc-client.d.ts +1 -0
  21. package/dist/modes/rpc/rpc-client.d.ts.map +1 -1
  22. package/dist/modes/rpc/rpc-client.js +2 -1
  23. package/dist/modes/rpc/rpc-client.js.map +1 -1
  24. package/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
  25. package/dist/modes/rpc/rpc-mode.js +1 -1
  26. package/dist/modes/rpc/rpc-mode.js.map +1 -1
  27. package/dist/modes/rpc/rpc-types.d.ts +1 -0
  28. package/dist/modes/rpc/rpc-types.d.ts.map +1 -1
  29. package/dist/modes/rpc/rpc-types.js.map +1 -1
  30. package/docs/models.md +26 -8
  31. package/docs/rpc.md +16 -6
  32. package/docs/settings.md +11 -3
  33. package/docs/tree.md +1 -1
  34. package/package.json +1 -1
package/README.md CHANGED
@@ -175,7 +175,7 @@ Type `/` in the editor to trigger commands. [Extensions](#extensions) can regist
175
175
  | `/name <name>` | Set session display name |
176
176
  | `/session` | Show session info (path, tokens, cost) |
177
177
  | `/tree` | Jump to any point in the session and continue from there |
178
- | `/fork` | Create a new session from the current branch |
178
+ | `/fork` | Branch a new session from any user or assistant message (assistant = continue from that answer, user = rewind and re-ask) |
179
179
  | `/compact [prompt]` | Manually compact context, optional custom instructions |
180
180
  | `/copy` | Open multi-select message picker to copy any messages to clipboard. Assistant reasoning is excluded by default and offered as a separate, selectable `Thinking` row. |
181
181
  | `/dream` | Consolidate and prune memories — backs up, merges duplicates, scans sessions for patterns |
@@ -243,7 +243,7 @@ dreb --fork <path> # Fork specific session file or ID into a new session
243
243
  - Filter modes (Ctrl+O): default → no-tools → user-only → labeled-only → all
244
244
  - Press `L` (Shift+L) to label entries as bookmarks
245
245
 
246
- **`/fork`** - Create a new session file from the current branch. Opens a selector, copies history up to the selected point, and places that message in the editor for modification.
246
+ **`/fork`** - Create a new session file by branching from any point in the current conversation. Opens a selector listing every user and assistant message: picking an **assistant** message keeps that response and everything before it (continue from that answer) with an empty editor; picking a **user** message rewinds to before it (dropping it and everything after) and places its text in the editor for re-asking.
247
247
 
248
248
  **`--fork <path|id>`** - Fork an existing session file or partial session UUID directly from the CLI. This copies the full source session into a new session file in the current project.
249
249
 
@@ -319,7 +319,7 @@ A trusted root permits lazy loading for that existing directory and all of its d
319
319
 
320
320
  Replace the default system prompt with `.dreb/SYSTEM.md` (project) or `~/.dreb/agent/SYSTEM.md` (global). Append without replacing via `APPEND_SYSTEM.md`.
321
321
 
322
- For persistent instructions that apply only to one exact provider/model pair, use `modelSettings` in `settings.json` with a canonical key such as `openai-codex/gpt-5.6-sol`. Set `systemPrompt` to replace dreb's built-in prompt or `appendSystemPrompt` to append instructions. The same mechanism works for local/custom models registered in `models.json`, and the prompt updates immediately when the model changes. Explicit session replacements (`--system-prompt`, `SYSTEM.md`, or SDK hooks) take precedence. See [Model settings](docs/settings.md#modelsettings).
322
+ For persistent instructions that apply only to one exact provider/model pair, set `systemPrompt` to replace dreb's built-in prompt or `appendSystemPrompt` to append instructions. Put the field directly on a custom `models[]` entry or built-in `modelOverrides` entry in `models.json`, or use `modelSettings` in `settings.json` with a canonical key such as `openai-codex/gpt-5.6-sol`. Configure prompt behavior in only one file for a canonical model: dreb fails loudly instead of applying implicit precedence when both files declare it. Prompt changes apply when the model changes, and `/reload` picks up edits from either file. Explicit session replacements (`--system-prompt`, `SYSTEM.md`, or SDK hooks) take precedence over model replacement; model append instructions still follow the selected base. See [Custom models](docs/models.md#model-configuration) and [Model settings](docs/settings.md#modelsettings).
323
323
 
324
324
  ---
325
325
 
@@ -431,6 +431,7 @@ export declare class AgentSession {
431
431
  getFilteredSkills(): import("./skills.js").Skill[];
432
432
  /** @deprecated Use getFilteredSkills() instead */
433
433
  private _getFilteredSkills;
434
+ private _resolveModelPromptSettings;
434
435
  private _rebuildSystemPrompt;
435
436
  /**
436
437
  * Send a prompt to the agent.
@@ -563,7 +564,7 @@ export declare class AgentSession {
563
564
  * resolves identically to how createAgentSession seeds it at startup.
564
565
  */
565
566
  private _refreshThinkingDisplay;
566
- /** Reject malformed target-model prompt settings before a model switch mutates session state. */
567
+ /** Reject malformed or conflicting target-model prompt settings before mutating session state. */
567
568
  private _validateModelPromptSettings;
568
569
  /**
569
570
  * Cycle to next/previous model.
@@ -721,18 +722,29 @@ export declare class AgentSession {
721
722
  */
722
723
  setSessionName(name: string): void;
723
724
  /**
724
- * Create a fork from a specific entry.
725
+ * Create a fork from a specific entry. The fork point may be any user or
726
+ * assistant message in the transcript; branch semantics depend on the role:
727
+ *
728
+ * - **Assistant message** -> the new branch *includes* the selected response
729
+ * (and everything before it); no editor pre-fill. "Continue from this answer."
730
+ * Forking at the last assistant message keeps the entire current state.
731
+ * - **User message** -> rewind to *before* the selected message (branch from its
732
+ * parent, dropping the message and everything after it) and offer its text as
733
+ * editor pre-fill. "Edit / re-ask this question."
734
+ *
725
735
  * Emits before_fork/fork session events to extensions.
726
736
  *
727
- * @param entryId ID of the entry to fork from
737
+ * @param entryId ID of the message entry to fork from
728
738
  * @returns Object with:
729
- * - selectedText: The text of the selected user message (for editor pre-fill)
739
+ * - selectedText: The selected user message text for editor pre-fill (empty
740
+ * when forking at an assistant message).
730
741
  * - cancelled: True if an extension cancelled the fork
731
742
  */
732
743
  fork(entryId: string): Promise<{
733
744
  selectedText: string;
734
745
  cancelled: boolean;
735
746
  }>;
747
+ private _performFork;
736
748
  /**
737
749
  * Navigate to a different node in the session tree.
738
750
  * Unlike fork() which creates a new session file, this stays in the same file.
@@ -756,13 +768,43 @@ export declare class AgentSession {
756
768
  summaryEntry?: BranchSummaryEntry;
757
769
  }>;
758
770
  /**
759
- * Get all user messages from session for fork selector.
771
+ * Get all forkable messages (user *and* assistant) for the fork selector.
772
+ *
773
+ * Each entry carries its role so callers can label it and choose the right
774
+ * fork semantics (assistant = continue-from-answer, user = rewind + re-ask).
775
+ * A forkable assistant turn with no renderable text (e.g. a thinking-only
776
+ * turn) still appears as a fork point, with a generic label.
777
+ *
778
+ * Assistant turns that cannot be safely branched from (interrupted turns, or
779
+ * turns containing a tool call whose result lives in a descendant entry) are
780
+ * excluded — see _isForkableAssistant.
760
781
  */
761
- getUserMessagesForForking(): Array<{
782
+ getForkableMessages(): Array<{
762
783
  entryId: string;
763
784
  text: string;
785
+ role: "user" | "assistant";
764
786
  }>;
765
- private _extractUserMessageText;
787
+ /**
788
+ * Whether an assistant turn can be safely used as a fork point.
789
+ *
790
+ * Forking anchors on the entry's ancestors only (SessionManager.getBranch
791
+ * walks parentId upward), and errored/aborted turns are dropped by
792
+ * transformMessages() before every request. Two kinds of assistant turn
793
+ * therefore produce a branch that silently does NOT match what was selected:
794
+ *
795
+ * - stopReason "error"/"aborted": transformMessages() skips the turn, so the
796
+ * reply vanishes from context on the next request (defeating "continue from
797
+ * this answer", and risking back-to-back user messages on strict providers).
798
+ * - turns containing tool calls: their tool results are *descendant* entries a
799
+ * branch cannot include, so transformMessages() substitutes a fabricated
800
+ * "No result provided" (isError) result — telling the model a successful
801
+ * tool call failed.
802
+ *
803
+ * A completed answer (the intended "continue from here" target) has a terminal
804
+ * stopReason and no unresolved tool calls, so it passes.
805
+ */
806
+ private _isForkableAssistant;
807
+ private _extractMessageText;
766
808
  /**
767
809
  * Get session statistics.
768
810
  */