@gajae-code/coding-agent 0.9.5 → 0.10.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 (194) hide show
  1. package/CHANGELOG.md +54 -0
  2. package/dist/types/cli/classify-install-target.d.ts +0 -10
  3. package/dist/types/cli/daemon-cli.d.ts +2 -0
  4. package/dist/types/cli/initial-message.d.ts +1 -1
  5. package/dist/types/cli/malloc-env-guard.d.ts +65 -0
  6. package/dist/types/cli/malloc-env-guard.test.d.ts +1 -0
  7. package/dist/types/cli/notify-cli.d.ts +3 -1
  8. package/dist/types/cli/session-picker.d.ts +4 -3
  9. package/dist/types/cli/update-cli.d.ts +22 -3
  10. package/dist/types/cli.d.ts +4 -0
  11. package/dist/types/commands/daemon.d.ts +6 -2
  12. package/dist/types/commands/launch.d.ts +1 -0
  13. package/dist/types/commands/notify.d.ts +6 -0
  14. package/dist/types/commit/analysis/conventional.d.ts +1 -1
  15. package/dist/types/commit/analysis/summary.d.ts +1 -1
  16. package/dist/types/commit/changelog/generate.d.ts +1 -1
  17. package/dist/types/commit/changelog/index.d.ts +2 -2
  18. package/dist/types/commit/map-reduce/map-phase.d.ts +1 -1
  19. package/dist/types/commit/map-reduce/reduce-phase.d.ts +1 -1
  20. package/dist/types/config/keybindings.d.ts +5 -0
  21. package/dist/types/config/model-profile-activation.d.ts +1 -0
  22. package/dist/types/config/settings-schema.d.ts +47 -7
  23. package/dist/types/coordinator-mcp/model-preset.d.ts +45 -0
  24. package/dist/types/coordinator-mcp/server.d.ts +67 -6
  25. package/dist/types/daemon/control-types.d.ts +10 -0
  26. package/dist/types/daemon/operator-contract.d.ts +47 -0
  27. package/dist/types/defaults/gjc/extensions/grok-cli-vendor/src/models/catalog.d.ts +4 -0
  28. package/dist/types/discovery/helpers.d.ts +1 -1
  29. package/dist/types/discovery/substitute-plugin-root.d.ts +0 -4
  30. package/dist/types/gjc-runtime/launch-tmux.d.ts +26 -7
  31. package/dist/types/gjc-runtime/session-state-sidecar.d.ts +34 -3
  32. package/dist/types/gjc-runtime/tmux-common.d.ts +6 -0
  33. package/dist/types/gjc-runtime/tmux-owner-isolation-cli.d.ts +5 -0
  34. package/dist/types/gjc-runtime/tmux-owner-isolation.d.ts +309 -0
  35. package/dist/types/gjc-runtime/tmux-sessions.d.ts +49 -17
  36. package/dist/types/internal-urls/local-protocol.d.ts +13 -9
  37. package/dist/types/main.d.ts +66 -2
  38. package/dist/types/modes/acp/acp-agent.d.ts +19 -2
  39. package/dist/types/modes/acp/acp-mode.d.ts +12 -0
  40. package/dist/types/modes/components/assistant-message.d.ts +1 -1
  41. package/dist/types/modes/components/custom-editor.d.ts +2 -0
  42. package/dist/types/modes/components/gajae-pet-widget.d.ts +59 -0
  43. package/dist/types/modes/components/hook-selector.d.ts +5 -0
  44. package/dist/types/modes/components/irc-sidebar.d.ts +32 -0
  45. package/dist/types/modes/components/pet-selector.d.ts +11 -0
  46. package/dist/types/modes/components/session-selector.d.ts +22 -9
  47. package/dist/types/modes/components/settings-selector.d.ts +2 -0
  48. package/dist/types/modes/components/tool-execution.d.ts +1 -0
  49. package/dist/types/modes/components/user-message.d.ts +2 -1
  50. package/dist/types/modes/controllers/event-controller.d.ts +4 -0
  51. package/dist/types/modes/controllers/selector-controller.d.ts +1 -0
  52. package/dist/types/modes/interactive-mode.d.ts +24 -2
  53. package/dist/types/modes/irc-observation-ledger.d.ts +22 -0
  54. package/dist/types/modes/shared/agent-wire/deep-interview-gate.d.ts +8 -0
  55. package/dist/types/modes/shared/agent-wire/unattended-run-controller.d.ts +5 -0
  56. package/dist/types/modes/shared/agent-wire/unattended-session.d.ts +45 -0
  57. package/dist/types/modes/shared/agent-wire/workflow-gate-broker.d.ts +42 -2
  58. package/dist/types/modes/theme/defaults/index.d.ts +568 -568
  59. package/dist/types/modes/types.d.ts +28 -2
  60. package/dist/types/modes/utils/abort-message.d.ts +1 -1
  61. package/dist/types/modes/utils/irc-message.d.ts +38 -0
  62. package/dist/types/modes/utils/ui-helpers.d.ts +13 -4
  63. package/dist/types/notifications/config.d.ts +34 -0
  64. package/dist/types/notifications/daemon-paths.d.ts +7 -0
  65. package/dist/types/notifications/index.d.ts +27 -0
  66. package/dist/types/notifications/lifecycle-control-runtime.d.ts +12 -4
  67. package/dist/types/notifications/notification-service.d.ts +144 -0
  68. package/dist/types/notifications/rate-limit-pool.d.ts +27 -9
  69. package/dist/types/notifications/telegram-daemon-control.d.ts +6 -0
  70. package/dist/types/notifications/telegram-daemon.d.ts +130 -3
  71. package/dist/types/notifications/telegram-reference.d.ts +19 -2
  72. package/dist/types/notifications/topic-registry.d.ts +24 -4
  73. package/dist/types/registry/agent-registry.d.ts +2 -0
  74. package/dist/types/rlm/index.d.ts +1 -1
  75. package/dist/types/sdk.d.ts +2 -0
  76. package/dist/types/secrets/obfuscator.d.ts +1 -1
  77. package/dist/types/session/agent-session.d.ts +26 -2
  78. package/dist/types/session/cache-economics.d.ts +79 -0
  79. package/dist/types/session/provider-safety-stop.d.ts +5 -0
  80. package/dist/types/session/session-manager.d.ts +124 -4
  81. package/dist/types/session/session-storage.d.ts +155 -13
  82. package/dist/types/setup/credential-auto-import.d.ts +2 -2
  83. package/dist/types/task/executor.d.ts +3 -0
  84. package/dist/types/task/receipt.d.ts +3 -1
  85. package/dist/types/task/types.d.ts +8 -0
  86. package/dist/types/tools/ask-answer-registry.d.ts +5 -0
  87. package/dist/types/tools/ask.d.ts +25 -1
  88. package/dist/types/tools/bash.d.ts +1 -1
  89. package/dist/types/tools/browser/tab-supervisor.d.ts +6 -0
  90. package/dist/types/tools/index.d.ts +58 -6
  91. package/dist/types/tools/telegram-send.d.ts +7 -0
  92. package/dist/types/utils/external-editor.d.ts +2 -0
  93. package/package.json +9 -9
  94. package/scripts/compile-args.ts +8 -2
  95. package/scripts/g004-tmux-smoke.ts +196 -36
  96. package/src/cli/daemon-cli.ts +19 -29
  97. package/src/cli/malloc-env-guard.test.ts +104 -0
  98. package/src/cli/malloc-env-guard.ts +149 -0
  99. package/src/cli/notify-cli.ts +78 -14
  100. package/src/cli/session-picker.ts +23 -40
  101. package/src/cli/update-cli.ts +56 -37
  102. package/src/cli.ts +50 -10
  103. package/src/commands/daemon.ts +19 -5
  104. package/src/commands/harness.ts +515 -47
  105. package/src/commands/launch.ts +11 -3
  106. package/src/commands/notify.ts +5 -1
  107. package/src/commands/session.ts +6 -1
  108. package/src/config/keybindings.ts +5 -0
  109. package/src/config/model-profile-activation.ts +1 -1
  110. package/src/config/model-profiles.ts +23 -23
  111. package/src/config/settings-schema.ts +41 -1
  112. package/src/coordinator-mcp/model-preset.ts +100 -0
  113. package/src/coordinator-mcp/server.ts +2653 -425
  114. package/src/daemon/control-types.ts +11 -0
  115. package/src/daemon/operator-contract.ts +121 -0
  116. package/src/deep-interview/render-middleware.ts +67 -2
  117. package/src/defaults/gjc/extensions/grok-cli-vendor/src/models/catalog.ts +57 -17
  118. package/src/defaults/gjc/extensions/grok-cli-vendor/src/payload/sanitize.ts +15 -2
  119. package/src/defaults/gjc/extensions/grok-cli-vendor/src/provider/register.ts +5 -1
  120. package/src/gjc-runtime/launch-tmux.ts +702 -135
  121. package/src/gjc-runtime/session-state-sidecar.ts +756 -135
  122. package/src/gjc-runtime/team-runtime.ts +6 -0
  123. package/src/gjc-runtime/tmux-common.ts +26 -7
  124. package/src/gjc-runtime/tmux-gc.ts +52 -9
  125. package/src/gjc-runtime/tmux-owner-isolation-cli.ts +185 -0
  126. package/src/gjc-runtime/tmux-owner-isolation.ts +2060 -0
  127. package/src/gjc-runtime/tmux-sessions.ts +871 -68
  128. package/src/internal-urls/docs-index.generated.ts +9 -8
  129. package/src/internal-urls/local-protocol.ts +29 -10
  130. package/src/main.ts +298 -75
  131. package/src/modes/acp/acp-agent.ts +728 -98
  132. package/src/modes/acp/acp-mode.ts +29 -2
  133. package/src/modes/components/assistant-message.ts +32 -3
  134. package/src/modes/components/bash-execution.ts +43 -13
  135. package/src/modes/components/custom-editor.ts +5 -0
  136. package/src/modes/components/gajae-pet-widget.ts +360 -0
  137. package/src/modes/components/hook-selector.ts +12 -0
  138. package/src/modes/components/irc-sidebar.ts +206 -0
  139. package/src/modes/components/pet-selector.ts +55 -0
  140. package/src/modes/components/session-selector.ts +222 -221
  141. package/src/modes/components/settings-selector.ts +10 -0
  142. package/src/modes/components/tool-execution.ts +47 -6
  143. package/src/modes/components/user-message.ts +26 -9
  144. package/src/modes/controllers/command-controller.ts +28 -2
  145. package/src/modes/controllers/event-controller.ts +159 -36
  146. package/src/modes/controllers/extension-ui-controller.ts +36 -17
  147. package/src/modes/controllers/input-controller.ts +8 -2
  148. package/src/modes/controllers/selector-controller.ts +62 -15
  149. package/src/modes/interactive-mode.ts +183 -7
  150. package/src/modes/irc-observation-ledger.ts +127 -0
  151. package/src/modes/shared/agent-wire/deep-interview-gate.ts +45 -2
  152. package/src/modes/shared/agent-wire/unattended-session.ts +288 -1
  153. package/src/modes/shared/agent-wire/workflow-gate-broker.ts +130 -20
  154. package/src/modes/types.ts +34 -2
  155. package/src/modes/utils/hotkeys-markdown.ts +1 -0
  156. package/src/modes/utils/irc-message.ts +138 -0
  157. package/src/modes/utils/ui-helpers.ts +216 -50
  158. package/src/notifications/config.ts +44 -0
  159. package/src/notifications/daemon-paths.ts +8 -0
  160. package/src/notifications/index.ts +535 -75
  161. package/src/notifications/lifecycle-control-runtime.ts +930 -77
  162. package/src/notifications/notification-service.ts +710 -0
  163. package/src/notifications/rate-limit-pool.ts +46 -12
  164. package/src/notifications/telegram-daemon-cli.ts +2 -0
  165. package/src/notifications/telegram-daemon-control.ts +27 -2
  166. package/src/notifications/telegram-daemon.ts +635 -94
  167. package/src/notifications/telegram-reference.ts +73 -13
  168. package/src/notifications/topic-registry.ts +86 -9
  169. package/src/prompts/system/irc-peer-roster.md +1 -0
  170. package/src/prompts/system/subagent-system-prompt.md +1 -0
  171. package/src/prompts/system/system-prompt.md +1 -0
  172. package/src/prompts/tools/irc.md +1 -1
  173. package/src/registry/agent-registry.ts +3 -0
  174. package/src/sdk.ts +52 -1
  175. package/src/secrets/obfuscator.ts +4 -2
  176. package/src/session/agent-session.ts +396 -145
  177. package/src/session/cache-economics.ts +275 -0
  178. package/src/session/provider-safety-stop.ts +9 -0
  179. package/src/session/session-dump-format.ts +6 -0
  180. package/src/session/session-manager.ts +809 -39
  181. package/src/session/session-storage.ts +582 -38
  182. package/src/slash-commands/builtin-registry.ts +143 -9
  183. package/src/task/executor.ts +12 -3
  184. package/src/task/index.ts +8 -0
  185. package/src/task/receipt.ts +7 -2
  186. package/src/task/types.ts +26 -0
  187. package/src/tools/ask-answer-registry.ts +25 -0
  188. package/src/tools/ask.ts +355 -33
  189. package/src/tools/browser/tab-supervisor.ts +63 -6
  190. package/src/tools/browser.ts +8 -3
  191. package/src/tools/index.ts +81 -6
  192. package/src/tools/sqlite-reader.ts +8 -4
  193. package/src/tui/output-block.ts +18 -6
  194. package/src/utils/external-editor.ts +6 -1
@@ -0,0 +1,59 @@
1
+ import { type Component, type Container, type PetMode, type PetSkinId, type TUI } from "@gajae-code/tui";
2
+ import type { CustomEditor } from "./custom-editor";
3
+ /** Re-exported from the tui skin registry so widget-relative imports stay valid. */
4
+ export type { PetMode, PetSkinId };
5
+ /**
6
+ * Wraps the composer editor, reserving a right-side area beside it where the
7
+ * real-pixel pet is drawn. The editor just renders narrower; the pet pixels
8
+ * are emitted separately as an absolute-positioned overlay.
9
+ */
10
+ export declare class PetFramedEditor implements Component {
11
+ #private;
12
+ constructor(editor: CustomEditor);
13
+ setReserve(columns: number): void;
14
+ canFit(width: number): boolean;
15
+ invalidate(): void;
16
+ render(width: number): string[];
17
+ }
18
+ /**
19
+ * The gajae pet: a 16x16 real-pixel sprite living in a reserved area beside
20
+ * the composer. It is nearest-neighbor scaled to the two terminal rows occupied
21
+ * by an empty one-line composer and lifted one row so its feet meet the input
22
+ * box's bottom edge.
23
+ *
24
+ * Rendering has two paths that share one payload builder:
25
+ * - a post-render emitter re-draws the sprite after every TUI write (line
26
+ * renders clear the pet cells, so the overlay must be re-applied), and
27
+ * - frame advances write the payload directly to the terminal, because the
28
+ * TUI skips writes entirely when no component line changed.
29
+ *
30
+ * Requires a sixel- or kitty-graphics terminal (`pixelProtocol()`).
31
+ */
32
+ export declare class GajaePetWidget {
33
+ #private;
34
+ constructor(options: {
35
+ ui: TUI;
36
+ editor: CustomEditor;
37
+ editorContainer: Container;
38
+ floorContainer: Container;
39
+ isWorking: () => boolean;
40
+ /** Rows rendered below the composer box (pet floor + hook widgets). */
41
+ getComposerBottomOffset: () => number;
42
+ forcePixelProtocol?: "sixel" | "kitty";
43
+ /** Random [min, max] ms between auto-flexes; null disables. */
44
+ autoFlexGapMs?: [number, number] | null;
45
+ });
46
+ /** Protocol available for the real-pixel pet, if any. */
47
+ static pixelProtocol(): "sixel" | "kitty" | null;
48
+ get mode(): PetMode;
49
+ get isFlexing(): boolean;
50
+ setMode(mode: PetMode): void;
51
+ /** Live preview during a selector: change the sprite without re-mounting the
52
+ * composer editor (that would tear down the open overlay). After a short idle
53
+ * eye-roll it fires the signature burst once (RedGajae flex, BlueGajae para-para
54
+ * then sob) so the selector demos the animation instead of waiting the random gap. */
55
+ previewMode(mode: PetMode): void;
56
+ dispose(): void;
57
+ /** Re-mount the composer editor (framed when a skin is active) after an overlay. */
58
+ remountComposer(): void;
59
+ }
@@ -44,6 +44,11 @@ export interface HookSelectorOptions {
44
44
  * completion behavior as the main prompt editor.
45
45
  */
46
46
  autocompleteProvider?: AutocompleteProvider;
47
+ /**
48
+ * Maps raw single-key accelerators to option labels. Unset maps preserve
49
+ * the legacy selector key handling exactly.
50
+ */
51
+ acceleratorMap?: Readonly<Record<string, string>>;
47
52
  }
48
53
  export declare class HookSelectorComponent extends Container {
49
54
  #private;
@@ -0,0 +1,32 @@
1
+ import { type Component, type ViewportAnchorProvider, type ViewportAnchorRender } from "@gajae-code/tui";
2
+ import type { IrcObservationLedger } from "../irc-observation-ledger";
3
+ export declare const IRC_SIDEBAR_WIDTH_RATIO = 0.3;
4
+ export declare const IRC_SIDEBAR_MAX_RENDER_ROWS = 2048;
5
+ /** Computes transcript/sidebar widths while preserving at least half the terminal for the transcript. */
6
+ export declare function computeIrcSplitWidths(width: number): {
7
+ leftWidth: number;
8
+ separatorWidth: number;
9
+ rightWidth: number;
10
+ };
11
+ export interface IrcSidebarTheme {
12
+ fg(color: "dim" | "accent", text: string): string;
13
+ bold(text: string): string;
14
+ readonly boxSharp: {
15
+ readonly vertical: string;
16
+ };
17
+ }
18
+ export type IrcSidebarThemeSource = IrcSidebarTheme | (() => IrcSidebarTheme);
19
+ /** Read-only IRC history alongside the active transcript. */
20
+ export declare class IrcSplitViewComponent implements ViewportAnchorProvider {
21
+ #private;
22
+ private readonly leftPane;
23
+ private readonly ledger;
24
+ private readonly componentTheme;
25
+ constructor(leftPane: Component, ledger: IrcObservationLedger, componentTheme: IrcSidebarThemeSource);
26
+ get visible(): boolean;
27
+ effectiveSidebarVisible(width?: number): boolean;
28
+ setVisible(visible: boolean): void;
29
+ render(width: number): string[];
30
+ renderWithViewportAnchors(width: number): ViewportAnchorRender;
31
+ invalidate(): void;
32
+ }
@@ -0,0 +1,11 @@
1
+ import { Container, SelectList } from "@gajae-code/tui";
2
+ import type { PetMode } from "./gajae-pet-widget";
3
+ /**
4
+ * Theme-style picker for the gajae pet skin (Off / RedGajae / BlueGajae). Preview
5
+ * fires as the selection moves; select commits, cancel restores.
6
+ */
7
+ export declare class PetSelectorComponent extends Container {
8
+ #private;
9
+ constructor(current: PetMode, onSelect: (mode: PetMode) => void, onCancel: () => void, onPreview: (mode: PetMode) => void);
10
+ getSelectList(): SelectList;
11
+ }
@@ -1,28 +1,41 @@
1
1
  import { type Component, Container } from "@gajae-code/tui";
2
- import type { SessionInfo } from "../../session/session-manager";
3
- /**
4
- * Custom session list component with multi-line items and search
5
- */
2
+ import type { ResumeSessionIdentity, ResumeTailInspection, SessionInfo } from "../../session/session-manager";
3
+ export interface SelectedSession {
4
+ kind: "selected";
5
+ path: string;
6
+ identity: ResumeSessionIdentity;
7
+ action: "continue-tail" | "open-idle";
8
+ }
9
+ export interface CancelledSessionSelection {
10
+ kind: "cancelled";
11
+ }
12
+ export type SessionSelectionResult = SelectedSession | CancelledSessionSelection;
13
+ export type SessionInspector = (sessionPath: string) => Promise<ResumeTailInspection>;
6
14
  declare class SessionList implements Component {
7
15
  #private;
8
16
  private readonly allSessions;
9
17
  private readonly showCwd;
10
- onSelect?: (sessionPath: string) => void;
18
+ onSelect?: (session: SessionInfo) => void;
11
19
  onCancel?: () => void;
12
20
  onExit: () => void;
13
21
  onDeleteRequest?: (session: SessionInfo) => void;
14
22
  constructor(allSessions: SessionInfo[], showCwd?: boolean);
23
+ setInputFrozen(frozen: boolean): void;
15
24
  removeSession(sessionPath: string): void;
16
25
  invalidate(): void;
17
26
  render(width: number): string[];
18
27
  handleInput(keyData: string): void;
19
28
  }
20
- /**
21
- * Component that renders a session selector with optional confirmation dialog
22
- */
29
+ /** A one-shot resume consent selector. It never opens or mutates sessions. */
23
30
  export declare class SessionSelectorComponent extends Container {
24
31
  #private;
25
- constructor(sessions: SessionInfo[], onSelect: (sessionPath: string) => void, onCancel: () => void, onExit: () => void, onDelete?: (session: SessionInfo) => Promise<boolean>);
32
+ private readonly onSelect;
33
+ private readonly onCancel;
34
+ private readonly onExit;
35
+ private readonly onDelete?;
36
+ private readonly inspector?;
37
+ private readonly onSelection?;
38
+ constructor(sessions: SessionInfo[], onSelect: (sessionPath: string) => void, onCancel: () => void, onExit: () => void, onDelete?: ((session: SessionInfo) => Promise<boolean>) | undefined, inspector?: SessionInspector | undefined, onSelection?: ((selection: SessionSelectionResult) => void) | undefined);
26
39
  setOnRequestRender(callback: () => void): void;
27
40
  handleInput(keyData: string): void;
28
41
  getSessionList(): SessionList;
@@ -39,6 +39,8 @@ export interface SettingsCallbacks {
39
39
  onThemePreview?: (theme: string) => void | Promise<void>;
40
40
  /** Called to restore the rendered theme when theme settings preview is cancelled */
41
41
  onThemePreviewCancel?: (theme: string) => void | Promise<void>;
42
+ /** Called to live-preview the gajae pet skin while browsing the pet setting. */
43
+ onPetPreview?: (mode: string) => void;
42
44
  /** Called for status line preview while configuring */
43
45
  onStatusLinePreview?: (settings: StatusLinePreviewSettings) => void;
44
46
  /** Get current rendered status line for inline preview */
@@ -51,4 +51,5 @@ export declare class ToolExecutionComponent extends Container {
51
51
  setExpanded(expanded: boolean): void;
52
52
  setShowImages(show: boolean): void;
53
53
  invalidate(): void;
54
+ render(width: number): string[];
54
55
  }
@@ -3,5 +3,6 @@ import { Container } from "@gajae-code/tui";
3
3
  * Component that renders a user message
4
4
  */
5
5
  export declare class UserMessageComponent extends Container {
6
- constructor(text: string, synthetic?: boolean);
6
+ #private;
7
+ constructor(text: string, synthetic?: boolean, viewportAnchorId?: string);
7
8
  }
@@ -1,3 +1,4 @@
1
+ import { type Component } from "@gajae-code/tui";
1
2
  import type { InteractiveModeContext } from "../../modes/types";
2
3
  import type { AgentSessionEvent } from "../../session/agent-session";
3
4
  /** Test-only performance counters for advisory baseline tests. */
@@ -12,6 +13,9 @@ export declare class EventController {
12
13
  dispose(): void;
13
14
  subscribeToAgent(): void;
14
15
  handleEvent(event: AgentSessionEvent): Promise<void>;
16
+ clearIrcExpiryTimers(): void;
17
+ resetIrcObservations(): void;
18
+ reconcileIrcExpiryTimers(componentsByObservationId: Map<string, readonly Component[]>): void;
15
19
  sendCompletionNotification(): void;
16
20
  handleBackgroundEvent(event: AgentSessionEvent): Promise<void>;
17
21
  }
@@ -29,6 +29,7 @@ export declare class SelectorController {
29
29
  showEffortSelector(): void;
30
30
  showSettingsSelector(): void;
31
31
  showThemeSelector(): void;
32
+ showPetSelector(): void;
32
33
  showHistorySearch(): void;
33
34
  /**
34
35
  * Show the Extension Control Center dashboard.
@@ -18,16 +18,20 @@ import type { AssistantMessageComponent } from "./components/assistant-message";
18
18
  import type { BashExecutionComponent } from "./components/bash-execution";
19
19
  import { CustomEditor } from "./components/custom-editor";
20
20
  import type { EvalExecutionComponent } from "./components/eval-execution";
21
+ import { GajaePetWidget, type PetMode } from "./components/gajae-pet-widget";
21
22
  import type { HookEditorComponent } from "./components/hook-editor";
22
23
  import type { HookInputComponent } from "./components/hook-input";
23
24
  import type { HookSelectorComponent } from "./components/hook-selector";
24
25
  import { StatusLineComponent } from "./components/status-line";
25
26
  import type { ToolExecutionHandle } from "./components/tool-execution";
26
27
  import { type WelcomeLogoMode } from "./components/welcome";
28
+ import { IrcObservationLedger } from "./irc-observation-ledger";
27
29
  import { OAuthManualInputManager } from "./oauth-manual-input";
28
30
  import type { Theme } from "./theme/theme";
29
- import type { CompactionQueuedMessage, InteractiveModeContext, SubmittedUserInput, TodoItem, TodoPhase } from "./types";
31
+ import type { CompactionQueuedMessage, InteractiveModeContext, IrcArrivalSnapshot, SubmittedUserInput, TodoItem, TodoPhase, TranscriptRebuildPolicy } from "./types";
32
+ import type { ParsedIrcMessage } from "./utils/irc-message";
30
33
  export declare const DEFAULT_COMPOSER_PLACEHOLDER: string;
34
+ export declare function getWelcomeTranscriptReservedRows(chatContainer: Container, width: number): number;
31
35
  export type WelcomeBannerSettingMode = "auto" | "unicode" | "square" | "ascii";
32
36
  export declare function resolveWelcomeLogoMode(mode: WelcomeBannerSettingMode, env?: Record<string, string | undefined>, platform?: NodeJS.Platform): WelcomeLogoMode;
33
37
  /** Options for creating an InteractiveMode instance (for future API use) */
@@ -51,6 +55,7 @@ export declare class InteractiveMode implements InteractiveModeContext {
51
55
  keybindings: KeybindingsManager;
52
56
  agent: Agent;
53
57
  historyStorage?: HistoryStorage;
58
+ readonly ircLedger: IrcObservationLedger;
54
59
  ui: TUI;
55
60
  chatContainer: Container;
56
61
  pendingMessagesContainer: Container;
@@ -61,6 +66,8 @@ export declare class InteractiveMode implements InteractiveModeContext {
61
66
  editorContainer: Container;
62
67
  hookWidgetContainerAbove: Container;
63
68
  hookWidgetContainerBelow: Container;
69
+ petFloorContainer: Container;
70
+ petWidget: GajaePetWidget | undefined;
64
71
  statusLine: StatusLineComponent;
65
72
  isInitialized: boolean;
66
73
  isBackgrounded: boolean;
@@ -132,7 +139,10 @@ export declare class InteractiveMode implements InteractiveModeContext {
132
139
  updateEditorChrome(): void;
133
140
  updateEditorBorderColor(): void;
134
141
  updateEditorTopBorder(): void;
135
- rebuildChatFromMessages(): void;
142
+ setPetMode(mode: PetMode): void;
143
+ previewPetMode(mode: PetMode): void;
144
+ restoreComposer(): void;
145
+ rebuildChatFromMessages(policy: TranscriptRebuildPolicy): void;
136
146
  /** Apply any deferred model switch after the current stream ends. */
137
147
  flushPendingModelSwitch(): Promise<void>;
138
148
  handlePlanModeCommand(initialPrompt?: string): Promise<void>;
@@ -166,15 +176,22 @@ export declare class InteractiveMode implements InteractiveModeContext {
166
176
  addMessageToChat(message: AgentMessage, options?: {
167
177
  populateHistory?: boolean;
168
178
  }): Component[];
179
+ addLiveIrcObservationToChat(message: ParsedIrcMessage, arrival: IrcArrivalSnapshot): Component[];
180
+ removeRenderedIrcInlineComponents(observationId: string): readonly Component[] | undefined;
181
+ resetRenderedIrcInlineComponents(): readonly (readonly Component[])[];
169
182
  renderSessionContext(sessionContext: SessionContext, options?: {
170
183
  updateFooter?: boolean;
171
184
  populateHistory?: boolean;
172
185
  }): void;
186
+ rebuildInitialMessages(policy: TranscriptRebuildPolicy, prebuiltContext?: SessionContext, options?: {
187
+ preserveExistingChat?: boolean;
188
+ }): void;
173
189
  renderInitialMessages(prebuiltContext?: SessionContext, options?: {
174
190
  preserveExistingChat?: boolean;
175
191
  }): void;
176
192
  getUserMessageText(message: Message): string;
177
193
  findLastAssistantMessage(): AssistantMessage | undefined;
194
+ getAssistantViewportAnchorId(message: AssistantMessage): string;
178
195
  extractAssistantText(message: AssistantMessage): string;
179
196
  handleExportCommand(text: string): Promise<void>;
180
197
  handleDumpCommand(): void;
@@ -213,6 +230,7 @@ export declare class InteractiveMode implements InteractiveModeContext {
213
230
  openInBrowser(urlOrPath: string): void;
214
231
  showSettingsSelector(): void;
215
232
  showThemeSelector(): void;
233
+ showPetSelector(): void;
216
234
  showHistorySearch(): void;
217
235
  showExtensionsDashboard(): void;
218
236
  showAgentsDashboard(): void;
@@ -244,6 +262,10 @@ export declare class InteractiveMode implements InteractiveModeContext {
244
262
  }): Promise<void>;
245
263
  toggleToolOutputExpansion(): void;
246
264
  setToolsExpanded(expanded: boolean): void;
265
+ captureIrcArrivalSnapshot(): IrcArrivalSnapshot;
266
+ toggleIrcSidebar(): void;
267
+ applyIrcSidebarAvailability(enabled: boolean): void;
268
+ resetIrcSidebarSession(): void;
247
269
  toggleThinkingBlockVisibility(): void;
248
270
  toggleTodoExpansion(): void;
249
271
  setTodos(todos: TodoItem[] | TodoPhase[]): void;
@@ -0,0 +1,22 @@
1
+ import type { ParsedIrcMessage } from "./utils/irc-message";
2
+ type InlineMode = "persistent" | "ephemeral";
3
+ export type IrcObservationRecord = Readonly<ParsedIrcMessage & {
4
+ mode: InlineMode;
5
+ observedAt: number;
6
+ sequence: number;
7
+ expiresAt?: number;
8
+ retainedUtf8Bytes: number;
9
+ }>;
10
+ /** Runtime-only IRC observations. This intentionally has no persistence layer. */
11
+ export declare class IrcObservationLedger {
12
+ #private;
13
+ /** Inline observations expire after 10 seconds; closed-panel observations persist inline. */
14
+ observe(message: ParsedIrcMessage, panelVisibleAtObservation: boolean): IrcObservationRecord | undefined;
15
+ getRecord(observationId: string): IrcObservationRecord | undefined;
16
+ getSidebarRecords(): readonly IrcObservationRecord[];
17
+ getInlineProjection(now: number): readonly IrcObservationRecord[];
18
+ /** Returns and clears IDs whose retained payload was released. */
19
+ drainEvictedObservationIds(): readonly string[];
20
+ reset(): void;
21
+ }
22
+ export {};
@@ -42,6 +42,8 @@ export interface AskGateQuestion {
42
42
  deepInterview?: AskGateDeepInterviewState;
43
43
  /** Override the emitted workflow gate address for non-deep-interview ask prompts. */
44
44
  workflowGate?: AskGateWorkflowGateMeta;
45
+ allowEmpty?: boolean;
46
+ navigationLabel?: "Next" | "Done";
45
47
  }
46
48
  export interface AskGateResult {
47
49
  id: string;
@@ -90,5 +92,11 @@ export declare function questionToGate(question: AskGateQuestion): OpenGateInput
90
92
  * semantically invalid answer.
91
93
  */
92
94
  export declare function gateAnswerToResult(question: AskGateQuestion, answer: unknown): AskGateResult;
95
+ /**
96
+ * Classify an accepted ask-domain gate answer independently of its transport.
97
+ * Schema-invalid and semantically invalid answers throw, so callers leave the
98
+ * durable gate pending rather than treating them as a non-committing answer.
99
+ */
100
+ export declare function classifyAskGateDisposition(gate: Pick<OpenGateInput, "context" | "options">, answer: unknown): "commit" | "resolve_without_commit";
93
101
  /** Convenience: map a batch of ask questions to gate open-inputs. */
94
102
  export declare function questionsToGates(questions: AskGateQuestion[]): OpenGateInput[];
@@ -156,6 +156,11 @@ export declare class UnattendedRunController {
156
156
  /** Returns the in-flight/settled abort completion once aborting has begun. */
157
157
  get abortCompletion(): Promise<void> | undefined;
158
158
  private fireAbort;
159
+ /**
160
+ * Invoke every configured abort hook exactly once with per-hook isolation, so a
161
+ * failing hook never prevents the other cancellation surfaces from running.
162
+ * Returns the number of hooks that rejected.
163
+ */
159
164
  private runAbortHooks;
160
165
  }
161
166
  export {};
@@ -15,10 +15,45 @@
15
15
  * RPC server can route `negotiate_unattended` + `workflow_gate_response` here.
16
16
  */
17
17
  import type { Model } from "@gajae-code/ai";
18
+ import type { AskSelectedAckOutcome } from "../../../tools";
18
19
  import type { RpcCommand, RpcUnattendedAccepted, RpcUnattendedDeclaration, RpcWorkflowGate, RpcWorkflowGateResolution, RpcWorkflowGateResponse } from "../../rpc/rpc-types";
19
20
  import type { RpcUnattendedControlPlane } from "./command-dispatch";
20
21
  import { type UnattendedAbortHooks, type UnattendedAuditEvent, UnattendedRunController } from "./unattended-run-controller";
21
22
  import { type GateStore, type OpenGateInput } from "./workflow-gate-broker";
23
+ export interface WorkflowGateTerminalController {
24
+ completeGateInteractions(gateId: string): void | Promise<void>;
25
+ cancelGateInteractions(gateId: string, reason: string): void | Promise<void>;
26
+ }
27
+ export interface WorkflowGateTerminalEvent {
28
+ gateId: string;
29
+ kind: "accepted" | "cancelled";
30
+ origin?: "rpc" | "bridge" | "other" | "telegram_notification";
31
+ reason?: string;
32
+ }
33
+ export interface NotificationGateResolutionOptions {
34
+ interactionActionId: string;
35
+ replyReceiptId: string;
36
+ answerJson: string;
37
+ idempotencyKey?: string;
38
+ requestSelectedAck(input: {
39
+ replyReceiptId: string;
40
+ actionId: string;
41
+ commitKey: string;
42
+ daemonDeadlineAt: number;
43
+ hostTimeoutMs: number;
44
+ }): Promise<AskSelectedAckOutcome>;
45
+ resolveClaim(): void;
46
+ closeClaimInvalid(reason: string): void;
47
+ }
48
+ export interface AskSelectedAckRecoveryParticipant {
49
+ requestRecoveredAskSelectedAck(input: {
50
+ sessionId: string;
51
+ actionId: string;
52
+ commitKey: string;
53
+ deadlineAt: number;
54
+ hostTimeoutMs: number;
55
+ }): Promise<AskSelectedAckOutcome>;
56
+ }
22
57
  /**
23
58
  * Derive an explicit `providerSupportsTokenCostMetrics` capability from the
24
59
  * active model so unattended negotiation fails closed when token/cost usage
@@ -41,7 +76,10 @@ export interface WorkflowGateEmitter {
41
76
  */
42
77
  onGateEmitted?(listener: (gate: RpcWorkflowGate) => void): () => void;
43
78
  resolveGate?(response: RpcWorkflowGateResponse): Promise<RpcWorkflowGateResolution>;
79
+ resolveGateFromNotification?(response: RpcWorkflowGateResponse, options: NotificationGateResolutionOptions): Promise<RpcWorkflowGateResolution>;
80
+ registerGateTerminalController?(controller: WorkflowGateTerminalController): () => void;
44
81
  listPendingGates?(): RpcWorkflowGate[];
82
+ setAckRecoveryParticipant?(participant: AskSelectedAckRecoveryParticipant | null): void;
45
83
  }
46
84
  export interface UnattendedSessionOptions {
47
85
  runId: string;
@@ -72,10 +110,17 @@ export declare class UnattendedSessionControlPlane implements RpcUnattendedContr
72
110
  /** Observe every emitted gate (e.g. so an extension can map an ask to its gate_id). */
73
111
  onGateEmitted(listener: (gate: RpcWorkflowGate) => void): () => void;
74
112
  get controller(): UnattendedRunController | undefined;
113
+ registerGateTerminalController(controller: WorkflowGateTerminalController): () => void;
114
+ setAckRecoveryParticipant(participant: AskSelectedAckRecoveryParticipant | null): void;
75
115
  negotiate(declaration: RpcUnattendedDeclaration): RpcUnattendedAccepted;
76
116
  preflightCommand(command: RpcCommand): void;
77
117
  reconcileUsage(phase?: string): void;
78
118
  resolveGate(response: RpcWorkflowGateResponse): Promise<RpcWorkflowGateResolution>;
119
+ resolveGateFromNotification(response: RpcWorkflowGateResponse, options: NotificationGateResolutionOptions): Promise<RpcWorkflowGateResolution>;
120
+ startRecoveryOnce(options?: {
121
+ participantGraceMs?: number;
122
+ }): Promise<void>;
123
+ dispose(reason?: string): void;
79
124
  listPendingGates(): import("../../rpc/rpc-types").RpcWorkflowGate[];
80
125
  emitGate(input: OpenGateInput): Promise<unknown>;
81
126
  recover(): Promise<void>;
@@ -1,4 +1,32 @@
1
- import type { RpcWorkflowGate, RpcWorkflowGateContext, RpcWorkflowGateKind, RpcWorkflowGateOption, RpcWorkflowGateResolution, RpcWorkflowGateResponse, RpcWorkflowStage } from "../../rpc/rpc-types";
1
+ import type { AskSelectedAckOutcome } from "../../../tools";
2
+ import type { RpcWorkflowGate, RpcWorkflowGateContext, RpcWorkflowGateKind, RpcWorkflowGateOption, RpcWorkflowGateResolution, RpcWorkflowGateResponse, RpcWorkflowGateValidationError, RpcWorkflowStage } from "../../rpc/rpc-types";
3
+ export type PersistedSemanticDisposition = "commit" | "resolve_without_commit";
4
+ export type PersistedResolutionOrigin = {
5
+ kind: "generic";
6
+ channel: "rpc" | "bridge" | "other";
7
+ } | {
8
+ kind: "telegram_notification";
9
+ interactionActionId: string;
10
+ } | {
11
+ kind: "legacy_unknown";
12
+ };
13
+ export type PersistedAckPolicy = {
14
+ kind: "none";
15
+ reason: "non_telegram" | "semantic_noncommit" | "legacy_unproven";
16
+ } | {
17
+ kind: "telegram_selected_v1";
18
+ commitKey: string;
19
+ actionId: string;
20
+ state: "pending" | "attempt_started" | "delivered" | "failed" | "unknown";
21
+ outcome?: AskSelectedAckOutcome;
22
+ updatedAt: string;
23
+ };
24
+ export interface GateResolutionOptions {
25
+ semanticDisposition?: PersistedSemanticDisposition;
26
+ resolutionOrigin?: PersistedResolutionOrigin;
27
+ ackPolicy?: PersistedAckPolicy;
28
+ beforeAdvance?: () => Promise<void>;
29
+ }
2
30
  export interface PersistedGate {
3
31
  gate: RpcWorkflowGate;
4
32
  status: "pending" | "accepted";
@@ -8,6 +36,9 @@ export interface PersistedGate {
8
36
  answer?: unknown;
9
37
  resolution?: RpcWorkflowGateResolution;
10
38
  advanced: boolean;
39
+ semanticDisposition?: PersistedSemanticDisposition;
40
+ resolutionOrigin?: PersistedResolutionOrigin;
41
+ ackPolicy?: PersistedAckPolicy;
11
42
  }
12
43
  export interface GateStore {
13
44
  nextSeq(stage: RpcWorkflowStage): number;
@@ -74,6 +105,8 @@ export interface BrokerHooks {
74
105
  * it for any gate left `accepted` but not `advanced` by a crash.
75
106
  */
76
107
  advance?(gate: RpcWorkflowGate, answer: unknown): void | Promise<void>;
108
+ /** Runs after durable acceptance and before advance, including crash recovery. */
109
+ finalizeAccepted?(record: PersistedGate): Promise<void>;
77
110
  /** Append-only audit sink. */
78
111
  audit?(event: GateAuditEvent): void;
79
112
  }
@@ -92,7 +125,13 @@ export declare class WorkflowGateBroker {
92
125
  private readonly runId;
93
126
  private readonly store;
94
127
  private readonly hooks;
128
+ private readonly recovering;
129
+ private readonly gateLocks;
130
+ private withGateLock;
95
131
  constructor(runId: string, store: GateStore, hooks?: BrokerHooks);
132
+ classifyDisposition(gateId: string, answer: unknown): PersistedSemanticDisposition;
133
+ validationError(gateId: string, keyword: string, message: string): RpcWorkflowGateValidationError;
134
+ updateAckPolicy(gateId: string, ackPolicy: PersistedAckPolicy): void;
96
135
  private runShort;
97
136
  /** Open and emit a gate. The pending record is persisted BEFORE emission. */
98
137
  openGate(input: OpenGateInput): RpcWorkflowGate;
@@ -101,7 +140,8 @@ export declare class WorkflowGateBroker {
101
140
  * On success the resolution is persisted BEFORE `advance` is invoked exactly
102
141
  * once. Invalid answers leave the gate pending (per #315 acceptance).
103
142
  */
104
- resolve(response: RpcWorkflowGateResponse): Promise<RpcWorkflowGateResolution>;
143
+ resolve(response: RpcWorkflowGateResponse, options?: GateResolutionOptions): Promise<RpcWorkflowGateResolution>;
144
+ private resolveUnlocked;
105
145
  /**
106
146
  * Recover any gate left `accepted` but not `advanced` by a crash between the
107
147
  * durable accept and the advanced commit. Replays `advance` (which must be