@gajae-code/coding-agent 0.7.6 → 0.7.8

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 (111) hide show
  1. package/CHANGELOG.md +26 -1
  2. package/README.md +8 -0
  3. package/dist/types/cli/local-provider-smoke.d.ts +59 -0
  4. package/dist/types/cli/notify-cli.d.ts +1 -1
  5. package/dist/types/cli/update-cli.d.ts +24 -1
  6. package/dist/types/commands/local-provider.d.ts +34 -0
  7. package/dist/types/config/model-profiles.d.ts +2 -2
  8. package/dist/types/config/model-registry.d.ts +8 -3
  9. package/dist/types/config/models-config-schema.d.ts +5 -5
  10. package/dist/types/config/settings-schema.d.ts +123 -9
  11. package/dist/types/config/settings.d.ts +7 -0
  12. package/dist/types/coordinator-mcp/server.d.ts +8 -0
  13. package/dist/types/export/html/template.generated.d.ts +1 -1
  14. package/dist/types/gjc-runtime/launch-tmux.d.ts +2 -2
  15. package/dist/types/gjc-runtime/state-renderer.d.ts +5 -0
  16. package/dist/types/gjc-runtime/team-runtime.d.ts +1 -1
  17. package/dist/types/gjc-runtime/tmux-common.d.ts +12 -0
  18. package/dist/types/gjc-runtime/ultragoal-guard.d.ts +37 -1
  19. package/dist/types/gjc-runtime/ultragoal-runtime.d.ts +80 -0
  20. package/dist/types/modes/components/custom-model-preset-wizard.d.ts +1 -1
  21. package/dist/types/modes/components/model-selector.d.ts +2 -0
  22. package/dist/types/modes/components/settings-selector.d.ts +4 -1
  23. package/dist/types/modes/components/status-line/types.d.ts +5 -7
  24. package/dist/types/modes/components/status-line.d.ts +4 -3
  25. package/dist/types/modes/controllers/input-controller.d.ts +1 -0
  26. package/dist/types/modes/controllers/selector-controller.d.ts +2 -1
  27. package/dist/types/modes/prompt-action-autocomplete.d.ts +1 -0
  28. package/dist/types/modes/tmux-scroll.d.ts +18 -0
  29. package/dist/types/modes/utils/terminal-bell.d.ts +3 -0
  30. package/dist/types/notifications/telegram-daemon-cli.d.ts +13 -2
  31. package/dist/types/tools/browser/tab-supervisor.d.ts +31 -0
  32. package/dist/types/tools/computer-gc.d.ts +23 -0
  33. package/dist/types/tools/cron.d.ts +36 -61
  34. package/dist/types/tools/index.d.ts +0 -1
  35. package/dist/types/tools/resource-gc.d.ts +54 -0
  36. package/dist/types/web/search/index.d.ts +1 -0
  37. package/dist/types/web/search/providers/utils.d.ts +11 -4
  38. package/package.json +7 -7
  39. package/src/cli/args.ts +0 -1
  40. package/src/cli/fast-help.ts +0 -1
  41. package/src/cli/local-provider-smoke.ts +632 -0
  42. package/src/cli/notify-cli.ts +4 -2
  43. package/src/cli/update-cli.ts +155 -13
  44. package/src/cli/web-search-cli.ts +5 -0
  45. package/src/cli.ts +18 -0
  46. package/src/commands/launch.ts +46 -1
  47. package/src/commands/local-provider.ts +62 -0
  48. package/src/commands/notify.ts +1 -1
  49. package/src/config/model-profiles.ts +3 -4
  50. package/src/config/model-registry.ts +58 -7
  51. package/src/config/models-config-schema.ts +10 -1
  52. package/src/config/settings-schema.ts +127 -10
  53. package/src/config/settings.ts +11 -0
  54. package/src/coordinator-mcp/server.ts +276 -34
  55. package/src/export/html/template.generated.ts +1 -1
  56. package/src/export/html/template.js +0 -12
  57. package/src/gjc-runtime/launch-tmux.ts +34 -8
  58. package/src/gjc-runtime/launch-worktree.ts +16 -2
  59. package/src/gjc-runtime/state-renderer.ts +13 -0
  60. package/src/gjc-runtime/team-runtime.ts +21 -6
  61. package/src/gjc-runtime/tmux-common.ts +16 -0
  62. package/src/gjc-runtime/tmux-sessions.ts +13 -9
  63. package/src/gjc-runtime/ultragoal-guard.ts +167 -0
  64. package/src/gjc-runtime/ultragoal-runtime.ts +221 -1
  65. package/src/goals/tools/goal-tool.ts +14 -1
  66. package/src/internal-urls/docs-index.generated.ts +7 -7
  67. package/src/modes/components/agent-dashboard.ts +2 -1
  68. package/src/modes/components/custom-model-preset-wizard.ts +30 -189
  69. package/src/modes/components/model-selector.ts +182 -5
  70. package/src/modes/components/session-observer-overlay.ts +3 -3
  71. package/src/modes/components/settings-selector.ts +491 -5
  72. package/src/modes/components/status-line/segments.ts +7 -18
  73. package/src/modes/components/status-line/types.ts +6 -2
  74. package/src/modes/components/status-line.ts +69 -35
  75. package/src/modes/controllers/event-controller.ts +98 -4
  76. package/src/modes/controllers/extension-ui-controller.ts +3 -0
  77. package/src/modes/controllers/input-controller.ts +15 -0
  78. package/src/modes/controllers/selector-controller.ts +18 -4
  79. package/src/modes/prompt-action-autocomplete.ts +8 -0
  80. package/src/modes/tmux-scroll.ts +92 -0
  81. package/src/modes/utils/terminal-bell.ts +48 -0
  82. package/src/notifications/telegram-daemon-cli.ts +112 -9
  83. package/src/notifications/telegram-daemon.ts +4 -0
  84. package/src/prompts/system/system-prompt.md +2 -2
  85. package/src/prompts/tools/cron.md +5 -3
  86. package/src/prompts/tools/read.md +1 -1
  87. package/src/sdk.ts +5 -0
  88. package/src/session/agent-session.ts +118 -5
  89. package/src/slash-commands/builtin-registry.ts +106 -13
  90. package/src/tools/browser/tab-supervisor.ts +86 -2
  91. package/src/tools/computer-gc.ts +66 -0
  92. package/src/tools/computer.ts +2 -0
  93. package/src/tools/cron.ts +75 -112
  94. package/src/tools/index.ts +2 -8
  95. package/src/tools/read.ts +25 -55
  96. package/src/tools/renderers.ts +0 -2
  97. package/src/tools/resource-gc.ts +291 -0
  98. package/src/tools/ultragoal-ask-guard.ts +7 -1
  99. package/src/web/search/index.ts +1 -0
  100. package/src/web/search/providers/utils.ts +22 -5
  101. package/vendor/insane-search/MANIFEST.json +3 -1
  102. package/vendor/insane-search/engine/__init__.py +14 -0
  103. package/vendor/insane-search/engine/content_safety.py +151 -0
  104. package/vendor/insane-search/engine/fetch_chain.py +32 -0
  105. package/vendor/insane-search/engine/tests/test_u8.py +216 -0
  106. package/dist/types/tools/inspect-image-renderer.d.ts +0 -26
  107. package/dist/types/tools/inspect-image.d.ts +0 -31
  108. package/src/prompts/tools/inspect-image-system.md +0 -20
  109. package/src/prompts/tools/inspect-image.md +0 -32
  110. package/src/tools/inspect-image-renderer.ts +0 -103
  111. package/src/tools/inspect-image.ts +0 -172
@@ -1,6 +1,6 @@
1
1
  import type { Args } from "../cli/args";
2
- import { buildGjcTmuxProfileCommands, GJC_DEFAULT_TMUX_SESSION, GJC_TMUX_COMMAND_ENV, GJC_TMUX_MOUSE_ENV, GJC_TMUX_PROFILE_ENV, GJC_TMUX_SESSION_PREFIX, type GjcTmuxProfileCommand } from "./tmux-common";
3
- export { buildGjcTmuxProfileCommands, GJC_DEFAULT_TMUX_SESSION, GJC_TMUX_COMMAND_ENV, GJC_TMUX_MOUSE_ENV, GJC_TMUX_PROFILE_ENV, GJC_TMUX_SESSION_PREFIX, };
2
+ import { buildGjcTmuxExactSessionTarget, buildGjcTmuxProfileCommands, GJC_DEFAULT_TMUX_SESSION, GJC_TMUX_COMMAND_ENV, GJC_TMUX_MOUSE_ENV, GJC_TMUX_PROFILE_ENV, GJC_TMUX_SESSION_PREFIX, type GjcTmuxProfileCommand } from "./tmux-common";
3
+ export { buildGjcTmuxExactSessionTarget, buildGjcTmuxProfileCommands, GJC_DEFAULT_TMUX_SESSION, GJC_TMUX_COMMAND_ENV, GJC_TMUX_MOUSE_ENV, GJC_TMUX_PROFILE_ENV, GJC_TMUX_SESSION_PREFIX, };
4
4
  export declare const GJC_TMUX_LAUNCHED_ENV = "GJC_TMUX_LAUNCHED";
5
5
  export declare const GJC_LAUNCH_POLICY_ENV = "GJC_LAUNCH_POLICY";
6
6
  export declare const GJC_TMUX_WINDOW_LABEL_MAX_WIDTH = 48;
@@ -39,6 +39,11 @@ export declare function renderUltragoalStatusMarkdown(summary: {
39
39
  };
40
40
  counts: Record<string, number>;
41
41
  goals: unknown[];
42
+ nudgeBudget?: number;
43
+ nudgeCount?: number;
44
+ nudgeRemaining?: number;
45
+ nudgeGoalId?: string;
46
+ nudgeTargetKind?: string;
42
47
  }): string;
43
48
  export declare function renderTeamStatusMarkdown(snapshot: {
44
49
  team_name: string;
@@ -280,7 +280,7 @@ export declare function pruneTeamWorkerGcRecord(record: GcRecord, probe: GcPidPr
280
280
  export declare function persistGjcTeamModeStateSummary(snapshot: GjcTeamSnapshot, cwd?: string): Promise<void>;
281
281
  export declare function recoverGjcTeamStaleClaims(teamName: string, cwd?: string, env?: NodeJS.ProcessEnv): Promise<GjcTeamLivenessRecoveryResult>;
282
282
  type GjcTeamTaskMetadataInput = Partial<Pick<GjcTeamTask, "owner" | "lane" | "required_role" | "allowed_roles" | "depends_on" | "blocked_by">>;
283
- export declare function resolveGjcWorkerCommand(cwd?: string, env?: NodeJS.ProcessEnv): string;
283
+ export declare function resolveGjcWorkerCommand(cwd?: string, env?: NodeJS.ProcessEnv, platform?: NodeJS.Platform, argv?: string[], execPath?: string): string;
284
284
  /** @internal Exported for unit tests. */
285
285
  export declare function buildWorkerCommand(config: GjcTeamConfig, worker: GjcTeamWorker, platform?: NodeJS.Platform): string;
286
286
  export type GjcWorkerCheckpointClassification = {
@@ -60,6 +60,18 @@ export declare function buildGjcTmuxExactOptionTarget(sessionName: string, opts?
60
60
  platform?: NodeJS.Platform;
61
61
  binary?: ResolvedTmuxBinary;
62
62
  }): string;
63
+ /**
64
+ * Build the exact-session target for tmux *session-scoped* commands such as
65
+ * `attach-session` and `kill-session`. Native tmux accepts `=NAME` for an
66
+ * exact session match, but Windows psmux 3.3.x rejects that target form for
67
+ * session commands even though the bare `NAME` resolves. Keep native tmux on
68
+ * exact targets and intentionally use the bare session name for psmux.
69
+ */
70
+ export declare function buildGjcTmuxExactSessionTarget(sessionName: string, opts?: {
71
+ env?: NodeJS.ProcessEnv;
72
+ platform?: NodeJS.Platform;
73
+ binary?: ResolvedTmuxBinary;
74
+ }): string;
63
75
  export declare const GJC_TMUX_UNTAGGED_REASON = "gjc_tmux_session_untagged";
64
76
  export declare function buildGjcTmuxUntaggedSessionHint(tmuxCommand: string): string;
65
77
  export declare function buildGjcTmuxUntaggedSessionError(sessionName: string, tmuxCommand: string): string;
@@ -1,4 +1,4 @@
1
- import { type UltragoalGoal, type UltragoalLedgerEvent, type UltragoalPlan, type UltragoalReceiptKind } from "./ultragoal-runtime";
1
+ import { type UltragoalGoal, type UltragoalLedgerEvent, type UltragoalNudgeSurface, type UltragoalPlan, type UltragoalReceiptKind } from "./ultragoal-runtime";
2
2
  export type UltragoalGuardState = "inactive" | "unrelated_goal" | "active_verified_complete" | "active_missing_receipt" | "active_stale_receipt" | "active_missing_final_receipt" | "active_dirty_quality_gate" | "active_review_blocked_unrecorded" | "active_review_blocked_recorded" | "unreadable_fail_closed";
3
3
  export interface UltragoalGuardDiagnostic {
4
4
  state: UltragoalGuardState;
@@ -30,6 +30,29 @@ export declare function readUltragoalVerificationState(input: {
30
30
  sessionId?: string | null;
31
31
  }): Promise<UltragoalGuardDiagnostic>;
32
32
  export declare function isUltragoalAskBlocked(cwd: string): Promise<UltragoalAskBlockDiagnostic>;
33
+ /**
34
+ * Escalating per-attempt refusal text. Deliberately avoids every
35
+ * `isUltragoalBypassPrompt` trigger: no `update_goal(`, no "skip/weaken verification",
36
+ * no "mark ... complete", no "--status complete", and the word "complete" never
37
+ * appears (so the `goal` ... `complete` proximity rule cannot match).
38
+ */
39
+ export declare function formatUltragoalNudgeMessage(input: {
40
+ surface: UltragoalNudgeSurface;
41
+ attempt: number;
42
+ budget: number;
43
+ goalId: string;
44
+ }): string;
45
+ /**
46
+ * Assert-path entry for the `ask` surface (the ask guard lives in another module).
47
+ * Resolves the active (leader) Ultragoal session so subagent/headless asks consume
48
+ * the leader run's budget rather than a fresh child ledger.
49
+ */
50
+ export declare function consumeUltragoalAskNudge(cwd: string, sessionId?: string | null): Promise<{
51
+ nudged: true;
52
+ message: string;
53
+ } | {
54
+ nudged: false;
55
+ }>;
33
56
  export declare function assertCanCompleteCurrentGoal(input: {
34
57
  cwd: string;
35
58
  currentGoal?: CurrentGoalLike | null;
@@ -49,3 +72,16 @@ export interface UltragoalPauseBlockDiagnostic {
49
72
  */
50
73
  export declare function isUltragoalPauseBlocked(cwd: string): Promise<UltragoalPauseBlockDiagnostic>;
51
74
  export declare function assertUltragoalPauseAllowed(cwd: string): Promise<void>;
75
+ /**
76
+ * Guard `goal({"op":"drop"})` during an active Ultragoal run. A *real give-up* (an
77
+ * aggregate run still mid-flight with incomplete required stories) is nudged while
78
+ * budget remains; once exhausted it falls through to today's drop behavior. Legitimate
79
+ * aggregate-reset drops — no durable run, unrelated goal, an already dropped/stale
80
+ * aggregate, or an all-stories-complete run — are never nudged. If durable state
81
+ * exists but cannot be read to classify the drop, fail closed.
82
+ */
83
+ export declare function assertUltragoalDropAllowed(input: {
84
+ cwd: string;
85
+ currentGoal?: CurrentGoalLike | null;
86
+ sessionId?: string | null;
87
+ }): Promise<void>;
@@ -53,6 +53,41 @@ export interface UltragoalLedgerEvent extends JsonObject {
53
53
  goalId?: string;
54
54
  timestamp?: string;
55
55
  }
56
+ export type UltragoalNudgeSurface = "pause" | "drop" | "ask" | "premature_complete";
57
+ export type UltragoalNudgeTargetKind = "story" | "final_aggregate_receipt";
58
+ export interface UltragoalNudgeLedgerEvent extends UltragoalLedgerEvent {
59
+ event: "nudge";
60
+ goalId: string;
61
+ targetKind: UltragoalNudgeTargetKind;
62
+ surface: UltragoalNudgeSurface;
63
+ attempt: number;
64
+ budget: number;
65
+ reason: string;
66
+ currentGoalObjective?: string;
67
+ }
68
+ export interface UltragoalNudgeTarget {
69
+ goalId: string;
70
+ targetKind: UltragoalNudgeTargetKind;
71
+ }
72
+ export type UltragoalNudgeOutcome = {
73
+ nudged: true;
74
+ attempt: number;
75
+ budget: number;
76
+ goalId: string;
77
+ targetKind: UltragoalNudgeTargetKind;
78
+ event: UltragoalNudgeLedgerEvent;
79
+ } | {
80
+ nudged: false;
81
+ exhausted: true;
82
+ count: number;
83
+ budget: number;
84
+ goalId: string;
85
+ targetKind: UltragoalNudgeTargetKind;
86
+ } | {
87
+ nudged: false;
88
+ inactive: true;
89
+ reason: string;
90
+ };
56
91
  export interface UltragoalPaths {
57
92
  dir: string;
58
93
  briefPath: string;
@@ -67,6 +102,11 @@ export interface UltragoalStatusSummary {
67
102
  currentGoal?: UltragoalGoal;
68
103
  counts: Record<UltragoalGoalStatus, number>;
69
104
  goals: UltragoalGoal[];
105
+ nudgeBudget?: number;
106
+ nudgeCount?: number;
107
+ nudgeRemaining?: number;
108
+ nudgeGoalId?: string;
109
+ nudgeTargetKind?: UltragoalNudgeTargetKind;
70
110
  }
71
111
  export interface UltragoalCommandResult {
72
112
  reviewBlockerGoalIds?: string[];
@@ -82,6 +122,46 @@ interface JsonObject {
82
122
  export declare function hashStructuredValue(value: unknown): string;
83
123
  export declare function getUltragoalPaths(cwd: string, sessionId?: string | null): UltragoalPaths;
84
124
  export declare function readUltragoalLedger(cwd: string, sessionId?: string | null): Promise<UltragoalLedgerEvent[]>;
125
+ export declare const DEFAULT_ULTRAGOAL_NUDGE_BUDGET = 10;
126
+ /** Pure: count ledger `nudge` rows for an exact goalId. */
127
+ export declare function countUltragoalNudges(ledger: readonly UltragoalLedgerEvent[], goalId: string): number;
128
+ /**
129
+ * Resolve the per-story nudge budget. Project `./.gjc/settings.json` overrides the
130
+ * user settings (`$GJC_CONFIG_DIR/settings.json` or `~/.gjc/settings.json`), else the
131
+ * default. Mirrors the `gjc.deepInterview.ambiguityThreshold` user+project precedence.
132
+ */
133
+ export declare function resolveUltragoalNudgeBudget(cwd: string): Promise<{
134
+ budget: number;
135
+ source: string;
136
+ }>;
137
+ /**
138
+ * Pure canonical selector shared by guards and status so `nudgeGoalId` can never
139
+ * diverge between what a guard consumes and what status displays. Prefers the active
140
+ * current-goal objective, then active > pending > failed (matching `chooseNextGoal`),
141
+ * then the aggregate final-receipt target when all stories are complete but the
142
+ * aggregate run still needs a final receipt. Returns null for verified-complete or
143
+ * absent/unrelated plans.
144
+ */
145
+ export declare function selectUltragoalNudgeTarget(plan: UltragoalPlan, options?: {
146
+ currentGoalObjective?: string;
147
+ retryFailed?: boolean;
148
+ }): UltragoalNudgeTarget | null;
149
+ /**
150
+ * Atomic consuming writer. Locks the ledger path, rereads + counts nudge rows for the
151
+ * target story, and appends exactly one `nudge` row inside the same critical section
152
+ * only while budget remains. Reuses the lockless `appendLedger` inside the lock (it
153
+ * does not acquire a conflicting lock), so concurrent guarded attempts cannot both
154
+ * observe `count = budget - 1` and overshoot the budget.
155
+ */
156
+ export declare function recordUltragoalNudgeIfBudgetRemaining(input: {
157
+ cwd: string;
158
+ sessionId?: string | null;
159
+ target: UltragoalNudgeTarget;
160
+ surface: UltragoalNudgeSurface;
161
+ budget: number;
162
+ reason: string;
163
+ currentGoalObjective?: string;
164
+ }): Promise<UltragoalNudgeOutcome>;
85
165
  export declare function computeUltragoalPlanGeneration(input: {
86
166
  plan: UltragoalPlan;
87
167
  ledger: readonly UltragoalLedgerEvent[];
@@ -6,7 +6,7 @@ export interface CustomModelPresetWizardSubmit {
6
6
  }
7
7
  export declare class CustomModelPresetWizardComponent extends Container {
8
8
  #private;
9
- constructor(onSubmit: (input: CustomModelPresetWizardSubmit) => void, onCancel: () => void, onRender?: () => void);
9
+ constructor(snapshot: ModelProfileConfig, onSubmit: (input: CustomModelPresetWizardSubmit) => void, onCancel: () => void, onRender?: () => void);
10
10
  setSubmitError(error: string): void;
11
11
  handleInput(keyData: string): void;
12
12
  }
@@ -3,6 +3,7 @@ import { type Model } from "@gajae-code/ai";
3
3
  import { Container, Input, type TUI } from "@gajae-code/tui";
4
4
  import type { GjcModelAssignmentTargetId, ModelRegistry } from "../../config/model-registry";
5
5
  import { type ScopedModelSelection } from "../../config/model-resolver";
6
+ import type { ModelProfileConfig } from "../../config/models-config-schema";
6
7
  import type { Settings } from "../../config/settings";
7
8
  type ScopedModelItem = ScopedModelSelection;
8
9
  export type ModelSelectorSelection = {
@@ -17,6 +18,7 @@ export type ModelSelectorSelection = {
17
18
  setDefault: boolean;
18
19
  } | {
19
20
  kind: "createProfile";
21
+ profile: ModelProfileConfig;
20
22
  };
21
23
  type RoleSelectCallback = (selection: ModelSelectorSelection) => void | Promise<void>;
22
24
  /**
@@ -4,6 +4,7 @@ import { Container, SettingsList } from "@gajae-code/tui";
4
4
  import { type SettingPath } from "../../config/settings";
5
5
  import type { StatusLinePreset, StatusLineSegmentId, StatusLineSeparatorStyle } from "../../config/settings-schema";
6
6
  import { PluginSettingsComponent } from "./plugin-settings";
7
+ import type { StatusLineSegmentOptions } from "./status-line";
7
8
  /**
8
9
  * Dynamic context for settings that need runtime data.
9
10
  * Some settings (like thinking level) are managed by the session, not Settings.
@@ -24,6 +25,8 @@ export interface StatusLinePreviewSettings {
24
25
  leftSegments?: StatusLineSegmentId[];
25
26
  rightSegments?: StatusLineSegmentId[];
26
27
  separator?: StatusLineSeparatorStyle;
28
+ segmentOptions?: StatusLineSegmentOptions;
29
+ previewHighlightSegment?: StatusLineSegmentId;
27
30
  sessionAccent?: boolean;
28
31
  }
29
32
  export interface SettingsCallbacks {
@@ -36,7 +39,7 @@ export interface SettingsCallbacks {
36
39
  /** Called for status line preview while configuring */
37
40
  onStatusLinePreview?: (settings: StatusLinePreviewSettings) => void;
38
41
  /** Get current rendered status line for inline preview */
39
- getStatusLinePreview?: () => string;
42
+ getStatusLinePreview?: (width?: number) => string;
40
43
  /** Called when plugins change */
41
44
  onPluginsChanged?: () => void;
42
45
  /** Called when settings panel is closed */
@@ -44,14 +44,12 @@ export interface SegmentContext {
44
44
  } | null;
45
45
  };
46
46
  usage: {
47
- fiveHour?: {
47
+ windows: Array<{
48
+ label: string;
48
49
  percent: number;
49
- resetMinutes?: number;
50
- };
51
- sevenDay?: {
52
- percent: number;
53
- resetHours?: number;
54
- };
50
+ resetValue?: number;
51
+ resetUnit?: "m" | "h";
52
+ }>;
55
53
  } | null;
56
54
  }
57
55
  export interface RenderedSegment {
@@ -29,6 +29,7 @@ export interface StatusLineSettings {
29
29
  rightSegments?: StatusLineSegmentId[];
30
30
  separator?: StatusLineSeparatorStyle;
31
31
  segmentOptions?: StatusLineSegmentOptions;
32
+ previewHighlightSegment?: StatusLineSegmentId;
32
33
  showHookStatus?: boolean;
33
34
  showSkillHud?: boolean;
34
35
  sessionAccent?: boolean;
@@ -59,9 +60,9 @@ export declare class StatusLineComponent implements Component {
59
60
  dispose(): void;
60
61
  invalidate(): void;
61
62
  /**
62
- * Background-refresh the Anthropic OAuth quota report. Guarded by a 5-min
63
- * TTL on both success (cache lifetime) and error (backoff). Exposed
64
- * (non-private) so unit tests can verify the backoff invariant.
63
+ * Background-refresh the OAuth quota report. Guarded by a 5-min TTL on both
64
+ * success (cache lifetime) and error (backoff). Exposed (non-private) so
65
+ * unit tests can verify the backoff invariant.
65
66
  */
66
67
  refreshUsageInBackground(): void;
67
68
  /**
@@ -32,6 +32,7 @@ export declare class InputController {
32
32
  temporary?: boolean;
33
33
  }): Promise<void>;
34
34
  toggleToolOutputExpansion(): void;
35
+ scrollTmuxToPreviousUserInput(): void;
35
36
  setToolsExpanded(expanded: boolean): void;
36
37
  toggleThinkingBlockVisibility(): void;
37
38
  openExternalEditor(): Promise<void>;
@@ -1,4 +1,5 @@
1
1
  import type { Component } from "@gajae-code/tui";
2
+ import type { ModelProfileConfig } from "../../config/models-config-schema";
2
3
  import type { InteractiveModeContext, OAuthSelectorOptions } from "../../modes/types";
3
4
  import type { JobsObserver } from "../jobs-observer";
4
5
  import type { SessionObserverRegistry } from "../session-observer-registry";
@@ -15,7 +16,7 @@ export declare class SelectorController {
15
16
  focus: Component;
16
17
  }): void;
17
18
  showProviderOnboarding(): void;
18
- showCustomModelPresetWizard(): void;
19
+ showCustomModelPresetWizard(snapshot: ModelProfileConfig): void;
19
20
  showCustomProviderWizard(): void;
20
21
  showSettingsSelector(): void;
21
22
  showThemeSelector(): void;
@@ -14,6 +14,7 @@ interface PromptActionAutocompleteOptions {
14
14
  copyCurrentLine: () => void;
15
15
  copyPrompt: () => void;
16
16
  pasteImage: () => void;
17
+ scrollTmuxToPreviousUserInput: () => void;
17
18
  undo: (prefix: string) => void;
18
19
  moveCursorToMessageEnd: () => void;
19
20
  moveCursorToMessageStart: () => void;
@@ -0,0 +1,18 @@
1
+ export declare const TMUX_PREVIOUS_USER_INPUT_SEARCH_PATTERN = "^ *user *$";
2
+ type TmuxScrollFailureReason = "not_inside_tmux" | "tmux_command_failed" | "copy_mode_failed" | "history_bottom_failed" | "search_failed";
3
+ export type TmuxScrollToPreviousUserInputResult = {
4
+ ok: true;
5
+ } | {
6
+ ok: false;
7
+ reason: TmuxScrollFailureReason;
8
+ error?: string;
9
+ };
10
+ interface TmuxSpawnResult {
11
+ exitCode: number | null;
12
+ stderr?: {
13
+ toString(): string;
14
+ };
15
+ }
16
+ type TmuxSpawnSync = (command: string, args: string[], env: NodeJS.ProcessEnv) => TmuxSpawnResult;
17
+ export declare function scrollTmuxToPreviousUserInput(env?: NodeJS.ProcessEnv, spawnSync?: TmuxSpawnSync): TmuxScrollToPreviousUserInputResult;
18
+ export {};
@@ -0,0 +1,3 @@
1
+ export type TerminalBellEvent = "complete" | "approval" | "ask";
2
+ export declare function ringTerminalBell(event: TerminalBellEvent, output?: Pick<NodeJS.WriteStream, "write">): void;
3
+ export declare function classifyHookSelectorBellEvent(title: string): TerminalBellEvent;
@@ -1,10 +1,21 @@
1
- import { Settings } from "../config/settings";
1
+ import type { Settings } from "../config/settings";
2
2
  import { TelegramNotificationDaemon } from "./telegram-daemon";
3
3
  export interface RunDaemonInternalDeps {
4
- SettingsImpl?: Pick<typeof Settings, "init">;
4
+ SettingsImpl?: {
5
+ init: (options?: {
6
+ agentDir?: string;
7
+ }) => Promise<Pick<Settings, "get" | "getAgentDir">>;
8
+ };
5
9
  DaemonImpl?: typeof TelegramNotificationDaemon;
6
10
  processPid?: number;
11
+ pidAlive?: (pid: number) => boolean;
7
12
  }
13
+ export declare function createLightweightDaemonSettings(input: {
14
+ agentDir: string;
15
+ rawConfig?: unknown;
16
+ }): Pick<Settings, "get" | "getAgentDir">;
17
+ export declare function loadLightweightDaemonSettings(agentDir: string): Promise<Pick<Settings, "get" | "getAgentDir">>;
18
+ export declare function ownerPidFromOwnerId(ownerId: string): number | undefined;
8
19
  export declare function runDaemonSmoke(opts?: {
9
20
  agentDir?: string;
10
21
  }): Promise<void>;
@@ -28,6 +28,10 @@ export interface TabSession {
28
28
  kindTag: BrowserKindTag;
29
29
  /** Session that acquired this tab; used for session-scoped teardown (F13). */
30
30
  ownerId?: string;
31
+ /** Unix-ms timestamp of the last acquire/run activity; drives GC idle + LRU ordering. */
32
+ lastUsedAt: number;
33
+ /** Set synchronously by the shared begin-release guard so concurrent release is a no-op. */
34
+ releasing?: boolean;
31
35
  }
32
36
  export interface AcquireTabOptions {
33
37
  url?: string;
@@ -58,6 +62,33 @@ export interface ReleaseTabOptions {
58
62
  kill?: boolean;
59
63
  }
60
64
  export declare function getTab(name: string): TabSession | undefined;
65
+ /** Read-only, GC-facing projection of a live tab. Never exposes the mutable `tabs` map. */
66
+ export interface TabGcSnapshot {
67
+ name: string;
68
+ ownerId?: string;
69
+ state: TabSession["state"];
70
+ pendingCount: number;
71
+ kindTag: BrowserKindTag;
72
+ lastUsedAt: number;
73
+ browserRefCount: number;
74
+ }
75
+ export interface BrowserGcEligibilityPolicy {
76
+ now: () => number;
77
+ idleMs: number;
78
+ }
79
+ /** Snapshot every live tab for GC ordering/diagnostics. */
80
+ export declare function listTabsForGc(): TabGcSnapshot[];
81
+ /**
82
+ * Evict a tab only if it is still GC-eligible against the LIVE supervisor state. The full
83
+ * predicate is checked synchronously and `releaseTab` is invoked with no intervening await,
84
+ * so a tab that became busy after a GC snapshot cannot be closed (its run rejected). Returns
85
+ * true only when the tab was actually released.
86
+ */
87
+ export declare function releaseTabIfGcEligible(name: string, policy: BrowserGcEligibilityPolicy): Promise<boolean>;
88
+ /** Test-only: install a fabricated tab session. */
89
+ export declare function setTabForTest(tab: TabSession): void;
90
+ /** Test-only: clear the tab registry between cases. */
91
+ export declare function clearTabsForTest(): void;
61
92
  export declare function acquireTab(name: string, browser: BrowserHandle, opts: AcquireTabOptions): Promise<AcquireTabResult>;
62
93
  export declare function runInTab(name: string, opts: RunInTabOptions): Promise<RunResultOk>;
63
94
  export declare function releaseTab(name: string, opts?: ReleaseTabOptions): Promise<boolean>;
@@ -0,0 +1,23 @@
1
+ /** Prefix of every computer-use screenshot fallback directory created under the OS temp dir. */
2
+ export declare const SCREENSHOT_FALLBACK_DIR_PREFIX = "gjc-computer-screenshots-";
3
+ /** Lazy-arm marker: called when the first screenshot fallback dir is created this process. */
4
+ export declare function markScreenshotFallbackDirCreatedForGc(): void;
5
+ /** Whether any screenshot fallback dir has been created this process (GC lazy-arm gate). */
6
+ export declare function hasCreatedScreenshotFallbackDir(): boolean;
7
+ /** Test-only: reset the lazy-arm marker between cases. */
8
+ export declare function resetScreenshotFallbackGcForTest(): void;
9
+ export interface ScreenshotGcOptions {
10
+ now: () => number;
11
+ staleMs: number;
12
+ /** Base dir to scan; defaults to os.tmpdir(). Injectable for tests. */
13
+ tmpDir?: string;
14
+ }
15
+ /**
16
+ * Disk-only GC for stale computer-use screenshot fallback directories. Scans the temp dir for
17
+ * `gjc-computer-screenshots-*` directories and removes those whose mtime is older than `staleMs`.
18
+ * Never throws on a per-directory failure; the whole sweep is best-effort.
19
+ */
20
+ export declare function cleanupStaleScreenshotFallbackDirs(options: ScreenshotGcOptions): Promise<{
21
+ scanned: number;
22
+ removed: number;
23
+ }>;
@@ -5,18 +5,18 @@ import type { ToolSession } from "./index";
5
5
  export declare const MAX_CRON_TASKS_PER_OWNER = 50;
6
6
  /** Recurring tasks auto-expire 7 days after creation (mirrors upstream). */
7
7
  export declare const CRON_RECURRING_MAX_AGE_MS: number;
8
- declare const cronCreateSchema: z.ZodObject<{
9
- cron_expression: z.ZodString;
10
- prompt: z.ZodString;
11
- recurring: z.ZodDefault<z.ZodBoolean>;
12
- }, z.core.$strip>;
13
- export type CronCreateParams = z.infer<typeof cronCreateSchema>;
14
- declare const cronListSchema: z.ZodObject<{}, z.core.$strip>;
15
- export type CronListParams = z.infer<typeof cronListSchema>;
16
- declare const cronDeleteSchema: z.ZodObject<{
17
- id: z.ZodString;
18
- }, z.core.$strip>;
19
- export type CronDeleteParams = z.infer<typeof cronDeleteSchema>;
8
+ declare const cronSchema: z.ZodObject<{
9
+ op: z.ZodEnum<{
10
+ create: "create";
11
+ delete: "delete";
12
+ list: "list";
13
+ }>;
14
+ cron_expression: z.ZodOptional<z.ZodString>;
15
+ prompt: z.ZodOptional<z.ZodString>;
16
+ recurring: z.ZodOptional<z.ZodBoolean>;
17
+ id: z.ZodOptional<z.ZodString>;
18
+ }, z.core.$strict>;
19
+ export type CronParams = z.infer<typeof cronSchema>;
20
20
  export interface CronJobSnapshot {
21
21
  id: string;
22
22
  cron_expression: string;
@@ -35,18 +35,14 @@ export interface CronListJobDetails {
35
35
  prompt: string;
36
36
  humanSchedule: string;
37
37
  }
38
- export interface CronCreateToolDetails {
39
- id: string;
40
- cron_expression: string;
41
- recurring: boolean;
38
+ export interface CronToolDetails {
39
+ op: "create" | "list" | "delete";
40
+ id?: string;
41
+ cron_expression?: string;
42
+ recurring?: boolean;
42
43
  nextFireAt?: number;
43
- }
44
- export interface CronListToolDetails {
45
- jobs: CronListJobDetails[];
46
- }
47
- export interface CronDeleteToolDetails {
48
- id: string;
49
- deleted: boolean;
44
+ jobs?: CronListJobDetails[];
45
+ deleted?: boolean;
50
46
  }
51
47
  /** Clear every schedule for an owner. Exported for tests + lifecycle teardown. */
52
48
  export declare function clearOwnerSchedules(ownerId: string | undefined): void;
@@ -68,49 +64,28 @@ export declare function calculateCronFireTimeMs(params: {
68
64
  nowMs: number;
69
65
  expiresAt?: number;
70
66
  }): number;
71
- export declare class CronCreateTool implements AgentTool<typeof cronCreateSchema, CronCreateToolDetails> {
72
- private readonly session;
73
- readonly name = "CronCreate";
74
- readonly label = "CronCreate";
75
- readonly summary = "Schedule a prompt on a 5-field cron expression";
76
- readonly description: string;
77
- readonly parameters: z.ZodObject<{
78
- cron_expression: z.ZodString;
79
- prompt: z.ZodString;
80
- recurring: z.ZodDefault<z.ZodBoolean>;
81
- }, z.core.$strip>;
82
- readonly strict = true;
83
- readonly loadMode = "discoverable";
84
- constructor(session: ToolSession);
85
- static createIf(session: ToolSession): CronCreateTool | null;
86
- execute(_toolCallId: string, params: CronCreateParams, _signal?: AbortSignal, _onUpdate?: AgentToolUpdateCallback<CronCreateToolDetails>, _context?: AgentToolContext): Promise<AgentToolResult<CronCreateToolDetails>>;
87
- }
88
- export declare class CronListTool implements AgentTool<typeof cronListSchema, CronListToolDetails> {
89
- private readonly session;
90
- readonly name = "CronList";
91
- readonly label = "CronList";
92
- readonly summary = "List scheduled cron jobs";
93
- readonly description: string;
94
- readonly parameters: z.ZodObject<{}, z.core.$strip>;
95
- readonly strict = true;
96
- readonly loadMode = "discoverable";
97
- constructor(session: ToolSession);
98
- static createIf(session: ToolSession): CronListTool | null;
99
- execute(_toolCallId: string, _params: CronListParams, _signal?: AbortSignal, _onUpdate?: AgentToolUpdateCallback<CronListToolDetails>, _context?: AgentToolContext): Promise<AgentToolResult<CronListToolDetails>>;
100
- }
101
- export declare class CronDeleteTool implements AgentTool<typeof cronDeleteSchema, CronDeleteToolDetails> {
67
+ export declare class CronTool implements AgentTool<typeof cronSchema, CronToolDetails> {
68
+ #private;
102
69
  private readonly session;
103
- readonly name = "CronDelete";
104
- readonly label = "CronDelete";
105
- readonly summary = "Cancel a scheduled cron job by ID";
70
+ readonly name = "cron";
71
+ readonly label = "Cron";
72
+ readonly summary = "Schedule, list, and cancel cron-style prompts (op: create | list | delete)";
106
73
  readonly description: string;
107
74
  readonly parameters: z.ZodObject<{
108
- id: z.ZodString;
109
- }, z.core.$strip>;
75
+ op: z.ZodEnum<{
76
+ create: "create";
77
+ delete: "delete";
78
+ list: "list";
79
+ }>;
80
+ cron_expression: z.ZodOptional<z.ZodString>;
81
+ prompt: z.ZodOptional<z.ZodString>;
82
+ recurring: z.ZodOptional<z.ZodBoolean>;
83
+ id: z.ZodOptional<z.ZodString>;
84
+ }, z.core.$strict>;
110
85
  readonly strict = true;
111
86
  readonly loadMode = "discoverable";
112
87
  constructor(session: ToolSession);
113
- static createIf(session: ToolSession): CronDeleteTool | null;
114
- execute(_toolCallId: string, params: CronDeleteParams, _signal?: AbortSignal, _onUpdate?: AgentToolUpdateCallback<CronDeleteToolDetails>, _context?: AgentToolContext): Promise<AgentToolResult<CronDeleteToolDetails>>;
88
+ static createIf(session: ToolSession): CronTool | null;
89
+ execute(_toolCallId: string, params: CronParams, _signal?: AbortSignal, _onUpdate?: AgentToolUpdateCallback<CronToolDetails>, _context?: AgentToolContext): Promise<AgentToolResult<CronToolDetails>>;
115
90
  }
116
91
  export {};
@@ -41,7 +41,6 @@ export * from "./eval";
41
41
  export * from "./find";
42
42
  export * from "./gh";
43
43
  export * from "./image-gen";
44
- export * from "./inspect-image";
45
44
  export * from "./irc";
46
45
  export * from "./job";
47
46
  export * from "./monitor";
@@ -0,0 +1,54 @@
1
+ import type { Settings } from "../config/settings";
2
+ import { type TabGcSnapshot } from "./browser/tab-supervisor";
3
+ export interface BrowserGcPolicy {
4
+ enabled: boolean;
5
+ idleMs: number;
6
+ rssLimitBytes: number;
7
+ }
8
+ export interface ComputerGcPolicy {
9
+ enabled: boolean;
10
+ staleMs: number;
11
+ scanIntervalMs: number;
12
+ }
13
+ export declare function resolveBrowserGcPolicy(settings: Settings): BrowserGcPolicy;
14
+ export declare function resolveComputerGcPolicy(settings: Settings): ComputerGcPolicy;
15
+ export declare function resolveSweepIntervalMs(settings: Settings): number;
16
+ /** Injectable seams so the controller is fully testable without real browsers/filesystem/RSS. */
17
+ export interface ResourceGcDeps {
18
+ now: () => number;
19
+ rssBytes: () => number;
20
+ logWarn: (msg: string, meta?: Record<string, unknown>) => void;
21
+ listTabs: () => TabGcSnapshot[];
22
+ releaseTab: (name: string, policy: {
23
+ now: () => number;
24
+ idleMs: number;
25
+ }) => Promise<boolean>;
26
+ cleanupScreenshots: (opts: {
27
+ now: () => number;
28
+ staleMs: number;
29
+ }) => Promise<{
30
+ scanned: number;
31
+ removed: number;
32
+ }>;
33
+ screenshotArmed: () => boolean;
34
+ }
35
+ export interface ResourceGcRegistration {
36
+ sessionId: string;
37
+ settings: Settings;
38
+ }
39
+ /**
40
+ * Register a session with the resource GC. Starts the single shared timer on the first
41
+ * registration. Returns an idempotent unregister function; the timer stops only when the last
42
+ * session unregisters.
43
+ */
44
+ export declare function registerResourceGcSession(reg: ResourceGcRegistration): () => void;
45
+ export declare function sweepOnce(d?: ResourceGcDeps): Promise<void>;
46
+ export declare function __setResourceGcDepsForTest(overrides: Partial<ResourceGcDeps>): void;
47
+ export declare function __runResourceGcTickForTest(): Promise<void>;
48
+ export declare function __getResourceGcStateForTest(): {
49
+ timerActive: boolean;
50
+ sessionCount: number;
51
+ rssWarningActive: boolean;
52
+ inProgress: boolean;
53
+ };
54
+ export declare function __resetResourceGcForTest(): void;
@@ -111,5 +111,6 @@ export declare class WebSearchTool implements AgentTool<typeof webSearchSchema,
111
111
  export declare const webSearchCustomTool: CustomTool<typeof webSearchSchema, SearchRenderDetails>;
112
112
  export declare function getSearchTools(): CustomTool<any, any>[];
113
113
  export { getSearchProvider, setPreferredSearchProvider, setSearchFallbackProviders } from "./provider";
114
+ export { setSearchHardTimeoutMs } from "./providers/utils";
114
115
  export type { SearchProviderId as SearchProvider, SearchResponse } from "./types";
115
116
  export { isConfigurableSearchProviderId, isSearchProviderPreference } from "./types";