@gajae-code/coding-agent 0.2.3 → 0.2.5

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 (197) hide show
  1. package/CHANGELOG.md +34 -8600
  2. package/README.md +1 -1
  3. package/dist/types/async/job-manager.d.ts +61 -0
  4. package/dist/types/cli/update-cli.d.ts +3 -0
  5. package/dist/types/config/settings-schema.d.ts +27 -3
  6. package/dist/types/config/settings.d.ts +1 -1
  7. package/dist/types/defaults/gjc-defaults.d.ts +19 -6
  8. package/dist/types/discovery/helpers.d.ts +1 -0
  9. package/dist/types/exec/bash-executor.d.ts +8 -1
  10. package/dist/types/gjc-runtime/restricted-role-agent-bash.d.ts +2 -0
  11. package/dist/types/modes/acp/acp-client-bridge.d.ts +1 -1
  12. package/dist/types/modes/components/settings-selector.d.ts +4 -0
  13. package/dist/types/modes/components/skill-hud/render.d.ts +1 -1
  14. package/dist/types/modes/controllers/selector-controller.d.ts +1 -0
  15. package/dist/types/modes/interactive-mode.d.ts +2 -0
  16. package/dist/types/modes/theme/defaults/index.d.ts +45 -9351
  17. package/dist/types/modes/theme/theme.d.ts +6 -5
  18. package/dist/types/modes/types.d.ts +2 -0
  19. package/dist/types/sdk.d.ts +2 -0
  20. package/dist/types/session/streaming-output.d.ts +11 -0
  21. package/dist/types/skill-state/active-state.d.ts +1 -0
  22. package/dist/types/task/types.d.ts +1 -0
  23. package/dist/types/tools/bash-allowed-prefixes.d.ts +5 -0
  24. package/dist/types/tools/bash.d.ts +24 -0
  25. package/dist/types/tools/cron.d.ts +110 -0
  26. package/dist/types/tools/index.d.ts +4 -0
  27. package/dist/types/tools/monitor.d.ts +54 -0
  28. package/dist/types/web/search/index.d.ts +1 -0
  29. package/dist/types/web/search/provider.d.ts +11 -4
  30. package/dist/types/web/search/providers/duckduckgo.d.ts +57 -0
  31. package/dist/types/web/search/types.d.ts +1 -1
  32. package/package.json +7 -7
  33. package/src/async/job-manager.ts +224 -0
  34. package/src/cli/agents-cli.ts +3 -0
  35. package/src/cli/update-cli.ts +67 -16
  36. package/src/config/settings-schema.ts +30 -2
  37. package/src/config/settings.ts +44 -7
  38. package/src/defaults/gjc/skills/deep-interview/SKILL.md +48 -6
  39. package/src/defaults/gjc/skills/deep-interview/auto-answer-uncertain.md +37 -0
  40. package/src/defaults/gjc/skills/deep-interview/auto-research-greenfield.md +42 -0
  41. package/src/defaults/gjc/skills/ralplan/SKILL.md +8 -4
  42. package/src/defaults/gjc/skills/ultragoal/SKILL.md +9 -6
  43. package/src/defaults/gjc-defaults.ts +68 -16
  44. package/src/discovery/helpers.ts +5 -0
  45. package/src/eval/js/shared/rewrite-imports.ts +1 -2
  46. package/src/exec/bash-executor.ts +20 -9
  47. package/src/gjc-runtime/deep-interview-runtime.ts +44 -0
  48. package/src/gjc-runtime/ralplan-runtime.ts +2 -0
  49. package/src/gjc-runtime/restricted-role-agent-bash.ts +5 -0
  50. package/src/gjc-runtime/state-runtime.ts +3 -2
  51. package/src/goals/tools/goal-tool.ts +5 -1
  52. package/src/hooks/skill-state.ts +1 -1
  53. package/src/internal-urls/docs-index.generated.ts +8 -4
  54. package/src/lsp/render.ts +1 -1
  55. package/src/memories/index.ts +5 -4
  56. package/src/modes/acp/acp-agent.ts +1 -1
  57. package/src/modes/acp/acp-client-bridge.ts +1 -1
  58. package/src/modes/components/agent-dashboard.ts +1 -1
  59. package/src/modes/components/diff.ts +2 -2
  60. package/src/modes/components/settings-selector.ts +25 -14
  61. package/src/modes/components/skill-hud/render.ts +7 -2
  62. package/src/modes/controllers/command-controller.ts +1 -1
  63. package/src/modes/controllers/input-controller.ts +10 -2
  64. package/src/modes/controllers/selector-controller.ts +67 -0
  65. package/src/modes/interactive-mode.ts +34 -3
  66. package/src/modes/theme/defaults/blue-crab.json +126 -0
  67. package/src/modes/theme/defaults/index.ts +2 -196
  68. package/src/modes/theme/theme.ts +75 -36
  69. package/src/modes/types.ts +2 -0
  70. package/src/prompts/agents/architect.md +5 -1
  71. package/src/prompts/agents/critic.md +5 -1
  72. package/src/prompts/agents/frontmatter.md +1 -0
  73. package/src/prompts/agents/planner.md +5 -1
  74. package/src/prompts/memories/unavailable.md +9 -0
  75. package/src/prompts/tools/bash.md +9 -0
  76. package/src/prompts/tools/cron.md +25 -0
  77. package/src/prompts/tools/monitor.md +30 -0
  78. package/src/runtime-mcp/oauth-flow.ts +4 -2
  79. package/src/sdk.ts +7 -0
  80. package/src/session/agent-session.ts +16 -5
  81. package/src/session/streaming-output.ts +21 -0
  82. package/src/skill-state/active-state.ts +163 -12
  83. package/src/slash-commands/builtin-registry.ts +11 -1
  84. package/src/task/agents.ts +1 -0
  85. package/src/task/executor.ts +1 -0
  86. package/src/task/types.ts +1 -0
  87. package/src/tools/bash-allowed-prefixes.ts +169 -0
  88. package/src/tools/bash.ts +190 -29
  89. package/src/tools/browser/tab-worker.ts +1 -1
  90. package/src/tools/cron.ts +665 -0
  91. package/src/tools/index.ts +20 -2
  92. package/src/tools/monitor.ts +136 -0
  93. package/src/vim/engine.ts +3 -3
  94. package/src/web/search/index.ts +31 -18
  95. package/src/web/search/provider.ts +57 -12
  96. package/src/web/search/providers/duckduckgo.ts +279 -0
  97. package/src/web/search/types.ts +2 -0
  98. package/src/modes/theme/dark.json +0 -95
  99. package/src/modes/theme/defaults/alabaster.json +0 -93
  100. package/src/modes/theme/defaults/amethyst.json +0 -96
  101. package/src/modes/theme/defaults/anthracite.json +0 -93
  102. package/src/modes/theme/defaults/basalt.json +0 -91
  103. package/src/modes/theme/defaults/birch.json +0 -95
  104. package/src/modes/theme/defaults/dark-abyss.json +0 -91
  105. package/src/modes/theme/defaults/dark-arctic.json +0 -104
  106. package/src/modes/theme/defaults/dark-aurora.json +0 -95
  107. package/src/modes/theme/defaults/dark-catppuccin.json +0 -107
  108. package/src/modes/theme/defaults/dark-cavern.json +0 -91
  109. package/src/modes/theme/defaults/dark-copper.json +0 -95
  110. package/src/modes/theme/defaults/dark-cosmos.json +0 -90
  111. package/src/modes/theme/defaults/dark-cyberpunk.json +0 -102
  112. package/src/modes/theme/defaults/dark-dracula.json +0 -98
  113. package/src/modes/theme/defaults/dark-eclipse.json +0 -91
  114. package/src/modes/theme/defaults/dark-ember.json +0 -95
  115. package/src/modes/theme/defaults/dark-equinox.json +0 -90
  116. package/src/modes/theme/defaults/dark-forest.json +0 -96
  117. package/src/modes/theme/defaults/dark-github.json +0 -105
  118. package/src/modes/theme/defaults/dark-gruvbox.json +0 -112
  119. package/src/modes/theme/defaults/dark-lavender.json +0 -95
  120. package/src/modes/theme/defaults/dark-lunar.json +0 -89
  121. package/src/modes/theme/defaults/dark-midnight.json +0 -95
  122. package/src/modes/theme/defaults/dark-monochrome.json +0 -94
  123. package/src/modes/theme/defaults/dark-monokai.json +0 -98
  124. package/src/modes/theme/defaults/dark-nebula.json +0 -90
  125. package/src/modes/theme/defaults/dark-nord.json +0 -97
  126. package/src/modes/theme/defaults/dark-ocean.json +0 -101
  127. package/src/modes/theme/defaults/dark-one.json +0 -100
  128. package/src/modes/theme/defaults/dark-poimandres.json +0 -141
  129. package/src/modes/theme/defaults/dark-rainforest.json +0 -91
  130. package/src/modes/theme/defaults/dark-reef.json +0 -91
  131. package/src/modes/theme/defaults/dark-retro.json +0 -92
  132. package/src/modes/theme/defaults/dark-rose-pine.json +0 -96
  133. package/src/modes/theme/defaults/dark-sakura.json +0 -95
  134. package/src/modes/theme/defaults/dark-slate.json +0 -95
  135. package/src/modes/theme/defaults/dark-solarized.json +0 -97
  136. package/src/modes/theme/defaults/dark-solstice.json +0 -90
  137. package/src/modes/theme/defaults/dark-starfall.json +0 -91
  138. package/src/modes/theme/defaults/dark-sunset.json +0 -99
  139. package/src/modes/theme/defaults/dark-swamp.json +0 -90
  140. package/src/modes/theme/defaults/dark-synthwave.json +0 -103
  141. package/src/modes/theme/defaults/dark-taiga.json +0 -91
  142. package/src/modes/theme/defaults/dark-terminal.json +0 -95
  143. package/src/modes/theme/defaults/dark-tokyo-night.json +0 -101
  144. package/src/modes/theme/defaults/dark-tundra.json +0 -91
  145. package/src/modes/theme/defaults/dark-twilight.json +0 -91
  146. package/src/modes/theme/defaults/dark-volcanic.json +0 -91
  147. package/src/modes/theme/defaults/graphite.json +0 -92
  148. package/src/modes/theme/defaults/light-arctic.json +0 -107
  149. package/src/modes/theme/defaults/light-aurora-day.json +0 -91
  150. package/src/modes/theme/defaults/light-canyon.json +0 -91
  151. package/src/modes/theme/defaults/light-catppuccin.json +0 -106
  152. package/src/modes/theme/defaults/light-cirrus.json +0 -90
  153. package/src/modes/theme/defaults/light-coral.json +0 -95
  154. package/src/modes/theme/defaults/light-cyberpunk.json +0 -96
  155. package/src/modes/theme/defaults/light-dawn.json +0 -90
  156. package/src/modes/theme/defaults/light-dunes.json +0 -91
  157. package/src/modes/theme/defaults/light-eucalyptus.json +0 -95
  158. package/src/modes/theme/defaults/light-forest.json +0 -100
  159. package/src/modes/theme/defaults/light-frost.json +0 -95
  160. package/src/modes/theme/defaults/light-github.json +0 -115
  161. package/src/modes/theme/defaults/light-glacier.json +0 -91
  162. package/src/modes/theme/defaults/light-gruvbox.json +0 -108
  163. package/src/modes/theme/defaults/light-haze.json +0 -90
  164. package/src/modes/theme/defaults/light-honeycomb.json +0 -95
  165. package/src/modes/theme/defaults/light-lagoon.json +0 -91
  166. package/src/modes/theme/defaults/light-lavender.json +0 -95
  167. package/src/modes/theme/defaults/light-meadow.json +0 -91
  168. package/src/modes/theme/defaults/light-mint.json +0 -95
  169. package/src/modes/theme/defaults/light-monochrome.json +0 -101
  170. package/src/modes/theme/defaults/light-ocean.json +0 -99
  171. package/src/modes/theme/defaults/light-one.json +0 -99
  172. package/src/modes/theme/defaults/light-opal.json +0 -91
  173. package/src/modes/theme/defaults/light-orchard.json +0 -91
  174. package/src/modes/theme/defaults/light-paper.json +0 -95
  175. package/src/modes/theme/defaults/light-poimandres.json +0 -141
  176. package/src/modes/theme/defaults/light-prism.json +0 -90
  177. package/src/modes/theme/defaults/light-retro.json +0 -98
  178. package/src/modes/theme/defaults/light-sand.json +0 -95
  179. package/src/modes/theme/defaults/light-savanna.json +0 -91
  180. package/src/modes/theme/defaults/light-solarized.json +0 -102
  181. package/src/modes/theme/defaults/light-soleil.json +0 -90
  182. package/src/modes/theme/defaults/light-sunset.json +0 -99
  183. package/src/modes/theme/defaults/light-synthwave.json +0 -98
  184. package/src/modes/theme/defaults/light-tokyo-night.json +0 -111
  185. package/src/modes/theme/defaults/light-wetland.json +0 -91
  186. package/src/modes/theme/defaults/light-zenith.json +0 -89
  187. package/src/modes/theme/defaults/limestone.json +0 -94
  188. package/src/modes/theme/defaults/mahogany.json +0 -97
  189. package/src/modes/theme/defaults/marble.json +0 -93
  190. package/src/modes/theme/defaults/obsidian.json +0 -91
  191. package/src/modes/theme/defaults/onyx.json +0 -91
  192. package/src/modes/theme/defaults/pearl.json +0 -93
  193. package/src/modes/theme/defaults/porcelain.json +0 -91
  194. package/src/modes/theme/defaults/quartz.json +0 -96
  195. package/src/modes/theme/defaults/sandstone.json +0 -95
  196. package/src/modes/theme/defaults/titanium.json +0 -90
  197. package/src/modes/theme/light.json +0 -93
@@ -186,6 +186,7 @@ export interface ThemeInfo {
186
186
  }
187
187
  export declare function getAvailableThemesWithPaths(): Promise<ThemeInfo[]>;
188
188
  export declare function getThemeByName(name: string): Promise<Theme | undefined>;
189
+ export declare function getDetectedThemeSettingsPath(): "theme.dark" | "theme.light";
189
190
  export declare var theme: Theme;
190
191
  /** Get the name of the currently active theme. */
191
192
  export declare function getCurrentThemeName(): string | undefined;
@@ -198,6 +199,10 @@ export declare function previewTheme(name: string): Promise<{
198
199
  success: boolean;
199
200
  error?: string;
200
201
  }>;
202
+ export declare function restoreThemePreview(name: string): Promise<{
203
+ success: boolean;
204
+ error?: string;
205
+ }>;
201
206
  /**
202
207
  * Enable auto-detection mode, switching to the appropriate dark/light theme.
203
208
  */
@@ -246,11 +251,7 @@ export declare function stopThemeWatcher(): void;
246
251
  * Used by HTML export to generate CSS custom properties.
247
252
  */
248
253
  export declare function getResolvedThemeColors(themeName?: string): Promise<Record<string, string>>;
249
- /**
250
- * Check if a theme is a "light" theme by analyzing its background color luminance.
251
- * Loads theme JSON synchronously (built-in or custom file) and resolves userMessageBg.
252
- */
253
- export declare function isLightTheme(themeName?: string): boolean;
254
+ export declare function isLightTheme(themeName?: string, agentDir?: string): boolean;
254
255
  /**
255
256
  * Get explicit export colors from theme JSON, if specified.
256
257
  * Returns undefined for each color that isn't explicitly set.
@@ -70,6 +70,7 @@ export interface InteractiveModeContext {
70
70
  isInitialized: boolean;
71
71
  isBackgrounded: boolean;
72
72
  isBashMode: boolean;
73
+ isBashNoContext: boolean;
73
74
  toolOutputExpanded: boolean;
74
75
  todoExpanded: boolean;
75
76
  planModeEnabled: boolean;
@@ -208,6 +209,7 @@ export interface InteractiveModeContext {
208
209
  openInBrowser(urlOrPath: string): void;
209
210
  refreshSlashCommandState(cwd?: string): Promise<void>;
210
211
  showSettingsSelector(): void;
212
+ showThemeSelector(): void;
211
213
  showHistorySearch(): void;
212
214
  showExtensionsDashboard(): void;
213
215
  showAgentsDashboard(): void;
@@ -99,6 +99,8 @@ export interface CreateAgentSessionOptions {
99
99
  agentId?: string;
100
100
  /** Display name for the agent in IRC. Default: "main" or "sub". */
101
101
  agentDisplayName?: string;
102
+ /** Optional restricted bash command prefixes for read-only role agents. */
103
+ bashAllowedPrefixes?: string[];
102
104
  /** Optional shared agent registry for IRC routing. Default: AgentRegistry.global(). */
103
105
  agentRegistry?: AgentRegistry;
104
106
  /** Parent task ID prefix for nested artifact naming (e.g., "6-Extensions") */
@@ -41,6 +41,17 @@ export interface OutputSinkOptions {
41
41
  onChunk?: (chunk: string) => void;
42
42
  /** Minimum ms between onChunk calls. 0 = every chunk (default). */
43
43
  chunkThrottleMs?: number;
44
+ /**
45
+ * Unthrottled per-chunk callback fired *after* sanitization but *before*
46
+ * any throttle gating, column capping, or head/tail bookkeeping. Used by
47
+ * background-job substrate to record the complete process stream for the
48
+ * Monitor tool while keeping `onChunk` cheap for UI/progress.
49
+ *
50
+ * Receives the sanitized chunk verbatim; never receives the column-capped
51
+ * or minimized text. Implementations must be fast and side-effect-free
52
+ * relative to the sink (the sink does not catch errors from this callback).
53
+ */
54
+ onRawChunk?: (chunk: string) => void;
44
55
  }
45
56
  export interface TruncationResult {
46
57
  content: string;
@@ -74,6 +74,7 @@ export declare function isCanonicalGjcWorkflowSkill(skill: string): skill is Can
74
74
  export declare function listActiveSkills(raw: unknown): SkillActiveEntry[];
75
75
  export declare function normalizeSkillActiveState(raw: unknown): SkillActiveState | null;
76
76
  export declare function getSkillActiveStatePaths(cwd: string, sessionId?: string): SkillActiveStatePaths;
77
+ export declare function collapsePlanningPipeline(entries: readonly SkillActiveEntry[]): SkillActiveEntry[];
77
78
  export declare function readVisibleSkillActiveState(cwd: string, sessionId?: string): Promise<SkillActiveState | null>;
78
79
  export declare function syncSkillActiveState(options: SyncSkillActiveStateOptions): Promise<void>;
79
80
  export interface ApplyHandoffOptions {
@@ -161,6 +161,7 @@ export interface AgentDefinition {
161
161
  autoloadSkills?: string[];
162
162
  hide?: boolean;
163
163
  forkContext?: ForkContextPolicy;
164
+ bashAllowedPrefixes?: string[];
164
165
  source: AgentSource;
165
166
  filePath?: string;
166
167
  }
@@ -0,0 +1,5 @@
1
+ export interface BashAllowedPrefixesCheck {
2
+ allowed: boolean;
3
+ reason?: string;
4
+ }
5
+ export declare function checkBashAllowedPrefixes(command: string, allowedPrefixes: readonly string[] | undefined): BashAllowedPrefixesCheck;
@@ -59,6 +59,30 @@ export declare class BashTool implements AgentTool<BashToolSchema, BashToolDetai
59
59
  readonly concurrency = "exclusive";
60
60
  readonly strict = true;
61
61
  constructor(session: ToolSession);
62
+ /**
63
+ * Start a background bash job for the Monitor tool. Reuses the full Bash
64
+ * pipeline (interceptors, internal-URL expansion, env, cwd, timeout); the
65
+ * public `monitor` tool itself is ACP-gated by `AgentSession` before this
66
+ * helper is called. The caller-supplied `onRawLine` callback is invoked once
67
+ * per newline-terminated stdout chunk, between turns, so the upstream Claude
68
+ * Code "Each stdout line is a task-notification event" semantics are preserved
69
+ * through the agent's existing background-task delivery path.
70
+ */
71
+ startMonitorJob(input: {
72
+ command: string;
73
+ cwd?: string;
74
+ timeout?: number;
75
+ env?: Record<string, string>;
76
+ }, opts?: {
77
+ ownerId?: string;
78
+ label?: string;
79
+ ctx?: AgentToolContext;
80
+ onRawLine?: (line: string, jobId: string) => void;
81
+ }): Promise<{
82
+ jobId: string;
83
+ label: string;
84
+ commandCwd: string;
85
+ }>;
62
86
  execute(_toolCallId: string, { command: rawCommand, env: rawEnv, timeout: rawTimeout, cwd, async: asyncRequested, pty }: BashToolInput, signal?: AbortSignal, onUpdate?: AgentToolUpdateCallback<BashToolDetails>, ctx?: AgentToolContext): Promise<AgentToolResult<BashToolDetails>>;
63
87
  }
64
88
  export interface BashRenderArgs {
@@ -0,0 +1,110 @@
1
+ import type { AgentTool, AgentToolContext, AgentToolResult, AgentToolUpdateCallback } from "@gajae-code/agent-core";
2
+ import * as z from "zod/v4";
3
+ import type { ToolSession } from "./index";
4
+ /** Maximum scheduled tasks per owner. Mirrors upstream Claude Code's 50-task cap. */
5
+ export declare const MAX_CRON_TASKS_PER_OWNER = 50;
6
+ /** Recurring tasks auto-expire 7 days after creation (mirrors upstream). */
7
+ export declare const CRON_RECURRING_MAX_AGE_MS: number;
8
+ declare const cronCreateSchema: z.ZodObject<{
9
+ cron_expression: z.ZodString;
10
+ prompt: z.ZodString;
11
+ recurring: z.ZodDefault<z.ZodBoolean>;
12
+ }, z.core.$strip>;
13
+ export type CronCreateParams = z.infer<typeof cronCreateSchema>;
14
+ declare const cronListSchema: z.ZodObject<{}, z.core.$strip>;
15
+ export type CronListParams = z.infer<typeof cronListSchema>;
16
+ declare const cronDeleteSchema: z.ZodObject<{
17
+ id: z.ZodString;
18
+ }, z.core.$strip>;
19
+ export type CronDeleteParams = z.infer<typeof cronDeleteSchema>;
20
+ export interface CronJobSnapshot {
21
+ id: string;
22
+ cron_expression: string;
23
+ prompt: string;
24
+ recurring: boolean;
25
+ createdAt: number;
26
+ expiresAt?: number;
27
+ nextFireAt?: number;
28
+ humanSchedule: string;
29
+ ownerId?: string;
30
+ }
31
+ export interface CronListJobDetails {
32
+ id: string;
33
+ cron: string;
34
+ recurring: boolean;
35
+ prompt: string;
36
+ humanSchedule: string;
37
+ }
38
+ export interface CronCreateToolDetails {
39
+ id: string;
40
+ cron_expression: string;
41
+ recurring: boolean;
42
+ nextFireAt?: number;
43
+ }
44
+ export interface CronListToolDetails {
45
+ jobs: CronListJobDetails[];
46
+ }
47
+ export interface CronDeleteToolDetails {
48
+ id: string;
49
+ deleted: boolean;
50
+ }
51
+ /** Clear every schedule for an owner. Exported for tests + lifecycle teardown. */
52
+ export declare function clearOwnerSchedules(ownerId: string | undefined): void;
53
+ /** Reset every owner's schedule store. Test-only. */
54
+ export declare function resetCronRegistryForTests(): void;
55
+ export declare function validateCronExpression(expression: string): void;
56
+ export declare function findNextCronMatchMs(expression: string, afterMs: number, deadlineMs?: number): number | undefined;
57
+ export declare function calculateCronFireTimeMs(params: {
58
+ id: string;
59
+ cronExpression: string;
60
+ baseMatchMs: number;
61
+ recurring: boolean;
62
+ nowMs: number;
63
+ expiresAt?: number;
64
+ }): number;
65
+ export declare class CronCreateTool implements AgentTool<typeof cronCreateSchema, CronCreateToolDetails> {
66
+ private readonly session;
67
+ readonly name = "CronCreate";
68
+ readonly label = "CronCreate";
69
+ readonly summary = "Schedule a prompt on a 5-field cron expression";
70
+ readonly description: string;
71
+ readonly parameters: z.ZodObject<{
72
+ cron_expression: z.ZodString;
73
+ prompt: z.ZodString;
74
+ recurring: z.ZodDefault<z.ZodBoolean>;
75
+ }, z.core.$strip>;
76
+ readonly strict = true;
77
+ readonly loadMode = "discoverable";
78
+ constructor(session: ToolSession);
79
+ static createIf(session: ToolSession): CronCreateTool | null;
80
+ execute(_toolCallId: string, params: CronCreateParams, _signal?: AbortSignal, _onUpdate?: AgentToolUpdateCallback<CronCreateToolDetails>, _context?: AgentToolContext): Promise<AgentToolResult<CronCreateToolDetails>>;
81
+ }
82
+ export declare class CronListTool implements AgentTool<typeof cronListSchema, CronListToolDetails> {
83
+ private readonly session;
84
+ readonly name = "CronList";
85
+ readonly label = "CronList";
86
+ readonly summary = "List scheduled cron jobs";
87
+ readonly description: string;
88
+ readonly parameters: z.ZodObject<{}, z.core.$strip>;
89
+ readonly strict = true;
90
+ readonly loadMode = "discoverable";
91
+ constructor(session: ToolSession);
92
+ static createIf(session: ToolSession): CronListTool | null;
93
+ execute(_toolCallId: string, _params: CronListParams, _signal?: AbortSignal, _onUpdate?: AgentToolUpdateCallback<CronListToolDetails>, _context?: AgentToolContext): Promise<AgentToolResult<CronListToolDetails>>;
94
+ }
95
+ export declare class CronDeleteTool implements AgentTool<typeof cronDeleteSchema, CronDeleteToolDetails> {
96
+ private readonly session;
97
+ readonly name = "CronDelete";
98
+ readonly label = "CronDelete";
99
+ readonly summary = "Cancel a scheduled cron job by ID";
100
+ readonly description: string;
101
+ readonly parameters: z.ZodObject<{
102
+ id: z.ZodString;
103
+ }, z.core.$strip>;
104
+ readonly strict = true;
105
+ readonly loadMode = "discoverable";
106
+ constructor(session: ToolSession);
107
+ static createIf(session: ToolSession): CronDeleteTool | null;
108
+ execute(_toolCallId: string, params: CronDeleteParams, _signal?: AbortSignal, _onUpdate?: AgentToolUpdateCallback<CronDeleteToolDetails>, _context?: AgentToolContext): Promise<AgentToolResult<CronDeleteToolDetails>>;
109
+ }
110
+ export {};
@@ -32,6 +32,7 @@ export * from "./bash";
32
32
  export * from "./browser";
33
33
  export * from "./calculator";
34
34
  export * from "./checkpoint";
35
+ export * from "./cron";
35
36
  export * from "./debug";
36
37
  export * from "./eval";
37
38
  export * from "./find";
@@ -43,6 +44,7 @@ export * from "./image-gen";
43
44
  export * from "./inspect-image";
44
45
  export * from "./irc";
45
46
  export * from "./job";
47
+ export * from "./monitor";
46
48
  export * from "./read";
47
49
  export * from "./recipe";
48
50
  export * from "./render-mermaid";
@@ -118,6 +120,8 @@ export interface ToolSession {
118
120
  getToolByName?: (name: string) => AgentTool | undefined;
119
121
  /** Agent registry for IRC routing across live sessions. */
120
122
  agentRegistry?: AgentRegistry;
123
+ /** Optional restricted bash command prefixes for read-only role agents. */
124
+ bashAllowedPrefixes?: string[];
121
125
  /** Get artifacts directory for artifact:// URLs */
122
126
  getArtifactsDir?: () => string | null;
123
127
  /** Get the ArtifactManager backing this session (shared across parent + subagents). */
@@ -0,0 +1,54 @@
1
+ import type { AgentTool, AgentToolContext, AgentToolResult, AgentToolUpdateCallback } from "@gajae-code/agent-core";
2
+ import * as z from "zod/v4";
3
+ import type { ToolSession } from "./index";
4
+ declare const monitorKindEnum: z.ZodEnum<{
5
+ log: "log";
6
+ other: "other";
7
+ poll: "poll";
8
+ watch: "watch";
9
+ }>;
10
+ declare const monitorSchema: z.ZodObject<{
11
+ command: z.ZodString;
12
+ kind: z.ZodEnum<{
13
+ log: "log";
14
+ other: "other";
15
+ poll: "poll";
16
+ watch: "watch";
17
+ }>;
18
+ description: z.ZodString;
19
+ timeout: z.ZodOptional<z.ZodNumber>;
20
+ persistent: z.ZodOptional<z.ZodBoolean>;
21
+ }, z.core.$strip>;
22
+ export type MonitorParams = z.infer<typeof monitorSchema>;
23
+ export interface MonitorToolDetails {
24
+ taskId: string;
25
+ kind: z.infer<typeof monitorKindEnum>;
26
+ description: string;
27
+ command: string;
28
+ persistent: boolean;
29
+ }
30
+ export declare class MonitorTool implements AgentTool<typeof monitorSchema, MonitorToolDetails> {
31
+ private readonly session;
32
+ readonly name = "monitor";
33
+ readonly label = "Monitor";
34
+ readonly summary = "Start a background monitor that streams stdout lines as task notifications";
35
+ readonly description: string;
36
+ readonly parameters: z.ZodObject<{
37
+ command: z.ZodString;
38
+ kind: z.ZodEnum<{
39
+ log: "log";
40
+ other: "other";
41
+ poll: "poll";
42
+ watch: "watch";
43
+ }>;
44
+ description: z.ZodString;
45
+ timeout: z.ZodOptional<z.ZodNumber>;
46
+ persistent: z.ZodOptional<z.ZodBoolean>;
47
+ }, z.core.$strip>;
48
+ readonly strict = true;
49
+ readonly loadMode = "discoverable";
50
+ constructor(session: ToolSession);
51
+ static createIf(session: ToolSession): MonitorTool | null;
52
+ execute(_toolCallId: string, params: MonitorParams, _signal?: AbortSignal, _onUpdate?: AgentToolUpdateCallback<MonitorToolDetails>, context?: AgentToolContext): Promise<AgentToolResult<MonitorToolDetails>>;
53
+ }
54
+ export {};
@@ -40,6 +40,7 @@ export declare function runSearchQuery(params: SearchQueryParams, options?: {
40
40
  authStorage?: AuthStorage;
41
41
  sessionId?: string;
42
42
  signal?: AbortSignal;
43
+ activeModelProvider?: string;
43
44
  }): Promise<{
44
45
  content: Array<{
45
46
  type: "text";
@@ -14,8 +14,15 @@ export declare const SEARCH_PROVIDER_ORDER: SearchProviderId[];
14
14
  /** Set the preferred web search provider from settings */
15
15
  export declare function setPreferredSearchProvider(provider: SearchProviderId | "auto"): void;
16
16
  /**
17
- * Determine which providers are configured and currently available.
18
- * Each candidate is loaded (and its `isAvailable()` called) only as the chain
19
- * is walked, so unconfigured providers never pay the load cost.
17
+ * Resolve the ordered provider chain for a search request.
18
+ *
19
+ * Resolution is active-model-gated, never credential-scanning:
20
+ * 1. An explicitly preferred provider (settings) that is available is primary.
21
+ * 2. Otherwise the active model's own native search is primary, but only when
22
+ * that provider's own credentials are present (its `isAvailable()`).
23
+ * 3. DuckDuckGo (keyless) is always appended as the terminal fallback, so a
24
+ * missing primary — or a primary runtime failure — still returns results
25
+ * with zero configuration. Keyed standalone providers are never
26
+ * auto-selected; they are reachable only via explicit selection (step 1).
20
27
  */
21
- export declare function resolveProviderChain(authStorage: AuthStorage, preferredProvider?: SearchProviderId | "auto"): Promise<SearchProvider[]>;
28
+ export declare function resolveProviderChain(authStorage: AuthStorage, preferredProvider?: SearchProviderId | "auto", activeModelProvider?: string): Promise<SearchProvider[]>;
@@ -0,0 +1,57 @@
1
+ /**
2
+ * DuckDuckGo Web Search Provider
3
+ *
4
+ * Keyless, permissionless web search. Scrapes DuckDuckGo's no-JavaScript HTML
5
+ * endpoints and maps anchors/snippets into the unified SearchResponse shape
6
+ * (sources only — DuckDuckGo does not synthesize an answer).
7
+ *
8
+ * This is the zero-config default/fallback backend: it requires no API key and
9
+ * no OAuth, so `isAvailable()` is always true. Because DuckDuckGo applies
10
+ * anti-bot rate limiting (HTTP 202 / 403 / empty responses) from datacenter and
11
+ * VPN IPs, the provider is best-effort: it retries with backoff, rotates the
12
+ * user-agent, and alternates between the `html` and `lite` endpoints. When every
13
+ * attempt fails it throws a {@link SearchProviderError} rather than returning an
14
+ * empty success — it never falls through to keyed providers.
15
+ *
16
+ * Endpoints:
17
+ * https://html.duckduckgo.com/html/ (primary)
18
+ * https://lite.duckduckgo.com/lite/ (fallback markup)
19
+ *
20
+ * The HTML markup is liable to drift; the parser is deliberately small and is
21
+ * pinned by fixture-driven tests (see test/tools/web-search-duckduckgo.test.ts).
22
+ */
23
+ import type { AuthStorage } from "@gajae-code/ai";
24
+ import type { SearchResponse } from "../../../web/search/types";
25
+ import type { SearchParams } from "./base";
26
+ import { SearchProvider } from "./base";
27
+ interface ParsedResult {
28
+ title: string;
29
+ url: string;
30
+ snippet?: string;
31
+ }
32
+ /**
33
+ * Resolve a DuckDuckGo result href to the real destination URL. DuckDuckGo wraps
34
+ * external links in a `/l/?uddg=<encoded>` redirect; `lite` sometimes links
35
+ * directly. Returns null for unusable or internal links (so ads/redirect shells
36
+ * are dropped).
37
+ */
38
+ export declare function decodeResultUrl(href: string): string | null;
39
+ /** Parse results from the `html.duckduckgo.com/html/` markup. */
40
+ export declare function parseHtmlResults(html: string): ParsedResult[];
41
+ /** Parse results from the `lite.duckduckgo.com/lite/` markup. */
42
+ export declare function parseLiteResults(html: string): ParsedResult[];
43
+ /** Execute a keyless DuckDuckGo web search with light resilience. */
44
+ export declare function searchDuckDuckGo(params: {
45
+ query: string;
46
+ num_results?: number;
47
+ recency?: "day" | "week" | "month" | "year";
48
+ signal?: AbortSignal;
49
+ }): Promise<SearchResponse>;
50
+ /** Keyless, permissionless web search provider backed by DuckDuckGo. */
51
+ export declare class DuckDuckGoProvider extends SearchProvider {
52
+ readonly id = "duckduckgo";
53
+ readonly label = "DuckDuckGo";
54
+ isAvailable(_authStorage: AuthStorage): boolean;
55
+ search(params: SearchParams): Promise<SearchResponse>;
56
+ }
57
+ export {};
@@ -4,7 +4,7 @@
4
4
  * Unified types for web search responses across supported providers.
5
5
  */
6
6
  /** Supported web search providers */
7
- export type SearchProviderId = "exa" | "brave" | "jina" | "kimi" | "zai" | "anthropic" | "perplexity" | "gemini" | "codex" | "tavily" | "parallel" | "kagi" | "synthetic" | "searxng";
7
+ export type SearchProviderId = "duckduckgo" | "exa" | "brave" | "jina" | "kimi" | "zai" | "anthropic" | "perplexity" | "gemini" | "codex" | "tavily" | "parallel" | "kagi" | "synthetic" | "searxng";
8
8
  export declare function isSearchProviderId(value: string): value is SearchProviderId;
9
9
  export declare function isSearchProviderPreference(value: string): value is SearchProviderId | "auto";
10
10
  /** Source returned by search (all providers) */
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "type": "module",
3
3
  "name": "@gajae-code/coding-agent",
4
- "version": "0.2.3",
4
+ "version": "0.2.5",
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",
@@ -48,12 +48,12 @@
48
48
  "@agentclientprotocol/sdk": "0.21.0",
49
49
  "@babel/parser": "^7.29.3",
50
50
  "@mozilla/readability": "^0.6.0",
51
- "@gajae-code/stats": "0.2.3",
52
- "@gajae-code/agent-core": "0.2.3",
53
- "@gajae-code/ai": "0.2.3",
54
- "@gajae-code/natives": "0.2.3",
55
- "@gajae-code/tui": "0.2.3",
56
- "@gajae-code/utils": "0.2.3",
51
+ "@gajae-code/stats": "0.2.5",
52
+ "@gajae-code/agent-core": "0.2.5",
53
+ "@gajae-code/ai": "0.2.5",
54
+ "@gajae-code/natives": "0.2.5",
55
+ "@gajae-code/tui": "0.2.5",
56
+ "@gajae-code/utils": "0.2.5",
57
57
  "@puppeteer/browsers": "^2.13.0",
58
58
  "@types/turndown": "5.0.6",
59
59
  "@xterm/headless": "^6.0.0",