@gajae-code/coding-agent 0.7.7 → 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 (63) hide show
  1. package/CHANGELOG.md +20 -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-registry.d.ts +5 -0
  8. package/dist/types/config/models-config-schema.d.ts +5 -0
  9. package/dist/types/config/settings-schema.d.ts +45 -0
  10. package/dist/types/config/settings.d.ts +7 -0
  11. package/dist/types/coordinator-mcp/server.d.ts +8 -0
  12. package/dist/types/gjc-runtime/launch-tmux.d.ts +2 -2
  13. package/dist/types/gjc-runtime/team-runtime.d.ts +1 -1
  14. package/dist/types/gjc-runtime/tmux-common.d.ts +12 -0
  15. package/dist/types/modes/components/custom-model-preset-wizard.d.ts +1 -1
  16. package/dist/types/modes/components/model-selector.d.ts +2 -0
  17. package/dist/types/modes/components/settings-selector.d.ts +4 -1
  18. package/dist/types/modes/components/status-line/types.d.ts +5 -7
  19. package/dist/types/modes/components/status-line.d.ts +4 -3
  20. package/dist/types/modes/controllers/input-controller.d.ts +1 -0
  21. package/dist/types/modes/controllers/selector-controller.d.ts +2 -1
  22. package/dist/types/modes/prompt-action-autocomplete.d.ts +1 -0
  23. package/dist/types/modes/tmux-scroll.d.ts +18 -0
  24. package/dist/types/modes/utils/terminal-bell.d.ts +3 -0
  25. package/dist/types/notifications/telegram-daemon-cli.d.ts +13 -2
  26. package/package.json +7 -7
  27. package/src/cli/local-provider-smoke.ts +632 -0
  28. package/src/cli/notify-cli.ts +4 -2
  29. package/src/cli/update-cli.ts +155 -13
  30. package/src/cli.ts +18 -0
  31. package/src/commands/launch.ts +46 -1
  32. package/src/commands/local-provider.ts +62 -0
  33. package/src/commands/notify.ts +1 -1
  34. package/src/config/model-registry.ts +55 -1
  35. package/src/config/models-config-schema.ts +9 -0
  36. package/src/config/settings-schema.ts +47 -0
  37. package/src/config/settings.ts +11 -0
  38. package/src/coordinator-mcp/server.ts +276 -34
  39. package/src/gjc-runtime/launch-tmux.ts +34 -8
  40. package/src/gjc-runtime/launch-worktree.ts +16 -2
  41. package/src/gjc-runtime/team-runtime.ts +21 -6
  42. package/src/gjc-runtime/tmux-common.ts +16 -0
  43. package/src/gjc-runtime/tmux-sessions.ts +13 -9
  44. package/src/internal-urls/docs-index.generated.ts +5 -4
  45. package/src/modes/components/agent-dashboard.ts +2 -1
  46. package/src/modes/components/custom-model-preset-wizard.ts +30 -189
  47. package/src/modes/components/model-selector.ts +182 -5
  48. package/src/modes/components/session-observer-overlay.ts +3 -3
  49. package/src/modes/components/settings-selector.ts +491 -5
  50. package/src/modes/components/status-line/segments.ts +7 -18
  51. package/src/modes/components/status-line/types.ts +6 -2
  52. package/src/modes/components/status-line.ts +69 -35
  53. package/src/modes/controllers/event-controller.ts +98 -4
  54. package/src/modes/controllers/extension-ui-controller.ts +3 -0
  55. package/src/modes/controllers/input-controller.ts +15 -0
  56. package/src/modes/controllers/selector-controller.ts +12 -4
  57. package/src/modes/prompt-action-autocomplete.ts +8 -0
  58. package/src/modes/tmux-scroll.ts +92 -0
  59. package/src/modes/utils/terminal-bell.ts +48 -0
  60. package/src/notifications/telegram-daemon-cli.ts +112 -9
  61. package/src/notifications/telegram-daemon.ts +4 -0
  62. package/src/session/agent-session.ts +74 -5
  63. package/src/slash-commands/builtin-registry.ts +106 -13
package/CHANGELOG.md CHANGED
@@ -2,7 +2,24 @@
2
2
 
3
3
  ## [Unreleased]
4
4
 
5
+ ## [0.7.8] - 2026-06-30
6
+ ### Added
7
+
8
+ - Terminal bell notifications can now be enabled for agent completion, approval, and ask/user-input prompts (#1277).
9
+ - Added a generic `providers.local.openaiCompat` models config path for OpenAI-compatible local endpoints plus `gjc local-provider smoke` for bounded streaming chat-completion checks (#1246).
10
+ - Added `gjc local-provider discover` / `models` to list model IDs from a configured local OpenAI-compatible provider via `GET /v1/models`, with clear network and response-shape errors and no chat-completion request (#1247).
11
+
12
+ ### Fixed
13
+
14
+ - `gjc update` now verifies the installed runtime after package-manager failures and treats a nonzero Bun/npm exit as recoverable when the requested version and smoke test actually landed, avoiding false failures from Bun tarball extraction errors (#1280).
15
+ - Submitted user prompts now use the live terminal viewport width in wide Windows Terminal/PowerShell sessions, keeping Korean/CJK prompt wrapping responsive without changing narrow layouts (#1239).
16
+ - Coordinator MCP now fails tmux-delivered turns that never receive a runtime prompt acknowledgement/`turn_start`, surfacing an explicit unacknowledged delivery reason instead of leaving Hermes/Oren waiting on a normal active/running state (#1237).
17
+ - Telegram now advertises `/session_create`, `/session_recent`, `/session_close`, and `/session_resume` in the bot command menu so lifecycle control commands are discoverable from `/` autocomplete.
18
+
5
19
  ## [0.7.7] - 2026-06-28
20
+ ### Added
21
+
22
+ - Added a `#` prompt action that enters tmux copy-mode and searches backward to the previous rendered `user` input marker, providing a tmux-local previous-input scroll jump without relying on terminal-specific modified key chords.
6
23
 
7
24
  ### Fixed
8
25
 
@@ -22,7 +39,6 @@
22
39
  - Elided runaway thinking-token loops in the assistant message renderer so repeated thinking output no longer grows without bound (#1196).
23
40
  - Made `gjc session` create/list work on psmux-backed multiplexers (#1192).
24
41
  - Sanitized dot-prefixed cwd window titles so tmux window names render correctly (#1198).
25
-
26
42
  ## [0.7.4] - 2026-06-27
27
43
 
28
44
  ### Added
@@ -126,6 +142,9 @@
126
142
  - Corrected the auto-compaction output reserve so post-compaction responses keep adequate headroom (#1021).
127
143
  - Improved active-input shortcut hints and the busy-input queueing hint for clearer in-session guidance (#1022, #1024).
128
144
  - Fixed the Ultragoal ask guard blocking the `ask` tool when no GJC session can be resolved. `ultragoalReadPaths` falls back to the legacy/global `.gjc/ultragoal` directory when neither `GJC_SESSION_ID` nor an auto-detectable active session is present, but the follow-up `readUltragoalPlan`/`readUltragoalLedger` reads ignored that resolution and re-ran session detection, throwing `no active GJC session found` and surfacing `durable_state_unreadable` — which blocked `ask` for every agent even with no active Ultragoal run. `ultragoalReadPaths` now returns the resolved session id (or `null`); the ask guard treats a null session as inactive and falls open, and threads the resolved id into the plan/ledger reads so they no longer re-resolve. An inconsistent state (state dir present but `goals.json` missing/empty) still fails closed so the pause guard keeps blocking give-ups.
145
+ ### Added
146
+
147
+ - Added a user-level `completion.notifyCommand` hook that runs a shell command with `GJC_NOTIFICATION_*` payload environment variables when an agent turn completes, enabling cmux/desktop/webhook completion alerts without project-config command execution.
129
148
 
130
149
  ## [0.7.1] - 2026-06-23
131
150
  ### Fixed
package/README.md CHANGED
@@ -18,6 +18,14 @@ GJC already exposes public lifecycle events through the extension/hook event con
18
18
  - `turn_end` — a model/tool turn finished. The public payload is `{ type: "turn_end", turnIndex, message, toolResults }`.
19
19
  - `agent_end` — the agent loop for a submitted prompt reached a terminal boundary. The public payload is `{ type: "agent_end", messages }`.
20
20
 
21
+ For simple local side effects that do not need a full extension, set the user-level `completion.notifyCommand`. GJC runs it on completed agent turns with `GJC_NOTIFICATION_*` environment variables (`GJC_NOTIFICATION_TITLE`, `GJC_NOTIFICATION_BODY`, `GJC_NOTIFICATION_JSON`, etc.); project settings cannot activate this command hook.
22
+
23
+ ```sh
24
+ gjc config set completion.notifyCommand 'cmux notify --title "$GJC_NOTIFICATION_TITLE" --body "$GJC_NOTIFICATION_BODY"'
25
+ ```
26
+
27
+ `cmux notify` returning successfully means GJC handed the completion event to cmux. cmux may still suppress the native desktop banner when the app/window is focused, the emitting workspace is active, or the notification panel is open. In those cases, check cmux's notification panel or unread workspace state instead of treating the missing banner as a GJC delivery failure.
28
+
21
29
  Recommended external mapping:
22
30
 
23
31
  | Notification | Public event | Status guidance |
@@ -0,0 +1,59 @@
1
+ import type { ModelsConfig } from "../config/models-config-schema";
2
+ export interface LocalProviderSmokeCommandArgs {
3
+ model?: string;
4
+ modelsPath?: string;
5
+ timeoutMs?: number;
6
+ json?: boolean;
7
+ smoke?: boolean;
8
+ }
9
+ export interface LocalOpenAICompatConfig {
10
+ baseUrl: string;
11
+ apiKey?: string;
12
+ }
13
+ export type LocalProviderDiagnosticCheckName = "config" | "models" | "chat_stream";
14
+ export type LocalProviderDiagnosticStatus = "ok" | "skipped" | "error";
15
+ export type LocalProviderDiagnosticCategory = "auth" | "timeout" | "unreachable" | "not_ready" | "oom" | "malformed_response" | "http_error" | "configuration" | "empty_response";
16
+ export interface LocalProviderDiagnosticCheck {
17
+ name: LocalProviderDiagnosticCheckName;
18
+ status: LocalProviderDiagnosticStatus;
19
+ message: string;
20
+ action?: string;
21
+ category?: LocalProviderDiagnosticCategory;
22
+ error?: string;
23
+ httpStatus?: number;
24
+ }
25
+ export interface LocalProviderSmokeResult {
26
+ ok: boolean;
27
+ baseUrl?: string;
28
+ model?: string;
29
+ message: string;
30
+ error?: string;
31
+ category?: LocalProviderDiagnosticCategory;
32
+ action?: string;
33
+ }
34
+ export interface LocalProviderDiscoveryResult {
35
+ ok: boolean;
36
+ provider: string;
37
+ baseUrl?: string;
38
+ models: string[];
39
+ message: string;
40
+ error?: string;
41
+ category?: LocalProviderDiagnosticCategory;
42
+ action?: string;
43
+ }
44
+ export interface LocalProviderStatusResult {
45
+ ok: boolean;
46
+ provider: "local";
47
+ baseUrl?: string;
48
+ model?: string;
49
+ models: string[];
50
+ checks: LocalProviderDiagnosticCheck[];
51
+ message: string;
52
+ }
53
+ export declare function getLocalOpenAICompatConfig(config: ModelsConfig | undefined): LocalOpenAICompatConfig | undefined;
54
+ export declare function runLocalProviderDiscover(cmd: Omit<LocalProviderSmokeCommandArgs, "model" | "smoke">): Promise<LocalProviderDiscoveryResult>;
55
+ export declare function runLocalProviderStatus(cmd: LocalProviderSmokeCommandArgs): Promise<LocalProviderStatusResult>;
56
+ export declare function runLocalProviderSmoke(cmd: LocalProviderSmokeCommandArgs): Promise<LocalProviderSmokeResult>;
57
+ export declare function runLocalProviderDiscoverCommand(cmd: Omit<LocalProviderSmokeCommandArgs, "model" | "smoke">): Promise<void>;
58
+ export declare function runLocalProviderStatusCommand(cmd: LocalProviderSmokeCommandArgs): Promise<void>;
59
+ export declare function runLocalProviderSmokeCommand(cmd: LocalProviderSmokeCommandArgs): Promise<void>;
@@ -1,4 +1,4 @@
1
- import { Settings } from "../config/settings";
1
+ import type { Settings } from "../config/settings";
2
2
  export type NotifyAction = "setup" | "status" | "daemon-internal";
3
3
  export interface NotifyCommandArgs {
4
4
  action: NotifyAction;
@@ -5,6 +5,20 @@ export interface InstalledVersionVerification {
5
5
  path?: string;
6
6
  smokeTestFailed?: boolean;
7
7
  smokeTestOutput?: string;
8
+ cleanupWarning?: string;
9
+ }
10
+ export interface PackageManagerUpdateResult {
11
+ exitCode: number | null;
12
+ text: () => string;
13
+ }
14
+ export type PackageManagerUpdateRunner = (expectedVersion: string) => Promise<PackageManagerUpdateResult>;
15
+ export interface PackageManagerUpdateOptions {
16
+ managerName: string;
17
+ expectedVersion: string;
18
+ runInstall: PackageManagerUpdateRunner;
19
+ verifyInstalledRuntime: (expectedVersion: string) => Promise<InstalledVersionVerification>;
20
+ printVerificationResult?: (expectedVersion: string) => Promise<void>;
21
+ printRecoveredVerification?: (expectedVersion: string) => void;
8
22
  }
9
23
  /** Paths and verifier used while replacing a downloaded binary update. */
10
24
  export interface BinaryReplacementOptions {
@@ -22,7 +36,14 @@ export declare function parseUpdateArgs(args: string[]): {
22
36
  force: boolean;
23
37
  check: boolean;
24
38
  } | undefined;
25
- export declare function resolveUpdateMethodForTest(ompPath: string, bunBinDir: string | undefined): "bun" | "binary";
39
+ type PackageManagerTarget = {
40
+ manager: "npm";
41
+ packageName: string;
42
+ };
43
+ type PathPlatform = NodeJS.Platform;
44
+ type PackageExists = (packageName: string, packageRoot: string) => boolean;
45
+ export declare function resolveUpdateMethodForTest(ompPath: string, bunBinDir: string | undefined): "bun" | "npm" | "binary";
46
+ export declare function resolveNpmManagedTargetForTest(ompPath: string, platform: PathPlatform, packageExists: PackageExists): PackageManagerTarget | undefined;
26
47
  export declare function formatBinaryDownloadFailureMessageForTest(binaryName: string, url: string, status: string | number, platform?: NodeJS.Platform): string;
27
48
  export declare function buildReleaseBinaryUrlForTest(version: string, platform?: NodeJS.Platform, arch?: string): string;
28
49
  export declare function formatManualUpdateInstructionsForTest(platform?: NodeJS.Platform): string;
@@ -31,6 +52,7 @@ export declare function formatVerificationFailureForTest(result: InstalledVersio
31
52
  * Atomically replace the installed binary and roll back if version verification fails.
32
53
  */
33
54
  export declare function replaceBinaryForUpdate(options: BinaryReplacementOptions): Promise<InstalledVersionVerification>;
55
+ export declare function runPackageManagerUpdateForTest(options: PackageManagerUpdateOptions): Promise<InstalledVersionVerification>;
34
56
  /**
35
57
  * Run the update command.
36
58
  */
@@ -42,3 +64,4 @@ export declare function runUpdateCommand(opts: {
42
64
  * Print update command help.
43
65
  */
44
66
  export declare function printUpdateHelp(): void;
67
+ export {};
@@ -0,0 +1,34 @@
1
+ /**
2
+ * Test configured local OpenAI-compatible providers.
3
+ */
4
+ import { Command } from "@gajae-code/utils/cli";
5
+ export declare const LOCAL_PROVIDER_ACTIONS: readonly ["status", "diagnose", "discover", "models", "smoke"];
6
+ export declare const LOCAL_PROVIDER_DEFAULT_ACTION = "status";
7
+ export default class LocalProvider extends Command {
8
+ static description: string;
9
+ static args: {
10
+ action: import("@gajae-code/utils/cli").ArgDescriptor & {
11
+ description: string;
12
+ required: false;
13
+ options: readonly ["status", "diagnose", "discover", "models", "smoke"];
14
+ };
15
+ };
16
+ static flags: {
17
+ model: import("@gajae-code/utils/cli").FlagDescriptor<"string"> & {
18
+ description: string;
19
+ };
20
+ "models-path": import("@gajae-code/utils/cli").FlagDescriptor<"string"> & {
21
+ description: string;
22
+ };
23
+ "timeout-ms": import("@gajae-code/utils/cli").FlagDescriptor<"integer"> & {
24
+ description: string;
25
+ };
26
+ smoke: import("@gajae-code/utils/cli").FlagDescriptor<"boolean"> & {
27
+ description: string;
28
+ };
29
+ json: import("@gajae-code/utils/cli").FlagDescriptor<"boolean"> & {
30
+ description: string;
31
+ };
32
+ };
33
+ run(): Promise<void>;
34
+ }
@@ -256,6 +256,11 @@ export declare const ModelsConfigFile: ConfigFile<{
256
256
  disableStrictTools?: boolean | undefined;
257
257
  transport?: "pi-native" | undefined;
258
258
  cacheRetention?: "long" | "none" | "short" | undefined;
259
+ openaiCompat?: {
260
+ baseUrl: string;
261
+ apiKey?: string | undefined;
262
+ apiKeyEnv?: string | undefined;
263
+ } | undefined;
259
264
  }> | undefined;
260
265
  modelBindings?: {
261
266
  modelRoles?: Record<string, string> | undefined;
@@ -669,6 +669,11 @@ export declare const ModelsConfigSchema: z.ZodObject<{
669
669
  none: "none";
670
670
  short: "short";
671
671
  }>>;
672
+ openaiCompat: z.ZodOptional<z.ZodObject<{
673
+ baseUrl: z.ZodString;
674
+ apiKey: z.ZodOptional<z.ZodString>;
675
+ apiKeyEnv: z.ZodOptional<z.ZodString>;
676
+ }, z.core.$strict>>;
672
677
  }, z.core.$strict>>>;
673
678
  modelBindings: z.ZodOptional<z.ZodObject<{
674
679
  modelRoles: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
@@ -160,6 +160,42 @@ export declare const SETTINGS_SCHEMA: {
160
160
  readonly default: 60000;
161
161
  readonly validate: (value: number) => boolean;
162
162
  };
163
+ readonly "notifications.terminalBell": {
164
+ readonly type: "boolean";
165
+ readonly default: false;
166
+ readonly ui: {
167
+ readonly tab: "interaction";
168
+ readonly label: "Terminal Bell";
169
+ readonly description: "Emit a BEL character for local terminal notifications";
170
+ };
171
+ };
172
+ readonly "notifications.bellOnComplete": {
173
+ readonly type: "boolean";
174
+ readonly default: true;
175
+ readonly ui: {
176
+ readonly tab: "interaction";
177
+ readonly label: "Bell on Completion";
178
+ readonly description: "Ring the terminal bell when an agent turn completes";
179
+ };
180
+ };
181
+ readonly "notifications.bellOnApproval": {
182
+ readonly type: "boolean";
183
+ readonly default: true;
184
+ readonly ui: {
185
+ readonly tab: "interaction";
186
+ readonly label: "Bell on Approval";
187
+ readonly description: "Ring the terminal bell when a plan or approval prompt needs attention";
188
+ };
189
+ };
190
+ readonly "notifications.bellOnAsk": {
191
+ readonly type: "boolean";
192
+ readonly default: true;
193
+ readonly ui: {
194
+ readonly tab: "interaction";
195
+ readonly label: "Bell on Ask";
196
+ readonly description: "Ring the terminal bell when an ask/user-input prompt needs attention";
197
+ };
198
+ };
163
199
  readonly autoResume: {
164
200
  readonly type: "boolean";
165
201
  readonly default: false;
@@ -1301,6 +1337,15 @@ export declare const SETTINGS_SCHEMA: {
1301
1337
  readonly description: "Notify when the agent completes";
1302
1338
  };
1303
1339
  };
1340
+ readonly "completion.notifyCommand": {
1341
+ readonly type: "string";
1342
+ readonly default: "";
1343
+ readonly ui: {
1344
+ readonly tab: "interaction";
1345
+ readonly label: "Completion Notification Command";
1346
+ readonly description: "Optional user-level shell command to run when an agent turn completes; receives GJC_NOTIFICATION_* environment variables.";
1347
+ };
1348
+ };
1304
1349
  readonly "ask.timeout": {
1305
1350
  readonly type: "number";
1306
1351
  readonly default: 0;
@@ -54,6 +54,13 @@ export declare class Settings {
54
54
  * Returns the merged value from global + project + overrides, or the default.
55
55
  */
56
56
  get<P extends SettingPath>(path: P): SettingValue<P>;
57
+ /**
58
+ * Get a setting value from the user/global config only.
59
+ *
60
+ * Use for machine-local command hooks and other settings that must not be
61
+ * activated by project-scoped config files.
62
+ */
63
+ getGlobal<P extends SettingPath>(path: P): SettingValue<P> | undefined;
57
64
  /** Check whether a setting is present in loaded settings/overrides rather than coming from schema defaults. */
58
65
  has(path: SettingPath): boolean;
59
66
  /**
@@ -45,6 +45,14 @@ interface LegacyHandlerOptions {
45
45
  env?: NodeJS.ProcessEnv;
46
46
  createSession?: () => unknown;
47
47
  }
48
+ export declare const COORDINATOR_AWAIT_TURN_TIMEOUT_MAX_MS: number;
49
+ export declare const COORDINATOR_RUNTIME_PROMPT_ACK_TIMEOUT_MAX_MS: number;
50
+ export declare const COORDINATOR_EVENT_WATCH_TIMEOUT_MAX_MS = 30000;
51
+ export declare const COORDINATOR_POLL_INTERVAL_MAX_MS = 10000;
52
+ export declare function boundedAwaitTurnTimeoutMs(value: unknown): number;
53
+ export declare function boundedRuntimePromptAckTimeoutMs(value: unknown): number;
54
+ export declare function boundedEventWatchTimeoutMs(value: unknown): number;
55
+ export declare function boundedPollIntervalMs(value: unknown): number;
48
56
  export declare function readCoordinatorArtifact(config: CoordinatorMcpConfig, args: {
49
57
  path: unknown;
50
58
  }): Promise<Record<string, unknown>>;
@@ -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;
@@ -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;
@@ -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>;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "type": "module",
3
3
  "name": "@gajae-code/coding-agent",
4
- "version": "0.7.7",
4
+ "version": "0.7.8",
5
5
  "description": "Gajae Code CLI with read, bash, edit, write tools and session management",
6
6
  "homepage": "https://gaebal-gajae.dev",
7
7
  "author": "Yeachan-Heo",
@@ -52,12 +52,12 @@
52
52
  "@agentclientprotocol/sdk": "0.21.0",
53
53
  "@babel/parser": "^7.29.3",
54
54
  "@mozilla/readability": "^0.6.0",
55
- "@gajae-code/stats": "0.7.7",
56
- "@gajae-code/agent-core": "0.7.7",
57
- "@gajae-code/ai": "0.7.7",
58
- "@gajae-code/natives": "0.7.7",
59
- "@gajae-code/tui": "0.7.7",
60
- "@gajae-code/utils": "0.7.7",
55
+ "@gajae-code/stats": "0.7.8",
56
+ "@gajae-code/agent-core": "0.7.8",
57
+ "@gajae-code/ai": "0.7.8",
58
+ "@gajae-code/natives": "0.7.8",
59
+ "@gajae-code/tui": "0.7.8",
60
+ "@gajae-code/utils": "0.7.8",
61
61
  "@puppeteer/browsers": "^2.13.0",
62
62
  "@types/turndown": "5.0.6",
63
63
  "@xterm/headless": "^6.0.0",