@gajae-code/coding-agent 0.8.2 → 0.9.1

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 (214) hide show
  1. package/CHANGELOG.md +53 -0
  2. package/dist/types/append-only-mode.d.ts +31 -0
  3. package/dist/types/capability/rule.d.ts +8 -0
  4. package/dist/types/cli/fixture-report.d.ts +20 -0
  5. package/dist/types/cli/fixture-report.test.d.ts +1 -0
  6. package/dist/types/cli/nofile-limit.d.ts +11 -0
  7. package/dist/types/cli/update-cli.d.ts +22 -0
  8. package/dist/types/config/settings-schema.d.ts +119 -1
  9. package/dist/types/discovery/index.d.ts +1 -0
  10. package/dist/types/export/html/template.generated.d.ts +1 -1
  11. package/dist/types/export/ttsr.d.ts +14 -3
  12. package/dist/types/gjc-runtime/deep-interview-state.d.ts +5 -2
  13. package/dist/types/gjc-runtime/session-state-sidecar.d.ts +7 -0
  14. package/dist/types/gjc-runtime/state-writer.d.ts +3 -0
  15. package/dist/types/gjc-runtime/team-runtime.d.ts +26 -0
  16. package/dist/types/gjc-runtime/tmux-common.d.ts +1 -0
  17. package/dist/types/gjc-runtime/ultragoal-receipt-freshness.d.ts +42 -0
  18. package/dist/types/gjc-runtime/ultragoal-runtime.d.ts +119 -13
  19. package/dist/types/goals/runtime.d.ts +1 -0
  20. package/dist/types/hooks/native-skill-hook.d.ts +12 -0
  21. package/dist/types/modes/components/assistant-message.d.ts +5 -1
  22. package/dist/types/modes/components/status-line.d.ts +9 -0
  23. package/dist/types/modes/components/thinking-selector.d.ts +2 -2
  24. package/dist/types/modes/controllers/command-controller.d.ts +1 -0
  25. package/dist/types/modes/controllers/event-controller.d.ts +5 -0
  26. package/dist/types/modes/controllers/selector-controller.d.ts +1 -0
  27. package/dist/types/modes/interactive-mode.d.ts +4 -0
  28. package/dist/types/modes/rpc/rpc-mode.d.ts +1 -3
  29. package/dist/types/modes/rpc/rpc-socket-security.d.ts +3 -0
  30. package/dist/types/modes/rpc/rpc-types.d.ts +14 -0
  31. package/dist/types/modes/shared/agent-wire/event-contract.d.ts +19 -0
  32. package/dist/types/modes/shared/agent-wire/event-envelope.d.ts +23 -1
  33. package/dist/types/modes/types.d.ts +3 -0
  34. package/dist/types/modes/utils/injected-user-submission.d.ts +52 -0
  35. package/dist/types/modes/utils/ui-helpers.d.ts +1 -0
  36. package/dist/types/notifications/config-commands.d.ts +9 -0
  37. package/dist/types/notifications/config.d.ts +22 -0
  38. package/dist/types/notifications/index.d.ts +2 -0
  39. package/dist/types/notifications/lifecycle-commands.d.ts +1 -0
  40. package/dist/types/notifications/lifecycle-control-runtime.d.ts +2 -1
  41. package/dist/types/notifications/reply-sent-store.d.ts +53 -0
  42. package/dist/types/notifications/rich-draft.d.ts +68 -0
  43. package/dist/types/notifications/rich-render.d.ts +90 -0
  44. package/dist/types/notifications/telegram-daemon-cli.d.ts +3 -3
  45. package/dist/types/notifications/telegram-daemon.d.ts +30 -0
  46. package/dist/types/notifications/telegram-reference.d.ts +7 -0
  47. package/dist/types/notifications/threaded-render.d.ts +14 -0
  48. package/dist/types/sdk.d.ts +3 -0
  49. package/dist/types/session/agent-session.d.ts +43 -1
  50. package/dist/types/session/file-mention-pruning.d.ts +8 -0
  51. package/dist/types/session/messages.d.ts +4 -0
  52. package/dist/types/session/session-manager.d.ts +17 -1
  53. package/dist/types/skill-state/active-state.d.ts +18 -1
  54. package/dist/types/system-prompt.d.ts +18 -2
  55. package/dist/types/task/executor.d.ts +1 -0
  56. package/dist/types/task/fork-context-budget.d.ts +7 -0
  57. package/dist/types/task/token-log.d.ts +30 -0
  58. package/dist/types/task/token-log.test.d.ts +1 -0
  59. package/dist/types/tools/bisect.d.ts +81 -0
  60. package/dist/types/tools/index.d.ts +1 -0
  61. package/dist/types/tools/search.d.ts +2 -2
  62. package/dist/types/utils/file-mentions.d.ts +14 -0
  63. package/dist/types/utils/git.d.ts +32 -0
  64. package/dist/types/utils/pasted-image-path.d.ts +30 -0
  65. package/dist/types/web/scrapers/youtube.d.ts +8 -0
  66. package/package.json +8 -11
  67. package/src/append-only-mode.ts +58 -0
  68. package/src/autoresearch/prompt.md +1 -1
  69. package/src/autoresearch/tools/log-experiment.ts +1 -1
  70. package/src/capability/rule.ts +9 -0
  71. package/src/cli/config-cli.ts +27 -3
  72. package/src/cli/fixture-report.test.ts +230 -0
  73. package/src/cli/fixture-report.ts +171 -0
  74. package/src/cli/nofile-limit.ts +48 -0
  75. package/src/cli/notify-cli.ts +11 -9
  76. package/src/cli/update-cli.ts +85 -9
  77. package/src/cli.ts +26 -0
  78. package/src/commands/contribution-prep.ts +1 -1
  79. package/src/config/keybindings.ts +1 -1
  80. package/src/config/settings-schema.ts +76 -1
  81. package/src/defaults/gjc/skills/deep-interview/SKILL.md +12 -13
  82. package/src/defaults/gjc/skills/ralplan/SKILL.md +30 -93
  83. package/src/defaults/gjc/skills/team/SKILL.md +16 -13
  84. package/src/defaults/gjc/skills/ultragoal/SKILL.md +59 -4
  85. package/src/defaults/gjc/skills/ultragoal/pipeline-validation-contracts.md +30 -0
  86. package/src/defaults/gjc-defaults.ts +9 -0
  87. package/src/discovery/helpers.ts +10 -0
  88. package/src/discovery/index.ts +1 -0
  89. package/src/export/html/template.generated.ts +1 -1
  90. package/src/export/html/template.js +60 -2
  91. package/src/export/ttsr.ts +96 -18
  92. package/src/extensibility/extensions/runner.ts +181 -219
  93. package/src/extensibility/gjc-plugins/runtime-adapters.ts +156 -44
  94. package/src/gjc-runtime/deep-interview-state.ts +31 -2
  95. package/src/gjc-runtime/launch-tmux.ts +6 -0
  96. package/src/gjc-runtime/session-state-sidecar.ts +208 -13
  97. package/src/gjc-runtime/state-writer.ts +15 -0
  98. package/src/gjc-runtime/team-runtime.ts +175 -19
  99. package/src/gjc-runtime/tmux-common.ts +1 -0
  100. package/src/gjc-runtime/ultragoal-guard.ts +55 -66
  101. package/src/gjc-runtime/ultragoal-receipt-freshness.ts +315 -0
  102. package/src/gjc-runtime/ultragoal-runtime.ts +1602 -143
  103. package/src/gjc-runtime/workflow-manifest.generated.json +113 -2
  104. package/src/gjc-runtime/workflow-manifest.ts +74 -1
  105. package/src/goals/runtime.ts +10 -2
  106. package/src/hindsight/backend.ts +1 -3
  107. package/src/hooks/native-skill-hook.ts +95 -4
  108. package/src/internal-urls/docs-index.generated.ts +18 -9
  109. package/src/lsp/client.ts +1 -0
  110. package/src/main.ts +43 -2
  111. package/src/memories/index.ts +12 -1
  112. package/src/modes/components/assistant-message.ts +241 -82
  113. package/src/modes/components/custom-editor.ts +1 -0
  114. package/src/modes/components/footer.ts +7 -2
  115. package/src/modes/components/status-line.ts +167 -54
  116. package/src/modes/components/thinking-selector.ts +10 -8
  117. package/src/modes/components/tool-execution.ts +44 -19
  118. package/src/modes/controllers/command-controller.ts +39 -2
  119. package/src/modes/controllers/event-controller.ts +77 -49
  120. package/src/modes/controllers/extension-ui-controller.ts +8 -1
  121. package/src/modes/controllers/input-controller.ts +13 -18
  122. package/src/modes/controllers/selector-controller.ts +41 -0
  123. package/src/modes/interactive-mode.ts +14 -1
  124. package/src/modes/rpc/rpc-mode.ts +32 -12
  125. package/src/modes/rpc/rpc-socket-security.ts +13 -1
  126. package/src/modes/rpc/rpc-types.ts +9 -0
  127. package/src/modes/shared/agent-wire/command-validation.ts +4 -0
  128. package/src/modes/shared/agent-wire/event-contract.ts +22 -0
  129. package/src/modes/shared/agent-wire/event-envelope.ts +82 -0
  130. package/src/modes/shared/agent-wire/scopes.ts +1 -0
  131. package/src/modes/types.ts +3 -0
  132. package/src/modes/utils/injected-user-submission.ts +94 -0
  133. package/src/modes/utils/ui-helpers.ts +17 -4
  134. package/src/notifications/config-commands.ts +20 -0
  135. package/src/notifications/config.ts +43 -4
  136. package/src/notifications/index.ts +105 -9
  137. package/src/notifications/lifecycle-commands.ts +37 -16
  138. package/src/notifications/lifecycle-control-runtime.ts +8 -3
  139. package/src/notifications/reply-sent-store.ts +134 -0
  140. package/src/notifications/rich-draft.ts +107 -0
  141. package/src/notifications/rich-render.ts +142 -0
  142. package/src/notifications/telegram-daemon-cli.ts +54 -7
  143. package/src/notifications/telegram-daemon-control.ts +2 -2
  144. package/src/notifications/telegram-daemon.ts +390 -56
  145. package/src/notifications/telegram-reference.ts +17 -0
  146. package/src/notifications/threaded-render.ts +45 -2
  147. package/src/prompts/agents/architect.md +19 -10
  148. package/src/prompts/agents/critic.md +16 -18
  149. package/src/prompts/agents/executor.md +14 -11
  150. package/src/prompts/agents/planner.md +18 -13
  151. package/src/prompts/ci-green-request.md +3 -8
  152. package/src/prompts/goals/goal-continuation.md +0 -5
  153. package/src/prompts/goals/goal-mode-active.md +0 -5
  154. package/src/prompts/system/agent-creation-architect.md +2 -2
  155. package/src/prompts/system/plan-mode-active.md +1 -1
  156. package/src/prompts/system/plan-mode-subagent.md +3 -3
  157. package/src/prompts/system/project-prompt.md +0 -13
  158. package/src/prompts/system/subagent-system-prompt.md +3 -2
  159. package/src/prompts/system/system-prompt.md +26 -19
  160. package/src/prompts/system/volatile-project-context.md +10 -0
  161. package/src/prompts/system/web-search.md +4 -7
  162. package/src/prompts/tools/apply-patch.md +6 -0
  163. package/src/prompts/tools/ast-edit.md +1 -0
  164. package/src/prompts/tools/bash.md +1 -1
  165. package/src/prompts/tools/bisect.md +22 -0
  166. package/src/prompts/tools/browser.md +1 -1
  167. package/src/prompts/tools/cron.md +0 -2
  168. package/src/prompts/tools/eval.md +2 -2
  169. package/src/prompts/tools/find.md +1 -1
  170. package/src/prompts/tools/github.md +6 -6
  171. package/src/prompts/tools/goal.md +1 -3
  172. package/src/prompts/tools/image-gen.md +12 -5
  173. package/src/prompts/tools/irc.md +5 -4
  174. package/src/prompts/tools/job.md +2 -2
  175. package/src/prompts/tools/lsp.md +1 -1
  176. package/src/prompts/tools/monitor.md +2 -2
  177. package/src/prompts/tools/patch.md +2 -2
  178. package/src/prompts/tools/replace.md +2 -21
  179. package/src/prompts/tools/rewind.md +1 -1
  180. package/src/prompts/tools/search-tool-bm25.md +6 -11
  181. package/src/prompts/tools/search.md +1 -1
  182. package/src/prompts/tools/skill.md +3 -2
  183. package/src/prompts/tools/ssh.md +2 -1
  184. package/src/prompts/tools/subagent.md +2 -2
  185. package/src/prompts/tools/task.md +4 -5
  186. package/src/prompts/tools/todo-write.md +1 -1
  187. package/src/prompts/tools/vim.md +1 -0
  188. package/src/prompts/tools/web-search.md +2 -0
  189. package/src/prompts/tools/write.md +8 -2
  190. package/src/sdk.ts +68 -30
  191. package/src/session/agent-session.ts +734 -107
  192. package/src/session/file-mention-pruning.ts +64 -0
  193. package/src/session/messages.ts +4 -0
  194. package/src/session/session-manager.ts +59 -2
  195. package/src/skill-state/active-state.ts +141 -5
  196. package/src/skill-state/deep-interview-mutation-guard.ts +67 -3
  197. package/src/slash-commands/builtin-registry.ts +143 -1
  198. package/src/system-prompt.ts +57 -16
  199. package/src/task/executor.ts +125 -20
  200. package/src/task/fork-context-advisory.ts +2 -7
  201. package/src/task/fork-context-budget.ts +9 -0
  202. package/src/task/index.ts +4 -3
  203. package/src/task/output-manager.ts +4 -2
  204. package/src/task/token-log.test.ts +188 -0
  205. package/src/task/token-log.ts +179 -0
  206. package/src/tools/bisect.ts +367 -0
  207. package/src/tools/index.ts +3 -0
  208. package/src/tools/output-meta.ts +116 -4
  209. package/src/tools/search.ts +8 -2
  210. package/src/tools/skill.ts +15 -0
  211. package/src/utils/file-mentions.ts +39 -7
  212. package/src/utils/git.ts +73 -0
  213. package/src/utils/pasted-image-path.ts +170 -0
  214. package/src/web/scrapers/youtube.ts +24 -12
@@ -1,5 +1,6 @@
1
1
  import type { AgentMessage } from "@gajae-code/agent-core";
2
2
  import type { ImageContent, Message, MessageAttribution, ServiceTier, TextContent } from "@gajae-code/ai";
3
+ import type { TtsrInjectionRecord } from "../export/ttsr";
3
4
  import { ArtifactManager } from "./artifacts";
4
5
  import { type BlobPutResult, BlobStore } from "./blob-store";
5
6
  import { type BashExecutionMessage, type CustomMessage, type FileMentionMessage, type HookMessage, type PythonExecutionMessage } from "./messages";
@@ -141,6 +142,10 @@ export interface TtsrInjectionEntry extends SessionEntryBase {
141
142
  type: "ttsr_injection";
142
143
  /** Names of rules that were injected */
143
144
  injectedRules: string[];
145
+ /** Rich rule injection records with repeat state. */
146
+ injectedRuleRecords?: TtsrInjectionRecord[];
147
+ /** TTSR manager message count when this injection was recorded. */
148
+ ttsrMessageCount?: number;
144
149
  }
145
150
  /** Persisted MCP discovery selection state for a session branch. */
146
151
  export interface MCPToolSelectionEntry extends SessionEntryBase {
@@ -212,6 +217,10 @@ export interface SessionContext {
212
217
  models: Record<string, string>;
213
218
  /** Names of TTSR rules that have been injected this session */
214
219
  injectedTtsrRules: string[];
220
+ /** Rich TTSR rule injection records for repeat resume. */
221
+ injectedTtsrRuleRecords?: TtsrInjectionRecord[];
222
+ /** TTSR manager message count for repeat resume. */
223
+ ttsrMessageCount?: number;
215
224
  /** MCP tool names selected through discovery for this session branch. */
216
225
  selectedMCPToolNames: string[];
217
226
  /** Whether this branch contains an explicit persisted MCP selection entry. */
@@ -477,6 +486,13 @@ export declare class SessionManager {
477
486
  appendCompaction<T = unknown>(summary: string, shortSummary: string | undefined, firstKeptEntryId: string, tokensBefore: number, details?: T, fromExtension?: boolean, preserveData?: Record<string, unknown>): string;
478
487
  /** Append a custom entry (for extensions) as child of current leaf, then advance leaf. Returns entry id. */
479
488
  appendCustomEntry(customType: string, data?: unknown): string;
489
+ /**
490
+ * Append a root marker that starts a fresh active branch without changing the
491
+ * session id or deleting earlier durable entries. Subsequent messages descend
492
+ * from this marker, so provider context is clear while history remains
493
+ * available for diagnostics/export.
494
+ */
495
+ appendContextClearEntry(data?: Record<string, unknown>): string;
480
496
  /**
481
497
  * Write mutated message entries back into the canonical entry store by id.
482
498
  *
@@ -511,7 +527,7 @@ export declare class SessionManager {
511
527
  * @param ruleNames Names of rules that were injected
512
528
  * @returns Entry id
513
529
  */
514
- appendTtsrInjection(ruleNames: string[]): string;
530
+ appendTtsrInjection(ruleNames: string[], records?: TtsrInjectionRecord[], ttsrMessageCount?: number): string;
515
531
  /**
516
532
  * Get all unique TTSR rule names that have been injected in the current branch.
517
533
  * Scans from root to current leaf for ttsr_injection entries.
@@ -92,7 +92,24 @@ export declare function listActiveSkills(raw: unknown): SkillActiveEntry[];
92
92
  export declare function normalizeSkillActiveState(raw: unknown): SkillActiveState | null;
93
93
  export declare function getSkillActiveStatePaths(cwd: string, sessionId?: string): SkillActiveStatePaths;
94
94
  export declare function collapsePlanningPipeline(entries: readonly SkillActiveEntry[]): SkillActiveEntry[];
95
- export declare function readVisibleSkillActiveState(cwd: string, sessionId?: string): Promise<SkillActiveState | null>;
95
+ export type VisibleSkillActiveStateCacheTier = "security" | "hud";
96
+ export interface ReadVisibleSkillActiveStateOptions {
97
+ tier?: VisibleSkillActiveStateCacheTier;
98
+ }
99
+ interface ActiveStateStatSignature {
100
+ path: string;
101
+ mtimeMs: number;
102
+ size: number;
103
+ }
104
+ interface ActiveStateSignature {
105
+ sessionPath: ActiveStateStatSignature | null;
106
+ activeDir: ActiveStateStatSignature | null;
107
+ activeEntries: ActiveStateStatSignature[];
108
+ ralplanModeState: ActiveStateStatSignature | null;
109
+ }
110
+ export declare function computeActiveStateSignature(cwd: string, sessionId: string): Promise<ActiveStateSignature>;
111
+ export declare function invalidateVisibleSkillActiveStateCache(cwd?: string, sessionId?: string): void;
112
+ export declare function readVisibleSkillActiveState(cwd: string, sessionId?: string, opts?: ReadVisibleSkillActiveStateOptions): Promise<SkillActiveState | null>;
96
113
  export declare function syncSkillActiveState(options: SyncSkillActiveStateOptions): Promise<void>;
97
114
  export interface ApplyHandoffOptions {
98
115
  cwd: string;
@@ -17,9 +17,12 @@ export interface LoadContextFilesOptions {
17
17
  cwd?: string;
18
18
  }
19
19
  /**
20
- * Load all project context files using the capability API.
20
+ * Load all context files using the capability API.
21
21
  * Returns {path, content, depth} entries for all discovered context files.
22
- * Files are sorted by depth (descending) so files closer to cwd appear last/more prominent.
22
+ * Native user-global files (`~/.gjc/agent/AGENTS.md`) come first, then project
23
+ * files sorted by depth (descending) so files closer to cwd appear last/more
24
+ * prominent. User-home files from foreign providers (`~/.claude/CLAUDE.md`,
25
+ * `~/.codex/AGENTS.md`, …) stay excluded — only gjc's own user config applies.
23
26
  */
24
27
  export declare function loadProjectContextFiles(options?: LoadContextFilesOptions): Promise<Array<{
25
28
  path: string;
@@ -91,12 +94,25 @@ export interface BuildSystemPromptOptions {
91
94
  secretsEnabled?: boolean;
92
95
  /** Pre-loaded workspace tree (skips discovery if provided). May be a Promise to allow early kick-off. */
93
96
  workspaceTree?: WorkspaceTree | Promise<WorkspaceTree>;
97
+ /**
98
+ * Render a trimmed role-agent base prompt for subagent sessions: omits the
99
+ * workflow-surface/routing/self-awareness (`<gjc-runtime>`) and `<soul>` blocks
100
+ * that only apply to the top-level interactive/print agent. Tool safety, repo
101
+ * safety, and the completion contract are retained. Default: false.
102
+ */
103
+ subagent?: boolean;
94
104
  }
95
105
  /** Result of building provider-facing system prompt messages. */
96
106
  export interface BuildSystemPromptResult {
97
107
  /** Ordered system prompt blocks. Providers should preserve entries as distinct messages/blocks. */
98
108
  systemPrompt: string[];
99
109
  }
110
+ export interface BuildVolatileProjectContextOptions {
111
+ cwd?: string;
112
+ date?: string;
113
+ workspaceTree?: WorkspaceTree;
114
+ }
115
+ export declare function buildVolatileProjectContext(options?: BuildVolatileProjectContextOptions): string;
100
116
  /** Build the system prompt with tools, guidelines, and context */
101
117
  export declare function buildSystemPrompt(options?: BuildSystemPromptOptions): Promise<BuildSystemPromptResult>;
102
118
  export {};
@@ -114,6 +114,7 @@ interface FinalizeSubprocessOutputResult {
114
114
  }
115
115
  export declare const SUBAGENT_WARNING_NULL_YIELD = "SYSTEM WARNING: Subagent called yield with null data.";
116
116
  export declare const SUBAGENT_WARNING_MISSING_YIELD = "SYSTEM WARNING: Subagent exited without calling yield tool after 3 reminders.";
117
+ export declare const SUBAGENT_WARNING_PLACEHOLDER_YIELD = "SYSTEM WARNING: Subagent yield data contains a placeholder instead of the actual result.";
117
118
  export declare function finalizeSubprocessOutput(args: FinalizeSubprocessOutputArgs): FinalizeSubprocessOutputResult;
118
119
  export declare function createSubagentSettings(baseSettings: Settings, inheritedServiceTier?: ServiceTier): Settings;
119
120
  /**
@@ -0,0 +1,7 @@
1
+ export declare const FORK_CONTEXT_TOKEN_BUDGET_BY_MODE: {
2
+ readonly none: 0;
3
+ readonly receipt: 2000;
4
+ readonly "last-turn": 4000;
5
+ readonly bounded: 8000;
6
+ readonly full: 15000;
7
+ };
@@ -0,0 +1,30 @@
1
+ import type { ChatUsageSnapshot, CostEstimate } from "@gajae-code/agent-core";
2
+ import type { TaskTokenLog, TaskTokenMetrics } from "./types";
3
+ export interface TaskTokenLogChatBuckets {
4
+ readonly inputTokens: number;
5
+ readonly outputTokens: number;
6
+ readonly cachedInputTokens: number;
7
+ readonly cacheWriteTokens: number;
8
+ readonly costUsd?: number;
9
+ }
10
+ export interface TaskTokenLogSessionManager {
11
+ getSessionId(): string;
12
+ }
13
+ export interface TaskTokenLogContext {
14
+ readonly subagentId: string;
15
+ readonly agent?: string;
16
+ readonly turn: number;
17
+ readonly at: string;
18
+ readonly model?: string;
19
+ }
20
+ export declare function taskTokenLogFromChat(chat: TaskTokenLogChatBuckets, ctx: TaskTokenLogContext): TaskTokenLog;
21
+ export declare function taskTokenLogFromUsage(usage: ChatUsageSnapshot, ctx: TaskTokenLogContext & {
22
+ readonly cost?: CostEstimate;
23
+ }): TaskTokenLog;
24
+ export declare function resolveTaskTokenLogDir(cwd: string, sessionManager: TaskTokenLogSessionManager | undefined, envSessionId?: string | undefined): Promise<string | undefined>;
25
+ export declare function persistTaskTokenLog(entry: TaskTokenLog, opts: {
26
+ dir: string;
27
+ }): Promise<void>;
28
+ export declare function readTaskTokenLogs(dir: string): Promise<TaskTokenLog[]>;
29
+ export declare function computeTaskTokenMetrics(logs: readonly TaskTokenLog[]): TaskTokenMetrics;
30
+ export declare function computeCacheHitRate(input: number, cacheRead: number): number;
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,81 @@
1
+ import type { AgentTool, AgentToolContext, AgentToolResult, AgentToolUpdateCallback } from "@gajae-code/agent-core";
2
+ import * as z from "zod/v4";
3
+ import type { ToolSession } from ".";
4
+ import type { OutputMeta } from "./output-meta";
5
+ declare const bisectSchema: z.ZodObject<{
6
+ good: z.ZodString;
7
+ bad: z.ZodDefault<z.ZodString>;
8
+ run: z.ZodString;
9
+ invert: z.ZodDefault<z.ZodBoolean>;
10
+ maxSteps: z.ZodDefault<z.ZodNumber>;
11
+ stepTimeoutMs: z.ZodDefault<z.ZodNumber>;
12
+ }, z.core.$strip>;
13
+ type BisectParams = z.infer<typeof bisectSchema>;
14
+ export type BisectVerdict = "good" | "bad" | "skip";
15
+ export interface BisectStep {
16
+ rev: string;
17
+ verdict: BisectVerdict;
18
+ }
19
+ export interface BisectMarkResult {
20
+ exitCode: number;
21
+ output: string;
22
+ }
23
+ export interface BisectControllerDeps {
24
+ maxSteps: number;
25
+ /** SHA of the revision git currently has checked out. */
26
+ currentRev: () => Promise<string>;
27
+ /** Evaluate the predicate at the checked-out revision. */
28
+ evaluate: (rev: string) => Promise<BisectVerdict>;
29
+ /** Apply the verdict via `git bisect good|bad|skip` and return the raw result. */
30
+ mark: (verdict: BisectVerdict) => Promise<BisectMarkResult>;
31
+ }
32
+ export interface BisectOutcome {
33
+ culprit: string | null;
34
+ steps: BisectStep[];
35
+ concluded: boolean;
36
+ reason?: string;
37
+ }
38
+ export interface BisectToolDetails {
39
+ meta?: OutputMeta;
40
+ culprit: string | null;
41
+ invert: boolean;
42
+ concluded: boolean;
43
+ steps: BisectStep[];
44
+ author?: string;
45
+ date?: string;
46
+ subject?: string;
47
+ reason?: string;
48
+ }
49
+ /** Parse the culprit SHA from `git bisect good|bad` output, or null when not yet converged. */
50
+ export declare function parseFirstBadCommit(output: string): string | null;
51
+ /**
52
+ * Map a predicate exit code to a bisect verdict. `invert` swaps the good/bad
53
+ * mapping (to hunt for a fixing commit) but never reinterprets a skip.
54
+ */
55
+ export declare function classifyExit(exitCode: number, invert: boolean): BisectVerdict;
56
+ /**
57
+ * Drive the bisect loop. Pure orchestration — every git/predicate effect is
58
+ * injected — so it can be exercised deterministically without a real repo.
59
+ */
60
+ export declare function runBisectController(deps: BisectControllerDeps, signal?: AbortSignal): Promise<BisectOutcome>;
61
+ export declare class BisectTool implements AgentTool<typeof bisectSchema, BisectToolDetails> {
62
+ private readonly session;
63
+ readonly name = "bisect";
64
+ readonly label = "Bisect";
65
+ readonly summary = "Find the commit that introduced a regression by driving git bisect with a shell predicate";
66
+ readonly description: string;
67
+ readonly parameters: z.ZodObject<{
68
+ good: z.ZodString;
69
+ bad: z.ZodDefault<z.ZodString>;
70
+ run: z.ZodString;
71
+ invert: z.ZodDefault<z.ZodBoolean>;
72
+ maxSteps: z.ZodDefault<z.ZodNumber>;
73
+ stepTimeoutMs: z.ZodDefault<z.ZodNumber>;
74
+ }, z.core.$strip>;
75
+ readonly strict = true;
76
+ readonly loadMode = "discoverable";
77
+ readonly intent: (args: Partial<BisectParams>) => string;
78
+ constructor(session: ToolSession);
79
+ execute(_toolCallId: string, params: BisectParams, signal?: AbortSignal, _onUpdate?: AgentToolUpdateCallback<BisectToolDetails>, _context?: AgentToolContext): Promise<AgentToolResult<BisectToolDetails>>;
80
+ }
81
+ export {};
@@ -31,6 +31,7 @@ export * from "./ask";
31
31
  export * from "./ast-edit";
32
32
  export * from "./ast-grep";
33
33
  export * from "./bash";
34
+ export * from "./bisect";
34
35
  export * from "./browser";
35
36
  export * from "./calculator";
36
37
  export * from "./checkpoint";
@@ -8,7 +8,7 @@ import type { ToolSession } from ".";
8
8
  import { type OutputMeta } from "./output-meta";
9
9
  declare const searchSchema: z.ZodObject<{
10
10
  pattern: z.ZodString;
11
- paths: z.ZodArray<z.ZodString>;
11
+ paths: z.ZodOptional<z.ZodArray<z.ZodString>>;
12
12
  i: z.ZodOptional<z.ZodBoolean>;
13
13
  gitignore: z.ZodOptional<z.ZodBoolean>;
14
14
  skip: z.ZodOptional<z.ZodNumber>;
@@ -61,7 +61,7 @@ export declare class SearchTool implements AgentTool<typeof searchSchema, Search
61
61
  readonly description: string;
62
62
  readonly parameters: z.ZodObject<{
63
63
  pattern: z.ZodString;
64
- paths: z.ZodArray<z.ZodString>;
64
+ paths: z.ZodOptional<z.ZodArray<z.ZodString>>;
65
65
  i: z.ZodOptional<z.ZodBoolean>;
66
66
  gitignore: z.ZodOptional<z.ZodBoolean>;
67
67
  skip: z.ZodOptional<z.ZodNumber>;
@@ -1,4 +1,10 @@
1
1
  import type { AgentMessage } from "@gajae-code/agent-core";
2
+ /**
3
+ * Default inline cap for auto-read file mentions, deliberately below the
4
+ * read-tool cap (`DEFAULT_MAX_BYTES`, 50KB) so an incidental `@path` mention
5
+ * injects a smaller snippet than an explicit `read`. Overridable per call.
6
+ */
7
+ export declare const DEFAULT_FILE_MENTION_INLINE_BYTES: number;
2
8
  /** Extract all @filepath mentions from text */
3
9
  export declare function extractFileMentions(text: string): string[];
4
10
  /**
@@ -8,4 +14,12 @@ export declare function extractFileMentions(text: string): string[];
8
14
  export declare function generateFileMentionMessages(filePaths: string[], cwd: string, options?: {
9
15
  autoResizeImages?: boolean;
10
16
  useHashLines?: boolean;
17
+ /** Inline byte cap for auto-read text. Default: DEFAULT_FILE_MENTION_INLINE_BYTES. */
18
+ maxInlineBytes?: number;
19
+ /**
20
+ * Resolved paths already shown (read or mentioned) recently in the
21
+ * conversation. A mention of one of these emits a compact duplicate note
22
+ * instead of re-injecting the full body.
23
+ */
24
+ recentlyShownPaths?: ReadonlySet<string>;
11
25
  }): Promise<AgentMessage[]>;
@@ -307,6 +307,38 @@ export declare function clean(cwd: string, options?: {
307
307
  paths?: readonly string[];
308
308
  signal?: AbortSignal;
309
309
  }): Promise<void>;
310
+ export interface BisectCommitInfo {
311
+ sha: string;
312
+ author: string;
313
+ date: string;
314
+ subject: string;
315
+ stat: string;
316
+ }
317
+ /**
318
+ * Thin wrappers over `git bisect`. The marking commands (`good`/`bad`/`skip`)
319
+ * return the raw {@link GitCommandResult} without throwing so callers can both
320
+ * detect a genuine failure (non-zero exit) and scan the output for the
321
+ * "<sha> is the first bad commit" conclusion. `reset` is best-effort and never
322
+ * throws so it is safe to call from a `finally` block to restore the worktree.
323
+ */
324
+ export declare const bisect: {
325
+ /** Begin a bisect session (does not seed good/bad endpoints). */
326
+ start(cwd: string, signal?: AbortSignal): Promise<void>;
327
+ /** Mark a revision (or current HEAD when omitted) good. Returns raw output. */
328
+ good(cwd: string, ref?: string, signal?: AbortSignal): Promise<GitCommandResult>;
329
+ /** Mark a revision (or current HEAD when omitted) bad. Returns raw output. */
330
+ bad(cwd: string, ref?: string, signal?: AbortSignal): Promise<GitCommandResult>;
331
+ /** Skip the current (untestable) revision. Returns raw output. */
332
+ skip(cwd: string, signal?: AbortSignal): Promise<GitCommandResult>;
333
+ /** Read the replayable bisect log for the current session. */
334
+ log(cwd: string, signal?: AbortSignal): Promise<string>;
335
+ /** End the bisect session, restoring the original HEAD. Never throws. */
336
+ reset(cwd: string, signal?: AbortSignal): Promise<void>;
337
+ /** True when `ancestor` is a first-parent-or-merge ancestor of `descendant`. */
338
+ isAncestor(cwd: string, ancestor: string, descendant: string, signal?: AbortSignal): Promise<boolean>;
339
+ /** Resolve author/date/subject and a diffstat for a commit (for the receipt). */
340
+ describe(cwd: string, sha: string, signal?: AbortSignal): Promise<BisectCommitInfo>;
341
+ };
310
342
  export declare const ls: {
311
343
  /** List files tracked or untracked by git. */
312
344
  files(cwd: string, options?: {
@@ -0,0 +1,30 @@
1
+ export interface DecodePastedPathOptions {
2
+ /**
3
+ * Platform whose path semantics apply when decoding (shell unescaping,
4
+ * `file://` drive letters / UNC hosts). Defaults to `process.platform`;
5
+ * injectable so tests can pin the win32 contract from any host.
6
+ */
7
+ platform?: NodeJS.Platform;
8
+ /** Home directory for `~/` expansion. Defaults to `os.homedir()`. */
9
+ homedir?: string;
10
+ }
11
+ export interface ResolvePastedImagePathOptions extends DecodePastedPathOptions {
12
+ /** Base directory for relative paths. Defaults to `process.cwd()`. */
13
+ cwd?: string;
14
+ }
15
+ /**
16
+ * Decode pasted text into a filesystem path candidate. No filesystem access.
17
+ *
18
+ * Handles terminal drag-drop shell escaping (`\ `, `\(`, ...; skipped on
19
+ * win32 where `\` is the path separator), quoted paths, `file://` URIs
20
+ * (drive-letter, `file://localhost`, and UNC forms on win32), and `~/`
21
+ * expansion. Returns `undefined` when the text is empty, spans multiple
22
+ * lines, or is an invalid `file://` URI.
23
+ */
24
+ export declare function decodePastedPathCandidate(text: string, options?: DecodePastedPathOptions): string | undefined;
25
+ /**
26
+ * Returns the resolved path when the whole pasted text is a single path to an
27
+ * existing image file (verified by extension AND content signature),
28
+ * otherwise `undefined` (the paste is inserted as text).
29
+ */
30
+ export declare function resolvePastedImagePath(text: string, options?: ResolvePastedImagePathOptions): string | undefined;
@@ -1,4 +1,12 @@
1
1
  import type { SpecialHandler } from "./types";
2
+ export interface YouTubeUrl {
3
+ videoId: string;
4
+ playlistId?: string;
5
+ }
6
+ /**
7
+ * Parse YouTube URL into components
8
+ */
9
+ export declare function parseYouTubeUrl(url: string): YouTubeUrl | null;
2
10
  /**
3
11
  * Handle YouTube URLs - fetch metadata and transcript
4
12
  */
package/package.json CHANGED
@@ -1,13 +1,10 @@
1
1
  {
2
2
  "type": "module",
3
3
  "name": "@gajae-code/coding-agent",
4
- "version": "0.8.2",
4
+ "version": "0.9.1",
5
5
  "description": "Gajae Code CLI with read, bash, edit, write tools and session management",
6
6
  "homepage": "https://gajae-code.com",
7
- "author": "Yeachan-Heo",
8
- "contributors": [
9
- "Mario Zechner"
10
- ],
7
+ "author": "Yeachan-Heo and Gajae Code Contributors",
11
8
  "license": "MIT",
12
9
  "repository": {
13
10
  "type": "git",
@@ -52,12 +49,12 @@
52
49
  "@agentclientprotocol/sdk": "0.21.0",
53
50
  "@babel/parser": "^7.29.3",
54
51
  "@mozilla/readability": "^0.6.0",
55
- "@gajae-code/stats": "0.8.2",
56
- "@gajae-code/agent-core": "0.8.2",
57
- "@gajae-code/ai": "0.8.2",
58
- "@gajae-code/natives": "0.8.2",
59
- "@gajae-code/tui": "0.8.2",
60
- "@gajae-code/utils": "0.8.2",
52
+ "@gajae-code/stats": "0.9.1",
53
+ "@gajae-code/agent-core": "0.9.1",
54
+ "@gajae-code/ai": "0.9.1",
55
+ "@gajae-code/natives": "0.9.1",
56
+ "@gajae-code/tui": "0.9.1",
57
+ "@gajae-code/utils": "0.9.1",
61
58
  "@puppeteer/browsers": "^2.13.0",
62
59
  "@types/turndown": "5.0.6",
63
60
  "@xterm/headless": "^6.0.0",
@@ -0,0 +1,58 @@
1
+ /**
2
+ * Single source of truth for append-only context-mode resolution and manager
3
+ * construction. Both the initial session build (`sdk.ts`) and the runtime
4
+ * model/setting-change path (`agent-session.ts`), plus the status UI, resolve
5
+ * through here so the auto allowlist and prefix-reset diagnostics never drift.
6
+ */
7
+
8
+ import { AppendOnlyContextManager } from "@gajae-code/agent-core";
9
+ import { logger } from "@gajae-code/utils";
10
+
11
+ /**
12
+ * Providers for which append-only context auto-enables. Exact provider-string
13
+ * match only: `anthropic` reached via a gateway/aggregator provider string
14
+ * (e.g. `openrouter`, a custom gateway) does NOT match and stays opt-in via
15
+ * `provider.appendOnlyContext: "on"`, because those transports can rewrite or
16
+ * renormalize the request in ways that have not been validated for append-only
17
+ * prefix stability.
18
+ */
19
+ export function providerSupportsAppendOnlyAuto(provider: string): boolean {
20
+ return provider === "deepseek" || provider === "anthropic";
21
+ }
22
+
23
+ /**
24
+ * Resolve whether to enable append-only context mode based on the setting and provider.
25
+ *
26
+ * - `"on"` → always enable
27
+ * - `"off"` → never enable
28
+ * - `"auto"` → enable for providers with strong prompt-prefix caching that this
29
+ * harness has validated (see {@link providerSupportsAppendOnlyAuto})
30
+ */
31
+ export function resolveAppendOnlyMode(setting: "auto" | "on" | "off" | undefined, provider: string): boolean {
32
+ switch (setting ?? "auto") {
33
+ case "on":
34
+ return true;
35
+ case "off":
36
+ return false;
37
+ default:
38
+ return providerSupportsAppendOnlyAuto(provider);
39
+ }
40
+ }
41
+
42
+ /**
43
+ * Construct an {@link AppendOnlyContextManager} wired to emit per-session
44
+ * stable-prefix reset diagnostics. Use this at every creation site so the
45
+ * telemetry is uniform.
46
+ */
47
+ export function createAppendOnlyContextManager(provider: string | undefined): AppendOnlyContextManager {
48
+ return new AppendOnlyContextManager({
49
+ onPrefixChange: info =>
50
+ logger.debug("append-only stable prefix changed (cache prefix reset)", {
51
+ provider,
52
+ from: info.from,
53
+ to: info.to,
54
+ version: info.version,
55
+ reason: info.from === "<unbuilt>" ? "initial-build" : "prefix-mutation",
56
+ }),
57
+ });
58
+ }
@@ -22,7 +22,7 @@ You are running an autonomous experiment loop. Keep iterating until the user int
22
22
  ### Available tools
23
23
  - `init_experiment` — open or reconfigure the session. Pass `new_segment: true` to start a fresh baseline within the current session.
24
24
  - `run_experiment` — run the benchmark (`bash autoresearch.sh`). Output is captured automatically and `METRIC name=value` / `ASI key=value` lines printed by the harness are parsed back to you. The command is fixed; if you need a different workload, edit `autoresearch.sh` and bump segment via `init_experiment new_segment: true`.
25
- - `log_experiment` — record the result. On `keep`, modified files are committed for you; on `discard`/`crash`/`checks_failed`, the worktree is reverted. Pass `flag_runs` to mark earlier runs as suspect; flagged runs are excluded from baseline and best-metric math.
25
+ - `log_experiment` — record the result. On `keep`, changes are committed only on a dedicated `autoresearch/*` branch; otherwise the tool warns and leaves files in the worktree. On `discard`/`crash`/`checks_failed`, the worktree is reverted. Pass `flag_runs` to mark earlier runs as suspect; flagged runs are excluded from baseline and best-metric math.
26
26
  - `update_notes` — replace the durable session playbook (`body`) or append to the ideas backlog (`append_idea`). The notes are injected into your system prompt every iteration.
27
27
 
28
28
  ### Operating protocol
@@ -62,7 +62,7 @@ export function createLogExperimentTool(
62
62
  name: "log_experiment",
63
63
  label: "Log Experiment",
64
64
  description:
65
- "Log the result of the latest run_experiment. Records the metric, optional ASI metadata, modified paths, and scope deviations. On `keep`, modified files are committed; on `discard`/`crash`/`checks_failed`, the worktree is reverted. Pass `flag_runs` to mark earlier runs as suspect; flagged runs are excluded from baseline and best-metric math.",
65
+ "Log the result of the latest run_experiment. Records the metric, optional ASI metadata, modified paths, and scope deviations. On `keep`, modified files are committed only on a dedicated `autoresearch/*` branch; otherwise the tool warns and leaves them in the worktree. On `discard`/`crash`/`checks_failed`, the worktree is reverted. Pass `flag_runs` to mark earlier runs as suspect; flagged runs are excluded from baseline and best-metric math.",
66
66
  parameters: logExperimentSchema,
67
67
  defaultInactive: true,
68
68
  async execute(_toolCallId, params, _signal, _onUpdate, ctx) {
@@ -22,6 +22,11 @@ export interface RuleFrontmatter {
22
22
  scope?: string | string[];
23
23
  /** Per-rule TTSR interrupt mode override. */
24
24
  interruptMode?: "never" | "prose-only" | "tool-only" | "always";
25
+ /** Per-rule TTSR repeat mode override. */
26
+ repeatMode?: "once" | "after-gap";
27
+ /** Per-rule TTSR repeat gap override. */
28
+ repeatGap?: number;
29
+
25
30
  [key: string]: unknown;
26
31
  }
27
32
 
@@ -47,6 +52,10 @@ export interface Rule {
47
52
  scope?: string[];
48
53
  /** Per-rule TTSR interrupt mode override (falls back to global ttsr.interruptMode). */
49
54
  interruptMode?: "never" | "prose-only" | "tool-only" | "always";
55
+ /** Per-rule TTSR repeat mode override (falls back to global ttsr.repeatMode). */
56
+ repeatMode?: "once" | "after-gap";
57
+ /** Per-rule TTSR repeat gap override (falls back to global ttsr.repeatGap). */
58
+ repeatGap?: number;
50
59
  /** Source metadata */
51
60
  _source: SourceMeta;
52
61
  }
@@ -49,14 +49,38 @@ type CliSettingDef = {
49
49
 
50
50
  const ALL_SETTING_PATHS = Object.keys(SETTINGS_SCHEMA) as SettingPath[];
51
51
  const REDACTED_SECRET_VALUE = "<redacted>";
52
- const SECRET_SETTING_SEGMENT_PATTERN = /(?:api[-_]?key|token|secret|password|passwd|pwd|credential)/i;
52
+ const SECRET_SETTING_WORDS = new Set(["token", "secret", "password", "passwd", "pwd", "credential", "credentials"]);
53
+ const SECRET_SETTING_COMPOUND_PREFIXES = [
54
+ "api",
55
+ "auth",
56
+ "access",
57
+ "refresh",
58
+ "bearer",
59
+ "session",
60
+ "client",
61
+ "broker",
62
+ "bot",
63
+ "basic",
64
+ ];
65
+ const SECRET_SETTING_COMPOUND_SUFFIXES = ["token", "secret", "password", "credential"];
66
+
67
+ function isSecretSettingSegment(segment: string): boolean {
68
+ const normalized = segment.toLowerCase();
69
+ if (SECRET_SETTING_WORDS.has(normalized)) return true;
70
+ if (/api[-_]?key/i.test(segment)) return true;
71
+ const words = normalized.split(/[-_]/).filter(Boolean);
72
+ if (words.some(word => SECRET_SETTING_WORDS.has(word))) return true;
73
+ return SECRET_SETTING_COMPOUND_PREFIXES.some(prefix =>
74
+ SECRET_SETTING_COMPOUND_SUFFIXES.some(suffix => normalized === `${prefix}${suffix}`),
75
+ );
76
+ }
53
77
 
54
78
  function isSecretSettingPath(path: string): boolean {
55
- return path.split(".").some(segment => SECRET_SETTING_SEGMENT_PATTERN.test(segment));
79
+ return path.split(".").some(segment => isSecretSettingSegment(segment));
56
80
  }
57
81
 
58
82
  function redactConfigValue(path: string, value: unknown, showSecrets?: boolean): unknown {
59
- if (showSecrets || typeof value !== "string" || !isSecretSettingPath(path)) {
83
+ if (showSecrets || value === undefined || value === null || !isSecretSettingPath(path)) {
60
84
  return value;
61
85
  }
62
86
  return REDACTED_SECRET_VALUE;