@gajae-code/coding-agent 0.7.8 → 0.7.9

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 (60) hide show
  1. package/CHANGELOG.md +18 -0
  2. package/README.md +6 -0
  3. package/dist/types/config/keybindings.d.ts +1 -1
  4. package/dist/types/config/model-profile-activation.d.ts +19 -2
  5. package/dist/types/config/model-profiles.d.ts +1 -0
  6. package/dist/types/config/model-registry.d.ts +4 -0
  7. package/dist/types/config/settings-schema.d.ts +2 -2
  8. package/dist/types/gjc-runtime/launch-tmux.d.ts +12 -3
  9. package/dist/types/gjc-runtime/ultragoal-guard.d.ts +3 -1
  10. package/dist/types/modes/components/hook-input.d.ts +1 -0
  11. package/dist/types/modes/components/model-selector.d.ts +9 -0
  12. package/dist/types/modes/components/status-line.d.ts +3 -0
  13. package/dist/types/modes/controllers/extension-ui-controller.d.ts +3 -1
  14. package/dist/types/modes/interactive-mode.d.ts +3 -1
  15. package/dist/types/modes/shared/agent-wire/deep-interview-gate.d.ts +21 -1
  16. package/dist/types/modes/types.d.ts +3 -1
  17. package/dist/types/notifications/daemon-paths.d.ts +9 -0
  18. package/dist/types/notifications/telegram-daemon-cli.d.ts +8 -2
  19. package/dist/types/notifications/telegram-daemon.d.ts +1 -10
  20. package/dist/types/tools/ask.d.ts +24 -0
  21. package/dist/types/tools/ultragoal-ask-guard.d.ts +9 -2
  22. package/package.json +7 -7
  23. package/src/cli/notify-cli.ts +1 -1
  24. package/src/cli.ts +1 -0
  25. package/src/config/keybindings.ts +1 -1
  26. package/src/config/model-profile-activation.ts +92 -11
  27. package/src/config/model-profiles.ts +15 -2
  28. package/src/config/model-registry.ts +81 -5
  29. package/src/config/settings-schema.ts +3 -2
  30. package/src/coordinator-mcp/server.ts +4 -2
  31. package/src/deep-interview/render-middleware.ts +1 -0
  32. package/src/defaults/gjc/skills/deep-interview/SKILL.md +14 -6
  33. package/src/defaults/gjc/skills/ralplan/SKILL.md +14 -7
  34. package/src/gjc-runtime/deep-interview-runtime.ts +1 -1
  35. package/src/gjc-runtime/launch-tmux.ts +303 -46
  36. package/src/gjc-runtime/team-runtime.ts +69 -4
  37. package/src/gjc-runtime/ultragoal-guard.ts +11 -5
  38. package/src/internal-urls/docs-index.generated.ts +6 -6
  39. package/src/modes/components/custom-model-preset-wizard.ts +2 -4
  40. package/src/modes/components/hook-editor.ts +7 -4
  41. package/src/modes/components/hook-input.ts +4 -0
  42. package/src/modes/components/model-selector.ts +84 -13
  43. package/src/modes/components/settings-selector.ts +36 -21
  44. package/src/modes/components/status-line/segments.ts +10 -2
  45. package/src/modes/components/status-line.ts +1 -0
  46. package/src/modes/controllers/extension-ui-controller.ts +2 -0
  47. package/src/modes/controllers/selector-controller.ts +130 -7
  48. package/src/modes/interactive-mode.ts +7 -2
  49. package/src/modes/shared/agent-wire/deep-interview-gate.ts +11 -4
  50. package/src/modes/types.ts +6 -1
  51. package/src/notifications/daemon-paths.ts +22 -0
  52. package/src/notifications/telegram-daemon-cli.ts +13 -4
  53. package/src/notifications/telegram-daemon.ts +2 -21
  54. package/src/prompts/system/system-prompt.md +5 -0
  55. package/src/sdk.ts +10 -1
  56. package/src/session/agent-session.ts +10 -1
  57. package/src/tools/ask.ts +11 -1
  58. package/src/tools/eval.ts +2 -2
  59. package/src/tools/render-utils.ts +2 -0
  60. package/src/tools/ultragoal-ask-guard.ts +39 -5
package/CHANGELOG.md CHANGED
@@ -2,6 +2,19 @@
2
2
 
3
3
  ## [Unreleased]
4
4
 
5
+ ## [0.7.9] - 2026-07-01
6
+ ### Added
7
+
8
+ - Added an optional Tavily web search provider selectable through `providers.webSearch`, using `TAVILY_API_KEY` only when Tavily is selected (#1323).
9
+
10
+ ### Fixed
11
+
12
+ - Deep Interview now treats English `implementation` and Korean `구현` wording as eventual-target language, not permission to edit code or launch implementation before post-interview approval (#1320).
13
+ - Restored default Enter = submit in the main chat composer. #1326 rerouted plain Enter in the prompt to insert a newline (making Ctrl+Enter the submit chord); this reverts that so Enter submits again and Shift+Enter inserts a newline.
14
+ - Registered the optional `gjc acp` subcommand so Zed/custom ACP clients can launch the ACP stdio server through the documented command entrypoint, and documented the Zed `agent_servers` custom-agent shape (#1327).
15
+ - Compiled binaries can now include the hidden Telegram daemon CLI entrypoint without hanging root startup, and release builds preserve that entry so `gjc notify daemon-internal --smoke` is available in standalone binaries (#1288).
16
+ - Documented Windows Terminal BEL limitations for terminal bell notifications and added a PowerShell `completion.notifyCommand` beep workaround example (#1318).
17
+
5
18
  ## [0.7.8] - 2026-06-30
6
19
  ### Added
7
20
 
@@ -11,10 +24,15 @@
11
24
 
12
25
  ### Fixed
13
26
 
27
+ - Fixed a class of TUI renderer crashes (`TypeError: undefined is not an object (evaluating 'x.trim'/'x.split')`) where render helpers typed `(x: string)` ran a string op on an optional/possibly-undefined tool-detail field. The deep-interview/ralplan `ask` renderer crashed on a result with a missing `question`; caught during streaming but fatal on render/teardown paths such as `/background` detach. Hardened `normalizeText`, `getPreviewLines`, `shortenPath`, and the eval git_log status-event renderer (#1290).
28
+
14
29
  - `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).
30
+ - Deep Interview now prefers the native hook's pre-resolved ambiguity threshold state and avoids surfacing missing optional settings files as failed `Read` calls during Phase 0.
31
+ - Scoped Ultragoal ask-guard checks for `deep-interview` and `ralplan` asks to the current session, so stale or ambiguous Ultragoal state from other sessions no longer suppresses the choice UI while same-session active Ultragoal blockers still apply.
15
32
  - 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
33
  - 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
34
  - 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.
35
+ - `gjc --tmux` now prefixes the root terminal title (`GJC: tmp`) and managed tmux window names (`GJC-tmp`) with a GJC workspace label so terminal multiplexers and workspace switchers do not fall back to noisy launch paths.
18
36
 
19
37
  ## [0.7.7] - 2026-06-28
20
38
  ### Added
package/README.md CHANGED
@@ -24,6 +24,12 @@ 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
+ 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:
28
+
29
+ ```powershell
30
+ gjc config set completion.notifyCommand 'powershell.exe -NoProfile -Command "[Console]::Beep(880, 300)"'
31
+ ```
32
+
27
33
  `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
34
 
29
35
  Recommended external mapping:
@@ -231,7 +231,7 @@ export declare const KEYBINDINGS: {
231
231
  };
232
232
  readonly "app.message.followUp": {
233
233
  readonly defaultKeys: [];
234
- readonly description: "Send follow-up message (no default; Ctrl+Enter inserts a newline)";
234
+ readonly description: "Send follow-up message (no default; Ctrl+Enter submits)";
235
235
  };
236
236
  readonly "app.message.queue": {
237
237
  readonly defaultKeys: "alt+enter";
@@ -21,7 +21,7 @@ export interface PreparedModelProfileActivation {
21
21
  session: ModelProfileActivationSession & {
22
22
  setModelTemporary: AgentSession["setModelTemporary"];
23
23
  };
24
- settings: Pick<Settings, "get" | "override" | "set" | "flush">;
24
+ settings: Pick<Settings, "clearOverride" | "get" | "getGlobal" | "override" | "set" | "flush">;
25
25
  previousModel: Model<Api> | undefined;
26
26
  previousThinkingLevel: ThinkingLevel | undefined;
27
27
  previousAgentModelOverrides: Record<string, string>;
@@ -47,11 +47,28 @@ export interface MaterializeModelProfileAssignmentOptions {
47
47
  selector: string;
48
48
  }
49
49
  export declare function materializeActiveModelProfileAssignment(options: MaterializeModelProfileAssignmentOptions): boolean;
50
- export declare function formatModelProfileCredentialError(profileName: string, providers: readonly string[]): string;
50
+ export declare function formatModelProfileCredentialError(profileLabel: string, providers: readonly string[]): string;
51
51
  export declare function prepareModelProfileActivation(options: PrepareModelProfileActivationOptions): Promise<PreparedModelProfileActivation>;
52
52
  export declare function applyPreparedModelProfileActivation(prepared: PreparedModelProfileActivation, options?: {
53
53
  persistDefault?: boolean;
54
54
  }): Promise<void>;
55
+ export interface MaterializeModelProfileForDeletionResult {
56
+ modelRoles: Record<string, string>;
57
+ agentModelOverrides: Record<string, string>;
58
+ previousModelRoles: Record<string, string>;
59
+ previousAgentModelOverrides: Record<string, string>;
60
+ previousDefaultProfile: string | undefined;
61
+ previousPersistedDefaultProfile: string | undefined;
62
+ previousActiveModelProfile: string | undefined;
63
+ }
64
+ export declare function materializeModelProfileForDeletion(options: PrepareModelProfileActivationOptions & {
65
+ settings: Pick<Settings, "clearOverride" | "flush" | "get" | "getGlobal" | "override" | "set">;
66
+ }): Promise<MaterializeModelProfileForDeletionResult>;
67
+ export declare function restoreMaterializedModelProfileForDeletion(options: {
68
+ settings: Pick<Settings, "flush" | "override" | "set">;
69
+ session: Pick<ModelProfileActivationSession, "setActiveModelProfile">;
70
+ snapshot: MaterializeModelProfileForDeletionResult;
71
+ }): Promise<void>;
55
72
  export declare function activateModelProfile(options: PrepareModelProfileActivationOptions, applyOptions?: {
56
73
  persistDefault?: boolean;
57
74
  }): Promise<void>;
@@ -31,6 +31,7 @@ export interface ModelProfilePresentation {
31
31
  providerGroup: string;
32
32
  }
33
33
  export declare function getModelProfilePresentation(profile: string | Pick<ModelProfileDefinition, "name" | "displayName">): ModelProfilePresentation;
34
+ export declare function formatModelProfileDisplayLabel(profile: Pick<ModelProfileDefinition, "name" | "displayName">): string;
34
35
  export declare function groupModelProfilesForPresetLanding(profiles: ReadonlyMap<string, ModelProfileDefinition>): Map<string, ModelProfileDefinition[]>;
35
36
  export declare function recommendModelProfileForProvider(providerId: string, profiles: ReadonlyMap<string, ModelProfileDefinition>): ModelProfileDefinition | undefined;
36
37
  export declare function mergeModelProfiles(userProfiles?: ModelsConfig["profiles"]): Map<string, ModelProfileDefinition>;
@@ -19,6 +19,8 @@ export interface ModelRoleInfo {
19
19
  }
20
20
  export declare const MODEL_ROLES: Record<ModelRole, ModelRoleInfo>;
21
21
  export declare const MODEL_ROLE_IDS: ModelRole[];
22
+ export declare const MODEL_PROFILE_NAME_PATTERN: RegExp;
23
+ export declare const MODEL_PROFILE_NAME_PATTERN_DESCRIPTION = "lowercase letters, numbers, dots, underscores, or hyphens";
22
24
  export type GjcModelAssignmentTargetId = "default" | "executor" | "architect" | "planner" | "critic";
23
25
  export interface GjcModelAssignmentTargetInfo extends ModelRoleInfo {
24
26
  id: GjcModelAssignmentTargetId;
@@ -342,6 +344,8 @@ export declare class ModelRegistry {
342
344
  getModelProfile(name: string): ModelProfileDefinition | undefined;
343
345
  getAvailableModelProfileNames(): string[];
344
346
  saveCustomModelProfile(name: string, definition: ModelProfileConfig): Promise<ModelProfileDefinition>;
347
+ renameCustomModelProfile(name: string, displayName: string): Promise<ModelProfileDefinition>;
348
+ deleteCustomModelProfile(name: string): Promise<ModelProfileConfig>;
345
349
  applyConfiguredModelBindings(targetSettings: Settings): void;
346
350
  /**
347
351
  * Get all models (built-in + custom).
@@ -166,7 +166,7 @@ export declare const SETTINGS_SCHEMA: {
166
166
  readonly ui: {
167
167
  readonly tab: "interaction";
168
168
  readonly label: "Terminal Bell";
169
- readonly description: "Emit a BEL character for local terminal notifications";
169
+ readonly description: "Emit a BEL character for local terminal notifications. Windows Terminal may keep BEL silent depending on profile/system sound settings; use completion.notifyCommand for a PowerShell Console.Beep workaround.";
170
170
  };
171
171
  };
172
172
  readonly "notifications.bellOnComplete": {
@@ -1343,7 +1343,7 @@ export declare const SETTINGS_SCHEMA: {
1343
1343
  readonly ui: {
1344
1344
  readonly tab: "interaction";
1345
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.";
1346
+ readonly description: "Optional user-level shell command to run when an agent turn completes; receives GJC_NOTIFICATION_* environment variables. On Windows, this can call PowerShell [Console]::Beep when terminal BEL is silent.";
1347
1347
  };
1348
1348
  };
1349
1349
  readonly "ask.timeout": {
@@ -35,9 +35,18 @@ export type TmuxSpawnSync = (command: string, args: string[], options: TmuxSpawn
35
35
  export interface TmuxSpawnOptions {
36
36
  cwd: string;
37
37
  env: NodeJS.ProcessEnv;
38
- stdin: "inherit";
39
- stdout: "inherit";
40
- stderr: "inherit";
38
+ stdin: "inherit" | "pipe";
39
+ stdout: "inherit" | "pipe";
40
+ stderr: "inherit" | "pipe";
41
+ /**
42
+ * When true, the spawn captures stderr into a buffer and forwards it to
43
+ * the parent stderr so the user still sees the live output. The captured
44
+ * text is also returned in TmuxSpawnResult.stderr for diagnostic
45
+ * surfacing in "attach failed" / "profile tagging failed" messages.
46
+ * Defaults to false to preserve the previous PTY-binding behavior for
47
+ * attach-session and other interactive commands.
48
+ */
49
+ captureStderr?: boolean;
41
50
  }
42
51
  export interface TmuxLaunchPlan {
43
52
  tmuxCommand: string;
@@ -29,7 +29,9 @@ export declare function readUltragoalVerificationState(input: {
29
29
  currentGoal?: CurrentGoalLike | null;
30
30
  sessionId?: string | null;
31
31
  }): Promise<UltragoalGuardDiagnostic>;
32
- export declare function isUltragoalAskBlocked(cwd: string): Promise<UltragoalAskBlockDiagnostic>;
32
+ export declare function isUltragoalAskBlocked(cwd: string, options?: {
33
+ sessionId?: string | null;
34
+ }): Promise<UltragoalAskBlockDiagnostic>;
33
35
  /**
34
36
  * Escalating per-attempt refusal text. Deliberately avoids every
35
37
  * `isUltragoalBypassPrompt` trigger: no `update_goal(`, no "skip/weaken verification",
@@ -3,6 +3,7 @@
3
3
  */
4
4
  import { Container, type TUI } from "@gajae-code/tui";
5
5
  export interface HookInputOptions {
6
+ initialValue?: string;
6
7
  tui?: TUI;
7
8
  timeout?: number;
8
9
  onTimeout?: () => void;
@@ -19,6 +19,12 @@ export type ModelSelectorSelection = {
19
19
  } | {
20
20
  kind: "createProfile";
21
21
  profile: ModelProfileConfig;
22
+ } | {
23
+ kind: "renameProfile";
24
+ profileName: string;
25
+ } | {
26
+ kind: "deleteProfile";
27
+ profileName: string;
22
28
  };
23
29
  type RoleSelectCallback = (selection: ModelSelectorSelection) => void | Promise<void>;
24
30
  /**
@@ -47,7 +53,10 @@ export declare class ModelSelectorComponent extends Container {
47
53
  activeModelProfile?: string;
48
54
  }): void;
49
55
  handleInput(keyData: string): void;
56
+ refreshPresetProfiles(profileName?: string): void;
50
57
  getSearchInput(): Input;
51
58
  __testSelectProfile(profileName: string, setDefault: boolean): Promise<void>;
59
+ __testSelectPresetAction(profileName: string, action: "rename" | "delete"): Promise<void>;
60
+ __testSelectedPresetRowIdentity(): string | undefined;
52
61
  }
53
62
  export {};
@@ -22,6 +22,9 @@ export interface StatusLineSegmentOptions {
22
22
  format?: "12h" | "24h";
23
23
  showSeconds?: boolean;
24
24
  };
25
+ usage?: {
26
+ mode?: "used" | "remaining";
27
+ };
25
28
  }
26
29
  export interface StatusLineSettings {
27
30
  preset?: StatusLinePreset;
@@ -41,7 +41,9 @@ export declare class ExtensionUiController {
41
41
  /**
42
42
  * Show a text input for hooks.
43
43
  */
44
- showHookInput(title: string, placeholder?: string, dialogOptions?: ExtensionUIDialogOptions): Promise<string | undefined>;
44
+ showHookInput(title: string, placeholder?: string, dialogOptions?: ExtensionUIDialogOptions, inputOptions?: {
45
+ readonly initialValue?: string;
46
+ }): Promise<string | undefined>;
45
47
  /**
46
48
  * Hide the hook input.
47
49
  */
@@ -250,7 +250,9 @@ export declare class InteractiveMode implements InteractiveModeContext {
250
250
  setHookStatus(key: string, text: string | undefined): void;
251
251
  showHookSelector(title: string, options: string[], dialogOptions?: ExtensionUIDialogOptions): Promise<string | undefined>;
252
252
  hideHookSelector(): void;
253
- showHookInput(title: string, placeholder?: string): Promise<string | undefined>;
253
+ showHookInput(title: string, placeholder?: string, dialogOptions?: ExtensionUIDialogOptions, inputOptions?: {
254
+ readonly initialValue?: string;
255
+ }): Promise<string | undefined>;
254
256
  hideHookInput(): void;
255
257
  showHookEditor(title: string, prefill?: string, dialogOptions?: ExtensionUIDialogOptions, editorOptions?: {
256
258
  promptStyle?: boolean;
@@ -1,3 +1,17 @@
1
+ /**
2
+ * Deep-interview gate mapping (#316).
3
+ *
4
+ * Converts deep-interview `ask`-tool questions into machine-addressable
5
+ * `workflow_gate` { kind: "question" } events (option set + free-text shape
6
+ * encoded in `schema`/`options`) and decodes a `workflow_gate_response` answer
7
+ * back into the exact QuestionResult shape the human path produces, so ambiguity
8
+ * scoring/state updates proceed identically whether a human or an agent answers.
9
+ *
10
+ * This is the pure mapping primitive. Routing the ask tool through it (instead of
11
+ * the interactive select/editor UI) when an unattended controller + gate broker
12
+ * are attached is wired with the transport in #321 and exercised by #323.
13
+ */
14
+ import type { RpcWorkflowGateKind, RpcWorkflowStage } from "../../rpc/rpc-types";
1
15
  import type { OpenGateInput } from "./workflow-gate-broker";
2
16
  /** "Other (type your own)" sentinel, mirroring the interactive ask tool. */
3
17
  export declare const GATE_OTHER_OPTION = "Other (type your own)";
@@ -9,6 +23,10 @@ export interface AskGateDeepInterviewState {
9
23
  dimension: string;
10
24
  ambiguity: number;
11
25
  }
26
+ export interface AskGateWorkflowGateMeta {
27
+ stage: RpcWorkflowStage;
28
+ kind: RpcWorkflowGateKind;
29
+ }
12
30
  export interface AskGateQuestion {
13
31
  id: string;
14
32
  question: string;
@@ -22,6 +40,8 @@ export interface AskGateQuestion {
22
40
  * `stage_state`; when absent, the question text is regex-parsed as a fallback.
23
41
  */
24
42
  deepInterview?: AskGateDeepInterviewState;
43
+ /** Override the emitted workflow gate address for non-deep-interview ask prompts. */
44
+ workflowGate?: AskGateWorkflowGateMeta;
25
45
  }
26
46
  export interface AskGateResult {
27
47
  id: string;
@@ -47,7 +67,7 @@ export declare class DeepInterviewGateError extends Error {
47
67
  readonly code: "invalid_answer_shape" | "unknown_option" | "multi_not_allowed" | "missing_custom" | "empty_selection" | "duplicate_selection";
48
68
  constructor(code: "invalid_answer_shape" | "unknown_option" | "multi_not_allowed" | "missing_custom" | "empty_selection" | "duplicate_selection", message: string);
49
69
  }
50
- /** Build the `workflow_gate` open-input for one deep-interview question. */
70
+ /** Build the `workflow_gate` open-input for one ask question. */
51
71
  export declare function questionToGate(question: AskGateQuestion): OpenGateInput;
52
72
  /**
53
73
  * Decode a gate answer into the QuestionResult the interactive path produces.
@@ -260,7 +260,9 @@ export interface InteractiveModeContext {
260
260
  setHookStatus(key: string, text: string | undefined): void;
261
261
  showHookSelector(title: string, options: string[], dialogOptions?: ExtensionUIDialogOptions): Promise<string | undefined>;
262
262
  hideHookSelector(): void;
263
- showHookInput(title: string, placeholder?: string): Promise<string | undefined>;
263
+ showHookInput(title: string, placeholder?: string, dialogOptions?: ExtensionUIDialogOptions, inputOptions?: {
264
+ readonly initialValue?: string;
265
+ }): Promise<string | undefined>;
264
266
  hideHookInput(): void;
265
267
  showHookEditor(title: string, prefill?: string, dialogOptions?: ExtensionUIDialogOptions, editorOptions?: {
266
268
  promptStyle?: boolean;
@@ -0,0 +1,9 @@
1
+ export interface DaemonPaths {
2
+ dir: string;
3
+ lock: string;
4
+ state: string;
5
+ roots: string;
6
+ steal: string;
7
+ aliases: string;
8
+ }
9
+ export declare function daemonPaths(agentDir: string): DaemonPaths;
@@ -1,12 +1,17 @@
1
1
  import type { Settings } from "../config/settings";
2
- import { TelegramNotificationDaemon } from "./telegram-daemon";
2
+ import type { TelegramDaemonOptions } from "./telegram-daemon";
3
+ type TelegramDaemonRunner = {
4
+ run(): Promise<void>;
5
+ requestStop(reason?: "reload" | "signal" | "stop"): void;
6
+ };
7
+ type TelegramDaemonConstructor = new (opts: TelegramDaemonOptions) => TelegramDaemonRunner;
3
8
  export interface RunDaemonInternalDeps {
4
9
  SettingsImpl?: {
5
10
  init: (options?: {
6
11
  agentDir?: string;
7
12
  }) => Promise<Pick<Settings, "get" | "getAgentDir">>;
8
13
  };
9
- DaemonImpl?: typeof TelegramNotificationDaemon;
14
+ DaemonImpl?: TelegramDaemonConstructor;
10
15
  processPid?: number;
11
16
  pidAlive?: (pid: number) => boolean;
12
17
  }
@@ -20,3 +25,4 @@ export declare function runDaemonSmoke(opts?: {
20
25
  agentDir?: string;
21
26
  }): Promise<void>;
22
27
  export declare function runDaemonInternal(argv: string[], deps?: RunDaemonInternalDeps): Promise<void>;
28
+ export {};
@@ -16,14 +16,6 @@ export interface DaemonState {
16
16
  version: 1;
17
17
  stoppedAt?: number;
18
18
  }
19
- export interface DaemonPaths {
20
- dir: string;
21
- lock: string;
22
- state: string;
23
- roots: string;
24
- steal: string;
25
- aliases: string;
26
- }
27
19
  export interface TelegramDaemonFs {
28
20
  mkdir(path: string, opts?: fs.MakeDirectoryOptions): Promise<void>;
29
21
  readFile(path: string, encoding: BufferEncoding): Promise<string>;
@@ -59,7 +51,7 @@ export declare const DAEMON_VERSION = 1;
59
51
  export declare const CLIENT_PING_PONG_CAPABILITY = "client_ping_pong";
60
52
  /** Protocol version the daemon advertises in its ClientHello. */
61
53
  export declare const NOTIFICATION_PROTOCOL_VERSION = 2;
62
- export declare function daemonPaths(agentDir: string): DaemonPaths;
54
+ export { type DaemonPaths, daemonPaths } from "./daemon-paths";
63
55
  /**
64
56
  * Attach session-lifecycle control (create/close/resume) to the running daemon.
65
57
  *
@@ -390,4 +382,3 @@ export declare class TelegramNotificationDaemon {
390
382
  run(): Promise<void>;
391
383
  private controlStopRequested;
392
384
  }
393
- export {};
@@ -36,6 +36,18 @@ export declare const askSchema: z.ZodObject<{
36
36
  dimension: z.ZodString;
37
37
  ambiguity: z.ZodNumber;
38
38
  }, z.core.$strip>>;
39
+ workflowGate: z.ZodOptional<z.ZodObject<{
40
+ stage: z.ZodEnum<{
41
+ "deep-interview": "deep-interview";
42
+ ralplan: "ralplan";
43
+ ultragoal: "ultragoal";
44
+ }>;
45
+ kind: z.ZodEnum<{
46
+ approval: "approval";
47
+ execution: "execution";
48
+ question: "question";
49
+ }>;
50
+ }, z.core.$strip>>;
39
51
  }, z.core.$strip>>;
40
52
  }, z.core.$strip>;
41
53
  export type AskToolInput = z.infer<typeof askSchema>;
@@ -87,6 +99,18 @@ export declare class AskTool implements AgentTool<typeof askSchema, AskToolDetai
87
99
  dimension: z.ZodString;
88
100
  ambiguity: z.ZodNumber;
89
101
  }, z.core.$strip>>;
102
+ workflowGate: z.ZodOptional<z.ZodObject<{
103
+ stage: z.ZodEnum<{
104
+ "deep-interview": "deep-interview";
105
+ ralplan: "ralplan";
106
+ ultragoal: "ultragoal";
107
+ }>;
108
+ kind: z.ZodEnum<{
109
+ approval: "approval";
110
+ execution: "execution";
111
+ question: "question";
112
+ }>;
113
+ }, z.core.$strip>>;
90
114
  }, z.core.$strip>>;
91
115
  }, z.core.$strip>;
92
116
  readonly strict = true;
@@ -1,5 +1,12 @@
1
1
  import type { AgentTool } from "@gajae-code/agent-core";
2
2
  import { type UltragoalAskBlockDiagnostic } from "../gjc-runtime/ultragoal-guard";
3
+ export interface UltragoalAskGuardContext {
4
+ activeSkillState?: {
5
+ skill?: string;
6
+ session_id?: string;
7
+ } | null;
8
+ sessionId?: string | null;
9
+ }
3
10
  export declare function formatUltragoalAskBlockMessage(diagnostic: UltragoalAskBlockDiagnostic): string;
4
- export declare function assertUltragoalAskAllowed(cwd: string): Promise<void>;
5
- export declare function guardToolForUltragoalAsk<T extends AgentTool>(tool: T, getCwd: () => string): T;
11
+ export declare function assertUltragoalAskAllowed(cwd: string, context?: UltragoalAskGuardContext): Promise<void>;
12
+ export declare function guardToolForUltragoalAsk<T extends AgentTool>(tool: T, getCwd: () => string, getContext?: () => UltragoalAskGuardContext): T;
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.8",
4
+ "version": "0.7.9",
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.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",
55
+ "@gajae-code/stats": "0.7.9",
56
+ "@gajae-code/agent-core": "0.7.9",
57
+ "@gajae-code/ai": "0.7.9",
58
+ "@gajae-code/natives": "0.7.9",
59
+ "@gajae-code/tui": "0.7.9",
60
+ "@gajae-code/utils": "0.7.9",
61
61
  "@puppeteer/browsers": "^2.13.0",
62
62
  "@types/turndown": "5.0.6",
63
63
  "@xterm/headless": "^6.0.0",
@@ -4,7 +4,7 @@
4
4
  * Handles `gjc notify` setup/status and the hidden daemon entrypoint.
5
5
  */
6
6
  import { createInterface } from "node:readline/promises";
7
- import { APP_NAME } from "@gajae-code/utils";
7
+ import { APP_NAME } from "@gajae-code/utils/dirs";
8
8
  import chalk from "chalk";
9
9
  import type { Settings } from "../config/settings";
10
10
  import { getNotificationConfig, maskToken } from "../notifications/config";
package/src/cli.ts CHANGED
@@ -26,6 +26,7 @@ export const commands: CommandEntry[] = [
26
26
  { name: "codex-native-hook", load: () => import("./commands/codex-native-hook").then(m => m.default) },
27
27
  { name: "state", load: () => import("./commands/state").then(m => m.default) },
28
28
  { name: "setup", load: () => import("./commands/setup").then(m => m.default) },
29
+ { name: "acp", load: () => import("./commands/acp").then(m => m.default) },
29
30
  { name: "skills", load: () => import("./commands/skills").then(m => m.default) },
30
31
  { name: "session", load: () => import("./commands/session").then(m => m.default) },
31
32
  { name: "harness", load: () => import("./commands/harness").then(m => m.default) },
@@ -118,7 +118,7 @@ export const KEYBINDINGS = {
118
118
  },
119
119
  "app.message.followUp": {
120
120
  defaultKeys: [],
121
- description: "Send follow-up message (no default; Ctrl+Enter inserts a newline)",
121
+ description: "Send follow-up message (no default; Ctrl+Enter submits)",
122
122
  },
123
123
  "app.message.queue": {
124
124
  defaultKeys: "alt+enter",