@gajae-code/coding-agent 0.2.2 → 0.2.3

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 (78) hide show
  1. package/CHANGELOG.md +28 -0
  2. package/dist/types/cli/setup-cli.d.ts +1 -0
  3. package/dist/types/commands/deep-interview.d.ts +41 -0
  4. package/dist/types/commands/setup.d.ts +3 -0
  5. package/dist/types/config/settings-schema.d.ts +36 -0
  6. package/dist/types/discovery/helpers.d.ts +2 -0
  7. package/dist/types/extensibility/extensions/types.d.ts +6 -0
  8. package/dist/types/gjc-runtime/deep-interview-runtime.d.ts +18 -0
  9. package/dist/types/hooks/skill-state.d.ts +5 -0
  10. package/dist/types/memories/index.d.ts +1 -1
  11. package/dist/types/memory-backend/local-backend.d.ts +3 -3
  12. package/dist/types/modes/components/hook-selector.d.ts +7 -0
  13. package/dist/types/modes/components/settings-selector.d.ts +0 -2
  14. package/dist/types/modes/utils/context-usage.d.ts +6 -2
  15. package/dist/types/sdk.d.ts +6 -2
  16. package/dist/types/session/agent-session.d.ts +45 -1
  17. package/dist/types/session/session-manager.d.ts +3 -0
  18. package/dist/types/setup/model-onboarding-guidance.d.ts +1 -0
  19. package/dist/types/setup/provider-onboarding.d.ts +29 -5
  20. package/dist/types/skill-state/active-state.d.ts +26 -1
  21. package/dist/types/skill-state/deep-interview-mutation-guard.d.ts +1 -1
  22. package/dist/types/skill-state/initial-phase.d.ts +12 -0
  23. package/dist/types/task/executor.d.ts +2 -0
  24. package/dist/types/task/types.d.ts +11 -0
  25. package/dist/types/tools/index.d.ts +20 -1
  26. package/dist/types/tools/skill.d.ts +47 -0
  27. package/dist/types/utils/changelog.d.ts +18 -2
  28. package/package.json +7 -7
  29. package/src/cli/setup-cli.ts +26 -12
  30. package/src/cli.ts +1 -0
  31. package/src/commands/deep-interview.ts +25 -2
  32. package/src/commands/setup.ts +2 -0
  33. package/src/commands/state.ts +1 -0
  34. package/src/config/settings-schema.ts +41 -0
  35. package/src/defaults/gjc/skills/deep-interview/SKILL.md +19 -1
  36. package/src/defaults/gjc/skills/ralplan/SKILL.md +8 -0
  37. package/src/defaults/gjc/skills/team/SKILL.md +10 -0
  38. package/src/defaults/gjc/skills/ultragoal/SKILL.md +10 -0
  39. package/src/discovery/helpers.ts +24 -1
  40. package/src/extensibility/extensions/types.ts +6 -0
  41. package/src/gjc-runtime/deep-interview-runtime.ts +268 -1
  42. package/src/gjc-runtime/state-runtime.ts +173 -4
  43. package/src/hooks/skill-state.ts +8 -6
  44. package/src/internal-urls/docs-index.generated.ts +2 -2
  45. package/src/internal-urls/memory-protocol.ts +3 -2
  46. package/src/main.ts +2 -3
  47. package/src/memories/index.ts +2 -1
  48. package/src/memory-backend/local-backend.ts +14 -6
  49. package/src/modes/components/hook-selector.ts +156 -1
  50. package/src/modes/components/settings-selector.ts +5 -12
  51. package/src/modes/controllers/command-controller.ts +2 -3
  52. package/src/modes/controllers/extension-ui-controller.ts +1 -0
  53. package/src/modes/controllers/selector-controller.ts +4 -11
  54. package/src/modes/utils/context-usage.ts +66 -17
  55. package/src/prompts/agents/architect.md +3 -0
  56. package/src/prompts/agents/executor.md +2 -0
  57. package/src/prompts/agents/frontmatter.md +1 -0
  58. package/src/prompts/system/subagent-system-prompt.md +6 -0
  59. package/src/prompts/tools/skill.md +28 -0
  60. package/src/prompts/tools/task.md +3 -0
  61. package/src/sdk.ts +50 -10
  62. package/src/session/agent-session.ts +204 -21
  63. package/src/session/session-manager.ts +9 -1
  64. package/src/setup/model-onboarding-guidance.ts +6 -3
  65. package/src/setup/provider-onboarding.ts +177 -16
  66. package/src/skill-state/active-state.ts +150 -25
  67. package/src/skill-state/deep-interview-mutation-guard.ts +11 -24
  68. package/src/skill-state/initial-phase.ts +17 -0
  69. package/src/slash-commands/builtin-registry.ts +51 -13
  70. package/src/slash-commands/helpers/context-report.ts +123 -13
  71. package/src/task/agents.ts +1 -0
  72. package/src/task/executor.ts +9 -1
  73. package/src/task/index.ts +91 -4
  74. package/src/task/types.ts +6 -0
  75. package/src/tools/ask.ts +2 -0
  76. package/src/tools/index.ts +23 -1
  77. package/src/tools/skill.ts +153 -0
  78. package/src/utils/changelog.ts +67 -44
package/CHANGELOG.md CHANGED
@@ -2,6 +2,34 @@
2
2
 
3
3
  ## [Unreleased]
4
4
 
5
+ ## [0.2.3] - 2026-06-01
6
+
7
+ ### Added
8
+
9
+ - Added `/provider add --preset minimax|minimax-cn|glm` and matching `gjc setup provider --preset ...` shortcuts for OpenAI-compatible MiniMax and GLM/zAI custom-provider onboarding.
10
+ - Added a built-in `skill` tool so the agent can chain into another loaded skill on its next turn. Mirrors `/skill:<name>` typing and subagent `autoloadSkills` by dispatching the chained skill's SKILL.md as a user-attribution custom message; controlled by the new `skill.enabled` setting (default true).
11
+ - Added explicit fork-context task subagents with sanitized bounded parent-history seeds, global `task.forkContext.enabled`, per-agent `forkContext: allowed`, per-task `inheritContext: true`, audit-visible seed metadata, and fresh provider transport state by default.
12
+ - Defaulted the bundled `executor` and `architect` agents to `forkContext: allowed` so callers can opt them into a sanitized parent-context seed via `task({ inheritContext: true })`; per-task selection remains explicit (default false).
13
+ - Added a `/context` slash command that surfaces the active session's token usage breakdown via `buildSessionContext` without forking prompt assembly, so users can see active context before sessions overflow ([#150](https://github.com/Yeachan-Heo/gajae-code/pull/150)).
14
+ - Added multi-line focused-option rendering to the `ask` tool's `HookSelectorComponent` via an opt-in `wrapFocused` flag so long option labels stay readable in plan-mode and other shared consumers ([#148](https://github.com/Yeachan-Heo/gajae-code/pull/148)).
15
+ - Added a sanctioned native deep-interview spec persistence bridge so deep-interview can save final specs under `.gjc/specs/` before deliberate ralplan chaining without caller-side `.gjc` writes ([#134](https://github.com/Yeachan-Heo/gajae-code/pull/134)).
16
+ - Added the skill chaining lifecycle's `handoff` state verb with same-turn dispatch and atomic HUD-truth synchronization across callee mode-state, caller mode-state, session active-state, and root active-state ([#132](https://github.com/Yeachan-Heo/gajae-code/pull/132)).
17
+
18
+ ### Changed
19
+
20
+ - Clarified the README to position team as optional and ultragoal as implementation-through-evidence, so docs readers see workflow handoffs without spelunking into skill sources ([#145](https://github.com/Yeachan-Heo/gajae-code/pull/145)).
21
+ - Migrated CI to the gajae self-hosted Linux runner with fork-PR guards, idempotent `fd` symlink setup, and Node 24 pinning for self-hosted jobs ([#124](https://github.com/Yeachan-Heo/gajae-code/pull/124)).
22
+
23
+ ### Fixed
24
+
25
+ - Enforced the deep-interview phase boundary so active interviews block mutation tools until a handoff/spec is produced.
26
+ - Made settings theme browsing confirm-only so arrowing through themes no longer changes the rendered theme before the displayed/persisted theme name changes.
27
+ - Made startup CHANGELOG display deterministic by embedding `packages/coding-agent/CHANGELOG.md` into the binary so post-update launches show the shipped history regardless of cwd or `GJC_PACKAGE_DIR`/`PI_PACKAGE_DIR` overrides.
28
+ - Registered `gjc update` as a public root subcommand so it invokes the bundled updater instead of routing into the interactive launcher.
29
+ - Fixed local memory backend persistence so manual enqueue/rebuild starts maintenance immediately and prompt injection reads the active session's memory root.
30
+ - Aligned release-bump CI tests with the highest bundled upstream Claude family and stopped cancelling TTSR retries when an aborted partial was not persisted, so dev PRs no longer regress on v0.2.2-style release assumptions ([#142](https://github.com/Yeachan-Heo/gajae-code/pull/142)).
31
+ - Added a runtime guard in the built-in `skill` tool that rejects re-entry into the currently active skill via a typed active-skill bridge from agent sessions into tool sessions, preventing recursive skill handoffs that prompt-only guidance could not stop ([#129](https://github.com/Yeachan-Heo/gajae-code/pull/129)).
32
+
5
33
  ## [0.2.2] - 2026-05-31
6
34
 
7
35
  ### Added
@@ -5,6 +5,7 @@ export interface SetupCommandArgs {
5
5
  json?: boolean;
6
6
  check?: boolean;
7
7
  force?: boolean;
8
+ preset?: string;
8
9
  compat?: string;
9
10
  provider?: string;
10
11
  baseUrl?: string;
@@ -2,6 +2,47 @@ import { Command } from "@gajae-code/utils/cli";
2
2
  export default class DeepInterview extends Command {
3
3
  static description: string;
4
4
  static strict: boolean;
5
+ static flags: {
6
+ quick: import("@gajae-code/utils/cli").FlagDescriptor<"boolean"> & {
7
+ description: string;
8
+ };
9
+ standard: import("@gajae-code/utils/cli").FlagDescriptor<"boolean"> & {
10
+ description: string;
11
+ };
12
+ deep: import("@gajae-code/utils/cli").FlagDescriptor<"boolean"> & {
13
+ description: string;
14
+ };
15
+ threshold: import("@gajae-code/utils/cli").FlagDescriptor<"string"> & {
16
+ description: string;
17
+ };
18
+ "threshold-source": import("@gajae-code/utils/cli").FlagDescriptor<"string"> & {
19
+ description: string;
20
+ };
21
+ "session-id": import("@gajae-code/utils/cli").FlagDescriptor<"string"> & {
22
+ description: string;
23
+ };
24
+ write: import("@gajae-code/utils/cli").FlagDescriptor<"boolean"> & {
25
+ description: string;
26
+ };
27
+ stage: import("@gajae-code/utils/cli").FlagDescriptor<"string"> & {
28
+ description: string;
29
+ };
30
+ slug: import("@gajae-code/utils/cli").FlagDescriptor<"string"> & {
31
+ description: string;
32
+ };
33
+ spec: import("@gajae-code/utils/cli").FlagDescriptor<"string"> & {
34
+ description: string;
35
+ };
36
+ handoff: import("@gajae-code/utils/cli").FlagDescriptor<"string"> & {
37
+ description: string;
38
+ };
39
+ deliberate: import("@gajae-code/utils/cli").FlagDescriptor<"boolean"> & {
40
+ description: string;
41
+ };
42
+ json: import("@gajae-code/utils/cli").FlagDescriptor<"boolean"> & {
43
+ description: string;
44
+ };
45
+ };
5
46
  static examples: string[];
6
47
  run(): Promise<void>;
7
48
  }
@@ -24,6 +24,9 @@ export default class Setup extends Command {
24
24
  json: import("@gajae-code/utils/cli").FlagDescriptor<"boolean"> & {
25
25
  description: string;
26
26
  };
27
+ preset: import("@gajae-code/utils/cli").FlagDescriptor<"string"> & {
28
+ description: string;
29
+ };
27
30
  compat: import("@gajae-code/utils/cli").FlagDescriptor<"string"> & {
28
31
  description: string;
29
32
  };
@@ -2295,6 +2295,15 @@ export declare const SETTINGS_SCHEMA: {
2295
2295
  readonly description: "Enable the checkpoint and rewind tools for context checkpointing";
2296
2296
  };
2297
2297
  };
2298
+ readonly "skill.enabled": {
2299
+ readonly type: "boolean";
2300
+ readonly default: true;
2301
+ readonly ui: {
2302
+ readonly tab: "tools";
2303
+ readonly label: "Skill";
2304
+ readonly description: "Enable the skill tool so the agent can chain into another available skill on its next turn";
2305
+ };
2306
+ };
2298
2307
  readonly "fetch.enabled": {
2299
2308
  readonly type: "boolean";
2300
2309
  readonly default: true;
@@ -2705,6 +2714,33 @@ export declare const SETTINGS_SCHEMA: {
2705
2714
  readonly description: "Allow subagents spawned via the task tool to use the lsp tool. Off by default to keep subagents cheap; enable when LSP-aware delegation is worth the extra tokens.";
2706
2715
  };
2707
2716
  };
2717
+ readonly "task.forkContext.enabled": {
2718
+ readonly type: "boolean";
2719
+ readonly default: false;
2720
+ readonly ui: {
2721
+ readonly tab: "tasks";
2722
+ readonly label: "Fork Context for Subagents";
2723
+ readonly description: "Allow explicitly opted-in subagents to start from a sanitized snapshot of parent context when both the agent and task item also opt in.";
2724
+ };
2725
+ };
2726
+ readonly "task.forkContext.maxMessages": {
2727
+ readonly type: "number";
2728
+ readonly default: 50;
2729
+ readonly ui: {
2730
+ readonly tab: "tasks";
2731
+ readonly label: "Fork Context Max Messages";
2732
+ readonly description: "Maximum parent messages copied into an explicitly opted-in subagent fork-context seed.";
2733
+ };
2734
+ };
2735
+ readonly "task.forkContext.maxTokens": {
2736
+ readonly type: "number";
2737
+ readonly default: 0;
2738
+ readonly ui: {
2739
+ readonly tab: "tasks";
2740
+ readonly label: "Fork Context Max Tokens";
2741
+ readonly description: "Approximate token cap for fork-context seeds. 0 uses 25% of the target model context window.";
2742
+ };
2743
+ };
2708
2744
  readonly "task.maxRecursionDepth": {
2709
2745
  readonly type: "number";
2710
2746
  readonly default: 2;
@@ -3,6 +3,7 @@ import type { ExtensionModule } from "../capability/extension-module";
3
3
  import { type Rule } from "../capability/rule";
4
4
  import type { Skill } from "../capability/skill";
5
5
  import type { LoadContext, LoadResult, SourceMeta } from "../capability/types";
6
+ import type { ForkContextPolicy } from "../task/types";
6
7
  /**
7
8
  * Standard paths for each config source.
8
9
  */
@@ -104,6 +105,7 @@ export interface ParsedAgentFields {
104
105
  autoloadSkills?: string[];
105
106
  blocking?: boolean;
106
107
  hide?: boolean;
108
+ forkContext?: ForkContextPolicy;
107
109
  }
108
110
  /**
109
111
  * Parse agent fields from frontmatter.
@@ -50,6 +50,12 @@ export interface ExtensionUIDialogOptions {
50
50
  onExternalEditor?: () => void;
51
51
  /** Optional footer hint text rendered by interactive selector */
52
52
  helpText?: string;
53
+ /**
54
+ * For interactive TUI select dialogs, render the focused option across
55
+ * multiple rows instead of truncating it. This is a select-only rendering
56
+ * hint; non-TUI bridges (RPC, ACP) drop it and do not serialize it.
57
+ */
58
+ wrapFocused?: boolean;
53
59
  }
54
60
  /** Raw terminal input listener for extensions. */
55
61
  export type TerminalInputHandler = (data: string) => {
@@ -12,4 +12,22 @@ export interface DeepInterviewCommandResult {
12
12
  stdout?: string;
13
13
  stderr?: string;
14
14
  }
15
+ export interface ResolvedDeepInterviewSpecWriteArgs {
16
+ stage: "final";
17
+ slug: string;
18
+ spec: string;
19
+ sessionId?: string;
20
+ json: boolean;
21
+ deliberate: boolean;
22
+ handoff?: "ralplan";
23
+ }
24
+ export interface PersistedDeepInterviewSpec {
25
+ slug: string;
26
+ path: string;
27
+ stage: "final";
28
+ sha256: string;
29
+ createdAt: string;
30
+ statePath: string;
31
+ }
32
+ export declare function persistDeepInterviewSpec(cwd: string, resolved: ResolvedDeepInterviewSpecWriteArgs): Promise<PersistedDeepInterviewSpec>;
15
33
  export declare function runNativeDeepInterviewCommand(args: string[], cwd?: string): Promise<DeepInterviewCommandResult>;
@@ -50,6 +50,9 @@ export interface ModeState {
50
50
  thread_id?: string;
51
51
  cwd?: string;
52
52
  updated_at?: string;
53
+ handoff_from?: string;
54
+ handoff_to?: string;
55
+ handoff_at?: string;
53
56
  [key: string]: unknown;
54
57
  }
55
58
  export interface RecordSkillActivationInput {
@@ -79,6 +82,8 @@ export interface UserPromptSubmitStateInput {
79
82
  export declare function detectSkillKeywords(text: string): SkillKeywordMatch[];
80
83
  export declare function detectPrimarySkillKeyword(text: string): SkillKeywordMatch | null;
81
84
  export declare function resolveGjcStateDir(cwd: string, stateDir?: string): string;
85
+ import { initialPhaseForSkill } from "../skill-state/initial-phase";
86
+ export { initialPhaseForSkill };
82
87
  export declare function readVisibleSkillActiveState(cwd: string, sessionId?: string, stateDir?: string): Promise<SkillActiveState | null>;
83
88
  export declare function recordSkillActivation(input: RecordSkillActivationInput): Promise<SkillActiveState | null>;
84
89
  export declare function buildActiveUltragoalPromptContext(input: UserPromptSubmitStateInput): Promise<string | null>;
@@ -16,7 +16,7 @@ export declare function startMemoryStartupTask(options: {
16
16
  /**
17
17
  * Build memory usage instructions for prompt injection.
18
18
  */
19
- export declare function buildMemoryToolDeveloperInstructions(agentDir: string, settings: Settings): Promise<string | undefined>;
19
+ export declare function buildMemoryToolDeveloperInstructions(agentDir: string, settings: Settings, session?: AgentSession): Promise<string | undefined>;
20
20
  /**
21
21
  * Clear all persisted memory state and generated artifacts.
22
22
  */
@@ -2,8 +2,8 @@ import type { MemoryBackend } from "./types";
2
2
  /**
3
3
  * Wraps the existing `memories/` module as a `MemoryBackend`.
4
4
  *
5
- * No behavioural change every call delegates to the legacy entry points so
6
- * the local memory pipeline (rollout summarisation SQLite memory_summary.md)
7
- * keeps working exactly as before.
5
+ * The local pipeline owns rollout summarisation, SQLite retention, and
6
+ * `memory_summary.md`. Prompt reads use the live session cwd when available so
7
+ * manual enqueue/rebuild and startup hydration address the same memory root.
8
8
  */
9
9
  export declare const localBackend: MemoryBackend;
@@ -14,6 +14,13 @@ export interface HookSelectorOptions {
14
14
  onRight?: () => void;
15
15
  onExternalEditor?: () => void;
16
16
  helpText?: string;
17
+ /**
18
+ * When true, the focused option's label wraps across multiple rows so the
19
+ * full text is visible. Non-focused options remain single-row with the
20
+ * existing `…` truncation hint. When unset/false, rendering is
21
+ * byte-identical to the previous implementation for all consumers.
22
+ */
23
+ wrapFocused?: boolean;
17
24
  }
18
25
  export declare class HookSelectorComponent extends Container {
19
26
  #private;
@@ -29,8 +29,6 @@ export interface StatusLinePreviewSettings {
29
29
  export interface SettingsCallbacks {
30
30
  /** Called when any setting value changes */
31
31
  onChange: (path: SettingPath, newValue: unknown) => void;
32
- /** Called for theme preview while browsing */
33
- onThemePreview?: (theme: string) => void | Promise<void>;
34
32
  /** Called for status line preview while configuring */
35
33
  onStatusLinePreview?: (settings: StatusLinePreviewSettings) => void;
36
34
  /** Get current rendered status line for inline preview */
@@ -1,9 +1,10 @@
1
+ import type { AgentMessage } from "@gajae-code/agent-core";
1
2
  import type { Model } from "@gajae-code/ai";
2
3
  import type { Skill } from "../../extensibility/skills";
3
4
  import type { AgentSession } from "../../session/agent-session";
4
5
  import type { Tool } from "../../tools";
5
6
  import type { theme as Theme } from "../theme/theme";
6
- type CategoryId = "systemPrompt" | "systemContext" | "systemTools" | "skills" | "messages";
7
+ type CategoryId = "systemPrompt" | "systemContext" | "rules" | "tools" | "skills" | "messages" | "lastUserTurn";
7
8
  interface CategoryInfo {
8
9
  id: CategoryId;
9
10
  label: string;
@@ -15,6 +16,7 @@ export interface ContextBreakdown {
15
16
  model: Model | undefined;
16
17
  contextWindow: number;
17
18
  categories: CategoryInfo[];
19
+ lastUserTurnTokens: number;
18
20
  usedTokens: number;
19
21
  autoCompactBufferTokens: number;
20
22
  freeTokens: number;
@@ -38,7 +40,9 @@ export declare function computeNonMessageTokens(session: AgentSession): number;
38
40
  * Compute a breakdown of estimated context usage by category for the active
39
41
  * session and model.
40
42
  */
41
- export declare function computeContextBreakdown(session: AgentSession): ContextBreakdown;
43
+ export declare function computeContextBreakdown(session: AgentSession, options?: {
44
+ messages?: readonly AgentMessage[];
45
+ }): ContextBreakdown;
42
46
  /**
43
47
  * Render a colorful context-usage panel as ANSI text. Output is a series of
44
48
  * lines pairing the grid (left) with the legend (right).
@@ -1,5 +1,5 @@
1
1
  import { type AgentTelemetryConfig, type ThinkingLevel } from "@gajae-code/agent-core";
2
- import { type Model } from "@gajae-code/ai";
2
+ import { type Model, type ProviderSessionState } from "@gajae-code/ai";
3
3
  import { type Rule } from "./capability/rule";
4
4
  import { ModelRegistry } from "./config/model-registry";
5
5
  import { type ScopedModelSelection } from "./config/model-resolver";
@@ -15,7 +15,7 @@ import type { HindsightSessionState } from "./hindsight/state";
15
15
  import { type LocalProtocolOptions } from "./internal-urls";
16
16
  import { AgentRegistry } from "./registry/agent-registry";
17
17
  import { MCPManager } from "./runtime-mcp";
18
- import { AgentSession } from "./session/agent-session";
18
+ import { AgentSession, type ForkContextSeed } from "./session/agent-session";
19
19
  import { AuthStorage } from "./session/auth-storage";
20
20
  import { SessionManager } from "./session/session-manager";
21
21
  import { type BuildSystemPromptResult } from "./system-prompt";
@@ -121,6 +121,10 @@ export interface CreateAgentSessionOptions {
121
121
  * `@opentelemetry/api` package returns a no-op tracer in that case.
122
122
  */
123
123
  telemetry?: AgentTelemetryConfig;
124
+ /** Optional fork-context seed used to initialize a child session before its first prompt. */
125
+ forkContextSeed?: ForkContextSeed;
126
+ /** Optional provider state override. Fork-context children should omit this by default. */
127
+ providerSessionState?: Map<string, ProviderSessionState>;
124
128
  }
125
129
  /** Result from createAgentSession */
126
130
  export interface CreateAgentSessionResult {
@@ -12,9 +12,32 @@
12
12
  *
13
13
  * Modes use this class and add their own I/O layer on top.
14
14
  */
15
- import { type Agent, type AgentEvent, type AgentMessage, type AgentState, type AgentTool, ThinkingLevel } from "@gajae-code/agent-core";
15
+ import { type Agent, type AgentEvent, type AgentMessage, type AgentState, type AgentTool, type StablePrefixSnapshot, ThinkingLevel } from "@gajae-code/agent-core";
16
16
  import { type CompactionResult } from "@gajae-code/agent-core/compaction";
17
17
  import type { AssistantMessage, Effort, ImageContent, Message, MessageAttribution, Model, ProviderSessionState, ServiceTier, SimpleStreamOptions, TextContent, ToolChoice, UsageReport } from "@gajae-code/ai";
18
+ export interface ForkContextSeedMetadata {
19
+ sourceSessionId: string;
20
+ parentMessageCount: number;
21
+ includedMessages: number;
22
+ skippedMessages: number;
23
+ approximateTokens: number;
24
+ maxMessages: number;
25
+ maxTokens: number;
26
+ skippedReasons: Record<string, number>;
27
+ }
28
+ export interface ForkContextSeed {
29
+ messages: Message[];
30
+ agentMessages: AgentMessage[];
31
+ metadata: ForkContextSeedMetadata;
32
+ cacheIdentity?: string;
33
+ appendOnlyPrefixSnapshot?: StablePrefixSnapshot;
34
+ }
35
+ export interface ForkContextSeedOptions {
36
+ maxMessages: number;
37
+ maxTokens: number;
38
+ cacheIdentity?: string;
39
+ signal?: AbortSignal;
40
+ }
18
41
  import { type AsyncJob, type AsyncJobDeliveryState, AsyncJobManager } from "../async";
19
42
  import type { Rule } from "../capability/rule";
20
43
  import { type ModelRegistry } from "../config/model-registry";
@@ -138,6 +161,8 @@ export interface AgentSessionConfig {
138
161
  skillsSettings?: SkillsSettings;
139
162
  /** Model registry for API key resolution and model discovery */
140
163
  modelRegistry: ModelRegistry;
164
+ /** Task recursion depth for nested sessions. Top-level sessions use 0. */
165
+ taskDepth?: number;
141
166
  /** Tool registry for LSP and settings */
142
167
  toolRegistry?: Map<string, AgentTool>;
143
168
  /** Current session pre-LLM message transform pipeline */
@@ -188,6 +213,10 @@ export interface AgentSessionConfig {
188
213
  * **MUST NOT** dispose it on their own teardown.
189
214
  */
190
215
  ownedAsyncJobManager?: AsyncJobManager;
216
+ /** Optional fork-context seed used to initialize a child session before its first prompt. */
217
+ forkContextSeed?: ForkContextSeed;
218
+ /** Optional provider state override. Fork-context children should omit this by default. */
219
+ providerSessionState?: Map<string, ProviderSessionState>;
191
220
  /** Agent identity (registry id like "0-Main" or "3-Alice") used for IRC routing. */
192
221
  agentId?: string;
193
222
  /** Shared agent registry (for forwarding IRC observations to the main session UI). */
@@ -199,6 +228,8 @@ export interface AgentSessionConfig {
199
228
  * so that credential sticky selection is consistent with the session's streaming calls.
200
229
  */
201
230
  providerSessionId?: string;
231
+ /** Optional provider-facing cache identity, distinct from logical session identity. */
232
+ providerCacheSessionId?: string;
202
233
  }
203
234
  /** Options for AgentSession.prompt() */
204
235
  export interface PromptOptions {
@@ -263,6 +294,7 @@ export declare class AgentSession {
263
294
  readonly agent: Agent;
264
295
  readonly sessionManager: SessionManager;
265
296
  readonly settings: Settings;
297
+ readonly taskDepth: number;
266
298
  readonly yieldQueue: YieldQueue;
267
299
  readonly configWarnings: string[];
268
300
  readonly rawSseDebugBuffer: RawSseDebugBuffer;
@@ -279,12 +311,24 @@ export declare class AgentSession {
279
311
  setForcedToolChoice(toolName: string): void;
280
312
  /** The tool-choice queue: forces forthcoming tool invocations and carries handlers. */
281
313
  get toolChoiceQueue(): ToolChoiceQueue;
314
+ /** Current skill prompt executing in this session, if any. */
315
+ getActiveSkillState(): {
316
+ skill: string;
317
+ session_id?: string;
318
+ } | undefined;
319
+ /** Best-effort accessor for the active skill's `current_phase` field from
320
+ * its persisted mode-state file. Used by the `skill` tool to enforce the
321
+ * terminal-phase chain guard. Returns undefined when no active skill is
322
+ * recorded or the mode-state file is missing/unreadable; callers should
323
+ * treat undefined as a non-terminal phase (refuses to chain). */
324
+ getActiveSkillPhase(): string | undefined;
282
325
  /** Peek the in-flight directive's invocation handler for use by the resolve tool. */
283
326
  peekQueueInvoker(): ((input: unknown) => Promise<unknown> | unknown) | undefined;
284
327
  peekStandingResolveHandler(): ((input: unknown) => Promise<unknown> | unknown) | undefined;
285
328
  setStandingResolveHandler(handler: ((input: unknown) => Promise<unknown> | unknown) | null): void;
286
329
  /** Provider-scoped mutable state store for transport/session caches. */
287
330
  get providerSessionState(): Map<string, ProviderSessionState>;
331
+ buildForkContextSeed(options: ForkContextSeedOptions): Promise<ForkContextSeed>;
288
332
  getHindsightSessionState(): HindsightSessionState | undefined;
289
333
  setHindsightSessionState(state: HindsightSessionState | undefined): HindsightSessionState | undefined;
290
334
  /** TTSR manager for time-traveling stream rules */
@@ -111,6 +111,8 @@ export interface SessionInitEntry extends SessionEntryBase {
111
111
  tools: string[];
112
112
  /** Output schema if structured output was requested */
113
113
  outputSchema?: unknown;
114
+ /** Fork-context seed metadata for subagent debugging/replay. */
115
+ forkContext?: unknown;
114
116
  }
115
117
  /** Mode change entry - tracks agent mode transitions (e.g. plan mode). */
116
118
  export interface ModeChangeEntry extends SessionEntryBase {
@@ -393,6 +395,7 @@ export declare class SessionManager {
393
395
  task: string;
394
396
  tools: string[];
395
397
  outputSchema?: unknown;
398
+ forkContext?: unknown;
396
399
  }): string;
397
400
  /** Append a compaction summary as child of current leaf, then advance leaf. Returns entry id. */
398
401
  appendCompaction<T = unknown>(summary: string, shortSummary: string | undefined, firstKeptEntryId: string, tokensBefore: number, details?: T, fromExtension?: boolean, preserveData?: Record<string, unknown>): string;
@@ -1,4 +1,5 @@
1
1
  export declare const MODEL_ONBOARDING_API_PROVIDER_COMMAND = "/provider add --compat <openai|anthropic> --provider <id> --base-url <url> --api-key-env <ENV> --model <model>";
2
+ export declare const MODEL_ONBOARDING_PROVIDER_PRESET_COMMAND = "/provider add --preset <minimax|minimax-cn|glm>";
2
3
  export declare const MODEL_ONBOARDING_SETUP_COMMAND = "gjc setup provider";
3
4
  export declare const MODEL_ONBOARDING_OAUTH_COMMAND = "/provider login [provider-id] or /login [provider-id]";
4
5
  export declare function formatModelOnboardingGuidance(): string;
@@ -1,28 +1,52 @@
1
+ import { type ModelsConfig } from "../config/models-config-schema";
1
2
  export type ProviderCompatibility = "openai" | "anthropic";
3
+ export type ProviderSetupApi = "openai-responses" | "openai-completions" | "anthropic-messages";
2
4
  export interface ProviderSetupInput {
3
- compatibility: ProviderCompatibility;
4
- providerId: string;
5
- baseUrl: string;
5
+ compatibility?: ProviderCompatibility;
6
+ preset?: string;
7
+ providerId?: string;
8
+ baseUrl?: string;
6
9
  apiKey?: string;
7
10
  apiKeyEnv?: string;
8
- models: string[];
11
+ models?: string[];
9
12
  modelsPath?: string;
10
13
  force?: boolean;
11
14
  }
12
15
  export interface ProviderSetupResult {
13
16
  providerId: string;
14
17
  compatibility: ProviderCompatibility;
15
- api: "openai-responses" | "anthropic-messages";
18
+ api: ProviderSetupApi;
16
19
  baseUrl: string;
17
20
  modelIds: string[];
18
21
  modelsPath: string;
19
22
  redactedApiKey: string;
20
23
  credentialSource: "literal" | "env";
24
+ preset?: string;
25
+ presetName?: string;
26
+ }
27
+ type ProviderConfig = NonNullable<NonNullable<ModelsConfig["providers"]>[string]>;
28
+ type ProviderCompatConfig = NonNullable<ProviderConfig["compat"]>;
29
+ interface ProviderPreset {
30
+ id: string;
31
+ aliases: readonly string[];
32
+ name: string;
33
+ description: string;
34
+ compatibility: ProviderCompatibility;
35
+ api: ProviderSetupApi;
36
+ providerId: string;
37
+ baseUrl: string;
38
+ apiKeyEnv: string;
39
+ models: readonly string[];
40
+ compat?: ProviderCompatConfig;
21
41
  }
42
+ export declare const PROVIDER_PRESETS: readonly ProviderPreset[];
22
43
  export declare function getDefaultModelsPath(): string;
23
44
  export declare function normalizeProviderId(providerId: string): string;
24
45
  export declare function parseProviderCompatibility(value: string): ProviderCompatibility;
46
+ export declare function findProviderPreset(value: string | undefined): ProviderPreset | undefined;
47
+ export declare function formatProviderPresetList(): string;
25
48
  export declare function parseModelList(values: readonly string[]): string[];
26
49
  export declare function redactSecret(secret: string): string;
27
50
  export declare function addApiCompatibleProvider(input: ProviderSetupInput): Promise<ProviderSetupResult>;
28
51
  export declare function formatProviderSetupResult(result: ProviderSetupResult): string;
52
+ export {};
@@ -1,6 +1,5 @@
1
1
  import type { WorkflowStateReceipt } from "./workflow-state-contract";
2
2
  export declare const SKILL_ACTIVE_STATE_FILE = "skill-active-state.json";
3
- export declare const SKILL_ACTIVE_STALE_MS: number;
4
3
  export declare const CANONICAL_GJC_WORKFLOW_SKILLS: readonly ["deep-interview", "ralplan", "ultragoal", "team"];
5
4
  export type CanonicalGjcWorkflowSkill = (typeof CANONICAL_GJC_WORKFLOW_SKILLS)[number];
6
5
  export type WorkflowHudSeverity = "info" | "warning" | "blocked" | "error" | "success";
@@ -31,6 +30,9 @@ export interface SkillActiveEntry {
31
30
  hud?: WorkflowHudSummary;
32
31
  stale?: boolean;
33
32
  receipt?: WorkflowStateReceipt;
33
+ handoff_from?: string;
34
+ handoff_to?: string;
35
+ handoff_at?: string;
34
36
  }
35
37
  export interface SkillActiveState {
36
38
  version?: number;
@@ -63,6 +65,9 @@ export interface SyncSkillActiveStateOptions {
63
65
  source?: string;
64
66
  hud?: WorkflowHudSummary;
65
67
  receipt?: WorkflowStateReceipt;
68
+ handoff_from?: string;
69
+ handoff_to?: string;
70
+ handoff_at?: string;
66
71
  }
67
72
  export declare function normalizeWorkflowHudSummary(raw: unknown): WorkflowHudSummary | undefined;
68
73
  export declare function isCanonicalGjcWorkflowSkill(skill: string): skill is CanonicalGjcWorkflowSkill;
@@ -71,3 +76,23 @@ export declare function normalizeSkillActiveState(raw: unknown): SkillActiveStat
71
76
  export declare function getSkillActiveStatePaths(cwd: string, sessionId?: string): SkillActiveStatePaths;
72
77
  export declare function readVisibleSkillActiveState(cwd: string, sessionId?: string): Promise<SkillActiveState | null>;
73
78
  export declare function syncSkillActiveState(options: SyncSkillActiveStateOptions): Promise<void>;
79
+ export interface ApplyHandoffOptions {
80
+ cwd: string;
81
+ caller: SyncSkillActiveStateOptions;
82
+ callee: SyncSkillActiveStateOptions;
83
+ /** Shared timestamp; falls back to new Date().toISOString(). */
84
+ nowIso?: string;
85
+ /** When true, read errors other than ENOENT propagate. */
86
+ strict?: boolean;
87
+ }
88
+ /**
89
+ * Atomically apply a workflow-skill handoff to both the session-scoped and
90
+ * root `skill-active-state.json` files in a single write per file.
91
+ *
92
+ * Write order: **session first, root last**. The session file is the
93
+ * source of truth for HUD; the root aggregate must never lead the session
94
+ * during a handoff window. Each file is rewritten once with caller demoted
95
+ * to `active:false` (preserving `handoff_to`/`handoff_at` lineage) and
96
+ * callee promoted to `active:true` (with `handoff_from`/`handoff_at`).
97
+ */
98
+ export declare function applyHandoffToActiveState(options: ApplyHandoffOptions): Promise<void>;
@@ -1,5 +1,5 @@
1
1
  import type { AgentTool } from "@gajae-code/agent-core";
2
- export declare const DEEP_INTERVIEW_MUTATION_BLOCK_MESSAGE = "Deep-interview is active; continue interviewing with `ask`, write/finalize pending specs through the required GJC workflow CLI, or use an explicit force override. Direct `.gjc/` and product-code edits are blocked until explicit execution approval.";
2
+ export declare const DEEP_INTERVIEW_MUTATION_BLOCK_MESSAGE = "Deep-interview phase boundary: continue gathering context/questions/risks and emit a handoff/spec before code edits. Mutation tools and patch execution are blocked while deep-interview is active; finalize specs through `gjc deep-interview --write --stage final` or hand off to an execution phase.";
3
3
  export declare const WORKFLOW_STATE_MUTATION_BLOCK_MESSAGE = "Workflow state JSON is runtime-owned. Use `gjc state <skill> read|write --input '<json>'` for deep-interview, ralplan, ultragoal, and team. Planning artifacts under `.gjc/specs/` and `.gjc/plans/` remain allowed.";
4
4
  type ToolWithEditMode = AgentTool & {
5
5
  mode?: unknown;
@@ -0,0 +1,12 @@
1
+ import type { CanonicalGjcWorkflowSkill } from "./active-state";
2
+ /**
3
+ * Canonical initial phase for each GJC workflow skill. Used by both
4
+ * `recordSkillActivation` (UserPromptSubmit hook seeding initial mode-state)
5
+ * and the `gjc state <caller> handoff --to <callee>` runtime when promoting
6
+ * the callee.
7
+ *
8
+ * Keeping this mapping in a neutral skill-state module avoids cycles between
9
+ * `gjc-runtime/state-runtime.ts` and `hooks/skill-state.ts` (which pulls in
10
+ * session-manager and ultragoal verification code).
11
+ */
12
+ export declare function initialPhaseForSkill(skill: CanonicalGjcWorkflowSkill | string): string;
@@ -10,6 +10,7 @@ import { Settings } from "../config/settings";
10
10
  import { type Skill } from "../extensibility/skills";
11
11
  import type { HindsightSessionState } from "../hindsight/state";
12
12
  import type { LocalProtocolOptions } from "../internal-urls";
13
+ import type { ForkContextSeed } from "../session/agent-session";
13
14
  import type { ArtifactManager } from "../session/artifacts";
14
15
  import type { AuthStorage } from "../session/auth-storage";
15
16
  import type { ContextFileEntry } from "../tools";
@@ -73,6 +74,7 @@ export interface ExecutorOptions {
73
74
  parentTelemetry?: AgentTelemetryConfig;
74
75
  /** Skills to autoload via sendCustomMessage before the first prompt */
75
76
  autoloadSkills?: Skill[];
77
+ forkContextSeed?: ForkContextSeed;
76
78
  }
77
79
  export interface YieldItem {
78
80
  data?: unknown;