@gajae-code/coding-agent 0.7.10 → 0.7.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +25 -0
- package/README.md +1 -1
- package/dist/types/config/keybindings.d.ts +11 -5
- package/dist/types/defaults/gjc-defaults.d.ts +7 -0
- package/dist/types/gjc-runtime/launch-tmux.d.ts +3 -0
- package/dist/types/gjc-runtime/ralplan-runtime.d.ts +3 -2
- package/dist/types/gjc-runtime/restricted-role-agent-bash.d.ts +1 -0
- package/dist/types/gjc-runtime/state-writer.d.ts +1 -0
- package/dist/types/modes/components/custom-editor.d.ts +2 -1
- package/dist/types/modes/components/skill-message.d.ts +1 -0
- package/dist/types/modes/controllers/command-controller.d.ts +1 -0
- package/dist/types/modes/controllers/input-controller.d.ts +4 -0
- package/dist/types/modes/interactive-mode.d.ts +1 -0
- package/dist/types/modes/prompt-action-autocomplete.d.ts +2 -0
- package/dist/types/modes/slash-command-visibility.d.ts +1 -0
- package/dist/types/modes/types.d.ts +1 -0
- package/dist/types/sdk.d.ts +1 -1
- package/dist/types/session/agent-session.d.ts +8 -5
- package/dist/types/slash-commands/types.d.ts +2 -0
- package/dist/types/utils/cmux-workspace.d.ts +30 -1
- package/dist/types/web/search/index.d.ts +3 -1
- package/dist/types/web/search/provider.d.ts +9 -0
- package/dist/types/web/search/providers/utils.d.ts +42 -13
- package/package.json +7 -7
- package/src/cli/update-cli.ts +24 -0
- package/src/cli/web-search-cli.ts +2 -5
- package/src/cli.ts +1 -1
- package/src/commands/launch.ts +1 -1
- package/src/commands/ralplan.ts +1 -0
- package/src/config/keybindings.ts +14 -5
- package/src/config/model-profiles.ts +16 -0
- package/src/coordinator-mcp/server.ts +9 -3
- package/src/defaults/gjc/skills/ralplan/SKILL.md +16 -14
- package/src/defaults/gjc-defaults.ts +16 -0
- package/src/extensibility/extensions/runner.ts +2 -1
- package/src/gjc-runtime/launch-tmux.ts +164 -42
- package/src/gjc-runtime/ralplan-runtime.ts +22 -6
- package/src/gjc-runtime/restricted-role-agent-bash.ts +1 -0
- package/src/gjc-runtime/state-runtime.ts +8 -5
- package/src/gjc-runtime/state-writer.ts +5 -5
- package/src/internal-urls/docs-index.generated.ts +5 -4
- package/src/main.ts +2 -2
- package/src/migrate/executor.ts +23 -6
- package/src/modes/components/custom-editor.ts +8 -0
- package/src/modes/components/model-selector.ts +6 -2
- package/src/modes/components/settings-selector.ts +0 -2
- package/src/modes/components/skill-message.ts +18 -10
- package/src/modes/controllers/command-controller.ts +23 -0
- package/src/modes/controllers/input-controller.ts +41 -9
- package/src/modes/interactive-mode.ts +16 -7
- package/src/modes/prompt-action-autocomplete.ts +23 -1
- package/src/modes/slash-command-visibility.ts +9 -0
- package/src/modes/types.ts +1 -0
- package/src/modes/utils/hotkeys-markdown.ts +5 -2
- package/src/modes/utils/ui-helpers.ts +76 -3
- package/src/notifications/telegram-daemon.ts +4 -4
- package/src/prompts/agents/architect.md +7 -4
- package/src/prompts/agents/critic.md +15 -6
- package/src/prompts/agents/planner.md +8 -3
- package/src/prompts/tools/bash.md +1 -1
- package/src/sdk.ts +3 -6
- package/src/session/agent-session.ts +60 -17
- package/src/slash-commands/builtin-registry.ts +30 -10
- package/src/slash-commands/types.ts +2 -0
- package/src/tools/bash.ts +24 -8
- package/src/utils/cmux-workspace.ts +134 -7
- package/src/utils/title-generator.ts +1 -1
- package/src/web/kagi.ts +1 -1
- package/src/web/parallel.ts +2 -2
- package/src/web/search/index.ts +118 -45
- package/src/web/search/provider.ts +65 -0
- package/src/web/search/providers/anthropic.ts +1 -1
- package/src/web/search/providers/brave.ts +1 -1
- package/src/web/search/providers/codex.ts +1 -1
- package/src/web/search/providers/duckduckgo.ts +1 -1
- package/src/web/search/providers/exa.ts +1 -1
- package/src/web/search/providers/gemini.ts +7 -3
- package/src/web/search/providers/jina.ts +1 -1
- package/src/web/search/providers/kimi.ts +6 -1
- package/src/web/search/providers/openai-compatible.ts +1 -1
- package/src/web/search/providers/parallel.ts +1 -1
- package/src/web/search/providers/perplexity.ts +2 -2
- package/src/web/search/providers/searxng.ts +1 -1
- package/src/web/search/providers/synthetic.ts +1 -1
- package/src/web/search/providers/tavily.ts +1 -1
- package/src/web/search/providers/utils.ts +67 -17
- package/src/web/search/providers/xai.ts +1 -1
- package/src/web/search/providers/zai.ts +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,30 @@
|
|
|
2
2
|
|
|
3
3
|
## [Unreleased]
|
|
4
4
|
|
|
5
|
+
## [0.7.11] - 2026-07-03
|
|
6
|
+
### Fixed
|
|
7
|
+
|
|
8
|
+
- Native Windows terminals now default `app.message.queue` to `Alt+Q` instead of `Alt+Enter`, avoiding the Windows Terminal fullscreen shortcut conflict (#1422).
|
|
9
|
+
- Coordinator MCP tmux prompt delivery now submits with tmux `Enter` instead of `C-m`, while preserving runtime prompt-ack/`turn_start` as the delivery success gate (#1409).
|
|
10
|
+
- The session-close resume hint now prints the `gjc --resume <id>` command on its own line so it can be selected and copied without the surrounding prose.
|
|
11
|
+
- Coordinator MCP tmux prompt delivery now uses a paste buffer for prompt text before submitting with `Enter`, preserving multiline delegated `/skill:*` prompt separators that `send-keys -l` could flatten into an unstarted visible prompt (#1416).
|
|
12
|
+
|
|
13
|
+
- `/retry` now resumes sessions left with an interrupted user/custom/tool-result tail after a crash or power loss, and recovers unresolved assistant tool-use tails instead of reporting "Nothing to retry".
|
|
14
|
+
- Queued prompt shortcuts now keep working during auto context-full compaction: Tab/Alt+Enter queue text immediately, `/skill:*` entries replay through the skill invocation path after compaction, and Alt+Up restores only the newest queued prompt for editing instead of merging the full queue.
|
|
15
|
+
- Skill prompt cards now size their collapsed arguments preview to the current terminal width instead of wrapping at a fixed narrow column.
|
|
16
|
+
- `gjc update` now refreshes opted-in on-disk default workflow skill copies (written by `gjc setup defaults` under the agent dir) after a successful update, so they no longer stay stale relative to the embedded defaults; copies that were never installed are left absent.
|
|
17
|
+
- `gjc migrate` skill imports now tolerate project or agent directories reached through macOS system symlinks such as `/var` while still rejecting symlinked destination skill directories, so local dry-run/live parity tests no longer fail on Darwin temp paths.
|
|
18
|
+
- cmux workspace auto-renames now include a `GJC: ` prefix so renamed workspaces remain identifiable as GJC sessions.
|
|
19
|
+
- The cmux workspace auto-rename is now ownership-guarded: GJC reads the current workspace title via `cmux workspace list` and only renames a workspace that still has its default title, so it no longer overwrites a user-pinned workspace name or thrash a shared workspace title across multiple sessions running under the same `CMUX_WORKSPACE_ID`. Opt out with `GJC_NO_CMUX_RENAME`.
|
|
20
|
+
- `gjc --tmux --resume` now reaches the session picker/resume target instead of auto-attaching a same-branch managed tmux session before the inner resume resolver runs.
|
|
21
|
+
- `gjc --tmux` now preserves a newly created managed tmux session when `attach-session` exits after the parent SSH/PTY closes but the tmux server still reports the session live, so closing a Windows Terminal tab no longer kills the Mac host session before reattach.
|
|
22
|
+
- Managed `gjc --tmux` launches now size the inner tmux window to the caller terminal minus inherited tmux status lines, preventing the bottom of the GJC input from being clipped when the user's tmux status bar is visible.
|
|
23
|
+
- Managed `gjc --tmux` launches no longer pin the initial window to `manual` sizing on native tmux. The pre-attach reassert used `resize-window`, which flips the window's `window-size` option to `manual` and stops `attach-session` from resizing the window to the real terminal; when the attaching terminal was larger than the capture-time size, tmux left a smaller-than-client window and painted the uncovered area with `·` fill. The window now stays on `window-size latest` so it tracks the attaching client (psmux keeps the explicit `resize-window` reassert).
|
|
24
|
+
|
|
25
|
+
### Changed
|
|
26
|
+
|
|
27
|
+
- `web_search` latency overhaul: provider hard timeouts are now class-based (pure search APIs 15s, LLM-mediated providers 120s, Kimi 35s aligned to its upstream 30s budget, replacing the uniform 300s ceiling; an explicitly configured `web_search.timeout` still overrides — the schema default no longer reinstalls 300s), DuckDuckGo is fired as a background hedge 3s into a slower primary so a failing primary falls back to an already-settled result, the Gemini 429/5xx retry-delay budget dropped from 5 minutes to 30 seconds, resolved provider chains are cached per AuthStorage for 60s keyed on the credential generation (availability probes skipped on repeat searches; login/logout invalidates immediately), and `WebSearchTool` prewarms the chain at construction. Measured: hung-primary fallback 301s → 15s, slow-failing-primary fallback ~7s → 6s, repeat chain resolution ~26ms → ~0.01ms.
|
|
28
|
+
|
|
5
29
|
## [0.7.10] - 2026-07-02
|
|
6
30
|
### Added
|
|
7
31
|
|
|
@@ -13,6 +37,7 @@
|
|
|
13
37
|
|
|
14
38
|
- Deep Interview option-clarification prompts now stay out of the interview transcript and ambiguity recorder, so asking about displayed choices no longer persists as the round answer before the user selects an actual option.
|
|
15
39
|
- `gjc daemon reload telegram` now spawns the replacement daemon with a stable owner pid so the new daemon does not exit immediately after the short-lived reload CLI process ends.
|
|
40
|
+
- Ralplan role agents can now persist Planner/Architect/Critic artifacts through a sanctioned `GJC_RALPLAN_ARTIFACT` env handoff (`--artifact-env GJC_RALPLAN_ARTIFACT`), avoiding restricted-bash failures on markdown containing quotes, backslashes, shell-expansion characters, or command-substitution syntax.
|
|
16
41
|
- Managed `gjc --tmux` launches now size the initial window correctly (#1376).
|
|
17
42
|
- Coordinator tmux-delivered turns now submit correctly on Enter (#1372).
|
|
18
43
|
- Generic long `retry-after` rate limits are now kept retryable instead of being treated as fatal (#1370).
|
package/README.md
CHANGED
|
@@ -24,7 +24,7 @@ For simple local side effects that do not need a full extension, set the user-le
|
|
|
24
24
|
gjc config set completion.notifyCommand 'cmux notify --title "$GJC_NOTIFICATION_TITLE" --body "$GJC_NOTIFICATION_BODY"'
|
|
25
25
|
```
|
|
26
26
|
|
|
27
|
-
When GJC
|
|
27
|
+
When GJC runs inside a cmux terminal (`CMUX_WORKSPACE_ID` is set), GJC best-effort renames that cmux workspace to the current GJC session name (with a `GJC: ` prefix) — but only when the workspace still has its default title, so a name you pinned (or one set by a peer session sharing the workspace) is never overwritten. Opt out with `GJC_NO_CMUX_RENAME=1`.
|
|
28
28
|
|
|
29
29
|
Windows Terminal may keep BEL (`[Console]::Write([char]7)`) silent depending on profile and system sound settings even when `notifications.terminalBell` is enabled. For an audible Windows completion beep, configure a user-level PowerShell command hook instead:
|
|
30
30
|
|
|
@@ -10,6 +10,7 @@ interface AppKeybindings {
|
|
|
10
10
|
"app.suspend": true;
|
|
11
11
|
"app.thinking.cycle": true;
|
|
12
12
|
"app.thinking.toggle": true;
|
|
13
|
+
"app.commandPalette.open": true;
|
|
13
14
|
"app.model.cycleForward": true;
|
|
14
15
|
"app.model.cycleBackward": true;
|
|
15
16
|
"app.model.select": true;
|
|
@@ -45,6 +46,7 @@ declare module "@gajae-code/tui" {
|
|
|
45
46
|
interface Keybindings extends AppKeybindings {
|
|
46
47
|
}
|
|
47
48
|
}
|
|
49
|
+
export declare function defaultMessageQueueKeysForPlatform(platform?: NodeJS.Platform): KeyId;
|
|
48
50
|
/**
|
|
49
51
|
* All keybindings definitions: TUI + app-specific.
|
|
50
52
|
*/
|
|
@@ -201,12 +203,16 @@ export declare const KEYBINDINGS: {
|
|
|
201
203
|
readonly defaultKeys: "ctrl+t";
|
|
202
204
|
readonly description: "Toggle thinking mode";
|
|
203
205
|
};
|
|
204
|
-
readonly "app.
|
|
206
|
+
readonly "app.commandPalette.open": {
|
|
205
207
|
readonly defaultKeys: "ctrl+p";
|
|
208
|
+
readonly description: "Open command palette";
|
|
209
|
+
};
|
|
210
|
+
readonly "app.model.cycleForward": {
|
|
211
|
+
readonly defaultKeys: "alt+n";
|
|
206
212
|
readonly description: "Cycle to next model";
|
|
207
213
|
};
|
|
208
214
|
readonly "app.model.cycleBackward": {
|
|
209
|
-
readonly defaultKeys: "shift+
|
|
215
|
+
readonly defaultKeys: "alt+shift+n";
|
|
210
216
|
readonly description: "Cycle to previous model";
|
|
211
217
|
};
|
|
212
218
|
readonly "app.model.select": {
|
|
@@ -234,7 +240,7 @@ export declare const KEYBINDINGS: {
|
|
|
234
240
|
readonly description: "Send follow-up message (no default; Ctrl+Enter submits)";
|
|
235
241
|
};
|
|
236
242
|
readonly "app.message.queue": {
|
|
237
|
-
readonly defaultKeys:
|
|
243
|
+
readonly defaultKeys: KeyId;
|
|
238
244
|
readonly description: "Queue message for next turn";
|
|
239
245
|
};
|
|
240
246
|
readonly "app.message.dequeue": {
|
|
@@ -254,8 +260,8 @@ export declare const KEYBINDINGS: {
|
|
|
254
260
|
readonly description: "Copy prompt";
|
|
255
261
|
};
|
|
256
262
|
readonly "app.session.new": {
|
|
257
|
-
readonly defaultKeys:
|
|
258
|
-
readonly description: "
|
|
263
|
+
readonly defaultKeys: "ctrl+n";
|
|
264
|
+
readonly description: "Start a new session";
|
|
259
265
|
};
|
|
260
266
|
readonly "app.session.tree": {
|
|
261
267
|
readonly defaultKeys: [];
|
|
@@ -27,6 +27,13 @@ export type DefaultGjcDefinition = DefaultGjcSkillDefinition | DefaultGjcSkillFr
|
|
|
27
27
|
export interface InstallDefaultGjcDefinitionsOptions {
|
|
28
28
|
check?: boolean;
|
|
29
29
|
force?: boolean;
|
|
30
|
+
/**
|
|
31
|
+
* Only rewrite default definition files that already exist on disk but whose
|
|
32
|
+
* content differs from the embedded defaults. Files that are absent are left
|
|
33
|
+
* absent (status "missing"). Used by `gjc update` to refresh opted-in copies
|
|
34
|
+
* without materializing new on-disk copies for users who never installed them.
|
|
35
|
+
*/
|
|
36
|
+
refreshOnly?: boolean;
|
|
30
37
|
targetRoot?: string;
|
|
31
38
|
}
|
|
32
39
|
export type DefaultGjcDefinitionInstallFile = {
|
|
@@ -22,6 +22,7 @@ export interface TmuxLaunchContext {
|
|
|
22
22
|
tty?: TtyState;
|
|
23
23
|
spawnSync?: TmuxSpawnSync;
|
|
24
24
|
tmuxAvailable?: boolean;
|
|
25
|
+
tmuxStatusLines?: number;
|
|
25
26
|
worktreeBranch?: string | null;
|
|
26
27
|
currentBranch?: string | null;
|
|
27
28
|
existingBranchSessionName?: string | null;
|
|
@@ -66,6 +67,8 @@ export interface TmuxLaunchPlan {
|
|
|
66
67
|
project?: string | null;
|
|
67
68
|
sessionId?: string | null;
|
|
68
69
|
sessionStateFile?: string | null;
|
|
70
|
+
isPsmux: boolean;
|
|
71
|
+
platform: NodeJS.Platform;
|
|
69
72
|
}
|
|
70
73
|
export interface GjcTmuxProfileResult {
|
|
71
74
|
skipped: boolean;
|
|
@@ -10,8 +10,9 @@
|
|
|
10
10
|
* that lives in the bundled `/skill:ralplan` skill — but it accepts every documented flag so
|
|
11
11
|
* scripted users see a useful response and the active run is visible to the TUI.
|
|
12
12
|
*
|
|
13
|
-
* 2. **Artifact write**: `gjc ralplan --write --stage <type> --stage_n <N>
|
|
14
|
-
* <path-or-string>
|
|
13
|
+
* 2. **Artifact write**: `gjc ralplan --write --stage <type> --stage_n <N>
|
|
14
|
+
* (--artifact <path-or-string> | --artifact-env GJC_RALPLAN_ARTIFACT)
|
|
15
|
+
* [--run-id <id>] [--session-id <id>] [--json]` persists Planner / Architect
|
|
15
16
|
* / Critic / revision / post-interview / ADR / final markdown under `.gjc/plans/ralplan/<run-id>/`, maintains
|
|
16
17
|
* an `index.jsonl` audit log, copies `final` stages to `pending-approval.md`, and advances
|
|
17
18
|
* the HUD chip to reflect the latest persisted stage.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Editor, type KeyId } from "@gajae-code/tui";
|
|
2
2
|
import { type AppKeybinding } from "../../config/keybindings";
|
|
3
|
-
type ConfigurableEditorAction = Extract<AppKeybinding, "app.interrupt" | "app.clear" | "app.exit" | "app.suspend" | "app.thinking.cycle" | "app.model.cycleForward" | "app.model.cycleBackward" | "app.model.select" | "app.model.selectTemporary" | "app.tools.expand" | "app.thinking.toggle" | "app.editor.external" | "app.history.search" | "app.message.dequeue" | "app.message.followUp" | "app.message.queue" | "app.clipboard.pasteImage" | "app.clipboard.copyPrompt">;
|
|
3
|
+
type ConfigurableEditorAction = Extract<AppKeybinding, "app.interrupt" | "app.clear" | "app.exit" | "app.suspend" | "app.thinking.cycle" | "app.commandPalette.open" | "app.model.cycleForward" | "app.model.cycleBackward" | "app.model.select" | "app.model.selectTemporary" | "app.tools.expand" | "app.thinking.toggle" | "app.editor.external" | "app.history.search" | "app.message.dequeue" | "app.message.followUp" | "app.message.queue" | "app.clipboard.pasteImage" | "app.clipboard.copyPrompt">;
|
|
4
4
|
type PastePendingClearReason = "timeout" | "queue-limit";
|
|
5
5
|
/**
|
|
6
6
|
* Custom editor that handles configurable app-level shortcuts for coding-agent.
|
|
@@ -19,6 +19,7 @@ export declare class CustomEditor extends Editor {
|
|
|
19
19
|
onClear?: () => void;
|
|
20
20
|
onExit?: () => void;
|
|
21
21
|
onCycleThinkingLevel?: () => void;
|
|
22
|
+
onOpenCommandPalette?: () => void;
|
|
22
23
|
onCycleModelForward?: () => void;
|
|
23
24
|
onCycleModelBackward?: () => void;
|
|
24
25
|
onSelectModel?: () => void;
|
|
@@ -18,6 +18,7 @@ export declare class CommandController {
|
|
|
18
18
|
handleUsageCommand(reports?: UsageReport[] | null): Promise<void>;
|
|
19
19
|
handleChangelogCommand(showFull?: boolean): Promise<void>;
|
|
20
20
|
handleHotkeysCommand(): void;
|
|
21
|
+
handleHelpCommand(): void;
|
|
21
22
|
handleToolsCommand(): void;
|
|
22
23
|
handleContextCommand(): void;
|
|
23
24
|
handleMemoryCommand(text: string): Promise<void>;
|
|
@@ -14,6 +14,9 @@ export declare class InputController {
|
|
|
14
14
|
handleFollowUp(): Promise<void>;
|
|
15
15
|
/** Send editor text explicitly as a queued next-turn message. */
|
|
16
16
|
handleQueueSubmit(): Promise<void>;
|
|
17
|
+
restoreLatestQueuedMessageToEditor(options?: {
|
|
18
|
+
currentText?: string;
|
|
19
|
+
}): number;
|
|
17
20
|
restoreQueuedMessagesToEditor(options?: {
|
|
18
21
|
abort?: boolean;
|
|
19
22
|
currentText?: string;
|
|
@@ -27,6 +30,7 @@ export declare class InputController {
|
|
|
27
30
|
handleCopyCurrentLine(): void;
|
|
28
31
|
/** Copy current prompt text to system clipboard. */
|
|
29
32
|
handleCopyPrompt(): void;
|
|
33
|
+
openCommandPalette(): void;
|
|
30
34
|
cycleThinkingLevel(): void;
|
|
31
35
|
cycleRoleModel(options?: {
|
|
32
36
|
temporary?: boolean;
|
|
@@ -184,6 +184,7 @@ export declare class InteractiveMode implements InteractiveModeContext {
|
|
|
184
184
|
handleUsageCommand(reports?: UsageReport[] | null): Promise<void>;
|
|
185
185
|
handleChangelogCommand(showFull?: boolean): Promise<void>;
|
|
186
186
|
handleHotkeysCommand(): void;
|
|
187
|
+
handleHelpCommand(): void;
|
|
187
188
|
handleToolsCommand(): void;
|
|
188
189
|
handleContextCommand(): void;
|
|
189
190
|
handleClearCommand(): Promise<void>;
|
|
@@ -14,6 +14,8 @@ interface PromptActionAutocompleteOptions {
|
|
|
14
14
|
copyCurrentLine: () => void;
|
|
15
15
|
copyPrompt: () => void;
|
|
16
16
|
pasteImage: () => void;
|
|
17
|
+
newSession: () => void;
|
|
18
|
+
showHelp: () => void;
|
|
17
19
|
scrollTmuxToPreviousUserInput: () => void;
|
|
18
20
|
undo: (prefix: string) => void;
|
|
19
21
|
moveCursorToMessageEnd: () => void;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function shouldShowExtensionCommand(name: string, activeProvider: string | undefined): boolean;
|
|
@@ -191,6 +191,7 @@ export interface InteractiveModeContext {
|
|
|
191
191
|
handleUsageCommand(reports?: UsageReport[] | null): Promise<void>;
|
|
192
192
|
handleChangelogCommand(showFull?: boolean): Promise<void>;
|
|
193
193
|
handleHotkeysCommand(): void;
|
|
194
|
+
handleHelpCommand(): void;
|
|
194
195
|
handleToolsCommand(): void;
|
|
195
196
|
handleContextCommand(): void;
|
|
196
197
|
handleDumpCommand(): void;
|
package/dist/types/sdk.d.ts
CHANGED
|
@@ -47,7 +47,7 @@ export interface CreateAgentSessionOptions {
|
|
|
47
47
|
requestedModel: Model;
|
|
48
48
|
reason: string;
|
|
49
49
|
};
|
|
50
|
-
/** Models available for cycling (
|
|
50
|
+
/** Models available for cycling (Alt+N in interactive mode) */
|
|
51
51
|
scopedModels?: ScopedModelSelection[];
|
|
52
52
|
/** System prompt blocks. Array replaces default, function receives default blocks and returns final blocks. */
|
|
53
53
|
systemPrompt?: string[] | ((defaultPrompt: string[]) => string[]);
|
|
@@ -159,7 +159,7 @@ export interface AgentSessionConfig {
|
|
|
159
159
|
agent: Agent;
|
|
160
160
|
sessionManager: SessionManager;
|
|
161
161
|
settings: Settings;
|
|
162
|
-
/** Models to cycle through with
|
|
162
|
+
/** Models to cycle through with Alt+N (from --models flag) */
|
|
163
163
|
scopedModels?: ScopedModelSelection[];
|
|
164
164
|
/** Initial session thinking selector. */
|
|
165
165
|
thinkingLevel?: ThinkingLevel;
|
|
@@ -671,7 +671,7 @@ export declare class AgentSession {
|
|
|
671
671
|
followUp: readonly string[];
|
|
672
672
|
};
|
|
673
673
|
/**
|
|
674
|
-
* Pop the
|
|
674
|
+
* Pop the newest queued message across steering and follow-up queues.
|
|
675
675
|
* Used by dequeue keybinding to restore messages to editor one at a time.
|
|
676
676
|
* Returns the popped entry's `.text`; the tag (if any) dies with the
|
|
677
677
|
* record — no orphan state can outlive the queue entry.
|
|
@@ -905,9 +905,12 @@ export declare class AgentSession {
|
|
|
905
905
|
*/
|
|
906
906
|
setAutoRetryEnabled(enabled: boolean): void;
|
|
907
907
|
/**
|
|
908
|
-
* Manually retry the last failed assistant turn
|
|
909
|
-
*
|
|
910
|
-
*
|
|
908
|
+
* Manually retry the last failed assistant turn, or resume an interrupted tail
|
|
909
|
+
* left by a non-graceful process exit after the user/custom/tool-result message
|
|
910
|
+
* was persisted but before the agent emitted a terminal assistant response.
|
|
911
|
+
* Removes failed/aborted/unresolved tool-use assistant tails before
|
|
912
|
+
* re-attempting with a fresh retry budget.
|
|
913
|
+
* @returns true if retry/resume was initiated, false if no retryable tail exists or agent is busy
|
|
911
914
|
*/
|
|
912
915
|
retry(): Promise<boolean>;
|
|
913
916
|
/**
|
|
@@ -17,6 +17,8 @@ export interface BuiltinSlashCommand {
|
|
|
17
17
|
subcommands?: SubcommandDef[];
|
|
18
18
|
/** Static inline hint when command takes a simple argument (no subcommands). */
|
|
19
19
|
inlineHint?: string;
|
|
20
|
+
/** Higher values sort earlier in TUI slash-command autocomplete. */
|
|
21
|
+
priority?: number;
|
|
20
22
|
}
|
|
21
23
|
/** Parsed slash-command text after stripping the leading "/". */
|
|
22
24
|
export interface ParsedSlashCommand {
|
|
@@ -2,6 +2,13 @@ export interface CmuxWorkspaceRenameCommand {
|
|
|
2
2
|
command: string;
|
|
3
3
|
args: string[];
|
|
4
4
|
}
|
|
5
|
+
/** Current ownership state of a cmux workspace, read back from `cmux workspace list`. */
|
|
6
|
+
export interface CmuxWorkspaceOwnership {
|
|
7
|
+
/** cmux marks a workspace `has_custom_title` once an explicit title is set (by the user or by GJC). */
|
|
8
|
+
hasCustomTitle: boolean;
|
|
9
|
+
/** The workspace's current display title. */
|
|
10
|
+
title: string;
|
|
11
|
+
}
|
|
5
12
|
export interface CmuxWorkspaceRenameProcess {
|
|
6
13
|
exited: Promise<number>;
|
|
7
14
|
kill(): void;
|
|
@@ -17,7 +24,29 @@ export interface CmuxWorkspaceTitleSyncOptions {
|
|
|
17
24
|
stdout: "ignore";
|
|
18
25
|
stderr: "ignore";
|
|
19
26
|
}) => CmuxWorkspaceRenameProcess;
|
|
27
|
+
/** Reads the current ownership state of `workspaceId`. Injectable for tests. */
|
|
28
|
+
readOwnership?: (cmuxCommand: string, workspaceId: string, env: NodeJS.ProcessEnv) => Promise<CmuxWorkspaceOwnership | null>;
|
|
20
29
|
}
|
|
21
30
|
export declare function sanitizeCmuxWorkspaceTitle(title: string | undefined): string | undefined;
|
|
31
|
+
export declare function formatCmuxWorkspaceTitle(title: string | undefined): string | undefined;
|
|
22
32
|
export declare function buildCmuxWorkspaceRenameCommand(sessionName: string | undefined, env?: NodeJS.ProcessEnv): CmuxWorkspaceRenameCommand | null;
|
|
23
|
-
|
|
33
|
+
/** Parse `cmux workspace list --json --id-format both` output and return the
|
|
34
|
+
* ownership state of the workspace matching `workspaceId` (by UUID `id` or `ref`). */
|
|
35
|
+
export declare function parseCmuxWorkspaceOwnership(jsonText: string, workspaceId: string): CmuxWorkspaceOwnership | null;
|
|
36
|
+
/** Only rename when GJC owns the name:
|
|
37
|
+
* - unknown ownership (read failed) → skip (fail safe, never clobber)
|
|
38
|
+
* - already the desired title → skip (no-op)
|
|
39
|
+
* - workspace still on its default title → rename
|
|
40
|
+
* - any custom title (user- or peer-set) → skip
|
|
41
|
+
* This makes GJC name a fresh workspace once and then leave it alone, so it
|
|
42
|
+
* never overwrites a user-pinned name and multiple sessions sharing one
|
|
43
|
+
* CMUX_WORKSPACE_ID do not thrash the workspace title. */
|
|
44
|
+
export declare function shouldRenameCmuxWorkspace(ownership: CmuxWorkspaceOwnership | null, desiredTitle: string): boolean;
|
|
45
|
+
/**
|
|
46
|
+
* Best-effort sync of the containing cmux workspace title to the current GJC
|
|
47
|
+
* session name. Ownership-guarded: GJC reads the current workspace title and
|
|
48
|
+
* only renames a workspace that still has its default title, so it never
|
|
49
|
+
* overwrites a name the user pinned or a name a peer session (sharing the same
|
|
50
|
+
* CMUX_WORKSPACE_ID) set. Opt out with GJC_NO_CMUX_RENAME.
|
|
51
|
+
*/
|
|
52
|
+
export declare function syncCmuxWorkspaceTitle(sessionName: string | undefined, options?: CmuxWorkspaceTitleSyncOptions): Promise<void>;
|
|
@@ -44,6 +44,8 @@ export type SearchToolParams = z.infer<typeof webSearchSchema>;
|
|
|
44
44
|
export interface SearchQueryParams extends SearchToolParams {
|
|
45
45
|
provider?: SearchProviderId | "auto";
|
|
46
46
|
}
|
|
47
|
+
/** Override the hedge delay (tests). Non-finite/non-positive resets to default. */
|
|
48
|
+
export declare function setDdgHedgeDelayMs(ms: number | undefined): void;
|
|
47
49
|
/**
|
|
48
50
|
* Execute a web search query for CLI/testing workflows.
|
|
49
51
|
*
|
|
@@ -111,6 +113,6 @@ export declare class WebSearchTool implements AgentTool<typeof webSearchSchema,
|
|
|
111
113
|
export declare const webSearchCustomTool: CustomTool<typeof webSearchSchema, SearchRenderDetails>;
|
|
112
114
|
export declare function getSearchTools(): CustomTool<any, any>[];
|
|
113
115
|
export { getConfiguredSearchProviderPreference, getSearchProvider, setPreferredSearchProvider, setSearchFallbackProviders, } from "./provider";
|
|
114
|
-
export { setSearchHardTimeoutMs } from "./providers/utils";
|
|
116
|
+
export { applyConfiguredSearchTimeout, setSearchHardTimeoutMs } from "./providers/utils";
|
|
115
117
|
export type { SearchProviderId as SearchProvider, SearchResponse } from "./types";
|
|
116
118
|
export { isConfigurableSearchProviderId, isSearchProviderPreference } from "./types";
|
|
@@ -6,8 +6,17 @@ export { SearchProvider } from "./providers/base";
|
|
|
6
6
|
export declare function getSearchProviderLabel(id: SearchProviderId): string;
|
|
7
7
|
export declare function getSearchProvider(id: SearchProviderId): Promise<SearchProvider>;
|
|
8
8
|
export declare const SEARCH_PROVIDER_ORDER: SearchProviderId[];
|
|
9
|
+
/** Drop every cached resolved chain (settings changed, tests). */
|
|
10
|
+
export declare function clearResolvedChainCache(): void;
|
|
9
11
|
export declare function setPreferredSearchProvider(provider: SearchProviderId | "auto"): void;
|
|
10
12
|
export declare function setSearchFallbackProviders(ids: readonly string[]): void;
|
|
13
|
+
/**
|
|
14
|
+
* Fire-and-forget warm-up: resolve the provider chain once so the provider
|
|
15
|
+
* modules are imported and the chain cache is primed before the first
|
|
16
|
+
* user-visible search. Errors are intentionally swallowed — prewarming must
|
|
17
|
+
* never surface a failure the real search path would handle itself.
|
|
18
|
+
*/
|
|
19
|
+
export declare function prewarmSearchProviders(options: ResolveProviderChainOptions): void;
|
|
11
20
|
export interface SearchProviderPreferenceSource {
|
|
12
21
|
get(path: "providers.webSearch" | "web_search.provider"): SearchProviderId | "auto";
|
|
13
22
|
has(path: "providers.webSearch" | "web_search.provider"): boolean;
|
|
@@ -15,27 +15,53 @@ import { SearchProviderError, type SearchProviderId, type SearchSource } from ".
|
|
|
15
15
|
*/
|
|
16
16
|
export declare function findCredential(storage: AgentStorage | null | undefined, envKey: string | null | undefined, ...storageProviders: string[]): string | null;
|
|
17
17
|
/**
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
* Pure search APIs (brave, exa, jina, tavily, searxng, synthetic, zai)
|
|
24
|
-
* settle far faster in practice; reusing the same ceiling keeps the wiring
|
|
25
|
-
* uniform without compromising correctness.
|
|
18
|
+
* Legacy hard ceiling for a single web-search round-trip, retained as the
|
|
19
|
+
* fallback for call sites that do not declare a timeout class. 300s tolerates
|
|
20
|
+
* pathological cases while still guaranteeing the session unfreezes if Bun's
|
|
21
|
+
* `AbortSignal` fails to propagate on Windows.
|
|
26
22
|
*/
|
|
27
23
|
export declare const SEARCH_HARD_TIMEOUT_MS = 300000;
|
|
24
|
+
/**
|
|
25
|
+
* Hard ceiling for pure search APIs (brave, exa, jina, tavily, kagi,
|
|
26
|
+
* parallel, searxng, synthetic, zai, duckduckgo). These settle in ~1-3s in
|
|
27
|
+
* practice; a hung TCP/TLS connection should fall through to the next
|
|
28
|
+
* provider in seconds, not minutes. Kimi is the exception: it declares an
|
|
29
|
+
* explicit ceiling aligned with its upstream 30s request budget.
|
|
30
|
+
*/
|
|
31
|
+
export declare const SEARCH_API_TIMEOUT_MS = 15000;
|
|
32
|
+
/**
|
|
33
|
+
* Hard ceiling for LLM-mediated search providers (anthropic, codex, gemini,
|
|
34
|
+
* perplexity, xai, openai-compatible). These legitimately take tens of
|
|
35
|
+
* seconds because a model performs the search and synthesizes an answer.
|
|
36
|
+
*/
|
|
37
|
+
export declare const SEARCH_LLM_TIMEOUT_MS = 120000;
|
|
38
|
+
/** Timeout class a provider declares for its outbound round-trips. */
|
|
39
|
+
export type SearchTimeoutClass = "api" | "llm";
|
|
28
40
|
/**
|
|
29
41
|
* Override the hard timeout applied to every web-search round-trip.
|
|
30
42
|
*
|
|
31
43
|
* @param ms - Hard timeout in milliseconds. Non-finite or non-positive
|
|
32
|
-
* values
|
|
44
|
+
* values clear the override so per-class defaults apply.
|
|
33
45
|
*/
|
|
34
46
|
export declare function setSearchHardTimeoutMs(ms: number | undefined): void;
|
|
47
|
+
/** Structural settings source for {@link applyConfiguredSearchTimeout}. */
|
|
48
|
+
export interface SearchTimeoutSettingSource {
|
|
49
|
+
get(path: "web_search.timeout"): unknown;
|
|
50
|
+
has(path: "web_search.timeout"): boolean;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Install the `web_search.timeout` override from settings — but only when the
|
|
54
|
+
* user explicitly configured it. The settings schema ships a default value
|
|
55
|
+
* (300), and consuming that default via `get()` alone would reinstall a
|
|
56
|
+
* uniform 300s ceiling on every session, silently disabling the per-class
|
|
57
|
+
* timeout defaults. `has()` distinguishes loaded/overridden settings from
|
|
58
|
+
* schema defaults; unset clears any previous override so class defaults apply.
|
|
59
|
+
*/
|
|
60
|
+
export declare function applyConfiguredSearchTimeout(settings: SearchTimeoutSettingSource): void;
|
|
35
61
|
/**
|
|
36
62
|
* Compose a caller-supplied {@link AbortSignal} with a hard timeout so an
|
|
37
|
-
* outbound `fetch()` is guaranteed to settle
|
|
38
|
-
*
|
|
63
|
+
* outbound `fetch()` is guaranteed to settle even when the runtime fails to
|
|
64
|
+
* propagate cancellation to the underlying transport.
|
|
39
65
|
*
|
|
40
66
|
* Bun's WinHTTP backend on Windows is known to ignore `AbortSignal` once a
|
|
41
67
|
* TCP/TLS connection stalls (oven-sh/bun#15275, oven-sh/bun#18536); without
|
|
@@ -43,9 +69,12 @@ export declare function setSearchHardTimeoutMs(ms: number | undefined): void;
|
|
|
43
69
|
* because the user's Esc is never delivered to the native layer.
|
|
44
70
|
*
|
|
45
71
|
* @param signal - Caller cancellation signal, if any.
|
|
46
|
-
* @param
|
|
72
|
+
* @param msOrClass - Explicit timeout in milliseconds, or a
|
|
73
|
+
* {@link SearchTimeoutClass} resolved to its class default. Omitted falls
|
|
74
|
+
* back to the legacy {@link SEARCH_HARD_TIMEOUT_MS} ceiling. A user-set
|
|
75
|
+
* `web_search.timeout` overrides class defaults (but not explicit ms).
|
|
47
76
|
*/
|
|
48
|
-
export declare function withHardTimeout(signal: AbortSignal | undefined,
|
|
77
|
+
export declare function withHardTimeout(signal: AbortSignal | undefined, msOrClass?: number | SearchTimeoutClass): AbortSignal;
|
|
49
78
|
/**
|
|
50
79
|
* Map a provider's raw source list to the unified SearchSource shape,
|
|
51
80
|
* clamped to the requested result count and annotated with ageSeconds.
|
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.
|
|
4
|
+
"version": "0.7.11",
|
|
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.
|
|
56
|
-
"@gajae-code/agent-core": "0.7.
|
|
57
|
-
"@gajae-code/ai": "0.7.
|
|
58
|
-
"@gajae-code/natives": "0.7.
|
|
59
|
-
"@gajae-code/tui": "0.7.
|
|
60
|
-
"@gajae-code/utils": "0.7.
|
|
55
|
+
"@gajae-code/stats": "0.7.11",
|
|
56
|
+
"@gajae-code/agent-core": "0.7.11",
|
|
57
|
+
"@gajae-code/ai": "0.7.11",
|
|
58
|
+
"@gajae-code/natives": "0.7.11",
|
|
59
|
+
"@gajae-code/tui": "0.7.11",
|
|
60
|
+
"@gajae-code/utils": "0.7.11",
|
|
61
61
|
"@puppeteer/browsers": "^2.13.0",
|
|
62
62
|
"@types/turndown": "5.0.6",
|
|
63
63
|
"@xterm/headless": "^6.0.0",
|
package/src/cli/update-cli.ts
CHANGED
|
@@ -10,6 +10,7 @@ import { pipeline } from "node:stream/promises";
|
|
|
10
10
|
import { $which, APP_NAME, isEnoent, VERSION } from "@gajae-code/utils";
|
|
11
11
|
import { $ } from "bun";
|
|
12
12
|
import chalk from "chalk";
|
|
13
|
+
import { installDefaultGjcDefinitions } from "../defaults/gjc-defaults";
|
|
13
14
|
import { theme } from "../modes/theme/theme";
|
|
14
15
|
|
|
15
16
|
const RELEASE_REPO = "Yeachan-Heo/gajae-code";
|
|
@@ -628,6 +629,29 @@ export async function runUpdateCommand(opts: { force: boolean; check: boolean })
|
|
|
628
629
|
console.error(chalk.red(`Update failed: ${err}`));
|
|
629
630
|
process.exit(1);
|
|
630
631
|
}
|
|
632
|
+
|
|
633
|
+
await refreshInstalledDefaultSkills();
|
|
634
|
+
}
|
|
635
|
+
|
|
636
|
+
/**
|
|
637
|
+
* Refresh opted-in on-disk default workflow skill copies after a successful
|
|
638
|
+
* update. The four default skills ship embedded in the binary, so most users
|
|
639
|
+
* need nothing here. But users who ran `gjc setup defaults` have on-disk copies
|
|
640
|
+
* under the agent dir that shadow the embedded defaults; those would otherwise
|
|
641
|
+
* go stale after an update. Only rewrite files that already exist and differ —
|
|
642
|
+
* never materialize new copies for users who never opted in.
|
|
643
|
+
*/
|
|
644
|
+
async function refreshInstalledDefaultSkills(): Promise<void> {
|
|
645
|
+
try {
|
|
646
|
+
const result = await installDefaultGjcDefinitions({ refreshOnly: true });
|
|
647
|
+
if (result.written > 0) {
|
|
648
|
+
console.log(
|
|
649
|
+
chalk.dim(`Refreshed ${result.written} local default workflow skill file(s) at ${result.targetRoot}`),
|
|
650
|
+
);
|
|
651
|
+
}
|
|
652
|
+
} catch (err) {
|
|
653
|
+
console.error(chalk.yellow(`Warning: failed to refresh local default workflow skills: ${err}`));
|
|
654
|
+
}
|
|
631
655
|
}
|
|
632
656
|
|
|
633
657
|
/**
|
|
@@ -16,7 +16,7 @@ import {
|
|
|
16
16
|
type SearchQueryParams,
|
|
17
17
|
} from "../web/search/index";
|
|
18
18
|
import { SEARCH_PROVIDER_ORDER, setPreferredSearchProvider, setSearchFallbackProviders } from "../web/search/provider";
|
|
19
|
-
import {
|
|
19
|
+
import { applyConfiguredSearchTimeout } from "../web/search/providers/utils";
|
|
20
20
|
import { renderSearchResult } from "../web/search/render";
|
|
21
21
|
import type { SearchProviderId } from "../web/search/types";
|
|
22
22
|
|
|
@@ -181,10 +181,7 @@ export async function runSearchCommand(cmd: SearchCommandArgs): Promise<void> {
|
|
|
181
181
|
configuredFallback.filter(value => typeof value === "string" && isConfigurableSearchProviderId(value)),
|
|
182
182
|
);
|
|
183
183
|
}
|
|
184
|
-
|
|
185
|
-
if (typeof configuredTimeout === "number" && Number.isFinite(configuredTimeout) && configuredTimeout > 0) {
|
|
186
|
-
setSearchHardTimeoutMs(configuredTimeout * 1000);
|
|
187
|
-
}
|
|
184
|
+
applyConfiguredSearchTimeout(settings);
|
|
188
185
|
|
|
189
186
|
const params: SearchQueryParams = {
|
|
190
187
|
query: cmd.query,
|
package/src/cli.ts
CHANGED
|
@@ -141,7 +141,7 @@ class RootHelpCommand extends Command {
|
|
|
141
141
|
resume: Flags.string({ char: "r", description: "Resume a session (by ID prefix, path, or picker if omitted)" }),
|
|
142
142
|
"session-dir": Flags.string({ description: "Directory for session storage and lookup" }),
|
|
143
143
|
"no-session": Flags.boolean({ description: "Don't save session (ephemeral)" }),
|
|
144
|
-
models: Flags.string({ description: "Comma-separated model patterns for
|
|
144
|
+
models: Flags.string({ description: "Comma-separated model patterns for Alt+N cycling" }),
|
|
145
145
|
"no-tools": Flags.boolean({ description: "Disable all built-in tools" }),
|
|
146
146
|
"no-lsp": Flags.boolean({ description: "Disable LSP tools, formatting, and diagnostics" }),
|
|
147
147
|
"no-pty": Flags.boolean({ description: "Disable PTY-based interactive bash execution" }),
|
package/src/commands/launch.ts
CHANGED
|
@@ -119,7 +119,7 @@ export default class Index extends Command {
|
|
|
119
119
|
description: "Don't save session (ephemeral)",
|
|
120
120
|
}),
|
|
121
121
|
models: Flags.string({
|
|
122
|
-
description: "Comma-separated model patterns for
|
|
122
|
+
description: "Comma-separated model patterns for Alt+N cycling",
|
|
123
123
|
}),
|
|
124
124
|
"no-tools": Flags.boolean({
|
|
125
125
|
description: "Disable all built-in tools",
|
package/src/commands/ralplan.ts
CHANGED
|
@@ -8,6 +8,7 @@ export default class Ralplan extends Command {
|
|
|
8
8
|
'$ gjc ralplan "<task description>"',
|
|
9
9
|
'$ gjc ralplan --interactive --deliberate "<task description>"',
|
|
10
10
|
'$ gjc ralplan --write --stage planner --stage_n 1 --artifact "<markdown or path>"',
|
|
11
|
+
"$ gjc ralplan --write --stage critic --stage_n 1 --artifact-env GJC_RALPLAN_ARTIFACT",
|
|
11
12
|
];
|
|
12
13
|
|
|
13
14
|
async run(): Promise<void> {
|