@gajae-code/coding-agent 0.11.9 → 0.11.11

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 (150) hide show
  1. package/CHANGELOG.md +56 -1
  2. package/dist/types/cli.d.ts +8 -1
  3. package/dist/types/config/model-profile-activation.d.ts +1 -0
  4. package/dist/types/config/model-profile-contract.d.ts +2 -0
  5. package/dist/types/config/model-registry.d.ts +2 -0
  6. package/dist/types/config/settings-schema.d.ts +57 -2
  7. package/dist/types/config/settings.d.ts +1 -0
  8. package/dist/types/extensibility/extensions/types.d.ts +21 -0
  9. package/dist/types/gjc-runtime/linux-proc.d.ts +22 -14
  10. package/dist/types/gjc-runtime/ralplan-runtime.d.ts +60 -0
  11. package/dist/types/gjc-runtime/state-runtime.d.ts +3 -1
  12. package/dist/types/gjc-runtime/state-writer.d.ts +1 -0
  13. package/dist/types/modes/acp/acp-agent.d.ts +14 -9
  14. package/dist/types/modes/components/queue-pane.d.ts +8 -0
  15. package/dist/types/modes/components/queued-message-selector.d.ts +6 -0
  16. package/dist/types/modes/components/welcome.d.ts +1 -0
  17. package/dist/types/modes/controllers/selector-controller.d.ts +16 -8
  18. package/dist/types/modes/interactive-mode.d.ts +5 -1
  19. package/dist/types/runtime/memory-domain.d.ts +9 -0
  20. package/dist/types/runtime/memory-guard-contract.d.ts +71 -0
  21. package/dist/types/runtime/memory-guard.d.ts +39 -0
  22. package/dist/types/runtime/memory-limit.d.ts +11 -0
  23. package/dist/types/runtime-mcp/manager.d.ts +8 -0
  24. package/dist/types/sdk/acp/final-text.d.ts +19 -0
  25. package/dist/types/sdk/acp/mcp.d.ts +23 -0
  26. package/dist/types/sdk/broker/lifecycle.d.ts +2 -0
  27. package/dist/types/sdk/bus/chat-daemon-control.d.ts +2 -1
  28. package/dist/types/sdk/bus/daemon-paths.d.ts +1 -0
  29. package/dist/types/sdk/bus/index.d.ts +11 -2
  30. package/dist/types/sdk/bus/operator-runtime.d.ts +1 -0
  31. package/dist/types/sdk/bus/rate-limit-pool.d.ts +2 -0
  32. package/dist/types/sdk/bus/telegram-daemon-contract.d.ts +14 -7
  33. package/dist/types/sdk/bus/telegram-daemon.d.ts +97 -8
  34. package/dist/types/sdk/host/control/operations.d.ts +1 -0
  35. package/dist/types/sdk/lifecycle-session.d.ts +10 -1
  36. package/dist/types/sdk/session.d.ts +7 -0
  37. package/dist/types/sdk/startup-capability.d.ts +6 -0
  38. package/dist/types/session/agent-session.d.ts +11 -11
  39. package/dist/types/session/fallback-chain-controller.d.ts +18 -2
  40. package/dist/types/session/internal/managed-session-scope.d.ts +28 -1
  41. package/dist/types/session/session-manager.d.ts +34 -0
  42. package/dist/types/task/executor.d.ts +6 -0
  43. package/dist/types/task/provider-retry-status.d.ts +13 -0
  44. package/dist/types/task/types.d.ts +39 -0
  45. package/dist/types/task/ultragoal-redteam-activation.d.ts +33 -0
  46. package/dist/types/tools/index.d.ts +3 -1
  47. package/dist/types/tools/resource-gc.d.ts +19 -0
  48. package/package.json +8 -8
  49. package/scripts/generate-sdk-operation-inventory.ts +3 -0
  50. package/scripts/run-test-manifest.ts +6 -4
  51. package/src/cli/args.ts +14 -8
  52. package/src/cli/fast-help.ts +1 -1
  53. package/src/cli/notify-cli.ts +1 -0
  54. package/src/cli.ts +48 -2
  55. package/src/commands/sdk.ts +91 -7
  56. package/src/config/model-profile-activation.ts +1 -0
  57. package/src/config/model-profile-contract.ts +13 -0
  58. package/src/config/model-profiles.ts +31 -7
  59. package/src/config/model-registry.ts +4 -2
  60. package/src/config/settings-schema.ts +61 -2
  61. package/src/config/settings.ts +8 -0
  62. package/src/defaults/gjc/skills/ralplan/SKILL.md +21 -2
  63. package/src/defaults/gjc/skills/ultragoal/SKILL.md +1 -1
  64. package/src/eval/js/tool-bridge.ts +1 -1
  65. package/src/extensibility/extensions/runner.ts +4 -0
  66. package/src/extensibility/extensions/types.ts +14 -0
  67. package/src/gjc-runtime/deep-interview-ambiguity.ts +16 -2
  68. package/src/gjc-runtime/deep-interview-draft.ts +2 -1
  69. package/src/gjc-runtime/deep-interview-recorder.ts +16 -1
  70. package/src/gjc-runtime/deep-interview-state.ts +25 -3
  71. package/src/gjc-runtime/linux-proc.ts +70 -36
  72. package/src/gjc-runtime/ralplan-runtime.ts +252 -1
  73. package/src/gjc-runtime/state-runtime.ts +48 -11
  74. package/src/gjc-runtime/state-writer.ts +1 -1
  75. package/src/hooks/skill-state.ts +23 -1
  76. package/src/internal-urls/docs-index.generated.ts +7 -7
  77. package/src/internal-urls/local-protocol.ts +23 -4
  78. package/src/modes/acp/acp-agent.ts +554 -60
  79. package/src/modes/acp/acp-event-mapper.ts +93 -6
  80. package/src/modes/components/model-selector.ts +15 -1
  81. package/src/modes/components/notifications-settings-editor.ts +1 -1
  82. package/src/modes/components/queue-pane.ts +55 -9
  83. package/src/modes/components/queued-message-selector.ts +53 -10
  84. package/src/modes/components/tool-status-header.ts +1 -4
  85. package/src/modes/components/welcome.ts +18 -3
  86. package/src/modes/controllers/command-controller.ts +4 -0
  87. package/src/modes/controllers/extension-ui-controller.ts +4 -10
  88. package/src/modes/controllers/input-controller.ts +44 -3
  89. package/src/modes/controllers/selector-controller.ts +38 -8
  90. package/src/modes/interactive-mode.ts +65 -26
  91. package/src/modes/runtime-init.ts +1 -0
  92. package/src/prompts/agent-fragments/restricted-bash.md +1 -1
  93. package/src/prompts/agents/architect.md +8 -1
  94. package/src/prompts/agents/critic.md +8 -1
  95. package/src/prompts/agents/executor.md +1 -1
  96. package/src/prompts/agents/planner.md +8 -1
  97. package/src/runtime/memory-domain.ts +66 -0
  98. package/src/runtime/memory-guard-contract.ts +73 -0
  99. package/src/runtime/memory-guard.ts +292 -0
  100. package/src/runtime/memory-limit.ts +50 -0
  101. package/src/runtime-mcp/manager.ts +26 -6
  102. package/src/sdk/acp/adapter.ts +8 -1
  103. package/src/sdk/acp/final-text.ts +40 -0
  104. package/src/sdk/acp/mcp.ts +26 -0
  105. package/src/sdk/broker/identity.ts +22 -12
  106. package/src/sdk/broker/lifecycle.ts +82 -1
  107. package/src/sdk/bus/chat-daemon-cli.ts +2 -2
  108. package/src/sdk/bus/chat-daemon-control.ts +4 -3
  109. package/src/sdk/bus/config.ts +1 -1
  110. package/src/sdk/bus/daemon-paths.ts +2 -0
  111. package/src/sdk/bus/index.ts +222 -27
  112. package/src/sdk/bus/notification-service.ts +19 -5
  113. package/src/sdk/bus/operator-runtime.ts +31 -5
  114. package/src/sdk/bus/rate-limit-pool.ts +8 -0
  115. package/src/sdk/bus/telegram-cli.ts +6 -13
  116. package/src/sdk/bus/telegram-daemon-cli.ts +8 -3
  117. package/src/sdk/bus/telegram-daemon-contract.ts +15 -7
  118. package/src/sdk/bus/telegram-daemon-control.ts +14 -5
  119. package/src/sdk/bus/telegram-daemon.ts +1191 -164
  120. package/src/sdk/host/control/dispatch.ts +2 -0
  121. package/src/sdk/host/control/operations.ts +1 -0
  122. package/src/sdk/host/host.ts +2 -2
  123. package/src/sdk/lifecycle-session.ts +19 -3
  124. package/src/sdk/protocol/operation-inventory.generated.json +58 -0
  125. package/src/sdk/protocol/operation-registry.ts +1 -0
  126. package/src/sdk/session.ts +24 -1
  127. package/src/sdk/startup-capability.ts +6 -0
  128. package/src/session/agent-session.ts +290 -132
  129. package/src/session/fallback-chain-controller.ts +47 -8
  130. package/src/session/internal/managed-session-scope.ts +173 -127
  131. package/src/session/internal/native-publish-outcome.ts +8 -3
  132. package/src/session/session-manager.ts +608 -25
  133. package/src/skill-state/workflow-mutation-guard.ts +41 -7
  134. package/src/task/executor.ts +152 -42
  135. package/src/task/index.ts +2 -0
  136. package/src/task/provider-retry-status.ts +88 -0
  137. package/src/task/render.ts +45 -26
  138. package/src/task/types.ts +25 -11
  139. package/src/task/ultragoal-redteam-activation.ts +75 -0
  140. package/src/tools/bash-allowed-prefixes.ts +45 -1
  141. package/src/tools/index.ts +3 -1
  142. package/src/tools/resource-gc.ts +496 -120
  143. package/src/tools/subagent-render.ts +74 -16
  144. package/src/tools/subagent.ts +2 -0
  145. package/src/workflow/workflow-intent-diff.ts +4 -1
  146. package/vendor/insane-search/MANIFEST.json +4 -1
  147. package/vendor/insane-search/engine/bias_check.py +5 -0
  148. package/vendor/insane-search/engine/fetch_chain.py +67 -1
  149. package/vendor/insane-search/engine/transport.py +13 -2
  150. package/vendor/insane-search/engine/validators.py +4 -1
@@ -149,6 +149,13 @@ export interface CreateAgentSessionOptions {
149
149
  goalToolAllowedOps?: readonly ("create" | "get" | "complete" | "resume" | "drop" | "pause")[];
150
150
  /** Optional per-session allowlist for tools exposed through search_tool_bm25. */
151
151
  discoverableToolAllowedNames?: readonly string[];
152
+ /**
153
+ * Discoverable built-in tools that must stay in the initial active set even when
154
+ * `tools.discoveryMode === "all"` would otherwise hide them behind `search_tool_bm25`.
155
+ * Used for coordination tools (e.g. `irc`) that a subagent must be able to use
156
+ * immediately without first spending a discovery round-trip to find them.
157
+ */
158
+ alwaysActiveToolNames?: readonly string[];
152
159
  /** Optional shared agent registry for IRC routing. Default: AgentRegistry.global(). */
153
160
  agentRegistry?: AgentRegistry;
154
161
  /** Parent task ID prefix for nested artifact naming (e.g., "6-Extensions") */
@@ -16,6 +16,12 @@ export type SdkStartupResult = {
16
16
  };
17
17
  /** Internal symbols for lifecycle-only SDK startup construction and bus wiring. */
18
18
  export declare const lifecycleStartupCapabilityOption: unique symbol;
19
+ /**
20
+ * Internal option carrying the startup budget for ACP lifecycle MCP launches.
21
+ * Only set when the lifecycle request actually supplies `mcpServers`, so the
22
+ * longer ceiling never leaks to ordinary CLI/SDK `mcpConfigPath` consumers.
23
+ */
24
+ export declare const lifecycleMcpStartupTimeoutOption: unique symbol;
19
25
  export declare function attachLifecycleStartupCapability(api: object, capability: SdkStartupCapability): void;
20
26
  export declare function lifecycleStartupCapabilityForApi(api: object): SdkStartupCapability | undefined;
21
27
  export interface SdkStartupRollbackResult {
@@ -80,7 +80,7 @@ import type { TtsrManager } from "../export/ttsr";
80
80
  import type { LoadedCustomCommand } from "../extensibility/custom-commands";
81
81
  import type { CustomTool } from "../extensibility/custom-tools/types";
82
82
  import type { ExtensionRunner } from "../extensibility/extensions";
83
- import type { CompactOptions, ContextUsage } from "../extensibility/extensions/types";
83
+ import type { CompactOptions, ContextUsage, ExtensionTranscriptEntry } from "../extensibility/extensions/types";
84
84
  import { type Skill, type SkillWarning } from "../extensibility/skills";
85
85
  import { type FileSlashCommand } from "../extensibility/slash-commands";
86
86
  import { GoalRuntime } from "../goals/runtime";
@@ -102,7 +102,7 @@ export { DefaultModelSelectionRecoveryError } from "./default-model-selection";
102
102
  import type { ClientBridge, ClientBridgePermissionOption, ClientBridgePermissionOutcome, ClientBridgePermissionToolCall } from "./client-bridge";
103
103
  import { type ContributionPrepOptions, type ContributionPrepResult } from "./contribution-prep";
104
104
  import { type CustomMessage } from "./messages";
105
- import type { BranchSummaryEntry, CompactionEntry, NewSessionOptions, RecoveryHydrationContext, RecoveryHydrationPromotionFence, SessionContext, SessionManager, SessionManagerCloseOutcome } from "./session-manager";
105
+ import type { BranchSummaryEntry, CompactionEntry, NewSessionOptions, PreparedNewSession, RecoveryHydrationContext, RecoveryHydrationPromotionFence, SessionContext, SessionManager, SessionManagerCloseOutcome } from "./session-manager";
106
106
  import { ToolChoiceQueue } from "./tool-choice-queue";
107
107
  import { YieldQueue } from "./yield-queue";
108
108
  /** Session-specific events that extend the core AgentEvent */
@@ -677,6 +677,8 @@ export declare class AgentSession {
677
677
  * Get a tool by name from the registry.
678
678
  */
679
679
  getToolByName(name: string): AgentTool | undefined;
680
+ /** Get a registered tool with the same guards used for model-facing execution. */
681
+ getToolForExecution(name: string): AgentTool | undefined;
680
682
  /**
681
683
  * Register a UI/control-plane request handler for a currently foregrounded
682
684
  * managed bash execution. This is intentionally narrower than generic
@@ -760,6 +762,8 @@ export declare class AgentSession {
760
762
  /** Main startup calls this exactly once, after a strict open returned `kind: "opened"`. */
761
763
  continuePersistedHistory(): Promise<void>;
762
764
  buildDisplaySessionContext(): SessionContext;
765
+ /** Build display context from an unpublished successor without changing active session state. @internal */
766
+ buildPreparedDisplaySessionContext(prepared: PreparedNewSession): SessionContext;
763
767
  /** Convert session messages using the same pre-LLM pipeline as the active session. */
764
768
  convertMessagesToLlm(messages: AgentMessage[], signal?: AbortSignal): Promise<Message[]>;
765
769
  /** Apply session-level stream hooks to a direct side request. */
@@ -783,7 +787,7 @@ export declare class AgentSession {
783
787
  /** Live SDK configuration values exposed through the session query surface. */
784
788
  getSdkConfigItems(): Record<string, string>;
785
789
  setPlanModeState(state: PlanModeState | undefined): void;
786
- invokeSkill(name: string, args?: string): Promise<{
790
+ invokeSkill(name: string, args?: string, options?: Pick<PromptOptions, "onPreflightAccepted">): Promise<{
787
791
  name: string;
788
792
  path: string;
789
793
  args?: string;
@@ -791,13 +795,7 @@ export declare class AgentSession {
791
795
  }>;
792
796
  setSdkPlanMode(on: boolean): Promise<PlanModeState | undefined>;
793
797
  operateGoal(op: "create" | "get" | "resume" | "pause" | "complete" | "drop", objective?: string): Promise<unknown>;
794
- getTranscript(): Array<{
795
- id: string;
796
- role: string;
797
- textSummary: string;
798
- ts: string;
799
- body: string;
800
- }>;
798
+ getTranscript(): ExtensionTranscriptEntry[];
801
799
  getTranscriptBody(entryId: string): string | undefined;
802
800
  getGoalModeState(): GoalModeState | undefined;
803
801
  setGoalModeState(state: GoalModeState | undefined): void;
@@ -844,7 +842,7 @@ export declare class AgentSession {
844
842
  * @throws Error if no model selected or no API key available (when not streaming)
845
843
  */
846
844
  prompt(text: string, options?: PromptOptions): Promise<void>;
847
- promptCustomMessage<T = unknown>(message: Pick<CustomMessage<T>, "customType" | "content" | "display" | "details" | "attribution">, options?: Pick<PromptOptions, "streamingBehavior" | "toolChoice" | "followUpQueuePolicy">): Promise<void>;
845
+ promptCustomMessage<T = unknown>(message: Pick<CustomMessage<T>, "customType" | "content" | "display" | "details" | "attribution">, options?: Pick<PromptOptions, "streamingBehavior" | "toolChoice" | "followUpQueuePolicy" | "onPreflightAccepted">): Promise<void>;
848
846
  /**
849
847
  * Queue a steering message to interrupt the agent mid-run.
850
848
  */
@@ -986,6 +984,8 @@ export declare class AgentSession {
986
984
  }): Promise<void>;
987
985
  setActiveModelProfile(name: string | undefined): void;
988
986
  getActiveModelProfile(): string | undefined;
987
+ /** Activate a complete model profile through a nonvisual session control. */
988
+ activateModelProfileForControl(profileName: string): Promise<boolean>;
989
989
  /** Return the persisted configured fallback selectors for a model role. */
990
990
  getConfiguredModelChain(role: string): readonly string[] | undefined;
991
991
  /** Persist the configured fallback selectors for a model role. */
@@ -47,8 +47,9 @@ export declare class FallbackChainController {
47
47
  onAttemptFailure(triggerClass: FallbackTriggerClass, reason: string): FallbackFailureResult;
48
48
  advance(): boolean;
49
49
  /**
50
- * Restore the entry that just advanced when credential rotation permits a retry.
51
- * The chain-wide budget and failure history remain charged.
50
+ * Restore the entry that just advanced for one attempt with a rotated credential.
51
+ * Each non-terminal entry may be restored once, so credential rotation remains
52
+ * bounded and cannot consume the attempts reserved for downstream entries.
52
53
  */
53
54
  restorePreviousEntryForRetry(): boolean;
54
55
  isExhausted(): boolean;
@@ -56,5 +57,20 @@ export declare class FallbackChainController {
56
57
  resetSticky(): void;
57
58
  }
58
59
  export declare function cappedExponentialWithFullJitter(baseDelayMs: number, maxDelayMs: number, attemptK: number, random?: () => number): number;
60
+ /**
61
+ * Legacy auto-compaction retry delay.
62
+ *
63
+ * Deliberately the mirror image of `effectiveFallbackDelay`: this path recovers
64
+ * Retry-After by regex over provider error prose (`#parseRetryAfterMsFromError`),
65
+ * so it follows the documented legacy rule — `retry.maxDelayMs` caps every
66
+ * legacy session retry delay, including provider retry-after hints. Managed
67
+ * fallback stays uncapped because it retries within its own per-entry budget;
68
+ * compaction has no such budget, so the final candidate would otherwise sleep
69
+ * for the full server-suggested duration.
70
+ *
71
+ * `maxDelayMs <= 0` means "no cap", matching `cappedExponentialWithFullJitter`.
72
+ * A missing, NaN, or infinite hint collapses to "no usable hint".
73
+ */
74
+ export declare function compactionRetryDelay(baseDelayMs: number, maxDelayMs: number, attempt: number, retryAfterMs: number | undefined): number;
59
75
  /** Retry-After is intentionally uncapped. */
60
76
  export declare function effectiveFallbackDelay(baseDelayMs: number, maxDelayMs: number, attemptK: number, retryAfterMs: number | undefined, random?: () => number): number;
@@ -121,15 +121,42 @@ export declare function ensureManagedScope(scope: ManagedScope, policy?: Managed
121
121
  /** Synchronously create and validate the v2 binding before a default session writer exists. */
122
122
  export declare function prepareManagedSessionScopeForWriteSync(scope: ManagedScope, policy?: ManagedSessionSecurityPolicy, authority?: ManagedCandidateWriteAuthority): ManagedScopeResolution;
123
123
  export declare function listManagedCandidates(scope: ManagedScope): ManagedCandidateListing;
124
+ type DetachedArtifactRoot = {
125
+ originalPath: string;
126
+ detachedPath: string;
127
+ identity: {
128
+ dev: bigint;
129
+ ino: bigint;
130
+ size: bigint;
131
+ mtimeNs: bigint;
132
+ };
133
+ tree: NativeDirectoryTreeSnapshot;
134
+ };
124
135
  export declare function matchesMigrationArtifactRoot(pathname: string, identity: {
125
136
  dev: bigint;
126
137
  ino: bigint;
127
138
  size: bigint;
128
139
  mtimeNs: bigint;
129
140
  }, expectedTree: NativeDirectoryTreeSnapshot, platform?: NodeJS.Platform): boolean;
141
+ type SourceArtifactCleanup = {
142
+ state: "cleanup_pending";
143
+ role: "exchange_placeholder";
144
+ retainedPath: string;
145
+ identity: DetachedArtifactRoot["identity"];
146
+ tree: NativeDirectoryTreeSnapshot;
147
+ };
148
+ export declare function cleanupAuthorityMatches(cleanup: SourceArtifactCleanup, parent: string, platform?: NodeJS.Platform): boolean;
149
+ export declare function detachArtifactRootForMigration(plan: DetachedArtifactRoot, platform?: NodeJS.Platform): {
150
+ detached: DetachedArtifactRoot;
151
+ detachOutcome: "clean";
152
+ } | {
153
+ detached: DetachedArtifactRoot;
154
+ detachOutcome: "cleanup_pending";
155
+ cleanup: SourceArtifactCleanup;
156
+ };
130
157
  export declare function restorePreparedArtifactRoot(scope: ManagedScope, source: ManagedCandidate, lock?: ManagedStorageLock): void;
131
158
  /** Resume tombstoned cleanup under its original operation lease without restoring retired candidates. */
132
- export declare function reconcileManagedTombstones(scope: ManagedScope): Promise<void>;
159
+ export declare function reconcileManagedTombstones(scope: ManagedScope, expectedCandidate?: ManagedCandidate): Promise<void>;
133
160
  /** Create the v2 binding and private write protocol directories before managed writes. */
134
161
  export declare function prepareManagedSessionScopeForWrite(scope: ManagedScope, policy?: ManagedSessionSecurityPolicy, authority?: ManagedCandidateWriteAuthority, expectedCandidate?: ManagedCandidate, expectedIdentity?: ResumeSessionIdentity): Promise<ManagedScopeResolution>;
135
162
  /**
@@ -27,6 +27,13 @@ export interface NewSessionOptions {
27
27
  /** Skip flushing the current session and delete it instead of saving. */
28
28
  drop?: boolean;
29
29
  }
30
+ /** Internal successor prepared without changing the manager's visible identity. */
31
+ export interface PreparedNewSession {
32
+ readonly sessionId: string;
33
+ readonly sessionFile: string | undefined;
34
+ readonly artifactsDir: string | null;
35
+ readonly managedLegacyLocalMigrationSource: ManagedLegacyLocalMigrationSource | null;
36
+ }
30
37
  export interface SessionEntryBase {
31
38
  type: string;
32
39
  id: string;
@@ -597,6 +604,33 @@ export declare class SessionManager {
597
604
  setSessionFile(sessionFile: string): Promise<void>;
598
605
  /** Start a new session. Closes any existing writer first. */
599
606
  newSession(options?: NewSessionOptions): Promise<string | undefined>;
607
+ /**
608
+ * Allocate a fresh successor without publishing it through the manager's public
609
+ * getters. The returned authority is deliberately immutable so readiness work
610
+ * can resolve local:// against the successor while the predecessor stays live.
611
+ * @internal
612
+ */
613
+ prepareNewSession(options?: NewSessionOptions): Promise<PreparedNewSession>;
614
+ /** Append a model selection to an unpublished successor. @internal */
615
+ appendPreparedModelChange(prepared: PreparedNewSession, model: string): string;
616
+ /** Append a thinking-level selection to an unpublished successor. @internal */
617
+ appendPreparedThinkingLevelChange(prepared: PreparedNewSession, thinkingLevel?: string): string;
618
+ /** Append a service-tier selection to an unpublished successor. @internal */
619
+ appendPreparedServiceTierChange(prepared: PreparedNewSession, serviceTier: ServiceTier | null): string;
620
+ /** Append a displayable custom message to an unpublished successor. @internal */
621
+ appendPreparedCustomMessageEntry<T = unknown>(prepared: PreparedNewSession, customType: string, content: string | (TextContent | ImageContent)[], display: boolean, details?: T, attribution?: MessageAttribution): string;
622
+ /** Persist an unpublished successor without adopting it. @internal */
623
+ ensurePreparedNewSessionOnDisk(prepared: PreparedNewSession): Promise<void>;
624
+ /** Build context from an unpublished successor without reading active manager state. @internal */
625
+ buildPreparedNewSessionContext(prepared: PreparedNewSession): SessionContext;
626
+ /** Prepare a forked successor without publishing it through public manager state. @internal */
627
+ prepareFork(): Promise<PreparedNewSession | undefined>;
628
+ /** Prepare a path-only branch successor without publishing it through public manager state. @internal */
629
+ prepareBranchedSession(leafId: string): Promise<PreparedNewSession>;
630
+ /** Publish a prepared successor synchronously after all readiness awaits succeed. @internal */
631
+ commitPreparedNewSession(prepared: PreparedNewSession): void;
632
+ /** Exact-discard only an uncommitted successor prepared by this manager. @internal */
633
+ discardPreparedNewSession(prepared: PreparedNewSession): Promise<void>;
600
634
  /** Tombstone and exact-delete managed transcripts, detaching the active transcript first. */
601
635
  dropSession(sessionPath: string): Promise<void>;
602
636
  /**
@@ -20,6 +20,7 @@ import type { ContextFileEntry } from "../tools";
20
20
  import type { EventBus } from "../utils/event-bus";
21
21
  import type { WorkspaceTree } from "../workspace-tree";
22
22
  import { type AgentDefinition, type AgentProgress, type ReviewFinding, type SingleResult } from "./types";
23
+ import { type ExecutorExecutionMode } from "./ultragoal-redteam-activation";
23
24
  export declare function trimForkContextSeedForModel(seed: ForkContextSeed, model: Model | undefined): ForkContextSeed;
24
25
  /** Options for subagent execution */
25
26
  export interface ExecutorOptions {
@@ -28,6 +29,11 @@ export interface ExecutorOptions {
28
29
  agent: AgentDefinition;
29
30
  task: string;
30
31
  assignment?: string;
32
+ /**
33
+ * Typed executor execution mode. When set, overrides assignment-text heuristics
34
+ * for ultragoal red-team prompt injection (#2698 / #2456).
35
+ */
36
+ executionMode?: ExecutorExecutionMode;
31
37
  context?: string;
32
38
  description?: string;
33
39
  index: number;
@@ -0,0 +1,13 @@
1
+ import type { AgentProgress, TaskToolDetails } from "./types";
2
+ export type ProviderRetryKind = NonNullable<AgentProgress["retryState"]>["kind"];
3
+ export declare function classifyProviderRetry(errorMessage: string): ProviderRetryKind;
4
+ export declare function providerNameFromModel(model: string | undefined): string | undefined;
5
+ export declare function providerRetryPhaseLabel(kind: ProviderRetryKind): string;
6
+ export declare function providerProgressAgeLabel(retryState: NonNullable<AgentProgress["retryState"]>, nowMs: number): string;
7
+ export declare function hasActiveProviderRetryInTaskDetails(details: TaskToolDetails, seen?: WeakSet<object>): boolean;
8
+ export declare function hasActiveProviderRetryInProgress(progress: AgentProgress, seen?: WeakSet<object>): boolean;
9
+ export interface ProviderDegradationGroup {
10
+ provider: string;
11
+ count: number;
12
+ }
13
+ export declare function collectProviderDegradationGroups(progress: readonly AgentProgress[]): ProviderDegradationGroup[];
@@ -45,6 +45,10 @@ export declare const taskItemSchema: z.ZodObject<{
45
45
  id: z.ZodString;
46
46
  description: z.ZodString;
47
47
  assignment: z.ZodString;
48
+ executionMode: z.ZodOptional<z.ZodEnum<{
49
+ default: "default";
50
+ "ultragoal-red-team": "ultragoal-red-team";
51
+ }>>;
48
52
  inheritContext: z.ZodOptional<z.ZodEnum<{
49
53
  bounded: "bounded";
50
54
  full: "full";
@@ -69,6 +73,10 @@ export declare const taskSchema: z.ZodObject<{
69
73
  id: z.ZodString;
70
74
  description: z.ZodString;
71
75
  assignment: z.ZodString;
76
+ executionMode: z.ZodOptional<z.ZodEnum<{
77
+ default: "default";
78
+ "ultragoal-red-team": "ultragoal-red-team";
79
+ }>>;
72
80
  inheritContext: z.ZodOptional<z.ZodEnum<{
73
81
  bounded: "bounded";
74
82
  full: "full";
@@ -100,6 +108,10 @@ export declare const taskSchemaNoIsolation: z.ZodObject<{
100
108
  id: z.ZodString;
101
109
  description: z.ZodString;
102
110
  assignment: z.ZodString;
111
+ executionMode: z.ZodOptional<z.ZodEnum<{
112
+ default: "default";
113
+ "ultragoal-red-team": "ultragoal-red-team";
114
+ }>>;
103
115
  inheritContext: z.ZodOptional<z.ZodEnum<{
104
116
  bounded: "bounded";
105
117
  full: "full";
@@ -131,6 +143,10 @@ declare const ALL_TASK_SCHEMAS: readonly [z.ZodObject<{
131
143
  id: z.ZodString;
132
144
  description: z.ZodString;
133
145
  assignment: z.ZodString;
146
+ executionMode: z.ZodOptional<z.ZodEnum<{
147
+ default: "default";
148
+ "ultragoal-red-team": "ultragoal-red-team";
149
+ }>>;
134
150
  inheritContext: z.ZodOptional<z.ZodEnum<{
135
151
  bounded: "bounded";
136
152
  full: "full";
@@ -161,6 +177,10 @@ declare const ALL_TASK_SCHEMAS: readonly [z.ZodObject<{
161
177
  id: z.ZodString;
162
178
  description: z.ZodString;
163
179
  assignment: z.ZodString;
180
+ executionMode: z.ZodOptional<z.ZodEnum<{
181
+ default: "default";
182
+ "ultragoal-red-team": "ultragoal-red-team";
183
+ }>>;
164
184
  inheritContext: z.ZodOptional<z.ZodEnum<{
165
185
  bounded: "bounded";
166
186
  full: "full";
@@ -191,6 +211,10 @@ declare const ALL_TASK_SCHEMAS: readonly [z.ZodObject<{
191
211
  id: z.ZodString;
192
212
  description: z.ZodString;
193
213
  assignment: z.ZodString;
214
+ executionMode: z.ZodOptional<z.ZodEnum<{
215
+ default: "default";
216
+ "ultragoal-red-team": "ultragoal-red-team";
217
+ }>>;
194
218
  inheritContext: z.ZodOptional<z.ZodEnum<{
195
219
  bounded: "bounded";
196
220
  full: "full";
@@ -221,6 +245,10 @@ declare const ALL_TASK_SCHEMAS: readonly [z.ZodObject<{
221
245
  id: z.ZodString;
222
246
  description: z.ZodString;
223
247
  assignment: z.ZodString;
248
+ executionMode: z.ZodOptional<z.ZodEnum<{
249
+ default: "default";
250
+ "ultragoal-red-team": "ultragoal-red-team";
251
+ }>>;
224
252
  inheritContext: z.ZodOptional<z.ZodEnum<{
225
253
  bounded: "bounded";
226
254
  full: "full";
@@ -251,6 +279,10 @@ declare const ALL_TASK_SCHEMAS: readonly [z.ZodObject<{
251
279
  id: z.ZodString;
252
280
  description: z.ZodString;
253
281
  assignment: z.ZodString;
282
+ executionMode: z.ZodOptional<z.ZodEnum<{
283
+ default: "default";
284
+ "ultragoal-red-team": "ultragoal-red-team";
285
+ }>>;
254
286
  inheritContext: z.ZodOptional<z.ZodEnum<{
255
287
  bounded: "bounded";
256
288
  full: "full";
@@ -281,6 +313,10 @@ declare const ALL_TASK_SCHEMAS: readonly [z.ZodObject<{
281
313
  id: z.ZodString;
282
314
  description: z.ZodString;
283
315
  assignment: z.ZodString;
316
+ executionMode: z.ZodOptional<z.ZodEnum<{
317
+ default: "default";
318
+ "ultragoal-red-team": "ultragoal-red-team";
319
+ }>>;
284
320
  inheritContext: z.ZodOptional<z.ZodEnum<{
285
321
  bounded: "bounded";
286
322
  full: "full";
@@ -416,6 +452,9 @@ export interface AgentProgress {
416
452
  attempt: number;
417
453
  maxAttempts: number;
418
454
  unbounded?: boolean;
455
+ kind: "first_event_timeout" | "idle_stream_stall" | "provider_error";
456
+ provider?: string;
457
+ lastProviderProgressAtMs?: number;
419
458
  delayMs: number;
420
459
  errorMessage: string;
421
460
  startedAtMs: number;
@@ -0,0 +1,33 @@
1
+ /**
2
+ * Decide whether an executor assignment should inject the ultragoal red-team
3
+ * prompt fragment.
4
+ *
5
+ * Preference order (parse, don't re-validate later):
6
+ * 1. Explicit typed `executionMode` on the task / ExecutorOptions — authoritative.
7
+ * 2. Assignment text heuristics — only explicit Ultragoal QA/red-team phrasing.
8
+ *
9
+ * Bare mentions of `executorQa` (docs, quality-gate field names, negative
10
+ * instructions) must not flip the mode (#2698 / #2456).
11
+ *
12
+ * Mirrors `executor.md`:
13
+ * "activates only when the assignment explicitly labels Executor as Ultragoal
14
+ * completion QA/red-team or asks for `executorQa` red-team evidence."
15
+ */
16
+ export declare const EXECUTOR_EXECUTION_MODES: readonly ["default", "ultragoal-red-team"];
17
+ export type ExecutorExecutionMode = (typeof EXECUTOR_EXECUTION_MODES)[number];
18
+ export declare function isExecutorExecutionMode(value: unknown): value is ExecutorExecutionMode;
19
+ /**
20
+ * Parse a caller-supplied mode. Unknown values fail closed to `undefined`
21
+ * so the assignment heuristic (or default off) still applies — never invent on.
22
+ */
23
+ export declare function parseExecutorExecutionMode(value: unknown): ExecutorExecutionMode | undefined;
24
+ export declare function assignmentRequestsUltragoalRedTeam(assignment: string | undefined): boolean;
25
+ export interface ResolveUltragoalRedTeamArgs {
26
+ readonly executionMode?: unknown;
27
+ readonly assignment?: string;
28
+ }
29
+ /**
30
+ * Final activation decision for the executor prompt fragment.
31
+ * Typed mode wins; assignment text is a compatibility fallback only.
32
+ */
33
+ export declare function resolveUltragoalRedTeamActivation(args: ResolveUltragoalRedTeamArgs): boolean;
@@ -198,9 +198,11 @@ export interface ToolSession {
198
198
  /** Agent identity used for IRC routing. Returns the registry id (e.g. "0-Main", "0-AuthLoader"). */
199
199
  getAgentId?: () => string | null;
200
200
  /** Look up a registered tool by name (used by the eval js backend's tool bridge). */
201
+ getToolByName?: (name: string) => AgentTool | undefined;
202
+ /** Look up a registered tool with the session's execution guards applied. */
203
+ getToolForExecution?: (name: string) => AgentTool | undefined;
201
204
  /** Purge undelivered queued custom messages matching the predicate. Returns counts. */
202
205
  purgeQueuedCustomMessages?: (predicate: (message: CustomMessage) => boolean) => PurgeQueuedCustomMessagesResult;
203
- getToolByName?: (name: string) => AgentTool | undefined;
204
206
  /** Agent registry for IRC routing across live sessions. */
205
207
  agentRegistry?: AgentRegistry;
206
208
  /** Optional restricted bash command prefixes for read-only role agents and constrained modes. */
@@ -1,3 +1,4 @@
1
+ import type { WindowsJobMemoryProbeResult } from "@gajae-code/natives";
1
2
  import type { Settings } from "../config/settings";
2
3
  import { type TabGcSnapshot } from "./browser/tab-supervisor";
3
4
  export interface BrowserGcPolicy {
@@ -16,7 +17,10 @@ export declare function resolveSweepIntervalMs(settings: Settings): number;
16
17
  /** Injectable seams so the controller is fully testable without real browsers/filesystem/RSS. */
17
18
  export interface ResourceGcDeps {
18
19
  now: () => number;
20
+ monotonicNow: () => number;
19
21
  rssBytes: () => number;
22
+ memorySnapshot: () => Promise<MemoryPressureSnapshot>;
23
+ runGc: () => void;
20
24
  logWarn: (msg: string, meta?: Record<string, unknown>) => void;
21
25
  listTabs: () => TabGcSnapshot[];
22
26
  releaseTab: (name: string, policy: {
@@ -43,6 +47,21 @@ export interface ResourceGcRegistration {
43
47
  */
44
48
  export declare function registerResourceGcSession(reg: ResourceGcRegistration): () => void;
45
49
  export declare function sweepOnce(d?: ResourceGcDeps): Promise<void>;
50
+ export interface MemoryPressureDomain {
51
+ hardCapBytes: number;
52
+ totalUsageBytes: number;
53
+ source: MemoryPressureSnapshot["source"];
54
+ }
55
+ export interface MemoryPressureSnapshot {
56
+ hardCapBytes: number;
57
+ totalUsageBytes: number;
58
+ parentBytes: number;
59
+ source: "host" | "linux_cgroup_v2" | "linux_cgroup_v1" | "windows_job" | "windows_process_job_limit";
60
+ domains?: MemoryPressureDomain[];
61
+ }
62
+ export declare function __sampleLinuxCgroupHierarchyForTest(mountInfo: string, membership: string, fsType: "cgroup" | "cgroup2", hostBytes: number, parentBytes: number): Promise<MemoryPressureSnapshot | null>;
63
+ export declare function __sampleWindowsJobMemoryForTest(hostBytes: number, parentBytes: number, probeResult?: WindowsJobMemoryProbeResult): MemoryPressureSnapshot | null;
64
+ export declare function __selectMemoryPressureDomainForTest(snapshot: MemoryPressureSnapshot, policyLimitBytes: number | null): MemoryPressureSnapshot;
46
65
  export declare function __setResourceGcDepsForTest(overrides: Partial<ResourceGcDeps>): void;
47
66
  export declare function __setResourceGcSchedulerNowForTest(now: () => number): void;
48
67
  export declare function __runResourceGcTickForTest(): Promise<void>;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "type": "module",
3
3
  "name": "@gajae-code/coding-agent",
4
- "version": "0.11.9",
4
+ "version": "0.11.11",
5
5
  "description": "Gajae Code CLI with read, bash, edit, write tools and session management",
6
6
  "homepage": "https://gajae-code.com",
7
7
  "author": "Yeachan-Heo and Gajae Code Contributors",
@@ -53,13 +53,13 @@
53
53
  "@agentclientprotocol/sdk": "1.2.1",
54
54
  "@babel/parser": "^7.29.3",
55
55
  "@mozilla/readability": "^0.6.0",
56
- "@gajae-code/stats": "0.11.9",
57
- "@gajae-code/agent-core": "0.11.9",
58
- "@gajae-code/ai": "0.11.9",
59
- "@gajae-code/bridge-client": "0.11.9",
60
- "@gajae-code/natives": "0.11.9",
61
- "@gajae-code/tui": "0.11.9",
62
- "@gajae-code/utils": "0.11.9",
56
+ "@gajae-code/stats": "0.11.11",
57
+ "@gajae-code/agent-core": "0.11.11",
58
+ "@gajae-code/ai": "0.11.11",
59
+ "@gajae-code/bridge-client": "0.11.11",
60
+ "@gajae-code/natives": "0.11.11",
61
+ "@gajae-code/tui": "0.11.11",
62
+ "@gajae-code/utils": "0.11.11",
63
63
  "@puppeteer/browsers": "^2.13.0",
64
64
  "@types/turndown": "5.0.6",
65
65
  "@xterm/headless": "^6.0.0",
@@ -70,6 +70,7 @@ const LOCKED_EXCLUSIONS: Readonly<Record<string, string>> = {
70
70
  "agent_session:getAsyncDeliveryStateForAcp":
71
71
  "internal ACP lifecycle quiescence plumbing, not a user-facing control seam",
72
72
  "agent_session:getToolByName": "internal accessor/plumbing, not a user-facing control seam",
73
+ "agent_session:getToolForExecution": "internal accessor/plumbing, not a user-facing control seam",
73
74
  "agent_session:registerForegroundBashBackgroundRequestHandler":
74
75
  "internal accessor/plumbing, not a user-facing control seam",
75
76
  "agent_session:hasForegroundBashBackgroundRequestHandler":
@@ -85,6 +86,7 @@ const LOCKED_EXCLUSIONS: Readonly<Record<string, string>> = {
85
86
  "agent_session:refreshMCPTools": "internal accessor/plumbing, not a user-facing control seam",
86
87
  "agent_session:refreshGjcSubskillTools": "internal accessor/plumbing, not a user-facing control seam",
87
88
  "agent_session:buildDisplaySessionContext": "internal accessor/plumbing, not a user-facing control seam",
89
+ "agent_session:buildPreparedDisplaySessionContext": "internal accessor/plumbing, not a user-facing control seam",
88
90
  "agent_session:convertMessagesToLlm": "internal accessor/plumbing, not a user-facing control seam",
89
91
  "agent_session:prepareSimpleStreamOptions": "internal accessor/plumbing, not a user-facing control seam",
90
92
  "agent_session:getPlanModeState": "internal accessor/plumbing, not a user-facing control seam",
@@ -197,6 +199,7 @@ const SEAM_TO_SDK: Readonly<Record<string, string>> = {
197
199
  "agent_session:setSessionName": "session.rename",
198
200
  "agent_session:setModel": "model.set",
199
201
  "agent_session:setDefaultModelSelection": "model.set",
202
+ "agent_session:activateModelProfileForControl": "model.profile.set",
200
203
  "agent_session:cycleModel": "model.cycle",
201
204
  "agent_session:setThinkingLevel": "thinking.set",
202
205
  "agent_session:cycleThinkingLevel": "thinking.cycle",
@@ -36,6 +36,8 @@ try {
36
36
  function validateRowReceipts(rows: ManifestAdapterRow[]): void {
37
37
  const ids = new Set<string>();
38
38
  const counts = new Map<string, number>();
39
+ // Each operation has one receipt, plus the dedicated config.patch secret-input receipt.
40
+ const expectedRowsPerAdapter = OPERATIONS.length + 1;
39
41
  for (const row of rows) {
40
42
  if (ids.has(row.adapterTestId)) throw new Error(`Duplicate adapter test ID: ${row.adapterTestId}`);
41
43
  ids.add(row.adapterTestId);
@@ -60,11 +62,11 @@ function validateRowReceipts(rows: ManifestAdapterRow[]): void {
60
62
  }
61
63
  counts.set(row.adapter, (counts.get(row.adapter) ?? 0) + 1);
62
64
  }
63
- if (rows.length !== ADAPTERS.length * 93)
64
- throw new Error(`Expected ${ADAPTERS.length * 93} adapter rows; received ${rows.length}.`);
65
+ if (rows.length !== ADAPTERS.length * expectedRowsPerAdapter)
66
+ throw new Error(`Expected ${ADAPTERS.length * expectedRowsPerAdapter} adapter rows; received ${rows.length}.`);
65
67
  for (const adapter of ADAPTERS) {
66
- if (counts.get(adapter) !== 93)
67
- throw new Error(`Expected 93 ${adapter} rows; received ${counts.get(adapter) ?? 0}.`);
68
+ if (counts.get(adapter) !== expectedRowsPerAdapter)
69
+ throw new Error(`Expected ${expectedRowsPerAdapter} ${adapter} rows; received ${counts.get(adapter) ?? 0}.`);
68
70
  }
69
71
  process.stdout.write(
70
72
  `manifest check: ${rows.length} row receipts (${[...counts].map(([adapter, count]) => `${adapter}=${count}`).join(", ")})\n`,
package/src/cli/args.ts CHANGED
@@ -205,17 +205,23 @@ export function parseArgs(args: string[]): Args {
205
205
  }
206
206
  }
207
207
  result.tools = validTools;
208
- } else if (arg === "--thinking" && i + 1 < args.length) {
208
+ } else if (arg === "--thinking") {
209
+ // Match --credential / --mcp-config: a missing value or a following flag is
210
+ // a usage error, not a silent no-op / accidental consumption of `-p`.
211
+ const next = args[i + 1];
212
+ if (!next || next.startsWith("-")) {
213
+ throw new CliParseError(`--thinking requires <level> (${THINKING_EFFORTS.join(", ")})`);
214
+ }
209
215
  const rawThinking = args[++i];
210
216
  const thinking = parseEffort(rawThinking);
211
- if (thinking !== undefined) {
212
- result.thinking = thinking;
213
- } else {
214
- logger.warn("Invalid thinking level passed to --thinking", {
215
- level: rawThinking,
216
- validThinkingLevels: THINKING_EFFORTS,
217
- });
217
+ if (thinking === undefined) {
218
+ // Fail closed: a silent ignore left users believing `ultra` (or any typo)
219
+ // was applied. Help / Flags.options advertise the real Effort enum.
220
+ throw new CliParseError(
221
+ `Invalid --thinking level "${rawThinking}". Expected one of: ${THINKING_EFFORTS.join(", ")}`,
222
+ );
218
223
  }
224
+ result.thinking = thinking;
219
225
  } else if (arg === "--print" || arg === "-p") {
220
226
  result.print = true;
221
227
  } else if (arg === "--export" && i + 1 < args.length) {
@@ -84,7 +84,7 @@ Environment Variables:
84
84
  GJC_LAUNCH_POLICY - Launch policy for --tmux startup: tmux or direct
85
85
  GJC_TMUX_SESSION - Explicit tmux session name override for --tmux startup
86
86
  GJC_TMUX_PROFILE - Apply GJC tmux scroll/mouse/clipboard profile to --tmux sessions (set 0/off to skip)
87
- GJC_MOUSE - Mouse-wheel scroll in --tmux sessions (set 0/off to let the host terminal scroll)
87
+ GJC_MOUSE - Apply tmux copy-mode mouse capture in --tmux sessions (set 0/off to skip)
88
88
 
89
89
  For complete environment variable reference, see:
90
90
  docs/environment-variables.md
@@ -413,6 +413,7 @@ async function runTelegramSetup(cmd: NotifyCommandArgs, deps: NotifyCommandDeps)
413
413
  settings,
414
414
  cwd: process.cwd(),
415
415
  sessionId: `notify-cli-${process.pid}`,
416
+ registerRoot: false,
416
417
  }),
417
418
  persistInactive: async marker => await persistTelegramActivationMarker(settings, marker),
418
419
  clearInactive: async marker => await clearTelegramActivationMarker(settings, marker),