@gajae-code/coding-agent 0.16.1 → 0.16.4

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 (146) hide show
  1. package/CHANGELOG.md +70 -0
  2. package/dist/types/cli/args.d.ts +2 -2
  3. package/dist/types/cli/root-flags.d.ts +4 -2
  4. package/dist/types/cli.d.ts +1 -1
  5. package/dist/types/commands/launch.d.ts +1 -1
  6. package/dist/types/config/autorouting-tier-map.d.ts +3 -0
  7. package/dist/types/config/model-registry.d.ts +4 -0
  8. package/dist/types/config/model-resolver.d.ts +9 -0
  9. package/dist/types/config/settings-schema.d.ts +29 -1
  10. package/dist/types/discovery/claude-plugins.d.ts +3 -1
  11. package/dist/types/discovery/helpers.d.ts +2 -0
  12. package/dist/types/extensibility/gjc-plugins/mcp-policy.d.ts +16 -0
  13. package/dist/types/extensibility/gjc-plugins/paths.d.ts +2 -0
  14. package/dist/types/extensibility/runtime-skill-discovery.d.ts +1 -1
  15. package/dist/types/extensibility/shared-events.d.ts +1 -1
  16. package/dist/types/gjc-runtime/session-state-lock.d.ts +2 -0
  17. package/dist/types/modes/components/assistant-message.d.ts +1 -2
  18. package/dist/types/modes/components/settings-selector.d.ts +6 -1
  19. package/dist/types/modes/components/status-line/command.d.ts +35 -0
  20. package/dist/types/modes/components/status-line/index.d.ts +1 -0
  21. package/dist/types/modes/components/status-line/types.d.ts +5 -0
  22. package/dist/types/modes/components/tool-status-header.d.ts +14 -0
  23. package/dist/types/modes/controllers/event-controller.d.ts +6 -0
  24. package/dist/types/modes/interactive-mode.d.ts +1 -0
  25. package/dist/types/modes/types.d.ts +1 -0
  26. package/dist/types/runtime-mcp/client.d.ts +9 -1
  27. package/dist/types/runtime-mcp/manager.d.ts +7 -1
  28. package/dist/types/runtime-mcp/pool.d.ts +22 -3
  29. package/dist/types/runtime-mcp/transports/stdio.d.ts +0 -4
  30. package/dist/types/runtime-mcp/types.d.ts +22 -0
  31. package/dist/types/sdk/bus/chat-daemon-runtime.d.ts +12 -0
  32. package/dist/types/sdk/bus/slack-live-provider.d.ts +6 -0
  33. package/dist/types/sdk/bus/slack-provider.d.ts +12 -0
  34. package/dist/types/sdk/cli/rows.d.ts +7 -0
  35. package/dist/types/sdk/host/events.d.ts +1 -0
  36. package/dist/types/sdk/host/host.d.ts +2 -0
  37. package/dist/types/sdk/host/session-runtime.d.ts +23 -0
  38. package/dist/types/sdk/session-api-key.d.ts +26 -0
  39. package/dist/types/sdk/transport/serve-cli.d.ts +1 -1
  40. package/dist/types/session/agent-session.d.ts +9 -0
  41. package/dist/types/setup/paseo/announce.d.ts +111 -0
  42. package/dist/types/setup/paseo/setup-deps.d.ts +2 -1
  43. package/dist/types/system-prompt.d.ts +2 -0
  44. package/dist/types/task/executor.d.ts +2 -1
  45. package/dist/types/tools/fetch.d.ts +7 -0
  46. package/dist/types/tools/index.d.ts +8 -2
  47. package/dist/types/tools/path-utils.d.ts +2 -0
  48. package/dist/types/tools/search.d.ts +6 -0
  49. package/dist/types/utils/external-editor.d.ts +5 -0
  50. package/package.json +7 -7
  51. package/scripts/capture-status-line-custom-editor-showcase.ts +151 -0
  52. package/scripts/generate-sdk-operation-inventory.ts +9 -0
  53. package/scripts/verify-status-line-custom-editor-showcase.ts +309 -0
  54. package/src/cli/args.ts +20 -9
  55. package/src/cli/root-flags.ts +5 -3
  56. package/src/config/autorouting-tier-map.ts +1 -0
  57. package/src/config/file-lock.ts +181 -17
  58. package/src/config/model-preset-registry.ts +5 -3
  59. package/src/config/model-profiles.ts +40 -0
  60. package/src/config/model-registry.ts +57 -11
  61. package/src/config/model-resolver.ts +48 -0
  62. package/src/config/settings-schema.ts +33 -1
  63. package/src/config/settings.ts +1 -0
  64. package/src/defaults/gjc/extensions/grok-cli-vendor/src/models/catalog.ts +11 -11
  65. package/src/defaults/gjc/extensions/grok-cli-vendor/src/provider/register.ts +13 -2
  66. package/src/discovery/builtin.ts +13 -4
  67. package/src/discovery/claude-plugins.ts +12 -4
  68. package/src/discovery/helpers.ts +10 -2
  69. package/src/extensibility/gjc-plugins/compiler.ts +208 -58
  70. package/src/extensibility/gjc-plugins/installer.ts +13 -12
  71. package/src/extensibility/gjc-plugins/mcp-policy.ts +81 -52
  72. package/src/extensibility/gjc-plugins/paths.ts +13 -0
  73. package/src/extensibility/gjc-plugins/runtime-adapters.ts +758 -16
  74. package/src/extensibility/runtime-skill-discovery.ts +77 -151
  75. package/src/extensibility/shared-events.ts +1 -1
  76. package/src/extensibility/skills.ts +44 -16
  77. package/src/gjc-runtime/repository-binding.ts +1 -1
  78. package/src/gjc-runtime/session-state-lock.ts +94 -6
  79. package/src/internal-urls/docs-index.generated.ts +10 -10
  80. package/src/main.ts +72 -34
  81. package/src/modes/DESIGN.md +54 -0
  82. package/src/modes/acp/acp-agent.ts +29 -14
  83. package/src/modes/components/assistant-message.ts +22 -9
  84. package/src/modes/components/model-selector.ts +166 -33
  85. package/src/modes/components/settings-selector.ts +1075 -235
  86. package/src/modes/components/status-line/command.ts +190 -0
  87. package/src/modes/components/status-line/index.ts +1 -0
  88. package/src/modes/components/status-line/segments.ts +32 -5
  89. package/src/modes/components/status-line/types.ts +5 -0
  90. package/src/modes/components/tool-status-header.ts +393 -21
  91. package/src/modes/controllers/command-controller.ts +2 -0
  92. package/src/modes/controllers/event-controller.ts +148 -5
  93. package/src/modes/controllers/selector-controller.ts +21 -0
  94. package/src/modes/interactive-mode.ts +47 -1
  95. package/src/modes/types.ts +1 -0
  96. package/src/modes/utils/ui-helpers.ts +1 -0
  97. package/src/prompts/system/system-prompt.md +8 -0
  98. package/src/prompts/tools/bash.md +1 -1
  99. package/src/prompts/tools/job.md +1 -1
  100. package/src/prompts/tools/search.md +2 -0
  101. package/src/runtime-mcp/client.ts +60 -17
  102. package/src/runtime-mcp/manager.ts +171 -14
  103. package/src/runtime-mcp/pool.test.ts +209 -0
  104. package/src/runtime-mcp/pool.ts +224 -23
  105. package/src/runtime-mcp/transports/stdio.ts +158 -24
  106. package/src/runtime-mcp/types.ts +24 -0
  107. package/src/sdk/acp/adapter.ts +1 -1
  108. package/src/sdk/broker/broker.ts +5 -4
  109. package/src/sdk/bus/chat-daemon-control.ts +1 -1
  110. package/src/sdk/bus/chat-daemon-runtime.ts +44 -1
  111. package/src/sdk/bus/slack-daemon.ts +92 -2
  112. package/src/sdk/bus/slack-live-provider.ts +12 -0
  113. package/src/sdk/bus/slack-provider.ts +5 -0
  114. package/src/sdk/cli/rows.ts +47 -2
  115. package/src/sdk/cli/session-cli.ts +47 -23
  116. package/src/sdk/host/events.ts +25 -2
  117. package/src/sdk/host/host.ts +4 -1
  118. package/src/sdk/host/session-runtime.test.ts +36 -25
  119. package/src/sdk/host/session-runtime.ts +279 -43
  120. package/src/sdk/protocol/operation-inventory.generated.json +66 -0
  121. package/src/sdk/router/session-router.ts +60 -37
  122. package/src/sdk/session-api-key.ts +94 -0
  123. package/src/sdk/session.ts +73 -30
  124. package/src/sdk/transport/serve-cli.ts +3 -3
  125. package/src/session/agent-session.ts +123 -38
  126. package/src/session/contribution-prep.ts +214 -21
  127. package/src/setup/paseo/announce.ts +450 -0
  128. package/src/setup/paseo/setup-deps.ts +15 -3
  129. package/src/slash-commands/builtin-registry.ts +1 -0
  130. package/src/system-prompt.ts +4 -0
  131. package/src/task/executor.ts +2 -1
  132. package/src/task/index.ts +17 -4
  133. package/src/tools/bash.ts +50 -21
  134. package/src/tools/cron.ts +1 -1
  135. package/src/tools/fetch.ts +29 -1
  136. package/src/tools/index.ts +8 -2
  137. package/src/tools/job.ts +8 -2
  138. package/src/tools/monitor.ts +8 -2
  139. package/src/tools/path-utils.ts +7 -0
  140. package/src/tools/search.ts +116 -58
  141. package/src/tools/skill.ts +22 -2
  142. package/src/tools/subagent.ts +3 -1
  143. package/src/tools/tool-catalog.generated.ts +9 -2
  144. package/src/utils/external-editor.ts +16 -2
  145. package/src/web/insane/bridge.ts +113 -23
  146. package/src/web/search/providers/perplexity.ts +102 -41
@@ -23,7 +23,3 @@ export declare class StdioTransport implements MCPTransport {
23
23
  notify(method: string, params?: Record<string, unknown>): Promise<void>;
24
24
  close(): Promise<void>;
25
25
  }
26
- /**
27
- * Create and connect a stdio transport.
28
- */
29
- export declare function createStdioTransport(config: MCPStdioServerConfig): Promise<StdioTransport>;
@@ -78,6 +78,20 @@ export interface MCPServerConfigBase {
78
78
  };
79
79
  }
80
80
  /** Stdio server configuration */
81
+ export interface MCPStdioSpawnLaunch {
82
+ command: string;
83
+ args: readonly string[];
84
+ cwd: string;
85
+ /** Transport-supplied registrar for retryable cleanup before preparation allocates resources. */
86
+ registerCleanup?: (cleanup: () => Promise<void>) => void;
87
+ }
88
+ export interface MCPStdioPreparedLaunch extends MCPStdioSpawnLaunch {
89
+ /**
90
+ * Per-attempt cleanup run after confirmed child exit or failed spawn. The same
91
+ * callback may already have been registered during preparation.
92
+ */
93
+ afterProcessExit?: () => Promise<void>;
94
+ }
81
95
  export interface MCPStdioServerConfig extends MCPServerConfigBase {
82
96
  type?: "stdio";
83
97
  command: string;
@@ -91,6 +105,14 @@ export interface MCPStdioServerConfig extends MCPServerConfigBase {
91
105
  */
92
106
  noInheritEnv?: boolean;
93
107
  cwd?: string;
108
+ /** Internal trusted-boundary preparation of immutable per-spawn authority. */
109
+ prepareSpawn?: (launch: MCPStdioSpawnLaunch) => Promise<MCPStdioPreparedLaunch>;
110
+ /** Internal trusted-boundary check run immediately before process creation. */
111
+ spawnGuard?: (launch: MCPStdioSpawnLaunch) => Promise<void>;
112
+ /** Internal cleanup run only after the owned stdio child is confirmed exited. */
113
+ afterProcessExit?: () => Promise<void>;
114
+ /** Test seam for deterministic mutation after the guard and before process creation. */
115
+ afterSpawnGuardForTest?: () => Promise<void>;
94
116
  }
95
117
  /** HTTP server configuration (Streamable HTTP transport) */
96
118
  export interface MCPHttpServerConfig extends MCPServerConfigBase {
@@ -36,6 +36,18 @@ export interface ChatDaemonRuntimeDeps {
36
36
  createSlackProvider?: (config: NonNullable<ChatDaemonRuntimeConfig["notifications"]["slack"]>) => SlackProviderClient;
37
37
  routerDeps?: SessionRouterDeps;
38
38
  }
39
+ /**
40
+ * Chat notifications in lean mode are an answer surface, not a mirror of the
41
+ * session protocol. Lifecycle, identity, and activity frames remain available
42
+ * to verbose consumers, while finalized answers and action-needed events are
43
+ * delivered in lean mode.
44
+ */
45
+ export declare function shouldPublishChatFrame(frame: Record<string, unknown>, verbosity: "lean" | "verbose" | undefined): boolean;
46
+ /**
47
+ * A final answer's message ref identifies its one rendered message even when
48
+ * the SDK transport delivers an unpositioned duplicate frame.
49
+ */
50
+ export declare function publicationIdForFinalChatAnswer(sessionId: string, frame: Record<string, unknown>): string | undefined;
39
51
  /**
40
52
  * Worker-owned session discovery and event fanout. It connects only through the
41
53
  * public SDK transport and retains SDK credentials solely in live client objects.
@@ -59,6 +59,12 @@ export declare class SlackLiveProvider implements SlackProviderClient, SlackDiag
59
59
  clientMsgId: string;
60
60
  signal?: AbortSignal;
61
61
  }): Promise<SlackPostedMessage>;
62
+ addReaction(input: {
63
+ channel: string;
64
+ timestamp: string;
65
+ name: string;
66
+ signal?: AbortSignal;
67
+ }): Promise<void>;
62
68
  findMessageByClientMsgId(input: {
63
69
  channel: string;
64
70
  clientMsgId: string;
@@ -52,6 +52,12 @@ export interface SlackProviderClient {
52
52
  threadTs?: string;
53
53
  signal?: AbortSignal;
54
54
  }): Promise<SlackMessageSearchResult | null>;
55
+ addReaction?(input: {
56
+ channel: string;
57
+ timestamp: string;
58
+ name: string;
59
+ signal?: AbortSignal;
60
+ }): Promise<void>;
55
61
  /**
56
62
  * Prove that an operator-supplied timestamp addresses a real message in the
57
63
  * requested channel. Adoption of an existing root is refused when a client
@@ -87,6 +93,12 @@ export declare class SlackProvider {
87
93
  threadTs?: string;
88
94
  signal?: AbortSignal;
89
95
  }): Promise<SlackMessageSearchResult | null>;
96
+ addReaction(input: {
97
+ channel: string;
98
+ timestamp: string;
99
+ name: string;
100
+ signal?: AbortSignal;
101
+ }): Promise<void>;
90
102
  /** Fail-closed root verification: a client without this capability can never confirm a root. */
91
103
  findMessageByTimestamp(input: {
92
104
  channel: string;
@@ -75,6 +75,13 @@ export interface SdkTailEnvelopeV1 {
75
75
  gap?: SdkRetentionGapV1;
76
76
  items: SdkTailItemV1[];
77
77
  }
78
+ export declare function tailItemKey(item: SdkTailItemV1): string;
79
+ /** Holds positioned live frames until the checkpoint can stamp their authoritative revision. */
80
+ export declare class TailRevisionBuffer {
81
+ #private;
82
+ push(item: SdkTailItemV1): SdkTailItemV1[];
83
+ resolve(revision: number): SdkTailItemV1[];
84
+ }
78
85
  /** Recursively removes secret-shaped fields (defense in depth for DTO output). */
79
86
  export declare function stripSecretFields(value: unknown): unknown;
80
87
  /**
@@ -26,6 +26,7 @@ export declare class SessionEventStream {
26
26
  generation?: number;
27
27
  ringSize?: number;
28
28
  resyncQueryIds?: string[];
29
+ revisionProvider?: () => number | undefined;
29
30
  });
30
31
  get generation(): number;
31
32
  get sequence(): number;
@@ -34,6 +34,8 @@ export type SessionActivationGate = (input: {
34
34
  export interface SessionSdkHostOptions extends HostEndpointAdapters {
35
35
  control?: (connectionId: string, frame: SdkFrame) => unknown | Promise<unknown>;
36
36
  query?: (connectionId: string, frame: SdkFrame) => unknown | Promise<unknown>;
37
+ /** Supplies the durable transcript revision stamped on ordinary emitted events. */
38
+ eventRevision?: () => number | undefined;
37
39
  /** Test/lifecycle seam invoked synchronously before fire-and-forget dispatch. */
38
40
  onFrameAdmitted?: (connectionId: string, frame: SdkFrame) => void;
39
41
  /** Synchronously rejects external input while a runtime is being replaced. */
@@ -1,5 +1,6 @@
1
1
  import { type Settings } from "../../config/settings";
2
2
  import type { ExtensionAPI, ExtensionContext } from "../../extensibility/extensions";
3
+ import type { AgentEndEvent } from "../../extensibility/shared-events";
3
4
  import { type MasterRoleAttestationV2, SessionIndex, type SessionLocatorV2 } from "../broker/session-index";
4
5
  import type { SdkPromptTerminalOutcome } from "../prompt-status";
5
6
  import { type ReceiptState } from "../receipt-state";
@@ -24,6 +25,16 @@ export declare function verifyMasterCapabilityFrame(input: {
24
25
  nonce: string;
25
26
  attestationEpoch: string;
26
27
  };
28
+ /**
29
+ * Normalize an agent-loop stop reason into the published terminal outcome.
30
+ *
31
+ * Only reached for a boundary that actually terminalizes an owned invocation,
32
+ * so every result is a `stopped` disposition: a failed run publishes its own
33
+ * correlated `agent_failed` frame with the sanitized cause instead.
34
+ */
35
+ export declare function terminalStoppedOutcome(stopReason: AgentEndEvent["stopReason"], maintenanceOutcome: string | undefined): Extract<SdkPromptTerminalOutcome, {
36
+ kind: "stopped";
37
+ }>;
27
38
  /** Transport-neutral endpoint contract consumed by the SDK session runtime. */
28
39
  export interface SessionSdkTransport {
29
40
  readonly sessionId: string;
@@ -167,6 +178,18 @@ export declare class SessionSdkSessionRuntime {
167
178
  get generation(): number;
168
179
  getProviderDefinitions(capability: string): unknown | undefined;
169
180
  emitEvent(frame: SdkFrame): void;
181
+ /**
182
+ * Deliver a frame to specific connections without recording it.
183
+ *
184
+ * Deliberately not `emitEvent`: that assigns a ring position and broadcasts to
185
+ * every authenticated socket. Streamed turn content is high-frequency and
186
+ * unbounded in size, so a count-bounded ring would evict the lifecycle events
187
+ * clients depend on -- including the `agent_end` that settles their prompt --
188
+ * and broadcasting would hand every subscriber a stream only the submitter
189
+ * asked for. Delivery failure is ignored: a disconnected consumer must never
190
+ * disturb the turn producing the content.
191
+ */
192
+ sendFrameTo(connectionIds: Iterable<string>, frame: SdkFrame): void;
170
193
  publish(frame: SdkFrame): void;
171
194
  startHost(): Promise<"started" | "already">;
172
195
  startTransport(): Promise<{
@@ -0,0 +1,26 @@
1
+ /**
2
+ * AgentLoop calls `getApiKey(provider)` before `streamFn`.
3
+ * Resolve/stream already use `getApiKey(model)`. If those two lookups diverge,
4
+ * the child dies locally (~8ms, 0 tokens, sanitized "Agent run failed.")
5
+ * and never reaches the working model-scoped path (#5081).
6
+ */
7
+ export type SessionApiKeyModel = {
8
+ provider: string;
9
+ baseUrl?: string;
10
+ };
11
+ export type SessionApiKeyRegistry = {
12
+ getApiKey(model: SessionApiKeyModel, sessionId?: string, options?: {
13
+ signal?: AbortSignal;
14
+ }): Promise<string | undefined>;
15
+ getApiKeyForProvider(provider: string, sessionId?: string, baseUrl?: string, options?: {
16
+ signal?: AbortSignal;
17
+ }): Promise<string | undefined>;
18
+ };
19
+ export type SessionApiKeyResolution = {
20
+ apiKey: string;
21
+ credentialSessionId: string | undefined;
22
+ };
23
+ export type SessionApiKeyCredentialType = "api_key" | "oauth" | undefined;
24
+ export declare function isStableSessionApiKeyCredentialType(previous: SessionApiKeyCredentialType, replacement: SessionApiKeyCredentialType): boolean;
25
+ export declare function resolveLiveSessionApiKeyModel(live: SessionApiKeyModel | undefined, captured: SessionApiKeyModel | undefined, provider: string): SessionApiKeyModel | undefined;
26
+ export declare function lookupSessionApiKey(registry: SessionApiKeyRegistry, provider: string, sessionId: string | undefined, model: SessionApiKeyModel | undefined, allowUnscopedRetry?: boolean, signal?: AbortSignal): Promise<SessionApiKeyResolution>;
@@ -7,7 +7,7 @@ type BrokerSessionRow = {
7
7
  ambiguous: boolean;
8
8
  };
9
9
  /** Exhausts strict broker `session.list` pages into one full session snapshot. */
10
- export declare function listBrokerSessions(broker: SdkClient): Promise<BrokerSessionRow[]>;
10
+ export declare function listBrokerSessions(broker: SdkClient, explicitSessionId?: string): Promise<BrokerSessionRow[]>;
11
11
  /** Selects the session to serve through broker `session.list` truth (C10); exported for tests. */
12
12
  export declare function selectBrokerSession(sessions: BrokerSessionRow[], explicitSessionId: string | undefined): string;
13
13
  /**
@@ -241,6 +241,13 @@ export interface AgentSessionConfig {
241
241
  skills?: Skill[];
242
242
  /** Skill loading warnings (already captured by SDK) */
243
243
  skillWarnings?: SkillWarning[];
244
+ /** Re-enumerate filesystem and marketplace skills after plugin lifecycle changes. */
245
+ reloadSkills?: (cwd: string) => Promise<{
246
+ skills: Skill[];
247
+ warnings: SkillWarning[];
248
+ }>;
249
+ /** Publish a successfully committed skill catalog to SDK/process snapshots. */
250
+ onSkillsReloaded?: (skills: Skill[], warnings: SkillWarning[]) => void;
244
251
  /** Custom commands (TypeScript slash commands) */
245
252
  customCommands?: LoadedCustomCommand[];
246
253
  skillsSettings?: SkillsSettings;
@@ -1176,6 +1183,8 @@ export declare class AgentSession {
1176
1183
  * they must not survive a move out of it.
1177
1184
  */
1178
1185
  replaceSkills(skills: Skill[]): Promise<void>;
1186
+ /** Refresh the live registered-skill catalog after install/remove/reload. */
1187
+ reloadSkills(cwd?: string): Promise<void>;
1179
1188
  /**
1180
1189
  * Retire the cached workspace tree after a rescope so the next turn re-scans
1181
1190
  * at the new cwd instead of re-presenting the abandoned launcher root.
@@ -0,0 +1,111 @@
1
+ export { resolvePaseoHome } from "./setup-deps";
2
+ export type PaseoDaemonTarget = {
3
+ readonly kind: "ipc";
4
+ readonly socketPath: string;
5
+ } | {
6
+ readonly kind: "tcp";
7
+ readonly host: string;
8
+ readonly port: number;
9
+ };
10
+ /** Why an announcement did nothing. Each reason is a distinct, actionable state. */
11
+ export type PaseoAnnounceSkip = "no-paseo-config" | "no-provider" | "cli-missing" | "daemon-unreachable" | "unsupported-daemon-target" | "daemon-auth-required" | "session-not-live";
12
+ export type PaseoAnnounceOutcome = {
13
+ readonly kind: "imported";
14
+ readonly providerKey: string;
15
+ } | {
16
+ readonly kind: "already-imported";
17
+ readonly providerKey: string;
18
+ } | {
19
+ readonly kind: "skipped";
20
+ readonly reason: PaseoAnnounceSkip;
21
+ } | {
22
+ readonly kind: "failed";
23
+ readonly detail: string;
24
+ };
25
+ export interface PaseoAnnounceDependencies {
26
+ /** `~/.paseo/config.json` (or the `$PASEO_HOME` equivalent). */
27
+ readonly configJson: string;
28
+ /** `~/.paseo` (or `$PASEO_HOME`). */
29
+ readonly paseoHome: string;
30
+ readonly env: NodeJS.ProcessEnv;
31
+ /** Parsed JSON, or `undefined` when the file is absent or unreadable. */
32
+ readJson(file: string): Promise<unknown>;
33
+ /** Absolute path of the `paseo` CLI, or `undefined` when it is not installed. */
34
+ resolveCli(): string | undefined;
35
+ probeDaemon(target: PaseoDaemonTarget): Promise<boolean>;
36
+ /** True only when the broker index reports this session id as live in `cwd`. */
37
+ isSessionLive(sessionId: string, cwd: string): Promise<boolean>;
38
+ runImport(input: {
39
+ readonly cli: string;
40
+ readonly providerKey: string;
41
+ readonly cwd: string;
42
+ readonly sessionId: string;
43
+ readonly signal?: AbortSignal;
44
+ }): Promise<PaseoAnnounceOutcome>;
45
+ }
46
+ /**
47
+ * Pick the Paseo provider entry to import under.
48
+ *
49
+ * `gjc setup paseo` writes `gjc`, and `--mpreset <name>` writes `gjc-<name>`, so
50
+ * the base key is preferred and a preset provider is only used when it is the
51
+ * only one installed. A disabled entry is never selected: Paseo would refuse to
52
+ * launch it.
53
+ */
54
+ export declare function selectProviderKey(config: unknown): string | undefined;
55
+ /**
56
+ * Parse one Paseo listener spelling into a connectable target.
57
+ *
58
+ * Mirrors the spellings Paseo's own CLI accepts: `unix://`/`pipe://` prefixes, a
59
+ * bare absolute path, a bare port, `tcp://host:port`, and plain `host:port`.
60
+ */
61
+ export declare function parseDaemonListen(raw: string): PaseoDaemonTarget | undefined;
62
+ /**
63
+ * Resolve where the daemon listens, in the same precedence Paseo's CLI uses:
64
+ * environment override, then the running daemon's own pid file, then the
65
+ * configured listener, then Paseo's default.
66
+ */
67
+ export declare function resolveDaemonTarget(config: unknown, deps: Pick<PaseoAnnounceDependencies, "env" | "paseoHome" | "readJson">): Promise<PaseoDaemonTarget>;
68
+ /**
69
+ * Turn a non-zero `paseo import` into an outcome.
70
+ *
71
+ * Two of Paseo's refusals are not failures:
72
+ *
73
+ * - an already-known session is exactly the state we wanted to reach;
74
+ * - a password-protected daemon (`Cannot connect to daemon ...: Password
75
+ * required`) is a configuration the user chose. The socket probe cannot see
76
+ * it -- the TCP connect succeeds -- so it can only be recognized here, and
77
+ * reporting it would put an error on screen at every single launch for
78
+ * something GJC must not fix on its own. Exporting `PASEO_PASSWORD` makes it
79
+ * work, since the CLI inherits this process's environment.
80
+ */
81
+ export declare function classifyImportFailure(providerKey: string, detail: string): PaseoAnnounceOutcome;
82
+ /**
83
+ * Run the full announcement once.
84
+ *
85
+ * The order is load-bearing: every cheap filesystem check runs before the socket
86
+ * probe, and the socket probe runs before anything spawns the Paseo CLI.
87
+ */
88
+ export declare function announceSessionToPaseo(input: {
89
+ readonly sessionId: string;
90
+ readonly cwd: string;
91
+ }, deps: PaseoAnnounceDependencies, signal?: AbortSignal): Promise<PaseoAnnounceOutcome>;
92
+ /** Only a daemon that is not up yet, or a registration that has not landed yet, is worth retrying. */
93
+ export declare function isRetryableOutcome(outcome: PaseoAnnounceOutcome): boolean;
94
+ export interface PaseoAnnouncementHandle {
95
+ cancel(): void;
96
+ }
97
+ /**
98
+ * Announce the session, retrying only while Paseo is not ready to hear it.
99
+ *
100
+ * The user routinely opens Paseo after their terminal, so a single attempt at
101
+ * launch would silently never land. Retries are socket probes, not CLI spawns,
102
+ * and every timer is unref'd so the loop can never hold the process open.
103
+ */
104
+ export declare function startPaseoAnnouncement(input: {
105
+ readonly sessionId: string;
106
+ readonly cwd: string;
107
+ isEnabled?: () => boolean;
108
+ onOutcome?: (outcome: PaseoAnnounceOutcome) => void;
109
+ }, deps: PaseoAnnounceDependencies): PaseoAnnouncementHandle;
110
+ export declare function sessionListContainsLiveSessionForTests(sessions: readonly unknown[], sessionId: string, cwd: string): boolean;
111
+ export declare function createDefaultPaseoAnnounceDependencies(agentDir: string, env?: NodeJS.ProcessEnv): PaseoAnnounceDependencies;
@@ -61,7 +61,8 @@ export interface PaseoSetupDependencies {
61
61
  runProviderLs(timeoutMs: number): Promise<PaseoLsOutcome>;
62
62
  now(): Date;
63
63
  }
64
- export declare function createDefaultPaseoPaths(agentDir?: string, home?: string): PaseoPaths;
64
+ export declare function resolvePaseoHome(env?: NodeJS.ProcessEnv, home?: string): string;
65
+ export declare function createDefaultPaseoPaths(agentDir?: string, home?: string, env?: NodeJS.ProcessEnv): PaseoPaths;
65
66
  /**
66
67
  * Parse `paseo provider ls --json`.
67
68
  *
@@ -64,6 +64,8 @@ export interface BuildSystemPromptOptions {
64
64
  pluginAppendices?: string;
65
65
  /** Repeat full tool descriptions in system prompt. Default: false */
66
66
  repeatToolDescriptions?: boolean;
67
+ /** Language guidance for internal technical reasoning. Default: off. */
68
+ reasoningLanguage?: "off" | "english";
67
69
  /** Skills settings for discovery. */
68
70
  skillsSettings?: SkillsSettings;
69
71
  /** Working directory. Default: getProjectDir() */
@@ -114,7 +114,8 @@ export interface ExecutorOptions {
114
114
  managedPersistence?: ManagedTaskPersistence;
115
115
  /**
116
116
  * The parent session's ENDPOINT-owned AsyncJobManager (resolved by the
117
- * TaskTool via forEndpoint(sessionId) ?? instance()). Model metadata and
117
+ * TaskTool via its opaque async endpoint accessor, then the process-global
118
+ * fallback). Model metadata and
118
119
  * live-handle state for THIS subagent are recorded in the SAME manager the
119
120
  * task job runs in — with concurrent top-level sessions the process-global
120
121
  * instance belongs to a different session and would surface this subagent
@@ -58,6 +58,13 @@ interface ReadUrlCacheEntry {
58
58
  /** Offset of the preamble after `wrapUntrustedContent(output)` is persisted. */
59
59
  wrappedPreambleChars?: number;
60
60
  }
61
+ export declare const READ_URL_CACHE_MAX_KEYS = 64;
62
+ /** Test-only seam for deterministic module-global cache assertions. */
63
+ export declare const readUrlCacheTestHooks: {
64
+ readonly size: number;
65
+ readonly retainedOutputChars: number;
66
+ reset(): void;
67
+ };
61
68
  export declare function loadReadUrlCacheEntry(session: ToolSession, params: {
62
69
  path: string;
63
70
  raw?: boolean;
@@ -191,14 +191,20 @@ export interface ToolSession {
191
191
  hasForegroundBashBackgroundRequestHandler?: () => boolean;
192
192
  /** Request that a foreground wait fold into a background job, if supported. `reason` names the trigger; `adapter` targets a specific wait instead of the newest registration. */
193
193
  requestForegroundBashBackground?: (reason?: FoldReason, adapter?: FoldAdapter) => Promise<boolean>;
194
- /** Current tool interrupt policy; `finish_tools` lets the running tool finish, so a steer must not fold it. */
195
- getToolInterruptPolicy?: () => "abort_tools" | "finish_tools";
196
194
  /** Get the session-owned or inherited async job manager. */
197
195
  getAsyncJobManager?: () => AsyncJobManager | undefined;
198
196
  /** Resolves on a steer admitted after the wait starts, or when `signal` aborts, without consuming the steer. */
199
197
  waitForUserSteering?: (signal: AbortSignal) => Promise<void>;
200
198
  /** Get session ID */
201
199
  getSessionId?: () => string | null;
200
+ /**
201
+ * Opaque async-job ownership/lookup endpoint key. This is not a workflow or
202
+ * path identity: workflow/session consumers must use getSessionId(). Only
203
+ * AsyncJobManager ownership and endpoint-first lookup may use this accessor
204
+ * (subagent-inherited managers are registered under the parent's endpoint;
205
+ * review thread P1).
206
+ */
207
+ getAsyncEndpointId?: () => string | null;
202
208
  /** Get credential-selection session identity. */
203
209
  getCredentialSessionId?: () => string | null;
204
210
  /** Scope-held MCP facade for mcp:// resolution. */
@@ -122,6 +122,8 @@ export interface ToolScopeOptions {
122
122
  surfaceExactFilePaths?: boolean;
123
123
  /** Extra hint appended to "Path not found" when stat fails and the user supplied multiple paths. */
124
124
  multipathStatHint?: string;
125
+ /** Cancels internal-URL resolution and prevents further scope work. */
126
+ signal?: AbortSignal;
125
127
  }
126
128
  export interface ToolScopeResolution {
127
129
  searchPath: string;
@@ -1,4 +1,5 @@
1
1
  import type { AgentTool, AgentToolContext, AgentToolResult, AgentToolUpdateCallback } from "@gajae-code/agent-core";
2
+ import type { grep as grepFn } from "@gajae-code/natives";
2
3
  import type { Component } from "@gajae-code/tui";
3
4
  import * as z from "zod/v4";
4
5
  import type { RenderResultOptions } from "../extensibility/custom-tools/types";
@@ -12,6 +13,7 @@ declare const searchSchema: z.ZodObject<{
12
13
  i: z.ZodOptional<z.ZodBoolean>;
13
14
  gitignore: z.ZodOptional<z.ZodBoolean>;
14
15
  skip: z.ZodOptional<z.ZodNumber>;
16
+ timeout: z.ZodOptional<z.ZodDefault<z.ZodNumber>>;
15
17
  }, z.core.$strict>;
16
18
  export type SearchToolInput = z.infer<typeof searchSchema>;
17
19
  /** Maximum number of distinct files surfaced in a single response. The
@@ -56,6 +58,8 @@ export interface SearchToolOptions {
56
58
  context?: number;
57
59
  /** Per-call total match cap used by Cursor's native Pi grep frame. */
58
60
  totalMatchLimit?: number;
61
+ /** Test or remote override for the native grep implementation. */
62
+ grep?: typeof grepFn;
59
63
  }
60
64
  type SearchParams = z.infer<typeof searchSchema>;
61
65
  export declare class SearchTool implements AgentTool<typeof searchSchema, SearchToolDetails> {
@@ -72,6 +76,7 @@ export declare class SearchTool implements AgentTool<typeof searchSchema, Search
72
76
  i: z.ZodOptional<z.ZodBoolean>;
73
77
  gitignore: z.ZodOptional<z.ZodBoolean>;
74
78
  skip: z.ZodOptional<z.ZodNumber>;
79
+ timeout: z.ZodOptional<z.ZodDefault<z.ZodNumber>>;
75
80
  }, z.core.$strict>;
76
81
  readonly strict = true;
77
82
  constructor(session: ToolSession, options?: SearchToolOptions);
@@ -83,6 +88,7 @@ interface SearchRenderArgs {
83
88
  i?: boolean;
84
89
  gitignore?: boolean;
85
90
  skip?: number;
91
+ timeout?: number;
86
92
  }
87
93
  export declare const searchToolRenderer: {
88
94
  inline: boolean;
@@ -17,6 +17,10 @@ export declare function trimEditorTrailingNewline(text: string): string;
17
17
  * files still require a shell on Windows; ordinary executables do not.
18
18
  */
19
19
  export declare function shouldUseExternalEditorShell(editor: string, platform?: NodeJS.Platform): boolean;
20
+ interface RawModeInput {
21
+ setRawMode?: (mode: boolean) => unknown;
22
+ }
23
+ export declare function prepareWindowsConsoleForExternalEditor(platform?: NodeJS.Platform, input?: RawModeInput): void;
20
24
  /**
21
25
  * Opens `content` in the user's external editor and returns the edited text.
22
26
  * Returns `null` if the editor exits with a non-zero code.
@@ -24,3 +28,4 @@ export declare function shouldUseExternalEditorShell(editor: string, platform?:
24
28
  * The caller is responsible for stopping/starting the TUI around this call.
25
29
  */
26
30
  export declare function openInEditor(editorCmd: string, content: string, options?: OpenInEditorOptions): Promise<string | null>;
31
+ export {};
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "type": "module",
3
3
  "name": "@gajae-code/coding-agent",
4
- "version": "0.16.1",
4
+ "version": "0.16.4",
5
5
  "description": "Gajae Code CLI with read, bash, edit, write tools and session management",
6
6
  "homepage": "https://gajae-code.com",
7
7
  "author": "Yeachan-Heo and Gajae Code Contributors",
@@ -56,12 +56,12 @@
56
56
  "@agentclientprotocol/sdk": "1.3.0",
57
57
  "@babel/parser": "^7.29.3",
58
58
  "@mozilla/readability": "^0.6.0",
59
- "@gajae-code/stats": "0.16.1",
60
- "@gajae-code/agent-core": "0.16.1",
61
- "@gajae-code/ai": "0.16.1",
62
- "@gajae-code/natives": "0.16.1",
63
- "@gajae-code/tui": "0.16.1",
64
- "@gajae-code/utils": "0.16.1",
59
+ "@gajae-code/stats": "0.16.4",
60
+ "@gajae-code/agent-core": "0.16.4",
61
+ "@gajae-code/ai": "0.16.4",
62
+ "@gajae-code/natives": "0.16.4",
63
+ "@gajae-code/tui": "0.16.4",
64
+ "@gajae-code/utils": "0.16.4",
65
65
  "@puppeteer/browsers": "^2.13.0",
66
66
  "@types/turndown": "5.0.6",
67
67
  "@xterm/headless": "^6.0.0",