@gajae-code/coding-agent 0.11.4 → 0.11.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +23 -0
- package/dist/types/cli/notify-cli.d.ts +5 -1
- package/dist/types/config/settings-schema.d.ts +20 -0
- package/dist/types/export/html/template.generated.d.ts +1 -1
- package/dist/types/gjc-runtime/deep-interview-state.d.ts +28 -0
- package/dist/types/gjc-runtime/launch-tmux.d.ts +3 -0
- package/dist/types/gjc-runtime/managed-owner-admission.d.ts +42 -0
- package/dist/types/gjc-runtime/managed-owner-supervisor.d.ts +41 -0
- package/dist/types/gjc-runtime/tmux-owner-isolation.d.ts +9 -0
- package/dist/types/gjc-runtime/ultragoal-owner-loss-recovery.d.ts +94 -0
- package/dist/types/gjc-runtime/ultragoal-runtime.d.ts +1 -0
- package/dist/types/harness-control-plane/owner.d.ts +3 -1
- package/dist/types/internal-urls/local-protocol.d.ts +18 -0
- package/dist/types/main.d.ts +2 -2
- package/dist/types/modes/components/ansi-display-validator.d.ts +2 -0
- package/dist/types/modes/components/notifications-settings-editor.d.ts +4 -0
- package/dist/types/modes/components/session-observer-overlay.d.ts +3 -1
- package/dist/types/modes/components/settings-selector.d.ts +2 -0
- package/dist/types/modes/components/tool-transcript-format.d.ts +58 -0
- package/dist/types/modes/components/transcript-viewer-overlay.d.ts +3 -0
- package/dist/types/modes/controllers/goal-mode-controller.d.ts +8 -1
- package/dist/types/modes/controllers/selector-controller.d.ts +15 -0
- package/dist/types/modes/shared/agent-wire/workflow-gate-broker.d.ts +3 -0
- package/dist/types/modes/shared/agent-wire/workflow-gate-types.d.ts +16 -0
- package/dist/types/plan-mode/approved-plan.d.ts +1 -0
- package/dist/types/runtime-mcp/manager.d.ts +2 -0
- package/dist/types/runtime-mcp/oauth-discovery.d.ts +12 -1
- package/dist/types/sdk/bus/chat-daemon-cli.d.ts +3 -1
- package/dist/types/sdk/bus/chat-daemon-control.d.ts +39 -4
- package/dist/types/sdk/bus/config-commands.d.ts +8 -0
- package/dist/types/sdk/bus/config.d.ts +22 -0
- package/dist/types/sdk/bus/index.d.ts +162 -2
- package/dist/types/sdk/bus/notification-service.d.ts +71 -8
- package/dist/types/sdk/bus/session-control.d.ts +11 -8
- package/dist/types/sdk/bus/telegram-daemon-cli.d.ts +5 -0
- package/dist/types/sdk/bus/telegram-daemon-contract.d.ts +6 -3
- package/dist/types/sdk/bus/telegram-daemon-control.d.ts +23 -4
- package/dist/types/sdk/bus/telegram-daemon.d.ts +214 -20
- package/dist/types/sdk/session.d.ts +16 -1
- package/dist/types/secrets/index.d.ts +4 -2
- package/dist/types/secrets/obfuscator.d.ts +1 -1
- package/dist/types/session/agent-session.d.ts +31 -2
- package/dist/types/session/artifacts.d.ts +30 -8
- package/dist/types/session/internal/managed-session-scope.d.ts +7 -0
- package/dist/types/session/internal/managed-session-storage.d.ts +63 -6
- package/dist/types/session/session-manager.d.ts +88 -18
- package/dist/types/session/session-storage.d.ts +27 -0
- package/dist/types/session/streaming-output.d.ts +4 -0
- package/dist/types/task/executor.d.ts +9 -0
- package/dist/types/tool-discovery/tool-index.d.ts +2 -0
- package/dist/types/tools/ask.d.ts +48 -0
- package/dist/types/tools/bash-skill-urls.d.ts +2 -2
- package/dist/types/tools/index.d.ts +4 -0
- package/package.json +9 -9
- package/scripts/generate-sdk-operation-inventory.ts +2 -0
- package/src/cli/notify-cli.ts +40 -18
- package/src/commands/sdk.ts +7 -2
- package/src/config/settings-schema.ts +17 -0
- package/src/daemon/runtime.ts +2 -2
- package/src/defaults/gjc/skills/deep-interview/SKILL.md +70 -49
- package/src/defaults/gjc/skills/ralplan/SKILL.md +0 -6
- package/src/defaults/gjc/skills/team/SKILL.md +7 -9
- package/src/defaults/gjc/skills/ultragoal/SKILL.md +0 -2
- package/src/eval/py/index.ts +2 -2
- package/src/export/html/template.generated.ts +1 -1
- package/src/extensibility/plugins/marketplace/manager.ts +94 -10
- package/src/gjc-runtime/deep-interview-recorder.ts +7 -0
- package/src/gjc-runtime/deep-interview-runtime.ts +10 -0
- package/src/gjc-runtime/deep-interview-state.ts +127 -3
- package/src/gjc-runtime/launch-tmux.ts +61 -6
- package/src/gjc-runtime/managed-owner-admission.ts +352 -0
- package/src/gjc-runtime/managed-owner-supervisor.ts +162 -0
- package/src/gjc-runtime/state-runtime.ts +38 -12
- package/src/gjc-runtime/team-runtime.ts +1 -1
- package/src/gjc-runtime/tmux-owner-isolation.ts +117 -0
- package/src/gjc-runtime/ultragoal-owner-loss-recovery.ts +328 -0
- package/src/gjc-runtime/ultragoal-runtime.ts +14 -0
- package/src/harness-control-plane/owner.ts +59 -3
- package/src/hindsight/client.ts +65 -2
- package/src/internal-urls/agent-protocol.ts +76 -5
- package/src/internal-urls/docs-index.generated.ts +7 -6
- package/src/internal-urls/local-protocol.ts +416 -18
- package/src/lsp/index.ts +4 -88
- package/src/main.ts +37 -13
- package/src/modes/acp/acp-agent.ts +8 -0
- package/src/modes/components/ansi-display-validator.ts +54 -0
- package/src/modes/components/notifications-settings-editor.ts +26 -2
- package/src/modes/components/session-observer-overlay.ts +40 -24
- package/src/modes/components/settings-selector.ts +3 -1
- package/src/modes/components/tool-transcript-format.ts +321 -0
- package/src/modes/components/transcript-viewer-overlay.ts +39 -17
- package/src/modes/controllers/goal-mode-controller.ts +20 -1
- package/src/modes/controllers/plan-mode-controller.ts +2 -0
- package/src/modes/controllers/runtime-mcp-command-controller.ts +3 -0
- package/src/modes/controllers/selector-controller.ts +70 -8
- package/src/modes/interactive-mode.ts +1 -0
- package/src/modes/shared/agent-wire/deep-interview-gate.ts +31 -1
- package/src/modes/shared/agent-wire/workflow-gate-broker.ts +17 -1
- package/src/modes/shared/agent-wire/workflow-gate-schema.ts +4 -2
- package/src/modes/shared/agent-wire/workflow-gate-types.ts +120 -3
- package/src/plan-mode/approved-plan.ts +3 -1
- package/src/prompts/agents/architect.md +1 -0
- package/src/prompts/agents/critic.md +1 -0
- package/src/prompts/system/custom-system-prompt.md +1 -1
- package/src/prompts/system/system-prompt.md +2 -1
- package/src/prompts/tools/lsp.md +3 -3
- package/src/runtime-mcp/manager.ts +16 -1
- package/src/runtime-mcp/oauth-discovery.ts +116 -26
- package/src/sdk/broker/session-index.ts +122 -64
- package/src/sdk/bus/chat-daemon-cli.ts +72 -10
- package/src/sdk/bus/chat-daemon-control.ts +526 -130
- package/src/sdk/bus/chat-daemon-runtime.ts +1 -0
- package/src/sdk/bus/config-commands.ts +22 -0
- package/src/sdk/bus/config.ts +37 -0
- package/src/sdk/bus/index.ts +384 -92
- package/src/sdk/bus/lifecycle-control-runtime.ts +53 -3
- package/src/sdk/bus/notification-service.ts +284 -62
- package/src/sdk/bus/recent-activity.ts +14 -5
- package/src/sdk/bus/session-control.ts +150 -44
- package/src/sdk/bus/telegram-daemon-cli.ts +20 -14
- package/src/sdk/bus/telegram-daemon-contract.ts +6 -3
- package/src/sdk/bus/telegram-daemon-control.ts +294 -76
- package/src/sdk/bus/telegram-daemon.ts +1788 -267
- package/src/sdk/protocol/operation-inventory.generated.json +11 -0
- package/src/sdk/session.ts +155 -27
- package/src/secrets/index.ts +53 -10
- package/src/secrets/obfuscator.ts +21 -18
- package/src/secrets/regex.ts +2 -0
- package/src/session/agent-session.ts +495 -253
- package/src/session/artifacts.ts +188 -23
- package/src/session/context-estimation.ts +7 -2
- package/src/session/internal/managed-session-scope.ts +200 -38
- package/src/session/internal/managed-session-storage.ts +1152 -46
- package/src/session/session-manager.ts +1055 -148
- package/src/session/session-storage.ts +109 -11
- package/src/session/streaming-output.ts +6 -0
- package/src/task/executor.ts +71 -26
- package/src/task/index.ts +63 -20
- package/src/tool-discovery/tool-index.ts +18 -0
- package/src/tools/ask.ts +129 -32
- package/src/tools/bash-skill-urls.ts +14 -3
- package/src/tools/bash.ts +2 -2
- package/src/tools/index.ts +4 -0
- package/src/tools/plan-mode-guard.ts +1 -0
- package/src/tools/sqlite-reader.ts +3 -2
- package/src/tools/subagent.ts +2 -0
|
@@ -2,6 +2,8 @@ import * as fs from "node:fs";
|
|
|
2
2
|
import type { Settings } from "../../config/settings";
|
|
3
3
|
import type { DaemonRuntimeInfo } from "../../daemon/control-types";
|
|
4
4
|
import { HEARTBEAT_TTL_MS } from "./daemon-paths";
|
|
5
|
+
import { type DaemonTransitionLock, type NotificationEndpointFile, type NotificationEndpointFileIdentity, type NotificationExactUnlinkResult } from "./notification-service";
|
|
6
|
+
import { type DaemonProcessReference } from "./telegram-daemon-control";
|
|
5
7
|
export { DAEMON_GENERATION, NOTIFICATION_PROTOCOL_VERSION } from "./telegram-daemon-contract";
|
|
6
8
|
import { type ControlServerLike, type LifecycleControlServerFactory } from "./lifecycle-control-runtime";
|
|
7
9
|
import type { OrchestratorDeps } from "./lifecycle-orchestrator";
|
|
@@ -10,9 +12,16 @@ import { type AliasTable, type CallbackRoute } from "./telegram-reference";
|
|
|
10
12
|
export type EnsureDaemonResult = "owner_spawned" | "attached" | "disabled" | "blocked";
|
|
11
13
|
/** Detailed result for orchestration that must distinguish a #2028 handoff from a fresh spawn. */
|
|
12
14
|
export type EnsureTelegramDaemonDetailedResult = "spawned" | "reloaded" | "attached" | "disabled" | "blocked_identity";
|
|
15
|
+
export type TelegramDaemonOwnershipPhase = "provisional" | "ready" | "retired";
|
|
13
16
|
export interface DaemonState {
|
|
14
17
|
pid: number;
|
|
18
|
+
/** OS process-start provenance; mandatory for PID-authorized ownership actions. */
|
|
19
|
+
incarnation: string;
|
|
15
20
|
ownerId: string;
|
|
21
|
+
/** Unique, durable identity for one ownership acquisition. */
|
|
22
|
+
acquisitionId?: string;
|
|
23
|
+
/** A provisional owner is physical-live but MUST NOT be attached as ready. */
|
|
24
|
+
ownershipPhase?: TelegramDaemonOwnershipPhase;
|
|
16
25
|
tokenFingerprint: string;
|
|
17
26
|
chatId: string;
|
|
18
27
|
startedAt: number;
|
|
@@ -26,10 +35,8 @@ export interface DaemonState {
|
|
|
26
35
|
version: 1;
|
|
27
36
|
/**
|
|
28
37
|
* Operational daemon generation of the process that owns the lock, distinct
|
|
29
|
-
* from the persisted state-schema {@link DaemonState.version}
|
|
30
|
-
* wire
|
|
31
|
-
* freshly-upgraded host can detect — and reload — a still-live pre-upgrade
|
|
32
|
-
* daemon whose schema version is unchanged. Absent on pre-generation state.
|
|
38
|
+
* from both the persisted state-schema {@link DaemonState.version} and the
|
|
39
|
+
* notification wire protocol version. Absent on pre-generation state.
|
|
33
40
|
*/
|
|
34
41
|
generation?: number;
|
|
35
42
|
stoppedAt?: number;
|
|
@@ -45,8 +52,14 @@ export interface TelegramDaemonFs {
|
|
|
45
52
|
}>;
|
|
46
53
|
readdir(path: string): Promise<string[]>;
|
|
47
54
|
chmod(path: string, mode: number): Promise<void>;
|
|
55
|
+
stat?(path: string): Promise<{
|
|
56
|
+
mtimeMs: number;
|
|
57
|
+
}>;
|
|
58
|
+
readEndpointFile?(path: string): Promise<NotificationEndpointFile>;
|
|
59
|
+
exactUnlink?(path: string, identity: NotificationEndpointFileIdentity): Promise<NotificationExactUnlinkResult>;
|
|
48
60
|
}
|
|
49
61
|
export interface SpawnResult {
|
|
62
|
+
pid?: number;
|
|
50
63
|
unref?: () => void;
|
|
51
64
|
}
|
|
52
65
|
export interface TelegramDaemonDeps {
|
|
@@ -54,6 +67,10 @@ export interface TelegramDaemonDeps {
|
|
|
54
67
|
now?: () => number;
|
|
55
68
|
pid?: number;
|
|
56
69
|
pidAlive?: (pid: number) => boolean;
|
|
70
|
+
/** Opens an identity-stable process authority for destructive lifecycle operations. */
|
|
71
|
+
processReference?: (pid: number) => DaemonProcessReference | undefined;
|
|
72
|
+
/** Returns immutable process-start provenance, or undefined when unsupported. */
|
|
73
|
+
pidIncarnation?: (pid: number) => string | undefined;
|
|
57
74
|
spawn?: (command: string, args: string[], opts: {
|
|
58
75
|
detached: boolean;
|
|
59
76
|
stdio: "ignore";
|
|
@@ -71,6 +88,8 @@ export interface TelegramDaemonDeps {
|
|
|
71
88
|
sendSignal?: (pid: number, signal: NodeJS.Signals) => void;
|
|
72
89
|
sleep?: (ms: number) => Promise<void>;
|
|
73
90
|
waitStepMs?: number;
|
|
91
|
+
/** Bounded startup-readiness timeout; injectable for deterministic handoff tests. */
|
|
92
|
+
readinessTimeoutMs?: number;
|
|
74
93
|
}
|
|
75
94
|
export declare const HEARTBEAT_INTERVAL_MS = 5000;
|
|
76
95
|
export { HEARTBEAT_TTL_MS };
|
|
@@ -104,6 +123,53 @@ export declare function startDaemonLifecycleControl(input: {
|
|
|
104
123
|
auditRedactionKey: Uint8Array;
|
|
105
124
|
env?: NodeJS.ProcessEnv;
|
|
106
125
|
}): OrchestratorDeps;
|
|
126
|
+
export declare function tryCreateOwnershipLock(fsImpl: TelegramDaemonFs, file: string, initialization: OwnershipLockMetadata): Promise<boolean>;
|
|
127
|
+
type OwnershipLockMetadata = {
|
|
128
|
+
pid: number;
|
|
129
|
+
incarnation: string;
|
|
130
|
+
ownerId?: string;
|
|
131
|
+
acquisitionId?: string;
|
|
132
|
+
startedAt: number;
|
|
133
|
+
};
|
|
134
|
+
type LegacyOwnershipLockMetadata = {
|
|
135
|
+
pid: number;
|
|
136
|
+
incarnation?: string;
|
|
137
|
+
startedAt: number;
|
|
138
|
+
};
|
|
139
|
+
type OwnershipLockRead = {
|
|
140
|
+
kind: "missing";
|
|
141
|
+
} | {
|
|
142
|
+
kind: "malformed";
|
|
143
|
+
raw: string;
|
|
144
|
+
mtimeMs?: number;
|
|
145
|
+
} | {
|
|
146
|
+
kind: "legacy";
|
|
147
|
+
metadata: LegacyOwnershipLockMetadata;
|
|
148
|
+
} | {
|
|
149
|
+
kind: "valid";
|
|
150
|
+
metadata: OwnershipLockMetadata;
|
|
151
|
+
};
|
|
152
|
+
/** Read lock provenance without treating a corrupt legacy artifact as a filesystem failure. */
|
|
153
|
+
export declare function readOwnershipLock(fsImpl: TelegramDaemonFs, file: string): Promise<OwnershipLockRead>;
|
|
154
|
+
/**
|
|
155
|
+
* A live initializer lock only proves that a concurrent publisher is active.
|
|
156
|
+
* It never proves a ready daemon: legacy or unavailable provenance remains
|
|
157
|
+
* blocked, while a canonical mismatch proves PID reuse and can be reclaimed
|
|
158
|
+
* under the transition lock.
|
|
159
|
+
*/
|
|
160
|
+
export declare function liveOwnershipLockDecision(input: {
|
|
161
|
+
lock: OwnershipLockRead;
|
|
162
|
+
pidAlive: (pid: number) => boolean;
|
|
163
|
+
pidIncarnation: (pid: number) => string | undefined;
|
|
164
|
+
}): {
|
|
165
|
+
acquired: false;
|
|
166
|
+
attached: false;
|
|
167
|
+
blocked: true;
|
|
168
|
+
} | {
|
|
169
|
+
acquired: false;
|
|
170
|
+
attached: false;
|
|
171
|
+
provisional: true;
|
|
172
|
+
} | undefined;
|
|
107
173
|
export declare function registerNotificationRoot(input: {
|
|
108
174
|
settings: Settings;
|
|
109
175
|
cwd: string;
|
|
@@ -121,12 +187,39 @@ export declare function unregisterNotificationRoot(input: {
|
|
|
121
187
|
sessionId: string;
|
|
122
188
|
fs?: TelegramDaemonFs;
|
|
123
189
|
}): Promise<UnregisterNotificationRootResult>;
|
|
190
|
+
export declare function hasSafeDaemonStateShape(state: unknown): state is DaemonState;
|
|
191
|
+
/** True for a physically live owner with this configuration, including legacy generations. */
|
|
192
|
+
export declare function isPhysicalMatchingOwner(input: {
|
|
193
|
+
state: DaemonState | undefined;
|
|
194
|
+
tokenFingerprint: string;
|
|
195
|
+
chatId: string;
|
|
196
|
+
pidAlive: (pid: number) => boolean;
|
|
197
|
+
pidIncarnation?: (pid: number) => string | undefined;
|
|
198
|
+
}): boolean;
|
|
199
|
+
/** True only for a signalable legacy owner or this generation's ready bound child. */
|
|
200
|
+
export declare function isSignalableMatchingOwner(input: {
|
|
201
|
+
state: DaemonState | undefined;
|
|
202
|
+
tokenFingerprint: string;
|
|
203
|
+
chatId: string;
|
|
204
|
+
pidAlive: (pid: number) => boolean;
|
|
205
|
+
pidIncarnation?: (pid: number) => string | undefined;
|
|
206
|
+
}): boolean;
|
|
124
207
|
export declare function isFreshLiveOwner(input: {
|
|
125
208
|
state: DaemonState | undefined;
|
|
126
209
|
now: number;
|
|
127
210
|
tokenFingerprint: string;
|
|
128
211
|
chatId: string;
|
|
129
212
|
pidAlive: (pid: number) => boolean;
|
|
213
|
+
pidIncarnation?: (pid: number) => string | undefined;
|
|
214
|
+
}): boolean;
|
|
215
|
+
/** True only when a physically live matching owner can serve this build's daemon lifecycle contract. */
|
|
216
|
+
export declare function isCurrentCompatibleOwner(input: {
|
|
217
|
+
state: DaemonState | undefined;
|
|
218
|
+
now: number;
|
|
219
|
+
tokenFingerprint: string;
|
|
220
|
+
chatId: string;
|
|
221
|
+
pidAlive: (pid: number) => boolean;
|
|
222
|
+
pidIncarnation?: (pid: number) => string | undefined;
|
|
130
223
|
}): boolean;
|
|
131
224
|
export declare function acquireDaemonOwnership(input: {
|
|
132
225
|
settings: Settings;
|
|
@@ -137,6 +230,7 @@ export declare function acquireDaemonOwnership(input: {
|
|
|
137
230
|
now?: () => number;
|
|
138
231
|
pid?: number;
|
|
139
232
|
pidAlive?: (pid: number) => boolean;
|
|
233
|
+
pidIncarnation?: (pid: number) => string | undefined;
|
|
140
234
|
randomId?: () => string;
|
|
141
235
|
/** Permit one Windows source launcher PID to daemon PID handoff. */
|
|
142
236
|
allowPidRebind?: boolean;
|
|
@@ -145,32 +239,100 @@ export declare function acquireDaemonOwnership(input: {
|
|
|
145
239
|
}): Promise<{
|
|
146
240
|
acquired: boolean;
|
|
147
241
|
ownerId?: string;
|
|
242
|
+
acquisitionId?: string;
|
|
148
243
|
attached?: boolean;
|
|
149
244
|
blocked?: boolean;
|
|
245
|
+
provisional?: boolean;
|
|
150
246
|
reason?: "identity_mismatch";
|
|
151
247
|
reloadRequired?: boolean;
|
|
152
248
|
}>;
|
|
153
249
|
export declare function renewDaemonHeartbeat(input: {
|
|
154
250
|
settings: Settings;
|
|
155
251
|
ownerId: string;
|
|
156
|
-
|
|
252
|
+
acquisitionId?: string;
|
|
253
|
+
tokenFingerprint?: string;
|
|
254
|
+
chatId?: string;
|
|
255
|
+
fs?: TelegramDaemonFs;
|
|
256
|
+
now?: () => number;
|
|
257
|
+
pid?: number;
|
|
258
|
+
generation?: number;
|
|
259
|
+
pidIncarnation?: (pid: number) => string | undefined;
|
|
260
|
+
sleep?: (ms: number) => Promise<void>;
|
|
261
|
+
stealRetries?: number;
|
|
262
|
+
stealRetryDelayMs?: number;
|
|
263
|
+
}): Promise<boolean>;
|
|
264
|
+
/** Acquire the lifecycle transition lock with bounded retry for bind/retire races. */
|
|
265
|
+
export declare function acquireTransitionLock(input: {
|
|
266
|
+
fs: TelegramDaemonFs;
|
|
267
|
+
path: string;
|
|
268
|
+
pidAlive?: (pid: number) => boolean;
|
|
269
|
+
pidIncarnation?: (pid: number) => string | undefined;
|
|
270
|
+
sleep?: (ms: number) => Promise<void>;
|
|
271
|
+
retries?: number;
|
|
272
|
+
retryDelayMs?: number;
|
|
273
|
+
}): Promise<DaemonTransitionLock | undefined>;
|
|
274
|
+
/** Retire only the unchanged provisional acquisition after bounded readiness fails. */
|
|
275
|
+
export declare function retireProvisionalDaemonOwnership(input: {
|
|
276
|
+
settings: Settings;
|
|
277
|
+
ownerId: string;
|
|
278
|
+
acquisitionId?: string;
|
|
279
|
+
pidIncarnation?: (pid: number) => string | undefined;
|
|
280
|
+
pidAlive?: (pid: number) => boolean;
|
|
281
|
+
/** Detached child PID, when the launcher successfully reported it. */
|
|
282
|
+
pid: number;
|
|
283
|
+
/** PID which created the provisional reservation before the child was bound. */
|
|
284
|
+
launcherPid?: number;
|
|
285
|
+
fs?: TelegramDaemonFs;
|
|
286
|
+
now?: () => number;
|
|
287
|
+
sleep?: (ms: number) => Promise<void>;
|
|
288
|
+
stealRetries?: number;
|
|
289
|
+
stealRetryDelayMs?: number;
|
|
290
|
+
/** Only no-child confirmation may retire a ready-like launcher publication. */
|
|
291
|
+
allowReadyWithoutChildPid?: boolean;
|
|
292
|
+
}): Promise<boolean>;
|
|
293
|
+
/** Wait for a matching current-generation daemon to publish a ready state. */
|
|
294
|
+
export declare function waitForTelegramDaemonReady(input: {
|
|
295
|
+
settings: Settings;
|
|
296
|
+
ownerId?: string;
|
|
297
|
+
acquisitionId?: string;
|
|
298
|
+
pid?: number;
|
|
299
|
+
excludedPid?: number;
|
|
157
300
|
tokenFingerprint: string;
|
|
158
301
|
chatId: string;
|
|
159
|
-
/** Require the current daemon PID after the launcher-to-daemon PID rebind. */
|
|
160
|
-
pid: number;
|
|
161
302
|
fs?: TelegramDaemonFs;
|
|
162
303
|
now?: () => number;
|
|
304
|
+
pidAlive?: (pid: number) => boolean;
|
|
305
|
+
pidIncarnation?: (pid: number) => string | undefined;
|
|
306
|
+
sleep?: (ms: number) => Promise<void>;
|
|
307
|
+
waitStepMs?: number;
|
|
308
|
+
timeoutMs?: number;
|
|
163
309
|
}): Promise<boolean>;
|
|
164
|
-
|
|
310
|
+
/** Confirm the provisional owner or retire only its unchanged acquisition. */
|
|
311
|
+
export declare function confirmTelegramDaemonSpawn(input: {
|
|
165
312
|
settings: Settings;
|
|
166
|
-
|
|
167
|
-
/** Bind release to the Telegram identity that acquired the lock. */
|
|
313
|
+
spawned: TelegramSpawnOwnerResult;
|
|
168
314
|
tokenFingerprint: string;
|
|
169
315
|
chatId: string;
|
|
170
|
-
/** Require the current daemon PID after the launcher-to-daemon PID rebind. */
|
|
171
316
|
pid: number;
|
|
172
317
|
fs?: TelegramDaemonFs;
|
|
173
318
|
now?: () => number;
|
|
319
|
+
pidAlive?: (pid: number) => boolean;
|
|
320
|
+
pidIncarnation?: (pid: number) => string | undefined;
|
|
321
|
+
sleep?: (ms: number) => Promise<void>;
|
|
322
|
+
waitStepMs?: number;
|
|
323
|
+
timeoutMs?: number;
|
|
324
|
+
}): Promise<boolean>;
|
|
325
|
+
export declare function releaseDaemonOwnership(input: {
|
|
326
|
+
settings: Settings;
|
|
327
|
+
ownerId: string;
|
|
328
|
+
acquisitionId?: string;
|
|
329
|
+
tokenFingerprint?: string;
|
|
330
|
+
chatId?: string;
|
|
331
|
+
pid?: number;
|
|
332
|
+
generation?: number;
|
|
333
|
+
pidIncarnation?: (pid: number) => string | undefined;
|
|
334
|
+
fs?: TelegramDaemonFs;
|
|
335
|
+
now?: () => number;
|
|
174
336
|
}): Promise<void>;
|
|
175
337
|
/** Read the persisted daemon ownership state (or undefined when absent). */
|
|
176
338
|
export declare function readDaemonState(settings: Pick<Settings, "getAgentDir">, fs?: TelegramDaemonFs): Promise<DaemonState | undefined>;
|
|
@@ -182,18 +344,30 @@ export interface TelegramSpawnOwnerInput {
|
|
|
182
344
|
tokenFingerprint: string;
|
|
183
345
|
chatId: string;
|
|
184
346
|
}
|
|
185
|
-
export interface
|
|
186
|
-
|
|
187
|
-
|
|
347
|
+
export interface TelegramSpawnAcquisition {
|
|
348
|
+
readonly ownerId: string;
|
|
349
|
+
readonly acquisitionId: string;
|
|
350
|
+
/** PID of the launcher which reserved provisional ownership before spawn. */
|
|
351
|
+
readonly launcherPid?: number;
|
|
352
|
+
/** Actual detached child which must publish the ready owner state. */
|
|
353
|
+
readonly pid?: number;
|
|
354
|
+
}
|
|
355
|
+
export type TelegramSpawnOwnerResult = {
|
|
356
|
+
result: "owner_spawned";
|
|
357
|
+
acquisition: TelegramSpawnAcquisition;
|
|
358
|
+
runtime: DaemonRuntimeInfo;
|
|
359
|
+
warnings: string[];
|
|
360
|
+
} | {
|
|
361
|
+
result: "attached";
|
|
188
362
|
runtime: DaemonRuntimeInfo;
|
|
189
363
|
warnings: string[];
|
|
190
|
-
/**
|
|
191
|
-
* Set when ownership was NOT acquired because a still-live owner is running an
|
|
192
|
-
* older daemon generation. The caller must hand off via a reload rather than
|
|
193
|
-
* attach; see {@link ensureTelegramDaemonRunning}.
|
|
194
|
-
*/
|
|
195
364
|
reloadRequired?: boolean;
|
|
196
|
-
}
|
|
365
|
+
} | {
|
|
366
|
+
result: "blocked";
|
|
367
|
+
runtime: DaemonRuntimeInfo;
|
|
368
|
+
warnings: string[];
|
|
369
|
+
reloadRequired?: boolean;
|
|
370
|
+
};
|
|
197
371
|
/**
|
|
198
372
|
* Build the detached spawn command/args for the daemon-internal entrypoint.
|
|
199
373
|
* Source mode prepends the entry script so the respawn loads edited source;
|
|
@@ -331,6 +505,7 @@ export interface TelegramDaemonOptions {
|
|
|
331
505
|
pid?: number;
|
|
332
506
|
/** Liveness probe for skipping dead-PID endpoint records in {@link TelegramNotificationDaemon.scanRoots}. */
|
|
333
507
|
pidAlive?: (pid: number) => boolean;
|
|
508
|
+
pidIncarnation?: (pid: number) => string | undefined;
|
|
334
509
|
botApi?: BotApi;
|
|
335
510
|
control?: DaemonControlHooks;
|
|
336
511
|
/**
|
|
@@ -358,6 +533,10 @@ export interface TelegramDaemonOptions {
|
|
|
358
533
|
richDraft?: {
|
|
359
534
|
enabled: boolean;
|
|
360
535
|
};
|
|
536
|
+
/** Tool start/completion messages (enabled by default). */
|
|
537
|
+
toolActivity?: {
|
|
538
|
+
enabled: boolean;
|
|
539
|
+
};
|
|
361
540
|
/**
|
|
362
541
|
* Per-session Telegram forum-topic naming. `nameTemplate` supports the
|
|
363
542
|
* `{repo}`, `{branch}`, and `{title}` placeholders; unset preserves the
|
|
@@ -403,6 +582,16 @@ export declare class TelegramNotificationDaemon {
|
|
|
403
582
|
readonly messageRoutes: Map<string | number, CallbackRoute | Omit<CallbackRoute, "answer">>;
|
|
404
583
|
/** Telegram message id backing each streamed `${sessionId}:${coalesceKey}`, for in-place edits. */
|
|
405
584
|
private readonly liveMessages;
|
|
585
|
+
/** Endpoint-bound ownership for visible or dispatching tool bubbles. */
|
|
586
|
+
private readonly toolActivityOwners;
|
|
587
|
+
private readonly revokedToolEndpoints;
|
|
588
|
+
private readonly unresolvedToolTerminalizations;
|
|
589
|
+
private toolTerminalizationChain;
|
|
590
|
+
private toolActivityPolicyEpoch;
|
|
591
|
+
private toolActivityStopping;
|
|
592
|
+
private readonly replayToolActivityEpochs;
|
|
593
|
+
private toolShutdownBarrier;
|
|
594
|
+
private toolActivityAmbiguous;
|
|
406
595
|
readonly sessions: Map<string, SessionSocket>;
|
|
407
596
|
private readonly runtime;
|
|
408
597
|
private readonly sessionRouter;
|
|
@@ -525,6 +714,9 @@ export declare class TelegramNotificationDaemon {
|
|
|
525
714
|
* (so a delayed old close cannot delete a replacement), and best-effort closes
|
|
526
715
|
* the socket. `scanRoots()` then reconnects the session.
|
|
527
716
|
*/
|
|
717
|
+
private enqueueToolTerminalization;
|
|
718
|
+
private scheduleVisibleToolTerminalization;
|
|
719
|
+
private beginToolActivityShutdown;
|
|
528
720
|
private dropSession;
|
|
529
721
|
private deleteMessageRoutes;
|
|
530
722
|
private static readonly THREADED_FRAMES;
|
|
@@ -543,6 +735,8 @@ export declare class TelegramNotificationDaemon {
|
|
|
543
735
|
private topicIdentityBase;
|
|
544
736
|
private topicOwnerForIdentity;
|
|
545
737
|
private sessionCanClaimIdentity;
|
|
738
|
+
private toolActivityOwner;
|
|
739
|
+
private toolActivityAuthorityIsCurrent;
|
|
546
740
|
private submitThreadedFrame;
|
|
547
741
|
private existingTopicForPrivateChat;
|
|
548
742
|
private topicAuthorityLease;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type AgentTelemetryConfig, ThinkingLevel } from "@gajae-code/agent-core";
|
|
1
|
+
import { type AgentMessage, type AgentTelemetryConfig, ThinkingLevel } from "@gajae-code/agent-core";
|
|
2
2
|
import { type AuthCredentialSelector, type Model, type ProviderSessionState } from "@gajae-code/ai";
|
|
3
3
|
import { createAppendOnlyContextManager, providerSupportsAppendOnlyAuto, resolveAppendOnlyMode } from "../append-only-mode";
|
|
4
4
|
import { type Rule } from "../capability/rule";
|
|
@@ -25,6 +25,19 @@ import { type BuildSystemPromptResult } from "../system-prompt";
|
|
|
25
25
|
import { BashTool, BUILTIN_TOOLS, createTools, EditTool, EvalTool, FindTool, HIDDEN_TOOLS, type LspStartupServerInfo, loadSshTool, ReadTool, ResolveTool, SearchTool, type Tool, type ToolSession, WebSearchTool, WriteTool } from "../tools";
|
|
26
26
|
import { EventBus } from "../utils/event-bus";
|
|
27
27
|
import { type WorkspaceTree } from "../workspace-tree";
|
|
28
|
+
/**
|
|
29
|
+
* Reconcile a resumed transcript that ends on an unpaired tool call.
|
|
30
|
+
*
|
|
31
|
+
* When a subagent finishes by calling `yield` (or any turn is torn down right
|
|
32
|
+
* after a tool executes), the terminating abort can land before the tool
|
|
33
|
+
* result is persisted, leaving the saved session ending on an assistant
|
|
34
|
+
* `toolCall` with no matching `toolResult`. Replaying that history verbatim on
|
|
35
|
+
* resume produces an invalid provider request (a tool_use not followed by a
|
|
36
|
+
* tool_result) and the resumed turn fails immediately. Synthesize a placeholder
|
|
37
|
+
* result for any such trailing unpaired tool call so a resumed session always
|
|
38
|
+
* starts from a valid, paired history. No-op for well-formed transcripts.
|
|
39
|
+
*/
|
|
40
|
+
export declare function reconcileTrailingToolCalls(messages: AgentMessage[]): AgentMessage[];
|
|
28
41
|
export interface CreateAgentSessionOptions {
|
|
29
42
|
/** Working directory for project-local discovery. Default: getProjectDir() */
|
|
30
43
|
cwd?: string;
|
|
@@ -152,6 +165,8 @@ export interface CreateAgentSessionOptions {
|
|
|
152
165
|
notificationHostModeSupported?: boolean;
|
|
153
166
|
/** Whether this host mode can own the root SDK endpoint. Default: true. */
|
|
154
167
|
sdkHostModeSupported?: boolean;
|
|
168
|
+
/** Override configured Discord/Slack daemon readiness, primarily for embedded hosts and deterministic tests. */
|
|
169
|
+
ensureNotificationProviderDaemon?: (provider: "discord" | "slack", settings: Settings) => Promise<unknown>;
|
|
155
170
|
/**
|
|
156
171
|
* Opt-in OpenTelemetry instrumentation forwarded to the underlying Agent.
|
|
157
172
|
* Passing `{}` enables the loop's GenAI-semantic-convention spans. See
|
|
@@ -1,8 +1,10 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import { type SecretEntry, SecretObfuscator } from "./obfuscator";
|
|
2
|
+
/** Create an obfuscator using the process-local authenticated-placeholder key. */
|
|
3
|
+
export declare function createSecretObfuscator(entries: SecretEntry[]): SecretObfuscator;
|
|
2
4
|
export { deobfuscateSessionContext, obfuscateMessages, type SecretEntry, SecretObfuscator } from "./obfuscator";
|
|
3
5
|
/**
|
|
4
6
|
* Load secrets from project-local and global secrets.yml files.
|
|
5
|
-
* Project-local entries override global entries with matching content.
|
|
7
|
+
* Project-local plain entries override global entries with matching content.
|
|
6
8
|
*/
|
|
7
9
|
export declare function loadSecrets(cwd: string, agentDir: string): Promise<SecretEntry[]>;
|
|
8
10
|
/** Collect environment variable values that look like secrets. */
|
|
@@ -9,7 +9,7 @@ export interface SecretEntry {
|
|
|
9
9
|
}
|
|
10
10
|
export declare class SecretObfuscator {
|
|
11
11
|
#private;
|
|
12
|
-
constructor(entries: SecretEntry[]);
|
|
12
|
+
constructor(entries: SecretEntry[], key?: Uint8Array);
|
|
13
13
|
hasSecrets(): boolean;
|
|
14
14
|
/** Obfuscate all secrets in text. Bidirectional placeholders for obfuscate mode, one-way for replace. */
|
|
15
15
|
obfuscate(text: string): string;
|
|
@@ -101,7 +101,7 @@ export { DefaultModelSelectionRecoveryError } from "./default-model-selection";
|
|
|
101
101
|
import type { ClientBridge, ClientBridgePermissionOption, ClientBridgePermissionOutcome, ClientBridgePermissionToolCall } from "./client-bridge";
|
|
102
102
|
import { type ContributionPrepOptions, type ContributionPrepResult } from "./contribution-prep";
|
|
103
103
|
import { type CustomMessage } from "./messages";
|
|
104
|
-
import type { BranchSummaryEntry, CompactionEntry, NewSessionOptions, SessionContext, SessionManager, SessionManagerCloseOutcome } from "./session-manager";
|
|
104
|
+
import type { BranchSummaryEntry, CompactionEntry, NewSessionOptions, RecoveryHydrationContext, RecoveryHydrationPromotionFence, SessionContext, SessionManager, SessionManagerCloseOutcome } from "./session-manager";
|
|
105
105
|
import { ToolChoiceQueue } from "./tool-choice-queue";
|
|
106
106
|
import { YieldQueue } from "./yield-queue";
|
|
107
107
|
/** Session-specific events that extend the core AgentEvent */
|
|
@@ -250,12 +250,30 @@ export interface AgentSessionConfig {
|
|
|
250
250
|
discoveryMode?: "off" | "mcp-only" | "all";
|
|
251
251
|
/** MCP tool names to activate for the current session when discovery mode is enabled. */
|
|
252
252
|
initialSelectedMCPToolNames?: string[];
|
|
253
|
-
/**
|
|
253
|
+
/** Built-in discoverable tool names restored for the current all-discovery session. */
|
|
254
|
+
initialSelectedDiscoveredBuiltinToolNames?: string[];
|
|
255
|
+
/** Discoverable built-ins active for configured or explicit reasons independently of persisted discovery selection. */
|
|
256
|
+
initialBaselineDiscoveredBuiltinToolNames?: string[];
|
|
257
|
+
/** Whether an MCP selection was explicitly supplied to the constructor, including an empty selection. */
|
|
258
|
+
initialMCPToolSelectionIsExplicit?: boolean;
|
|
259
|
+
/** Whether a discoverable built-in selection was explicitly supplied to the constructor, including an empty selection. */
|
|
260
|
+
initialDiscoveredBuiltinToolSelectionIsExplicit?: boolean;
|
|
261
|
+
/** Whether constructor-provided MCP selections should be persisted immediately. */
|
|
254
262
|
persistInitialMCPToolSelection?: boolean;
|
|
263
|
+
/** Whether constructor-provided discovered-built-in selections should be persisted immediately. */
|
|
264
|
+
persistInitialDiscoveredBuiltinToolSelection?: boolean;
|
|
265
|
+
/** Explicit MCP authority to write for a new session; distinct from active fallback tools. */
|
|
266
|
+
initialPersistedMCPToolNames?: string[];
|
|
267
|
+
/** Explicit discovered built-in authority to write for a new session; distinct from active fallback tools. */
|
|
268
|
+
initialPersistedDiscoveredBuiltinToolNames?: string[];
|
|
269
|
+
/** Immutable predecessor authority while a recovery host is read-only. */
|
|
270
|
+
recoveryHydrationContext?: RecoveryHydrationContext;
|
|
255
271
|
/** MCP server names whose tools should seed discovery-mode sessions whenever those servers are connected. */
|
|
256
272
|
defaultSelectedMCPServerNames?: string[];
|
|
257
273
|
/** MCP tool names that should seed brand-new sessions created from this AgentSession. */
|
|
258
274
|
defaultSelectedMCPToolNames?: string[];
|
|
275
|
+
/** MCP capabilities that are always active and never part of persisted user selection. */
|
|
276
|
+
mandatoryMCPToolNames?: string[];
|
|
259
277
|
/** TTSR manager for time-traveling stream rules */
|
|
260
278
|
ttsrManager?: TtsrManager;
|
|
261
279
|
/** Secret obfuscator for deobfuscating streaming edit content */
|
|
@@ -472,6 +490,13 @@ export declare class AgentSession {
|
|
|
472
490
|
};
|
|
473
491
|
readonly rawSseDebugBuffer: RawSseDebugBuffer;
|
|
474
492
|
constructor(config: AgentSessionConfig);
|
|
493
|
+
/**
|
|
494
|
+
* Resolves when constructor-time workflow-gate tool restoration (ask
|
|
495
|
+
* registration plus durable active-workflow attachment) has settled. The
|
|
496
|
+
* SDK factory awaits this so a resumed canonical workflow session is
|
|
497
|
+
* returned with `ask` already resident.
|
|
498
|
+
*/
|
|
499
|
+
get workflowGateToolRestoration(): Promise<void>;
|
|
475
500
|
/** Model registry for API key resolution and model discovery */
|
|
476
501
|
get modelRegistry(): ModelRegistry;
|
|
477
502
|
/** Advance the tool-choice queue and return the next directive for the upcoming LLM call. */
|
|
@@ -704,6 +729,10 @@ export declare class AgentSession {
|
|
|
704
729
|
/** All messages including custom types like BashExecutionMessage */
|
|
705
730
|
get messages(): AgentMessage[];
|
|
706
731
|
get transcriptPromptGeneration(): number;
|
|
732
|
+
/** The immutable recovery authority, present only before external ownership promotion. */
|
|
733
|
+
get recoveryHydrationContext(): RecoveryHydrationContext | undefined;
|
|
734
|
+
/** Enables normal session mutations after the owner has published its durable fence and writer lease. */
|
|
735
|
+
promoteRecoveryHydrationAfterOwnershipReadyFence(fence: RecoveryHydrationPromotionFence): Promise<void>;
|
|
707
736
|
/** Main startup calls this exactly once, after a strict open returned `kind: "opened"`. */
|
|
708
737
|
continuePersistedHistory(): Promise<void>;
|
|
709
738
|
buildDisplaySessionContext(): SessionContext;
|
|
@@ -1,3 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Session-scoped artifact storage for truncated tool outputs.
|
|
3
|
+
*
|
|
4
|
+
* Artifacts are stored in a directory alongside the session file,
|
|
5
|
+
* accessible via artifact:// URLs.
|
|
6
|
+
*/
|
|
7
|
+
import { type ManagedSessionDescendantStore } from "./internal/managed-session-storage";
|
|
8
|
+
export interface ManagedOutputGeneration {
|
|
9
|
+
outputFilename: string;
|
|
10
|
+
metadataFilename: string;
|
|
11
|
+
outputSizeBytes: number;
|
|
12
|
+
outputSha256: string;
|
|
13
|
+
metadataSizeBytes: number;
|
|
14
|
+
metadataSha256: string;
|
|
15
|
+
}
|
|
1
16
|
export interface ArtifactSaveOptions {
|
|
2
17
|
maxBytes?: number;
|
|
3
18
|
}
|
|
@@ -16,32 +31,39 @@ export declare class ArtifactManager {
|
|
|
16
31
|
/**
|
|
17
32
|
* @param dir Directory that will hold artifact files. Created lazily on first save.
|
|
18
33
|
*/
|
|
19
|
-
constructor(
|
|
34
|
+
constructor(target: string | ManagedSessionDescendantStore);
|
|
20
35
|
/**
|
|
21
36
|
* Artifact directory path.
|
|
22
37
|
* Directory may not exist until first artifact is saved.
|
|
23
38
|
*/
|
|
24
39
|
get dir(): string;
|
|
40
|
+
getManagedRootAuthority(): import("./internal/managed-session-storage").ManagedDirectoryRoot | undefined;
|
|
41
|
+
getManagedSubtreeRootAuthority(): import("./internal/managed-session-storage").ManagedDirectoryRoot | undefined;
|
|
42
|
+
getManagedStore(): ManagedSessionDescendantStore | undefined;
|
|
43
|
+
assertManagedBinding(): void;
|
|
44
|
+
replaceNamed(filename: string, content: string): Promise<void>;
|
|
45
|
+
replaceNamedBytes(filename: string, bytes: Uint8Array): Promise<void>;
|
|
46
|
+
publishManagedOutputGeneration(selectorFilename: string, outputFilenamePrefix: string, outputBytes: Uint8Array, metadataBytes: Uint8Array): Promise<void>;
|
|
47
|
+
publishNamedNoReplace(filename: string, bytes: Uint8Array): Promise<void>;
|
|
25
48
|
/**
|
|
26
49
|
* Atomically allocate next artifact ID.
|
|
27
50
|
* IDs are sequential within the session.
|
|
28
51
|
*/
|
|
29
52
|
allocateId(): number;
|
|
30
53
|
/**
|
|
31
|
-
*
|
|
54
|
+
* Reserve an artifact ID without exposing a writable managed pathname.
|
|
32
55
|
*
|
|
33
|
-
*
|
|
56
|
+
* Streaming callers that only understand bare paths fail closed; use `save`
|
|
57
|
+
* for terminally published artifact content.
|
|
34
58
|
*/
|
|
35
59
|
allocatePath(toolType: string): Promise<{
|
|
36
60
|
id: string;
|
|
37
|
-
path
|
|
61
|
+
path?: string;
|
|
38
62
|
}>;
|
|
39
63
|
/**
|
|
40
64
|
* Save content as an artifact and return the artifact ID.
|
|
41
|
-
*
|
|
42
|
-
*
|
|
43
|
-
* @param toolType Tool name for file extension (e.g., "bash", "read")
|
|
44
|
-
* @returns Artifact ID (numeric string)
|
|
65
|
+
* Content is written to a private temporary inode, synced, and linked into
|
|
66
|
+
* the artifact directory only after the complete terminal payload exists.
|
|
45
67
|
*/
|
|
46
68
|
save(content: string, toolType: string, options?: ArtifactSaveOptions): Promise<string>;
|
|
47
69
|
/**
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import * as native from "@gajae-code/natives";
|
|
1
2
|
import type { ResumeSessionIdentity } from "../session-manager";
|
|
2
3
|
export declare const MANAGED_SESSION_LAYOUT_VERSION: 2;
|
|
3
4
|
export declare const MANAGED_SESSION_IDENTITY_VERSION: 1;
|
|
@@ -14,6 +15,12 @@ export interface ManagedScope {
|
|
|
14
15
|
directoryPath: string;
|
|
15
16
|
platform: "posix" | "win32";
|
|
16
17
|
}
|
|
18
|
+
export declare function managedDirectoryAuthorityForScope(scope: ManagedScope): native.RecoveryFsRoot | undefined;
|
|
19
|
+
export declare function managedDirectoryIdentityForScope(scope: ManagedScope): {
|
|
20
|
+
dev: bigint;
|
|
21
|
+
ino: bigint;
|
|
22
|
+
};
|
|
23
|
+
export declare function managedRootForScope(scope: ManagedScope): import("./managed-session-storage").ManagedDirectoryRoot;
|
|
17
24
|
export type ManagedMigrationPolicy = "copy-retain" | "disabled";
|
|
18
25
|
export type ManagedScopeErrorCode = "cwd_missing" | "cwd_not_directory" | "identity_unavailable" | "network_unsupported" | "sessions_root_unavailable" | "binding_conflict" | "binding_invalid";
|
|
19
26
|
export type ManagedScopeResolution = {
|