@gajae-code/coding-agent 0.3.1 → 0.4.0

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 (166) hide show
  1. package/CHANGELOG.md +46 -0
  2. package/README.md +1 -1
  3. package/dist/types/cli/args.d.ts +2 -0
  4. package/dist/types/commands/launch.d.ts +6 -0
  5. package/dist/types/config/model-profile-activation.d.ts +30 -0
  6. package/dist/types/config/model-profiles.d.ts +19 -0
  7. package/dist/types/config/model-registry.d.ts +25 -10
  8. package/dist/types/config/model-resolver.d.ts +1 -1
  9. package/dist/types/config/models-config-schema.d.ts +84 -0
  10. package/dist/types/config/settings-schema.d.ts +15 -0
  11. package/dist/types/edit/diff.d.ts +16 -0
  12. package/dist/types/edit/modes/replace.d.ts +7 -0
  13. package/dist/types/extensibility/gjc-plugins/activation.d.ts +14 -0
  14. package/dist/types/extensibility/gjc-plugins/index.d.ts +9 -0
  15. package/dist/types/extensibility/gjc-plugins/injection.d.ts +31 -0
  16. package/dist/types/extensibility/gjc-plugins/loader.d.ts +3 -0
  17. package/dist/types/extensibility/gjc-plugins/paths.d.ts +8 -0
  18. package/dist/types/extensibility/gjc-plugins/schema.d.ts +3 -0
  19. package/dist/types/extensibility/gjc-plugins/state.d.ts +9 -0
  20. package/dist/types/extensibility/gjc-plugins/tools.d.ts +8 -0
  21. package/dist/types/extensibility/gjc-plugins/types.d.ts +64 -0
  22. package/dist/types/extensibility/gjc-plugins/validation.d.ts +4 -0
  23. package/dist/types/extensibility/skills.d.ts +9 -1
  24. package/dist/types/gjc-runtime/state-runtime.d.ts +22 -0
  25. package/dist/types/harness-control-plane/storage.d.ts +7 -0
  26. package/dist/types/lsp/client.d.ts +1 -0
  27. package/dist/types/main.d.ts +10 -1
  28. package/dist/types/modes/bridge/bridge-mode.d.ts +2 -0
  29. package/dist/types/modes/components/custom-provider-wizard.d.ts +10 -0
  30. package/dist/types/modes/components/model-selector.d.ts +6 -1
  31. package/dist/types/modes/components/provider-onboarding-selector.d.ts +1 -1
  32. package/dist/types/modes/controllers/selector-controller.d.ts +1 -0
  33. package/dist/types/modes/prompt-action-autocomplete.d.ts +2 -2
  34. package/dist/types/modes/rpc/rpc-client.d.ts +9 -1
  35. package/dist/types/modes/rpc/rpc-types.d.ts +179 -2
  36. package/dist/types/modes/shared/agent-wire/approval-gate.d.ts +57 -0
  37. package/dist/types/modes/shared/agent-wire/command-dispatch.d.ts +16 -1
  38. package/dist/types/modes/shared/agent-wire/deep-interview-gate.d.ts +47 -0
  39. package/dist/types/modes/shared/agent-wire/event-envelope.d.ts +7 -0
  40. package/dist/types/modes/shared/agent-wire/handshake.d.ts +11 -1
  41. package/dist/types/modes/shared/agent-wire/protocol.d.ts +3 -1
  42. package/dist/types/modes/shared/agent-wire/responses.d.ts +1 -1
  43. package/dist/types/modes/shared/agent-wire/unattended-action-policy.d.ts +27 -0
  44. package/dist/types/modes/shared/agent-wire/unattended-audit.d.ts +68 -0
  45. package/dist/types/modes/shared/agent-wire/unattended-run-controller.d.ts +161 -0
  46. package/dist/types/modes/shared/agent-wire/unattended-session.d.ts +61 -0
  47. package/dist/types/modes/shared/agent-wire/workflow-gate-broker.d.ts +114 -0
  48. package/dist/types/modes/shared/agent-wire/workflow-gate-schema.d.ts +39 -0
  49. package/dist/types/modes/theme/theme.d.ts +2 -1
  50. package/dist/types/modes/types.d.ts +1 -0
  51. package/dist/types/runtime-mcp/transports/stdio.d.ts +0 -4
  52. package/dist/types/sdk.d.ts +8 -1
  53. package/dist/types/session/agent-session.d.ts +10 -0
  54. package/dist/types/session/blob-store.d.ts +17 -0
  55. package/dist/types/session/messages.d.ts +3 -0
  56. package/dist/types/session/session-storage.d.ts +6 -0
  57. package/dist/types/skill-state/active-state.d.ts +13 -0
  58. package/dist/types/task/executor.d.ts +1 -0
  59. package/dist/types/thinking.d.ts +3 -2
  60. package/dist/types/tools/hindsight-recall.d.ts +0 -2
  61. package/dist/types/tools/hindsight-reflect.d.ts +0 -2
  62. package/dist/types/tools/hindsight-retain.d.ts +0 -2
  63. package/dist/types/tools/index.d.ts +7 -4
  64. package/package.json +9 -7
  65. package/src/cli/args.ts +10 -0
  66. package/src/cli.ts +14 -0
  67. package/src/commands/harness.ts +192 -7
  68. package/src/commands/launch.ts +8 -0
  69. package/src/commands/ultragoal.ts +1 -21
  70. package/src/config/model-equivalence.ts +1 -1
  71. package/src/config/model-profile-activation.ts +157 -0
  72. package/src/config/model-profiles.ts +155 -0
  73. package/src/config/model-registry.ts +51 -5
  74. package/src/config/model-resolver.ts +3 -2
  75. package/src/config/models-config-schema.ts +42 -1
  76. package/src/config/settings-schema.ts +14 -1
  77. package/src/defaults/gjc/skills/ultragoal/SKILL.md +11 -1
  78. package/src/defaults/gjc/skills/ultragoal/ai-slop-cleaner.md +61 -0
  79. package/src/defaults/gjc-defaults.ts +7 -0
  80. package/src/discovery/claude-plugins.ts +25 -5
  81. package/src/edit/diff.ts +64 -1
  82. package/src/edit/modes/replace.ts +60 -2
  83. package/src/extensibility/gjc-plugins/activation.ts +87 -0
  84. package/src/extensibility/gjc-plugins/index.ts +9 -0
  85. package/src/extensibility/gjc-plugins/injection.ts +114 -0
  86. package/src/extensibility/gjc-plugins/loader.ts +131 -0
  87. package/src/extensibility/gjc-plugins/paths.ts +66 -0
  88. package/src/extensibility/gjc-plugins/schema.ts +79 -0
  89. package/src/extensibility/gjc-plugins/state.ts +29 -0
  90. package/src/extensibility/gjc-plugins/tools.ts +47 -0
  91. package/src/extensibility/gjc-plugins/types.ts +97 -0
  92. package/src/extensibility/gjc-plugins/validation.ts +76 -0
  93. package/src/extensibility/skills.ts +39 -7
  94. package/src/gjc-runtime/state-runtime.ts +93 -2
  95. package/src/gjc-runtime/state-writer.ts +17 -1
  96. package/src/gjc-runtime/ultragoal-runtime.ts +62 -2
  97. package/src/gjc-runtime/workflow-manifest.generated.json +5 -0
  98. package/src/gjc-runtime/workflow-manifest.ts +2 -2
  99. package/src/harness-control-plane/storage.ts +144 -2
  100. package/src/hashline/hash.ts +23 -0
  101. package/src/hooks/skill-state.ts +2 -0
  102. package/src/internal-urls/docs-index.generated.ts +8 -11
  103. package/src/lsp/client.ts +7 -0
  104. package/src/main.ts +67 -1
  105. package/src/modes/acp/acp-agent.ts +25 -2
  106. package/src/modes/bridge/bridge-mode.ts +124 -2
  107. package/src/modes/components/custom-provider-wizard.ts +318 -0
  108. package/src/modes/components/model-selector.ts +108 -18
  109. package/src/modes/components/provider-onboarding-selector.ts +6 -1
  110. package/src/modes/controllers/input-controller.ts +14 -2
  111. package/src/modes/controllers/selector-controller.ts +57 -1
  112. package/src/modes/prompt-action-autocomplete.ts +49 -10
  113. package/src/modes/rpc/rpc-client.ts +57 -3
  114. package/src/modes/rpc/rpc-mode.ts +67 -0
  115. package/src/modes/rpc/rpc-types.ts +224 -2
  116. package/src/modes/shared/agent-wire/approval-gate.ts +151 -0
  117. package/src/modes/shared/agent-wire/command-dispatch.ts +97 -4
  118. package/src/modes/shared/agent-wire/command-validation.ts +25 -1
  119. package/src/modes/shared/agent-wire/deep-interview-gate.ts +222 -0
  120. package/src/modes/shared/agent-wire/event-envelope.ts +13 -0
  121. package/src/modes/shared/agent-wire/handshake.ts +43 -3
  122. package/src/modes/shared/agent-wire/protocol.ts +7 -0
  123. package/src/modes/shared/agent-wire/responses.ts +2 -2
  124. package/src/modes/shared/agent-wire/scopes.ts +2 -0
  125. package/src/modes/shared/agent-wire/unattended-action-policy.ts +341 -0
  126. package/src/modes/shared/agent-wire/unattended-audit.ts +175 -0
  127. package/src/modes/shared/agent-wire/unattended-run-controller.ts +406 -0
  128. package/src/modes/shared/agent-wire/unattended-session.ts +180 -0
  129. package/src/modes/shared/agent-wire/workflow-gate-broker.ts +324 -0
  130. package/src/modes/shared/agent-wire/workflow-gate-schema.ts +331 -0
  131. package/src/modes/theme/theme.ts +6 -0
  132. package/src/modes/types.ts +1 -0
  133. package/src/prompts/memories/consolidation.md +1 -1
  134. package/src/prompts/memories/read-path.md +6 -7
  135. package/src/prompts/memories/unavailable.md +2 -2
  136. package/src/prompts/tools/bash.md +1 -1
  137. package/src/prompts/tools/irc.md +1 -1
  138. package/src/prompts/tools/read.md +2 -2
  139. package/src/prompts/tools/recall.md +1 -0
  140. package/src/prompts/tools/reflect.md +1 -0
  141. package/src/prompts/tools/retain.md +1 -0
  142. package/src/runtime-mcp/client.ts +7 -4
  143. package/src/runtime-mcp/manager.ts +45 -13
  144. package/src/runtime-mcp/transports/http.ts +40 -14
  145. package/src/runtime-mcp/transports/stdio.ts +11 -10
  146. package/src/sdk.ts +48 -1
  147. package/src/session/agent-session.ts +211 -2
  148. package/src/session/blob-store.ts +84 -0
  149. package/src/session/messages.ts +3 -0
  150. package/src/session/session-manager.ts +390 -33
  151. package/src/session/session-storage.ts +26 -0
  152. package/src/setup/provider-onboarding.ts +2 -2
  153. package/src/skill-state/active-state.ts +89 -1
  154. package/src/slash-commands/builtin-registry.ts +1 -1
  155. package/src/task/discovery.ts +7 -1
  156. package/src/task/executor.ts +18 -2
  157. package/src/task/index.ts +2 -0
  158. package/src/thinking.ts +8 -2
  159. package/src/tools/ask.ts +39 -9
  160. package/src/tools/hindsight-recall.ts +0 -2
  161. package/src/tools/hindsight-reflect.ts +0 -2
  162. package/src/tools/hindsight-retain.ts +0 -2
  163. package/src/tools/index.ts +7 -18
  164. package/src/tools/read.ts +3 -3
  165. package/src/tools/skill.ts +15 -3
  166. package/src/utils/edit-mode.ts +1 -1
@@ -0,0 +1,3 @@
1
+ import { type LoadedGjcPlugin } from "./types";
2
+ export declare function loadGjcPlugin(root: string): Promise<LoadedGjcPlugin>;
3
+ export declare function loadGjcPlugins(roots: readonly string[]): Promise<LoadedGjcPlugin[]>;
@@ -0,0 +1,8 @@
1
+ export declare function gjcPluginUserRoot(): string;
2
+ export declare function gjcPluginProjectRoot(cwd: string): string;
3
+ export declare function rootContainsGjcManifest(dir: string): Promise<boolean>;
4
+ export declare function discoverGjcPluginRoots({ cwd }: {
5
+ cwd: string;
6
+ home?: string;
7
+ }): Promise<string[]>;
8
+ export declare function resolveWithinRoot(root: string, rel: string): string;
@@ -0,0 +1,3 @@
1
+ import { type GjcPluginManifest, type SubskillFrontmatter } from "./types";
2
+ export declare function parseManifest(raw: unknown, manifestPath: string): GjcPluginManifest;
3
+ export declare function parseSubskillFrontmatter(fm: Record<string, unknown>, filePath: string): SubskillFrontmatter;
@@ -0,0 +1,9 @@
1
+ import type { ActiveSubskillEntry } from "../../skill-state/active-state";
2
+ import type { LoadedSubskillActivation } from "./types";
3
+ export declare function toActiveSubskillEntry(activation: LoadedSubskillActivation): ActiveSubskillEntry;
4
+ export declare function readActiveSubskillsForParent(input: {
5
+ cwd: string;
6
+ sessionId?: string;
7
+ parent: string;
8
+ phase: string;
9
+ }): Promise<ActiveSubskillEntry[]>;
@@ -0,0 +1,8 @@
1
+ import type { CustomTool } from "../custom-tools/types";
2
+ export declare function loadActiveSubskillTools(input: {
3
+ cwd: string;
4
+ sessionId?: string;
5
+ parent: string;
6
+ phase: string;
7
+ reservedToolNames?: string[];
8
+ }): Promise<CustomTool[]>;
@@ -0,0 +1,64 @@
1
+ import type { CanonicalGjcWorkflowSkill } from "../../skill-state/active-state";
2
+ export declare const GJC_PLUGIN_MANIFEST_FILENAME = "gajae-plugin.json";
3
+ export declare const GJC_PLUGIN_KIND = "gajae-code-plugin";
4
+ export declare const GJC_SUBSKILL_PARENT_SKILLS: readonly ["deep-interview", "ralplan", "ultragoal", "team"];
5
+ export type GjcSubskillParentSkill = CanonicalGjcWorkflowSkill;
6
+ export declare const GJC_SUBSKILL_PARENT_AGENTS: readonly ["executor", "architect", "planner", "critic"];
7
+ export type GjcSubskillParentAgent = (typeof GJC_SUBSKILL_PARENT_AGENTS)[number];
8
+ export type GjcSubskillParent = GjcSubskillParentSkill | GjcSubskillParentAgent;
9
+ export declare const GJC_AGENT_SUBSKILL_PHASES: Record<GjcSubskillParentAgent, string[]>;
10
+ export interface GjcPluginManifest {
11
+ name: string;
12
+ version: string;
13
+ kind: "gajae-code-plugin";
14
+ subskills: string[];
15
+ tools: string[];
16
+ }
17
+ export interface SubskillFrontmatter {
18
+ name: string;
19
+ binds_to: string;
20
+ phase: string;
21
+ activation_arg: string;
22
+ description: string;
23
+ }
24
+ export interface LoadedSubskillBinding {
25
+ plugin: string;
26
+ subskillName: string;
27
+ parent: string;
28
+ bindsTo: string;
29
+ phase: string;
30
+ activationArg: string;
31
+ description: string;
32
+ filePath: string;
33
+ body: string;
34
+ toolPaths: string[];
35
+ }
36
+ export interface LoadedSubskillActivation {
37
+ activationArg: string;
38
+ plugin: string;
39
+ subskillName: string;
40
+ parent: string;
41
+ bindsTo: string;
42
+ phase: string;
43
+ filePath: string;
44
+ toolPaths: string[];
45
+ }
46
+ export interface PhaseScopedToolBinding {
47
+ plugin: string;
48
+ parent: string;
49
+ phase: string;
50
+ toolPath: string;
51
+ }
52
+ export interface LoadedGjcPlugin {
53
+ name: string;
54
+ version: string;
55
+ root: string;
56
+ manifestPath: string;
57
+ bindings: LoadedSubskillBinding[];
58
+ toolBindings: PhaseScopedToolBinding[];
59
+ }
60
+ export type GjcPluginLoadErrorCode = "forbidden_surface" | "invalid_manifest" | "invalid_frontmatter" | "invalid_parent" | "invalid_phase" | "duplicate_arg" | "duplicate_parent_phase" | "missing_file" | "invalid_kind";
61
+ export declare class GjcPluginLoadError extends Error {
62
+ readonly code: GjcPluginLoadErrorCode;
63
+ constructor(code: GjcPluginLoadErrorCode, message: string, options?: ErrorOptions);
64
+ }
@@ -0,0 +1,4 @@
1
+ import { type LoadedSubskillBinding, type SubskillFrontmatter } from "./types";
2
+ export declare function validateBinding(fm: SubskillFrontmatter): void;
3
+ export declare function buildParentArgMap(bindings: readonly LoadedSubskillBinding[]): Map<string, Map<string, LoadedSubskillBinding>>;
4
+ export declare function buildParentPhaseSet(bindings: readonly LoadedSubskillBinding[]): Set<string>;
@@ -1,6 +1,7 @@
1
1
  import type { SourceMeta } from "../capability/types";
2
2
  import type { SkillsSettings } from "../config/settings";
3
3
  import type { SkillPromptDetails } from "../session/messages";
4
+ import type { LoadedSubskillActivation } from "./gjc-plugins";
4
5
  export interface Skill {
5
6
  name: string;
6
7
  description: string;
@@ -55,6 +56,13 @@ export interface BuiltSkillPromptMessage {
55
56
  message: string;
56
57
  details: SkillPromptDetails;
57
58
  }
59
+ export interface BuildSkillPromptMessageContext {
60
+ subskillActivation?: LoadedSubskillActivation;
61
+ subskillActivationSet?: LoadedSubskillActivation[];
62
+ currentPhase?: string;
63
+ cwd?: string;
64
+ sessionId?: string;
65
+ }
58
66
  export declare function getSkillSlashCommandName(skill: Pick<Skill, "name">): string;
59
67
  export declare function isNamespacedSkillSlashCommandName(commandName: string): boolean;
60
68
  export declare function getSkillSlashCommandNames(skill: Pick<Skill, "name">): string[];
@@ -71,4 +79,4 @@ export interface ParsedSkillInvocation {
71
79
  }
72
80
  export declare function parseSkillInvocations(text: string, skillsByCommandName: ReadonlyMap<string, Skill>): ParsedSkillInvocation[];
73
81
  export declare function resolveSkillSlashCommands(skills: readonly Skill[], _reservedDirectCommandNames: ReadonlySet<string>): ResolvedSkillSlashCommand[];
74
- export declare function buildSkillPromptMessage(skill: Pick<Skill, "name" | "filePath" | "content">, args: string): Promise<BuiltSkillPromptMessage>;
82
+ export declare function buildSkillPromptMessage(skill: Pick<Skill, "name" | "filePath" | "content">, args: string, context?: BuildSkillPromptMessageContext): Promise<BuiltSkillPromptMessage>;
@@ -11,5 +11,27 @@ export interface StateCommandResult {
11
11
  stdout?: string;
12
12
  stderr?: string;
13
13
  }
14
+ /**
15
+ * Reconcile a workflow skill's mode-state + active-state/HUD from a caller-derived
16
+ * payload. Unlike `gjc state write`, this is a derived repair: callers reconcile from
17
+ * an authoritative source (e.g. the ultragoal plan/ledger), where intermediate
18
+ * aggregate phases like ultragoal `active -> pending` are legitimate, so it bypasses
19
+ * ONLY verb transition-edge validation while preserving schema validation,
20
+ * unknown-phase rejection, version/checksum stamping, and audit/out-of-band tamper
21
+ * detection. Receipts carry `owner: "gjc-runtime"` and `verb: "reconcile"` so the
22
+ * provenance is distinguishable from a user-initiated write.
23
+ */
24
+ export declare function reconcileWorkflowSkillState(options: {
25
+ cwd: string;
26
+ mode: CanonicalGjcWorkflowSkill;
27
+ sessionId: string | undefined;
28
+ threadId?: string;
29
+ turnId?: string;
30
+ active: boolean;
31
+ phase: string;
32
+ payload: Record<string, unknown>;
33
+ }): Promise<{
34
+ stateFile: string;
35
+ }>;
14
36
  export declare function readWorkflowStateJson(cwd: string, skill: CanonicalGjcWorkflowSkill, sessionId?: string): Promise<Record<string, unknown>>;
15
37
  export declare function runNativeStateCommand(args: string[], cwd?: string): Promise<StateCommandResult>;
@@ -1,4 +1,8 @@
1
1
  import type { EventEnvelope, ReceiptFamily, SessionState } from "./types";
2
+ interface ResolveHarnessSessionRootOptions {
3
+ expectedWorkspace?: string;
4
+ }
5
+ export declare function canonicalWorkspacePath(workspace: string): string;
2
6
  export declare const MAX_UNIX_SOCKET_PATH_BYTES = 100;
3
7
  export declare function controlSocketPath(root: string, sessionId: string, env?: NodeJS.ProcessEnv): string;
4
8
  export declare class StorageError extends Error {
@@ -27,6 +31,8 @@ export interface SessionPaths {
27
31
  }
28
32
  export declare function sessionPaths(root: string, sessionId: string): SessionPaths;
29
33
  export declare function readSessionState(root: string, sessionId: string): Promise<SessionState | null>;
34
+ export declare function rememberHarnessSessionRoot(root: string, sessionId: string, env?: NodeJS.ProcessEnv): Promise<void>;
35
+ export declare function resolveHarnessSessionRoot(root: string, sessionId: string, env?: NodeJS.ProcessEnv, options?: ResolveHarnessSessionRootOptions): Promise<string>;
30
36
  export declare function writeSessionState(root: string, state: SessionState): Promise<void>;
31
37
  export declare function sessionExists(root: string, sessionId: string): Promise<boolean>;
32
38
  /** Append a single severity envelope to events.jsonl. Single-writer discipline is the owner's job (M3). */
@@ -51,3 +57,4 @@ export declare function writeReceiptImmutable(root: string, sessionId: string, f
51
57
  createdAt: string;
52
58
  }): Promise<ReceiptIndexEntry>;
53
59
  export declare function readReceiptIndex(root: string, sessionId: string, family?: ReceiptFamily): Promise<ReceiptIndexEntry[]>;
60
+ export {};
@@ -4,6 +4,7 @@ import type { LspClient, ServerConfig } from "./types";
4
4
  * @param ms - Timeout in milliseconds, or null/undefined to disable
5
5
  */
6
6
  export declare function setIdleTimeout(ms: number | null | undefined): void;
7
+ export declare function isIdleCheckerActiveForTests(): boolean;
7
8
  /** Timeout for warmup initialize requests (5 seconds) */
8
9
  export declare const WARMUP_TIMEOUT_MS = 5000;
9
10
  /**
@@ -24,10 +24,19 @@ export interface AcpSessionFactoryOptions {
24
24
  sessionDir?: string;
25
25
  authStorage: AuthStorage;
26
26
  modelRegistry: ModelRegistry;
27
- parsedArgs: Pick<Args, "apiKey">;
27
+ parsedArgs: Pick<Args, "apiKey" | "default" | "model" | "mpreset" | "thinking">;
28
28
  rawArgs: string[];
29
29
  createSession: (options: CreateAgentSessionOptions) => Promise<CreateAgentSessionResult>;
30
30
  }
31
+ export declare function applyStartupModelProfiles(args: {
32
+ session: AgentSession;
33
+ settings: Settings;
34
+ modelRegistry: ModelRegistry;
35
+ parsedArgs: Pick<Args, "default" | "model" | "mpreset" | "thinking">;
36
+ startupModel?: CreateAgentSessionOptions["model"];
37
+ startupThinkingLevel?: CreateAgentSessionOptions["thinkingLevel"];
38
+ }): Promise<void>;
39
+ export declare function applyStartupModelProfilesOrExit(args: Parameters<typeof applyStartupModelProfiles>[0]): Promise<void>;
31
40
  /**
32
41
  * Build the per-`session/new` factory used by ACP mode.
33
42
  *
@@ -7,6 +7,7 @@ import { RpcHostUriBridge } from "../shared/agent-wire/host-uri-bridge";
7
7
  import { type BridgeCommandScope } from "../shared/agent-wire/scopes";
8
8
  import { UiRequestBroker } from "../shared/agent-wire/ui-request-broker";
9
9
  import type { BridgeUiResult } from "../shared/agent-wire/ui-result";
10
+ import { UnattendedSessionControlPlane } from "../shared/agent-wire/unattended-session";
10
11
  import { type BridgePermissionRequestPayload } from "./bridge-client-bridge";
11
12
  import { type BridgeUiRequestPayload } from "./bridge-ui-context";
12
13
  import { BridgeEventStream } from "./event-stream";
@@ -30,6 +31,7 @@ interface BridgeFetchHandlerOptions {
30
31
  hostToolBridge?: RpcHostToolBridge;
31
32
  hostUriBridge?: RpcHostUriBridge;
32
33
  endpointMatrix?: Partial<BridgeEndpointMatrix>;
34
+ unattendedControlPlane?: UnattendedSessionControlPlane;
33
35
  }
34
36
  interface BridgeIdempotencyRecord {
35
37
  route: string;
@@ -0,0 +1,10 @@
1
+ import { Container } from "@gajae-code/tui";
2
+ import type { ProviderSetupInput } from "../../setup/provider-onboarding";
3
+ export type CustomProviderCredentialSource = "env" | "literal";
4
+ export type CustomProviderWizardSubmit = ProviderSetupInput;
5
+ export declare class CustomProviderWizardComponent extends Container {
6
+ #private;
7
+ constructor(onSubmit: (input: CustomProviderWizardSubmit) => void, onCancel: () => void, onRender?: () => void);
8
+ setSubmitError(error: string): void;
9
+ handleInput(keyData: string): void;
10
+ }
@@ -23,8 +23,12 @@ export type ModelSelectorSelection = {
23
23
  selector: string;
24
24
  preset: ModelAssignmentPreset;
25
25
  assignments: Record<GjcModelAssignmentTargetId, ThinkingLevel>;
26
+ } | {
27
+ kind: "profile";
28
+ profileName: string;
29
+ setDefault: boolean;
26
30
  };
27
- type RoleSelectCallback = (selection: ModelSelectorSelection) => void;
31
+ type RoleSelectCallback = (selection: ModelSelectorSelection) => void | Promise<void>;
28
32
  /**
29
33
  * Component that renders a canonical model selector with provider tabs.
30
34
  * - Tab/Arrow Left/Right: Switch between provider tabs
@@ -40,5 +44,6 @@ export declare class ModelSelectorComponent extends Container {
40
44
  });
41
45
  handleInput(keyData: string): void;
42
46
  getSearchInput(): Input;
47
+ __testSelectProfile(profileName: string, setDefault: boolean): Promise<void>;
43
48
  }
44
49
  export {};
@@ -1,5 +1,5 @@
1
1
  import { Container } from "@gajae-code/tui";
2
- export type ProviderOnboardingAction = "oauth-login" | "api-guide";
2
+ export type ProviderOnboardingAction = "custom-provider-wizard" | "oauth-login" | "api-guide";
3
3
  export declare class ProviderOnboardingSelectorComponent extends Container {
4
4
  #private;
5
5
  constructor(onSelect: (action: ProviderOnboardingAction) => void, onCancel: () => void);
@@ -15,6 +15,7 @@ export declare class SelectorController {
15
15
  focus: Component;
16
16
  }): void;
17
17
  showProviderOnboarding(): void;
18
+ showCustomProviderWizard(): void;
18
19
  showSettingsSelector(): void;
19
20
  showThemeSelector(): void;
20
21
  showHistorySearch(): void;
@@ -1,5 +1,5 @@
1
- import { type AutocompleteItem, type AutocompleteProvider, type SlashCommand } from "@gajae-code/tui";
2
- import { type KeybindingsManager } from "../config/keybindings";
1
+ import type { AutocompleteItem, AutocompleteProvider, SlashCommand } from "@gajae-code/tui";
2
+ import type { KeybindingsManager } from "../config/keybindings";
3
3
  interface PromptActionDefinition {
4
4
  id: string;
5
5
  label: string;
@@ -8,7 +8,7 @@ import type { CompactionResult } from "@gajae-code/agent-core/compaction";
8
8
  import type { ImageContent, Model } from "@gajae-code/ai";
9
9
  import type { BashResult } from "../../exec/bash-executor";
10
10
  import type { SessionStats } from "../../session/agent-session";
11
- import type { RpcHandoffResult, RpcHostToolDefinition, RpcSessionState } from "./rpc-types";
11
+ import type { RpcHandoffResult, RpcHostToolDefinition, RpcSessionState, RpcWorkflowGate, RpcWorkflowGateResolution } from "./rpc-types";
12
12
  export interface RpcClientOptions {
13
13
  /** Path to the CLI entry point (default: searches for dist/cli.js) */
14
14
  cliPath?: string;
@@ -60,6 +60,14 @@ export declare class RpcClient {
60
60
  * Subscribe to agent events.
61
61
  */
62
62
  onEvent(listener: RpcEventListener): () => void;
63
+ /**
64
+ * Subscribe to workflow lifecycle gates emitted by RPC mode.
65
+ */
66
+ onWorkflowGate(listener: (gate: RpcWorkflowGate) => void): () => void;
67
+ /**
68
+ * Answer a workflow lifecycle gate and wait for the server resolution envelope.
69
+ */
70
+ respondGate(gateId: string, answer: unknown, idempotencyKey?: string): Promise<RpcWorkflowGateResolution>;
63
71
  /**
64
72
  * Get collected stderr output (useful for debugging).
65
73
  */
@@ -145,7 +145,14 @@ export type RpcCommand = {
145
145
  id?: string;
146
146
  type: "login";
147
147
  providerId: string;
148
- };
148
+ } | {
149
+ id?: string;
150
+ type: "negotiate_unattended";
151
+ declaration: RpcUnattendedDeclaration;
152
+ } | ({
153
+ id?: string;
154
+ type: "workflow_gate_response";
155
+ } & RpcWorkflowGateResponse);
149
156
  export interface RpcSessionState {
150
157
  model?: Model;
151
158
  thinkingLevel: ThinkingLevel | undefined;
@@ -411,12 +418,24 @@ export type RpcResponse = {
411
418
  data: {
412
419
  providerId: string;
413
420
  };
421
+ } | {
422
+ id?: string;
423
+ type: "response";
424
+ command: "negotiate_unattended";
425
+ success: true;
426
+ data: RpcUnattendedAccepted;
427
+ } | {
428
+ id?: string;
429
+ type: "response";
430
+ command: "workflow_gate_response";
431
+ success: true;
432
+ data: RpcWorkflowGateResolution;
414
433
  } | {
415
434
  id?: string;
416
435
  type: "response";
417
436
  command: string;
418
437
  success: false;
419
- error: string;
438
+ error: string | object;
420
439
  };
421
440
  /** Emitted when an extension needs user input */
422
441
  export type RpcExtensionUIRequest = {
@@ -584,3 +603,161 @@ export type RpcExtensionUIResponse = {
584
603
  timedOut?: boolean;
585
604
  };
586
605
  export type RpcCommandType = RpcCommand["type"];
606
+ /**
607
+ * Lifecycle stages that emit machine-addressable gates. v1 is single-agent;
608
+ * `team` parallel execution over RPC is deferred, so it is intentionally absent
609
+ * from this union. Gate construction rejects any other stage value.
610
+ */
611
+ export type RpcWorkflowStage = "deep-interview" | "ralplan" | "ultragoal";
612
+ /** Reserved stage names that are explicitly not part of the v1 contract. */
613
+ export declare const RESERVED_WORKFLOW_STAGES: readonly string[];
614
+ export type RpcWorkflowGateKind = "question" | "approval" | "execution";
615
+ /**
616
+ * The documented JSON Schema 2020-12 subset supported by the gate validator.
617
+ * Schemas containing any keyword outside this shape are rejected at gate
618
+ * construction time so the server never advertises a schema it cannot validate.
619
+ */
620
+ export interface RpcJsonSchema {
621
+ type?: "string" | "number" | "integer" | "boolean" | "object" | "array" | "null";
622
+ enum?: unknown[];
623
+ const?: unknown;
624
+ properties?: Record<string, RpcJsonSchema>;
625
+ required?: string[];
626
+ additionalProperties?: boolean | RpcJsonSchema;
627
+ items?: RpcJsonSchema;
628
+ minLength?: number;
629
+ maxLength?: number;
630
+ minItems?: number;
631
+ maxItems?: number;
632
+ uniqueItems?: boolean;
633
+ minimum?: number;
634
+ maximum?: number;
635
+ title?: string;
636
+ description?: string;
637
+ oneOf?: RpcJsonSchema[];
638
+ anyOf?: RpcJsonSchema[];
639
+ }
640
+ export interface RpcWorkflowGateOption {
641
+ value: unknown;
642
+ label: string;
643
+ description?: string;
644
+ }
645
+ export interface RpcWorkflowGateContext {
646
+ title?: string;
647
+ prompt?: string;
648
+ summary?: string;
649
+ stage_state?: Record<string, unknown>;
650
+ artifact_refs?: Array<{
651
+ kind: string;
652
+ path?: string;
653
+ sha256?: string;
654
+ }>;
655
+ language?: string;
656
+ }
657
+ /** Outbound event: a machine-addressable workflow gate awaiting an answer. */
658
+ export interface RpcWorkflowGate {
659
+ type: "workflow_gate";
660
+ /** Run-scoped, monotonic, stable id (e.g. `wg_<run>_<stage>_000001`). */
661
+ gate_id: string;
662
+ stage: RpcWorkflowStage;
663
+ kind: RpcWorkflowGateKind;
664
+ schema: RpcJsonSchema;
665
+ /** Canonical hash of `schema`; advertised hash must equal server validation hash. */
666
+ schema_hash: string;
667
+ options?: RpcWorkflowGateOption[];
668
+ context: RpcWorkflowGateContext;
669
+ created_at: string;
670
+ required: true;
671
+ }
672
+ /** Inbound: the agent's answer to a workflow gate. */
673
+ export interface RpcWorkflowGateResponse {
674
+ gate_id: string;
675
+ answer: unknown;
676
+ /** Optional idempotency key; same key + body returns the cached resolution. */
677
+ idempotency_key?: string;
678
+ }
679
+ /** Outcome of resolving a gate, surfaced back to the answering client. */
680
+ export interface RpcWorkflowGateResolution {
681
+ gate_id: string;
682
+ status: "accepted" | "rejected";
683
+ answer_hash: string;
684
+ resolved_at: string;
685
+ /** Present only when `status === "rejected"`. */
686
+ error?: RpcWorkflowGateValidationError;
687
+ }
688
+ /** Typed error shape for schema validation failures (#315 acceptance). */
689
+ export interface RpcWorkflowGateValidationError {
690
+ code: "invalid_workflow_gate_answer";
691
+ gate_id: string;
692
+ schema_hash: string;
693
+ errors: Array<{
694
+ path: string;
695
+ keyword: string;
696
+ message: string;
697
+ expected?: unknown;
698
+ }>;
699
+ }
700
+ export interface RpcUnattendedBudget {
701
+ max_tokens: number;
702
+ max_tool_calls: number;
703
+ max_wall_time_ms: number;
704
+ max_cost_usd: number;
705
+ }
706
+ export interface RpcUnattendedDeclaration {
707
+ /** Identity of the operating external agent, recorded in the audit trail. */
708
+ actor: string;
709
+ budget: RpcUnattendedBudget;
710
+ /** Coarse command scopes the agent may use (maps to BridgeCommandScope). */
711
+ scopes: string[];
712
+ /** Action classes the agent is allowed to perform (default-deny otherwise). */
713
+ action_allowlist: string[];
714
+ }
715
+ export interface RpcUnattendedAccepted {
716
+ run_id: string;
717
+ actor: string;
718
+ budget: RpcUnattendedBudget;
719
+ scopes: string[];
720
+ action_allowlist: string[];
721
+ accepted_at: string;
722
+ }
723
+ export type RpcBudgetMetric = "tokens" | "tool_calls" | "wall_time" | "cost";
724
+ /** Typed payload emitted when a declared budget cap is breached (#318). */
725
+ export interface RpcBudgetExceeded {
726
+ code: "budget_exceeded";
727
+ metric: RpcBudgetMetric;
728
+ limit: number;
729
+ observed: number;
730
+ /** The accounting phase that detected the breach. */
731
+ phase: string;
732
+ run_id: string;
733
+ session_id?: string;
734
+ /** `aborting` = breach detected, async abort initiated; settled status follows in audit. */
735
+ abort_status: "aborting" | "aborted" | "abort_failed";
736
+ }
737
+ export type RpcUnattendedRefusalCode = "unattended_not_negotiated" | "incomplete_budget" | "unsupported_budget_metric" | "invalid_unattended_declaration" | "unattended_aborted";
738
+ /** Typed refusal emitted when unattended mode cannot start or continue (fail-closed). */
739
+ export interface RpcUnattendedRefused {
740
+ code: RpcUnattendedRefusalCode;
741
+ message: string;
742
+ }
743
+ /** v1 action taxonomy: every authorized operation maps to one of these classes. */
744
+ export type RpcUnattendedActionClass = "command.prompt" | "command.control" | "command.bash" | "command.export" | "command.session" | "command.model" | "command.message_read" | "command.host_tools" | "command.host_uri" | "command.admin" | "bash.readonly" | "bash.mutating" | "bash.destructive" | "git.force_push" | "file.delete" | "file.write" | "host_tool.invoke" | "host_uri.read" | "host_uri.write" | "auth.login";
745
+ /** Typed error when a command's coarse scope is not in the declared allowlist. */
746
+ export interface RpcScopeDenied {
747
+ code: "scope_denied";
748
+ scope: string;
749
+ command?: string;
750
+ run_id: string;
751
+ session_id?: string;
752
+ /** Always true: enforcement happens before the side effect runs. */
753
+ pre_side_effect: true;
754
+ }
755
+ /** Typed error when an action class is not in the declared allowlist (default-deny). */
756
+ export interface RpcActionDenied {
757
+ code: "action_denied";
758
+ action: string;
759
+ command?: string;
760
+ run_id: string;
761
+ session_id?: string;
762
+ pre_side_effect: true;
763
+ }
@@ -0,0 +1,57 @@
1
+ /**
2
+ * Ralplan approval + ultragoal execution gate mapping (#317).
3
+ *
4
+ * Maps the two human-gated lifecycle decisions onto `workflow_gate` events:
5
+ * - ralplan `pending approval` -> `workflow_gate` { kind: "approval" } whose
6
+ * answer is one of approve / request-changes / reject (+ optional comments);
7
+ * - ultragoal execution sign-off -> `workflow_gate` { kind: "execution" } whose
8
+ * answer is approve / decline (+ optional reason).
9
+ *
10
+ * Gates remain mandatory; the external agent substitutes for the human at the
11
+ * answer boundary only. Declining / requesting changes is honored and is NEVER
12
+ * silently treated as approval.
13
+ *
14
+ * This is the pure mapping primitive; routing ralplan/ultragoal through it when
15
+ * an unattended controller + gate broker are attached is wired with the transport
16
+ * in #321 and exercised end-to-end by #323.
17
+ */
18
+ import type { RpcWorkflowGateContext } from "../../rpc/rpc-types";
19
+ import type { OpenGateInput } from "./workflow-gate-broker";
20
+ export type ApprovalDecision = "approve" | "request-changes" | "reject";
21
+ export type ExecutionDecision = "approve" | "decline";
22
+ export interface ApprovalGateAnswer {
23
+ decision: ApprovalDecision;
24
+ comments?: string;
25
+ }
26
+ export interface ExecutionGateAnswer {
27
+ decision: ExecutionDecision;
28
+ reason?: string;
29
+ }
30
+ export interface ApprovalGateResult {
31
+ approved: boolean;
32
+ decision: ApprovalDecision;
33
+ comments?: string;
34
+ }
35
+ export interface ExecutionGateResult {
36
+ approved: boolean;
37
+ decision: ExecutionDecision;
38
+ reason?: string;
39
+ }
40
+ export declare class ApprovalGateError extends Error {
41
+ readonly code: "invalid_answer_shape" | "unknown_decision" | "missing_comments";
42
+ constructor(code: "invalid_answer_shape" | "unknown_decision" | "missing_comments", message: string);
43
+ }
44
+ /** Build the ralplan `pending approval` -> `workflow_gate { kind: "approval" }` open-input. */
45
+ export declare function approvalGate(context?: RpcWorkflowGateContext): OpenGateInput;
46
+ /** Build the ultragoal execution sign-off -> `workflow_gate { kind: "execution" }` open-input. */
47
+ export declare function executionGate(context?: RpcWorkflowGateContext): OpenGateInput;
48
+ /**
49
+ * Decode a ralplan approval answer. `request-changes` requires comments and is
50
+ * NEVER treated as approval; only an explicit `approve` advances.
51
+ */
52
+ export declare function decodeApproval(answer: unknown): ApprovalGateResult;
53
+ /**
54
+ * Decode an ultragoal execution answer. Only an explicit `approve` advances;
55
+ * `decline` is honored and never silently approved.
56
+ */
57
+ export declare function decodeExecution(answer: unknown): ExecutionGateResult;
@@ -1,7 +1,7 @@
1
1
  import type { AgentTool } from "@gajae-code/agent-core";
2
2
  import type { ExtensionUIContext } from "../../../extensibility/extensions";
3
3
  import type { AgentSession } from "../../../session/agent-session";
4
- import type { RpcCommand, RpcExtensionUIRequest, RpcHostToolDefinition, RpcHostUriSchemeDefinition, RpcResponse } from "../../rpc/rpc-types";
4
+ import type { RpcCommand, RpcExtensionUIRequest, RpcHostToolDefinition, RpcHostUriSchemeDefinition, RpcResponse, RpcUnattendedAccepted, RpcUnattendedDeclaration, RpcWorkflowGateResolution, RpcWorkflowGateResponse } from "../../rpc/rpc-types";
5
5
  export type RpcCommandDispatchOutput = (obj: RpcResponse | RpcExtensionUIRequest | object) => void;
6
6
  export interface RpcHostToolRegistry {
7
7
  setTools(tools: RpcHostToolDefinition[]): AgentTool[];
@@ -9,12 +9,27 @@ export interface RpcHostToolRegistry {
9
9
  export interface RpcHostUriRegistry {
10
10
  setSchemes(schemes: RpcHostUriSchemeDefinition[]): string[];
11
11
  }
12
+ /**
13
+ * Optional unattended control plane wired into RPC dispatch (#318/#319/#323).
14
+ * When present, `negotiate_unattended` and `workflow_gate_response` route here
15
+ * instead of falling through to the unknown-command path.
16
+ */
17
+ export interface RpcUnattendedControlPlane {
18
+ /** Enter unattended mode (fail-closed); throws an Error on refusal. */
19
+ negotiate(declaration: RpcUnattendedDeclaration): RpcUnattendedAccepted;
20
+ /** Resolve a pending workflow gate with the agent's answer. */
21
+ resolveGate(response: RpcWorkflowGateResponse): Promise<RpcWorkflowGateResolution>;
22
+ isUnattended?(): boolean;
23
+ preflightCommand?(command: RpcCommand): void;
24
+ reconcileUsage?(phase?: string): void;
25
+ }
12
26
  export interface RpcCommandDispatchContext {
13
27
  session: AgentSession;
14
28
  output: RpcCommandDispatchOutput;
15
29
  hostToolRegistry: RpcHostToolRegistry;
16
30
  hostUriRegistry: RpcHostUriRegistry;
17
31
  createUiContext: () => Pick<ExtensionUIContext, "notify">;
32
+ unattendedControlPlane?: RpcUnattendedControlPlane;
18
33
  }
19
34
  export declare function normalizeHostToolDefinitions(tools: RpcHostToolDefinition[]): RpcHostToolDefinition[];
20
35
  export declare function dispatchRpcCommand(command: RpcCommand, context: RpcCommandDispatchContext): Promise<RpcResponse>;