@gajae-code/coding-agent 0.18.6 → 0.18.7
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 +39 -0
- package/dist/types/capability/types.d.ts +4 -0
- package/dist/types/config/settings.d.ts +4 -0
- package/dist/types/discovery/helpers.d.ts +2 -2
- package/dist/types/runtime-mcp/elicitation.d.ts +12 -0
- package/dist/types/sdk/broker/lifecycle.d.ts +9 -0
- package/dist/types/sdk/broker/task-artifact-owner-validation.d.ts +55 -0
- package/dist/types/sdk/bus/telegram-daemon.d.ts +3 -2
- package/dist/types/sdk/host/host.d.ts +6 -0
- package/dist/types/sdk/router/session-router.d.ts +7 -0
- package/dist/types/session/internal/managed-session-storage.d.ts +11 -1
- package/dist/types/session/internal/task-artifact-owner-access.d.ts +17 -0
- package/dist/types/session/internal/task-artifact-owner-transcript.d.ts +3 -0
- package/dist/types/session/session-retirement.d.ts +47 -0
- package/dist/types/session/session-storage.d.ts +0 -46
- package/dist/types/session/session-transcript-header.d.ts +2 -0
- package/dist/types/session/task-artifact-owner-codec.d.ts +107 -0
- package/dist/types/session/task-artifact-owner-retirement.d.ts +7 -0
- package/dist/types/session/task-artifact-owner.d.ts +10 -0
- package/package.json +7 -7
- package/scripts/resident-memory-bench.ts +174 -20
- package/src/capability/index.ts +1 -0
- package/src/capability/types.ts +4 -0
- package/src/cli/config-cli.ts +8 -18
- package/src/cli-main.ts +7 -8
- package/src/commands/sdk.ts +112 -21
- package/src/config/settings.ts +44 -4
- package/src/discovery/helpers.ts +9 -3
- package/src/discovery/ssh.ts +8 -3
- package/src/gjc-runtime/gc-runtime.ts +2 -1
- package/src/hindsight/config.ts +9 -3
- package/src/internal-urls/docs-index.generated.ts +2 -2
- package/src/modes/acp/acp-agent.ts +75 -3
- package/src/runtime-mcp/client.ts +13 -4
- package/src/runtime-mcp/elicitation.ts +142 -0
- package/src/sdk/broker/broker.ts +8 -1
- package/src/sdk/broker/lifecycle.ts +109 -7
- package/src/sdk/broker/task-artifact-owner-validation.ts +259 -0
- package/src/sdk/bus/chat-daemon-control.ts +2 -2
- package/src/sdk/bus/chat-daemon-runtime.ts +3 -0
- package/src/sdk/bus/index.ts +3 -3
- package/src/sdk/bus/telegram-daemon.ts +4 -2
- package/src/sdk/host/host.ts +6 -0
- package/src/sdk/host/session-runtime.test.ts +43 -2
- package/src/sdk/host/session-runtime.ts +2 -2
- package/src/sdk/mcp/server.ts +15 -3
- package/src/sdk/router/session-router.ts +19 -2
- package/src/sdk/session.ts +14 -0
- package/src/session/agent-session.ts +57 -6
- package/src/session/internal/managed-session-storage.ts +107 -1
- package/src/session/internal/task-artifact-owner-access.ts +229 -0
- package/src/session/internal/task-artifact-owner-transcript.ts +68 -0
- package/src/session/session-retirement.ts +155 -0
- package/src/session/session-storage.ts +1 -160
- package/src/session/session-transcript-header.ts +17 -0
- package/src/session/task-artifact-owner-codec.ts +578 -0
- package/src/session/task-artifact-owner-retirement.ts +475 -0
- package/src/session/task-artifact-owner.ts +289 -0
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,45 @@
|
|
|
2
2
|
|
|
3
3
|
## [Unreleased]
|
|
4
4
|
|
|
5
|
+
## [0.18.7] - 2026-10-04
|
|
6
|
+
|
|
7
|
+
### Added
|
|
8
|
+
|
|
9
|
+
- Resolve readonly target-directory settings snapshots with normalized values and fresh operation-local metadata reads, without changing parent settings or publishing global hooks.
|
|
10
|
+
|
|
11
|
+
### Changed
|
|
12
|
+
|
|
13
|
+
- Cut startup memory for the light CLI invocations by deferring the per-path modules out of the eager root command graph: peak RSS dropped from 32.4 MB to 27.7 MB for `--version` and from 32.7 MB to 28.0 MB for `--help`. The quick lane, the bash-shell guardian/supervisor/worker executors, the isolated shell, the tab-worker smoke probe and the fixture report now load only when their own path actually runs, so their behaviour, output and exit codes are unchanged.
|
|
14
|
+
|
|
15
|
+
### Fixed
|
|
16
|
+
|
|
17
|
+
- `session.resume` of a session whose detached-idle host already exited no longer fails with `EEXIST` on `<id>.lifecycle.ready.json`: the host revokes its own ready marker on graceful exit, and a launch retires the same id's leftover ready/marker pair when the recorded owner is proven exited (a live or unknown owner still wins) (#6261).
|
|
18
|
+
|
|
19
|
+
- Settle active ACP prompts immediately when their SDK session host retires, while preserving prompts across same-generation attachment replacement instead of waiting for the inactivity watchdog.
|
|
20
|
+
|
|
21
|
+
- Apply ACP thinking-level changes through the session control setter so reasoning effort updates the live session state and session config readback reflects the requested level.
|
|
22
|
+
|
|
23
|
+
- ACP now rejects unsupported or unapplied thinking levels instead of reporting them as successful changes.
|
|
24
|
+
|
|
25
|
+
- Session heartbeat checkpoints no longer starve the SDK broker discovery heartbeat while waiting on the session-index lock.
|
|
26
|
+
|
|
27
|
+
- SDK broker readiness polling now uses the session-index change stamp instead of checkpointing live heartbeats and replaying the full index on every poll.
|
|
28
|
+
|
|
29
|
+
- `gjc config set|get|list` (text and `--json`) no longer print the Slack app-level token `notifications.slack.appToken` verbatim. Secret detection for setting keys now treats any key segment ending in a secret word (`token`, `secret`, `password`, `passwd`, `pwd`, `credential(s)`) as secret instead of relying on a fixed list of camelCase prefixes, so it shows `<redacted>` like every other token setting. Token-budget settings such as `compaction.reserveTokens` stay visible.
|
|
30
|
+
|
|
31
|
+
- Retry bare-default Codex overloads when the failed attempt contains only an empty unsigned thinking block.
|
|
32
|
+
|
|
33
|
+
- `HINDSIGHT_RETAIN_EVERY_N_TURNS`, `HINDSIGHT_RECALL_MAX_TOKENS`, `HINDSIGHT_RECALL_CONTEXT_TURNS` and `HINDSIGHT_RECALL_MAX_QUERY_CHARS` now accept only plain non-negative digits. Malformed values such as `5turns`, `1e3`, `1.5` or `-3` fall back to the matching `hindsight.*` setting instead of being read by `parseInt` as 5, 1, 1 or -3. A negative `HINDSIGHT_RETAIN_EVERY_N_TURNS` previously made chunked retention send nothing.
|
|
34
|
+
|
|
35
|
+
- Slack and Discord chat daemons no longer post every lean final answer twice. The host sends each turn frame on a positioned leg and a raw leg and drops the raw copy only for connections that negotiate `positioned_notification_effects_v1`; the chat daemons' session connections never did, and a lean final carries no `messageRef` to collapse the two copies onto one publication. Chat daemon session connections now negotiate positioned-only notification effects, while plain SDK observers such as `gjc sdk session tail` keep both surfaces.
|
|
36
|
+
|
|
37
|
+
- Answer modern MCP roots requests without requiring an interactive input handler, while keeping actual elicitation fail-closed when user input is unavailable.
|
|
38
|
+
- Connect supported MCP form requests to the session's user-input surface instead of failing before users can answer.
|
|
39
|
+
|
|
40
|
+
- SDK MCP initialize now negotiates supported protocol versions and includes the coding-agent package version in `serverInfo`.
|
|
41
|
+
|
|
42
|
+
- SSH hosts loaded from `ssh.json` no longer accept a malformed `port`. A string port must be plain digits and every port must be an integer from 1 to 65535, so `"22oops"`, `"+22"`, `2222.5`, `0` and `70000` are now dropped with an `Invalid port` warning (the host falls back to the default port) instead of being used as 22, 22, 2222.5, 0 and 70000.
|
|
43
|
+
|
|
5
44
|
## [0.18.6] - 2026-10-03
|
|
6
45
|
|
|
7
46
|
### Added
|
|
@@ -39,6 +39,8 @@ export interface LoadContext {
|
|
|
39
39
|
repoRoot: string | null;
|
|
40
40
|
/** Whether discovery must remain isolated to the supplied home boundary. */
|
|
41
41
|
isolatedHome?: boolean;
|
|
42
|
+
/** Bypass lexical filesystem caches for this discovery operation. */
|
|
43
|
+
bypassCache?: boolean;
|
|
42
44
|
/** Owning session settings for provider policy decisions. */
|
|
43
45
|
settings?: Settings;
|
|
44
46
|
}
|
|
@@ -104,6 +106,8 @@ export interface LoadOptions {
|
|
|
104
106
|
includeDisabledProviders?: boolean;
|
|
105
107
|
/** Explicit disabled extension IDs to apply instead of settings. */
|
|
106
108
|
disabledExtensions?: string[];
|
|
109
|
+
/** Bypass lexical filesystem caches for this discovery operation. */
|
|
110
|
+
bypassCache?: boolean;
|
|
107
111
|
/** Session settings whose provider policy applies to this load. */
|
|
108
112
|
settings?: Settings;
|
|
109
113
|
/** Internal: prevent explicit-home loads from consulting process-global policy. */
|
|
@@ -179,6 +179,10 @@ export declare class Settings implements NotificationSettingsReader {
|
|
|
179
179
|
flush(): Promise<void>;
|
|
180
180
|
/** Like {@link flush}, but reports a durable save failure to the caller. */
|
|
181
181
|
flushOrThrow(): Promise<void>;
|
|
182
|
+
/** Copy execution settings without reloading, persisting, or sharing mutable layers. */
|
|
183
|
+
snapshot(): Settings;
|
|
184
|
+
/** Resolve a retained execution's project layer without persistence or global hooks. */
|
|
185
|
+
snapshotForCwd(cwd: string): Promise<Settings>;
|
|
182
186
|
cloneForCwd(cwd: string): Promise<Settings>;
|
|
183
187
|
getStorage(): AgentStorage | null;
|
|
184
188
|
/** Flush and close storage owned by an isolated settings scope. */
|
|
@@ -93,8 +93,8 @@ export declare function getUserSkillScanDirs(home: string, userAgentDir?: string
|
|
|
93
93
|
*/
|
|
94
94
|
export declare function getProjectPath(ctx: LoadContext, source: SourceId, subpath: string): string | null;
|
|
95
95
|
/** Build the filesystem authority for a provider read. */
|
|
96
|
-
export declare function getReadOptions(ctx: Pick<LoadContext, "home" | "isolatedHome" | "userAgentDir" | "homeIdentity" | "userAgentIdentity">, scope: ReadScope): ReadFileOptions | undefined;
|
|
97
|
-
export declare function getReadOptionsForContainment(ctx: Pick<LoadContext, "home" | "isolatedHome" | "userAgentDir" | "homeIdentity" | "userAgentIdentity">, scope: ReadScope, containmentRoot?: string): Promise<ReadFileOptions | undefined>;
|
|
96
|
+
export declare function getReadOptions(ctx: Pick<LoadContext, "home" | "isolatedHome" | "userAgentDir" | "homeIdentity" | "userAgentIdentity" | "bypassCache">, scope: ReadScope): ReadFileOptions | undefined;
|
|
97
|
+
export declare function getReadOptionsForContainment(ctx: Pick<LoadContext, "home" | "isolatedHome" | "userAgentDir" | "homeIdentity" | "userAgentIdentity" | "bypassCache">, scope: ReadScope, containmentRoot?: string): Promise<ReadFileOptions | undefined>;
|
|
98
98
|
/**
|
|
99
99
|
* Create source metadata for an item.
|
|
100
100
|
*/
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { ExtensionUIContext } from "../extensibility/extensions/types";
|
|
2
|
+
import type { AskAnswerSource } from "../tools";
|
|
3
|
+
import type { MCPInputRequestHandler } from "./types";
|
|
4
|
+
export interface MCPFormInputDependencies {
|
|
5
|
+
getUi(): {
|
|
6
|
+
ui?: Pick<ExtensionUIContext, "select" | "input">;
|
|
7
|
+
hasUI: boolean;
|
|
8
|
+
};
|
|
9
|
+
getAskAnswerSource(): AskAnswerSource | undefined;
|
|
10
|
+
}
|
|
11
|
+
/** Register on an owned manager; dependencies are resolved per call for late UI registration. */
|
|
12
|
+
export declare function createMCPFormInputHandler(deps: MCPFormInputDependencies): MCPInputRequestHandler;
|
|
@@ -181,6 +181,15 @@ export declare function observeProcessForTest(pid: number, expectedIncarnation:
|
|
|
181
181
|
* deliberately left untouched.
|
|
182
182
|
*/
|
|
183
183
|
export declare function reapDeadLifecycleMarkers(root: string, limit?: number): Promise<number>;
|
|
184
|
+
/**
|
|
185
|
+
* Retires one launch id's lifecycle marker pair after its recorded owner has
|
|
186
|
+
* exited. Unlike the bounded background sweep, this launch-local repair is
|
|
187
|
+
* not age-gated and does not require the ready sibling to contain the same
|
|
188
|
+
* effect marker: the primary marker is the owner authority for this id.
|
|
189
|
+
*/
|
|
190
|
+
type RetireExitedLifecycleMarkerPairHook = () => void | Promise<void>;
|
|
191
|
+
export declare function retireExitedLifecycleMarkerPair(root: string, id: string): Promise<boolean>;
|
|
192
|
+
export declare function retireExitedLifecycleMarkerPairForTest(root: string, id: string, afterObservation: RetireExitedLifecycleMarkerPairHook): Promise<boolean>;
|
|
184
193
|
export declare function writeEffectMarker(root: string, id: string, marker: EffectMarker): Promise<void>;
|
|
185
194
|
export declare class LifecycleReadinessCleanupError extends Error {
|
|
186
195
|
constructor(cause: unknown);
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import type { NativeExactUnlinkResult } from "@gajae-code/natives";
|
|
2
|
+
import { type TaskArtifactOwnerDeletionEvidence, type TaskArtifactOwnerRetirementContinuation, type TaskArtifactOwnerRetirementOutcome, type TaskArtifactOwnerStorageContext } from "../../session/task-artifact-owner-codec";
|
|
3
|
+
export type BrokerCleanupPhase = "artifacts" | "transcript" | "metadata" | "lifecycle";
|
|
4
|
+
/** Exact owner-disposition wire shape. Evidence and continuation are supplied separately by cleanup replay. */
|
|
5
|
+
export type BrokerTaskArtifactOwnerRetirementDisposition = {
|
|
6
|
+
readonly kind: "completed";
|
|
7
|
+
readonly nativeOutcome?: NativeExactUnlinkResult;
|
|
8
|
+
} | {
|
|
9
|
+
readonly kind: "payload_retired";
|
|
10
|
+
readonly namespace: "retained";
|
|
11
|
+
readonly nativeOutcome: NativeExactUnlinkResult;
|
|
12
|
+
} | {
|
|
13
|
+
readonly kind: "cleanup_pending";
|
|
14
|
+
readonly nativeOutcome?: NativeExactUnlinkResult;
|
|
15
|
+
} | {
|
|
16
|
+
readonly kind: "uncertain";
|
|
17
|
+
readonly reason: string;
|
|
18
|
+
readonly nativeOutcome?: NativeExactUnlinkResult;
|
|
19
|
+
};
|
|
20
|
+
/** Owner-only projection of durable cleanup state accepted by the pure validator. */
|
|
21
|
+
export interface BrokerTaskArtifactOwnerCleanupFields {
|
|
22
|
+
readonly taskArtifactOwnerDeletionEvidence?: unknown;
|
|
23
|
+
readonly taskArtifactOwnerRetirementContinuation?: unknown;
|
|
24
|
+
readonly taskArtifactOwnerRetirementOutcome?: unknown;
|
|
25
|
+
readonly taskArtifactOwnerPayloadRetired?: unknown;
|
|
26
|
+
readonly taskArtifactOwnerNamespaceRetained?: unknown;
|
|
27
|
+
readonly taskArtifactOwnerRetired?: unknown;
|
|
28
|
+
readonly taskArtifactOwnerTranscriptDeleted?: unknown;
|
|
29
|
+
readonly taskArtifactOwnerCleanupError?: unknown;
|
|
30
|
+
}
|
|
31
|
+
/** Fully decoded owner-only cleanup state for an authorized session and phase. */
|
|
32
|
+
export interface BrokerTaskArtifactOwnerCleanupValidation {
|
|
33
|
+
readonly deletionEvidence?: TaskArtifactOwnerDeletionEvidence;
|
|
34
|
+
readonly retirementContinuation?: TaskArtifactOwnerRetirementContinuation;
|
|
35
|
+
readonly retirementOutcome?: TaskArtifactOwnerRetirementOutcome;
|
|
36
|
+
readonly payloadRetired?: true;
|
|
37
|
+
readonly namespaceRetained?: true;
|
|
38
|
+
readonly retired?: true;
|
|
39
|
+
readonly transcriptDeleted?: true;
|
|
40
|
+
readonly cleanupDiagnostic?: string;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Decode the owner-only wire disposition using its exact trusted evidence and continuation.
|
|
44
|
+
* A decoded `completed` value is historical DTO data, not proof of physical retirement or writer closure.
|
|
45
|
+
*/
|
|
46
|
+
export declare function parseBrokerTaskArtifactOwnerRetirementDisposition(value: unknown, context: TaskArtifactOwnerStorageContext, evidence: TaskArtifactOwnerDeletionEvidence, continuation: TaskArtifactOwnerRetirementContinuation | undefined): TaskArtifactOwnerRetirementOutcome;
|
|
47
|
+
/** Project an already validated internal outcome to the exact broker wire disposition. */
|
|
48
|
+
export declare function serializeBrokerTaskArtifactOwnerRetirementDisposition(outcome: TaskArtifactOwnerRetirementOutcome): BrokerTaskArtifactOwnerRetirementDisposition;
|
|
49
|
+
/**
|
|
50
|
+
* Strictly decode the owner-field projection of cleanup state against trusted session, scope context, phase,
|
|
51
|
+
* and artifact-removal state. Empty/legacy owner fields decode to an empty result. A decoded completion
|
|
52
|
+
* remains historical data: any later effect must separately verify current physical absence, fresh scrub
|
|
53
|
+
* proof, native success and current owner-parent/side-path authority before it mutates storage or transcripts.
|
|
54
|
+
*/
|
|
55
|
+
export declare function decodeBrokerTaskArtifactOwnerCleanupFields(value: unknown, context: TaskArtifactOwnerStorageContext, expectedSessionId: string, phase: BrokerCleanupPhase, artifactsRemoved: boolean | undefined): BrokerTaskArtifactOwnerCleanupValidation;
|
|
@@ -9,6 +9,7 @@ import { type DaemonProcessReference } from "./telegram-daemon-control";
|
|
|
9
9
|
import { type TelegramSetupPreflight } from "./telegram-setup";
|
|
10
10
|
export { loadInstallationHostId, loadLegacyInstallationHostId, type MachineIdentityDeps, parseMacPlatformUuid, parseWindowsMachineGuid, } from "../../config/machine-identity";
|
|
11
11
|
export { DAEMON_GENERATION, NOTIFICATION_EVENT_SCHEMA_VERSION, NOTIFICATION_PROTOCOL_VERSION, SDK_LIFECYCLE_ROUTER_PROTOCOL_VERSION, SERVING_EPOCH, TELEGRAM_TRANSPORT_GENERATION, } from "./telegram-daemon-contract";
|
|
12
|
+
import { POSITIONED_NOTIFICATION_EFFECTS_CAPABILITY } from "../host/host";
|
|
12
13
|
import { type AgentDirSessionLifecycleService } from "../lifecycle/client";
|
|
13
14
|
import { type NotificationSubscription, type SessionRouterProviderDeps } from "../router/session-router";
|
|
14
15
|
import { NotificationOperatorRuntime } from "./operator-runtime";
|
|
@@ -136,8 +137,8 @@ export declare const ASK_CONTROLS_CAPABILITY = "ask_controls_v1";
|
|
|
136
137
|
export declare const TOOL_ACTIVITY_CAPABILITY = "tool_activity_v2";
|
|
137
138
|
/** Receive-only compatibility capability for pre-v2 hosts. */
|
|
138
139
|
export declare const LEGACY_TOOL_ACTIVITY_CAPABILITY = "tool_activity_v1";
|
|
139
|
-
/**
|
|
140
|
-
export
|
|
140
|
+
/** Public `sdk/bus/telegram-daemon` path for the canonical `sdk/host` capability token. */
|
|
141
|
+
export { POSITIONED_NOTIFICATION_EFFECTS_CAPABILITY };
|
|
141
142
|
/**
|
|
142
143
|
* File-lock options whose acquisition budget covers the full reload-reservation
|
|
143
144
|
* critical section: the in-lock freshness poll plus the controller's
|
|
@@ -85,6 +85,12 @@ export declare const TOOL_ACTIVITY_CAPABILITY = "tool_activity_v2";
|
|
|
85
85
|
export declare const TURN_STREAM_CAPABILITY = "turn_stream";
|
|
86
86
|
/** Capability used by notification adapters that observe a host without owning its work. */
|
|
87
87
|
export declare const SESSION_HOST_OBSERVER_CAPABILITY = "session_host_observer_v1";
|
|
88
|
+
/**
|
|
89
|
+
* Opts notification adapters into positioned-only delivery for matching live
|
|
90
|
+
* effects: the host excludes a negotiating connection from the raw native leg
|
|
91
|
+
* of every frame its positioned envelope already reached.
|
|
92
|
+
*/
|
|
93
|
+
export declare const POSITIONED_NOTIFICATION_EFFECTS_CAPABILITY = "positioned_notification_effects_v1";
|
|
88
94
|
export declare const CAP_GATED_FRAME_KINDS: ReadonlySet<string>;
|
|
89
95
|
/** Keep live delivery and replay on one capability gate. */
|
|
90
96
|
export declare function canDeliverSdkEvent(kind: string, capabilities: ReadonlySet<string> | undefined): boolean;
|
|
@@ -181,6 +181,13 @@ export interface SessionRouterOptions {
|
|
|
181
181
|
attachFilter?: (sessionId: string) => boolean;
|
|
182
182
|
/** Marks default SDK clients as notification-only observers; demanding by default. */
|
|
183
183
|
observer?: boolean;
|
|
184
|
+
/**
|
|
185
|
+
* Negotiates positioned-only notification effects on default SDK clients, so the
|
|
186
|
+
* host stops sending them the raw native copy of frames whose positioned
|
|
187
|
+
* envelope already reached them. Only notification-effect publishers opt in;
|
|
188
|
+
* ordinary SDK observers keep both public surfaces.
|
|
189
|
+
*/
|
|
190
|
+
positionedNotificationEffects?: boolean;
|
|
184
191
|
deps?: SessionRouterDeps;
|
|
185
192
|
/** Runtime-specific identity validation; Router supplies a conservative fallback. */
|
|
186
193
|
correlateFrame?: SessionRouterFrameCorrelator;
|
|
@@ -174,7 +174,7 @@ export declare class ManagedSessionDescendantStore {
|
|
|
174
174
|
constructor(root: ManagedDirectoryRoot, baseDir: string, retained?: {
|
|
175
175
|
authority: RecoveryFsRoot;
|
|
176
176
|
authorityBaseDir: string;
|
|
177
|
-
}, policy?: ManagedSessionSecurityPolicy, profileAgentDir?: string);
|
|
177
|
+
}, policy?: ManagedSessionSecurityPolicy, profileAgentDir?: string, expectedSubtreeRoot?: ManagedDirectoryRoot);
|
|
178
178
|
get dir(): string;
|
|
179
179
|
get rootAuthority(): ManagedDirectoryRoot;
|
|
180
180
|
get subtreeRootAuthority(): ManagedDirectoryRoot;
|
|
@@ -189,6 +189,11 @@ export declare class ManagedSessionDescendantStore {
|
|
|
189
189
|
close(): void;
|
|
190
190
|
assertBound(): void;
|
|
191
191
|
verifyRootSecurity(): void;
|
|
192
|
+
/** Capture a directory identity through this store's retained managed root without repairing it. */
|
|
193
|
+
captureDirectoryIdentity(relativePath: string): {
|
|
194
|
+
dev: string;
|
|
195
|
+
ino: string;
|
|
196
|
+
};
|
|
192
197
|
ensureDirectory(relativePath?: string): ManagedDirectoryRoot;
|
|
193
198
|
publishNoReplace(relativePath: string, bytes: Uint8Array): Promise<void>;
|
|
194
199
|
publishNoReplaceSync(relativePath: string, bytes: Uint8Array): void;
|
|
@@ -240,6 +245,11 @@ export declare class ManagedSessionDescendantStore {
|
|
|
240
245
|
sourceStoreRelativePath: string;
|
|
241
246
|
}): ManagedFileSnapshot;
|
|
242
247
|
removeTreeExpected(relativePath: string, expected: NativeDirectoryTreeSnapshot): void;
|
|
248
|
+
/** Remove one exact managed tree through the parent-identity-bound native protocol. */
|
|
249
|
+
removeTreeExpectedWithParentIdentity(relativePath: string, expected: NativeDirectoryTreeSnapshot, parentIdentity: {
|
|
250
|
+
dev: bigint;
|
|
251
|
+
ino: bigint;
|
|
252
|
+
}): NativeExactUnlinkResult;
|
|
243
253
|
fsyncTree(): NativeDirectoryTreeSnapshot;
|
|
244
254
|
}
|
|
245
255
|
export declare function shouldFsyncManagedDirectory(platform?: NodeJS.Platform): boolean;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { NativeDirectoryTreeSnapshot } from "@gajae-code/natives";
|
|
2
|
+
import { type TaskArtifactOwnerDeletionEvidence, type TaskArtifactOwnerLocator, type TaskArtifactOwnerStorageContext } from "../task-artifact-owner-codec";
|
|
3
|
+
import { ManagedSessionDescendantStore } from "./managed-session-storage";
|
|
4
|
+
export interface OwnerManifest extends TaskArtifactOwnerLocator {
|
|
5
|
+
readonly sessionId: string;
|
|
6
|
+
}
|
|
7
|
+
export declare function newSessionRootStore(context: TaskArtifactOwnerStorageContext): ManagedSessionDescendantStore;
|
|
8
|
+
export declare function readOwnerManifest(store: ManagedSessionDescendantStore, locator: TaskArtifactOwnerLocator, relativePath?: string): OwnerManifest;
|
|
9
|
+
export declare function assertOwnerDirectoryExists(context: TaskArtifactOwnerStorageContext, ownerId: string): void;
|
|
10
|
+
export declare function assertOwnerIdentity(store: ManagedSessionDescendantStore, locator: TaskArtifactOwnerLocator): void;
|
|
11
|
+
export declare function openOwnerStore(context: TaskArtifactOwnerStorageContext, rootStore: ManagedSessionDescendantStore, locator: TaskArtifactOwnerLocator, sessionId: string): ManagedSessionDescendantStore;
|
|
12
|
+
export declare function locatorFromManifest(manifest: OwnerManifest): TaskArtifactOwnerLocator;
|
|
13
|
+
export declare function captureValidatedOwnerTree(context: TaskArtifactOwnerStorageContext, rootStore: ManagedSessionDescendantStore, sessionId: string, locator: TaskArtifactOwnerLocator): NativeDirectoryTreeSnapshot;
|
|
14
|
+
export declare function captureOwnerTreeIfPresent(context: TaskArtifactOwnerStorageContext, rootStore: ManagedSessionDescendantStore, ownerId: string, pathname: string): NativeDirectoryTreeSnapshot | undefined;
|
|
15
|
+
export declare function ownerTreeHasPendingManagedPublication(snapshot: NativeDirectoryTreeSnapshot): boolean;
|
|
16
|
+
/** Capture exact owner evidence without repairing its security, timestamps, or namespace. */
|
|
17
|
+
export declare function captureTaskArtifactOwnerDeletionEvidence(context: TaskArtifactOwnerStorageContext, sessionId: string, locatorValue: unknown): TaskArtifactOwnerDeletionEvidence | undefined;
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import { type TaskArtifactOwnerLocator } from "../task-artifact-owner-codec";
|
|
2
|
+
/** Resolve the path-free owner locator using transcript replay's header-patch semantics. */
|
|
3
|
+
export declare function taskArtifactOwnerLocatorFromTranscriptBytes(bytes: Uint8Array, expectedSessionId: string): TaskArtifactOwnerLocator | undefined;
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { type FileSessionStorage } from "./session-storage";
|
|
2
|
+
/**
|
|
3
|
+
* Outcome of a disk-retention retirement attempt.
|
|
4
|
+
*
|
|
5
|
+
* `kept` means the transcript survived and nothing of the session was
|
|
6
|
+
* destroyed, with the exact reason so `gjc gc --disk` can report it.
|
|
7
|
+
* `cleanup_pending` means the delete authority already detached or removed the
|
|
8
|
+
* session's artifact tree (or quarantined the transcript) before it stopped:
|
|
9
|
+
* the record survives, the session does not, and a caller must NOT report that
|
|
10
|
+
* as an ordinary keep.
|
|
11
|
+
*/
|
|
12
|
+
export type SessionRetirementOutcome = {
|
|
13
|
+
kind: "retired";
|
|
14
|
+
} | {
|
|
15
|
+
kind: "kept";
|
|
16
|
+
reason: string;
|
|
17
|
+
} | {
|
|
18
|
+
kind: "cleanup_pending";
|
|
19
|
+
reason: string;
|
|
20
|
+
};
|
|
21
|
+
/**
|
|
22
|
+
* Non-mutating projection of {@link retireSessionTranscript}: would the
|
|
23
|
+
* retention pass's own preconditions let this transcript be retired at all?
|
|
24
|
+
*
|
|
25
|
+
* `gjc gc --disk` runs it so a dry run reports the verdict a prune would reach
|
|
26
|
+
* instead of promising bytes the delete authority will refuse to release. The
|
|
27
|
+
* authority's verdict (containment, identity, artifact tree) is deliberately
|
|
28
|
+
* not predicted here — it is re-derived against live state at delete time.
|
|
29
|
+
*/
|
|
30
|
+
export declare function probeSessionRetirement(storage: FileSessionStorage, sessionsRoot: string, transcriptPath: string): {
|
|
31
|
+
kind: "retirable";
|
|
32
|
+
} | {
|
|
33
|
+
kind: "kept";
|
|
34
|
+
reason: string;
|
|
35
|
+
};
|
|
36
|
+
/**
|
|
37
|
+
* Retire one managed session transcript through the verified hard-delete
|
|
38
|
+
* authority.
|
|
39
|
+
*
|
|
40
|
+
* This is the only supported way for a retention pass to remove a transcript:
|
|
41
|
+
* identity, containment, header id/cwd, artifact tree and parent directory are
|
|
42
|
+
* all re-verified inside {@link FileSessionStorage.deleteSessionVerified}, and
|
|
43
|
+
* anything ambiguous fails closed as `kept` rather than deleting bytes. The
|
|
44
|
+
* caller owns the retention policy; this function owns nothing but the delete
|
|
45
|
+
* authority.
|
|
46
|
+
*/
|
|
47
|
+
export declare function retireSessionTranscript(storage: FileSessionStorage, sessionsRoot: string, transcriptPath: string): Promise<SessionRetirementOutcome>;
|
|
@@ -512,50 +512,4 @@ export declare class MemorySessionStorage implements SessionStorage {
|
|
|
512
512
|
openBufferedWriter(path: string, options?: SessionStorageWriterOpenOptions): SessionStorageBufferedWriter;
|
|
513
513
|
openStagedWriter(path: string): StagedStreamingWriter;
|
|
514
514
|
}
|
|
515
|
-
/**
|
|
516
|
-
* Outcome of a disk-retention retirement attempt.
|
|
517
|
-
*
|
|
518
|
-
* `kept` means the transcript survived and nothing of the session was
|
|
519
|
-
* destroyed, with the exact reason so `gjc gc --disk` can report it.
|
|
520
|
-
* `cleanup_pending` means the delete authority already detached or removed the
|
|
521
|
-
* session's artifact tree (or quarantined the transcript) before it stopped:
|
|
522
|
-
* the record survives, the session does not, and a caller must NOT report that
|
|
523
|
-
* as an ordinary keep.
|
|
524
|
-
*/
|
|
525
|
-
export type SessionRetirementOutcome = {
|
|
526
|
-
kind: "retired";
|
|
527
|
-
} | {
|
|
528
|
-
kind: "kept";
|
|
529
|
-
reason: string;
|
|
530
|
-
} | {
|
|
531
|
-
kind: "cleanup_pending";
|
|
532
|
-
reason: string;
|
|
533
|
-
};
|
|
534
|
-
/**
|
|
535
|
-
* Non-mutating projection of {@link retireSessionTranscript}: would the
|
|
536
|
-
* retention pass's own preconditions let this transcript be retired at all?
|
|
537
|
-
*
|
|
538
|
-
* `gjc gc --disk` runs it so a dry run reports the verdict a prune would reach
|
|
539
|
-
* instead of promising bytes the delete authority will refuse to release. The
|
|
540
|
-
* authority's verdict (containment, identity, artifact tree) is deliberately
|
|
541
|
-
* not predicted here — it is re-derived against live state at delete time.
|
|
542
|
-
*/
|
|
543
|
-
export declare function probeSessionRetirement(storage: FileSessionStorage, sessionsRoot: string, transcriptPath: string): {
|
|
544
|
-
kind: "retirable";
|
|
545
|
-
} | {
|
|
546
|
-
kind: "kept";
|
|
547
|
-
reason: string;
|
|
548
|
-
};
|
|
549
|
-
/**
|
|
550
|
-
* Retire one managed session transcript through the verified hard-delete
|
|
551
|
-
* authority.
|
|
552
|
-
*
|
|
553
|
-
* This is the only supported way for a retention pass to remove a transcript:
|
|
554
|
-
* identity, containment, header id/cwd, artifact tree and parent directory are
|
|
555
|
-
* all re-verified inside {@link FileSessionStorage.deleteSessionVerified}, and
|
|
556
|
-
* anything ambiguous fails closed as `kept` rather than deleting bytes. The
|
|
557
|
-
* caller owns the retention policy; this function owns nothing but the delete
|
|
558
|
-
* authority.
|
|
559
|
-
*/
|
|
560
|
-
export declare function retireSessionTranscript(storage: FileSessionStorage, sessionsRoot: string, transcriptPath: string): Promise<SessionRetirementOutcome>;
|
|
561
515
|
export {};
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import type { NativeExactUnlinkResult } from "@gajae-code/natives";
|
|
2
|
+
import type { ManagedDirectoryRoot, ManagedSessionSecurityPolicy } from "./internal/managed-session-storage";
|
|
3
|
+
import type { NativeDirectoryTreeSnapshot } from "./session-storage";
|
|
4
|
+
export declare const OWNER_DIRECTORY = ".task-artifact-owners";
|
|
5
|
+
export declare const OWNER_LOCK_DIRECTORY = ".task-artifact-owner-locks";
|
|
6
|
+
export declare const OWNER_MANIFEST = ".gjc-task-artifact-owner-v1.json";
|
|
7
|
+
export declare const OWNER_SCHEMA_VERSION: 1;
|
|
8
|
+
export declare const OWNER_DELETION_SCHEMA_VERSION: 2;
|
|
9
|
+
export declare const OWNER_RETIREMENT_SCHEMA_VERSION: 1;
|
|
10
|
+
export declare const EMPTY_PAYLOAD_SHA256: string;
|
|
11
|
+
export interface TaskArtifactOwnerLocator {
|
|
12
|
+
readonly schemaVersion: typeof OWNER_SCHEMA_VERSION;
|
|
13
|
+
readonly ownerId: string;
|
|
14
|
+
readonly directoryDev: string;
|
|
15
|
+
readonly directoryIno: string;
|
|
16
|
+
}
|
|
17
|
+
export interface TaskArtifactOwnerStorageContext {
|
|
18
|
+
readonly rootAuthority: ManagedDirectoryRoot;
|
|
19
|
+
readonly sessionsRoot: string;
|
|
20
|
+
readonly securityPolicy: ManagedSessionSecurityPolicy;
|
|
21
|
+
readonly profileAgentDir: string;
|
|
22
|
+
}
|
|
23
|
+
/** Exact parent directory identity authorizing direct native owner-tree removal. */
|
|
24
|
+
export interface TaskArtifactOwnerParentIdentity {
|
|
25
|
+
readonly dev: string;
|
|
26
|
+
readonly ino: string;
|
|
27
|
+
}
|
|
28
|
+
/** Immutable exact deletion input retained by managed lifecycle tombstones and retries. */
|
|
29
|
+
export interface TaskArtifactOwnerDeletionEvidence {
|
|
30
|
+
readonly schemaVersion: typeof OWNER_DELETION_SCHEMA_VERSION;
|
|
31
|
+
readonly sessionId: string;
|
|
32
|
+
readonly locator: TaskArtifactOwnerLocator;
|
|
33
|
+
readonly parentIdentity: TaskArtifactOwnerParentIdentity;
|
|
34
|
+
readonly treeSnapshot: NativeDirectoryTreeSnapshot;
|
|
35
|
+
}
|
|
36
|
+
/** Native retained-root and side-path state safe to persist for a later retirement attempt. */
|
|
37
|
+
export interface TaskArtifactOwnerRetirementContinuation {
|
|
38
|
+
readonly schemaVersion: typeof OWNER_RETIREMENT_SCHEMA_VERSION;
|
|
39
|
+
/** Must remain equal to the immutable evidence's managed owner-parent identity. */
|
|
40
|
+
readonly parentIdentity: TaskArtifactOwnerParentIdentity;
|
|
41
|
+
/** Only the original owner root or its native `.removing` sibling is actionable. */
|
|
42
|
+
readonly retainedRootPath: string;
|
|
43
|
+
/** Last identity-checked tree snapshot; it may only shrink from the original evidence. */
|
|
44
|
+
readonly retainedTreeSnapshot: NativeDirectoryTreeSnapshot;
|
|
45
|
+
/** Historical exact native detached-root roles; these paths are diagnostics, not extra authority. */
|
|
46
|
+
readonly detachedPaths?: readonly string[];
|
|
47
|
+
readonly nativeCodes?: readonly string[];
|
|
48
|
+
readonly payloadDurable?: boolean;
|
|
49
|
+
readonly retainedSuccessorPaths?: readonly string[];
|
|
50
|
+
readonly retainedPlaceholderPaths?: readonly string[];
|
|
51
|
+
readonly retainedUnknownPaths?: readonly string[];
|
|
52
|
+
readonly windowsErrorCodes?: readonly string[];
|
|
53
|
+
}
|
|
54
|
+
/** `completed` is decoded persisted data, not proof of physical retirement or writer closure. */
|
|
55
|
+
export type TaskArtifactOwnerRetirementOutcome = {
|
|
56
|
+
readonly kind: "completed";
|
|
57
|
+
readonly evidence: TaskArtifactOwnerDeletionEvidence;
|
|
58
|
+
readonly nativeOutcome?: NativeExactUnlinkResult;
|
|
59
|
+
} | {
|
|
60
|
+
/** Live payload is durably destroyed; native namespace cleanup remains pending. */
|
|
61
|
+
readonly kind: "payload_retired";
|
|
62
|
+
readonly namespace: "retained";
|
|
63
|
+
readonly evidence: TaskArtifactOwnerDeletionEvidence;
|
|
64
|
+
readonly continuation: TaskArtifactOwnerRetirementContinuation;
|
|
65
|
+
readonly nativeOutcome: NativeExactUnlinkResult;
|
|
66
|
+
} | {
|
|
67
|
+
/** Native explicitly retained cleanup state with a validated, non-expanding continuation. */
|
|
68
|
+
readonly kind: "cleanup_pending";
|
|
69
|
+
readonly evidence: TaskArtifactOwnerDeletionEvidence;
|
|
70
|
+
readonly continuation: TaskArtifactOwnerRetirementContinuation;
|
|
71
|
+
readonly nativeOutcome?: NativeExactUnlinkResult;
|
|
72
|
+
} | {
|
|
73
|
+
/** No safe completion proof exists; callers must retain evidence and continuation. */
|
|
74
|
+
readonly kind: "uncertain";
|
|
75
|
+
readonly evidence: TaskArtifactOwnerDeletionEvidence;
|
|
76
|
+
readonly continuation: TaskArtifactOwnerRetirementContinuation;
|
|
77
|
+
readonly reason: string;
|
|
78
|
+
readonly nativeOutcome?: NativeExactUnlinkResult;
|
|
79
|
+
};
|
|
80
|
+
/** True only for canonical unsigned decimal strings within the native u64 range. */
|
|
81
|
+
export declare function isCanonicalDecimal(value: unknown): value is string;
|
|
82
|
+
export declare function isCanonicalNativeId(value: unknown): value is string;
|
|
83
|
+
/** Deterministic owner identity bound to one non-empty logical session ID. */
|
|
84
|
+
export declare function ownerIdForSession(sessionId: string): string;
|
|
85
|
+
export declare function ownerRelativePath(ownerId: string): string;
|
|
86
|
+
export declare function manifestRelativePath(ownerId: string): string;
|
|
87
|
+
export declare function assertSafeRelativePath(relativePath: string): void;
|
|
88
|
+
export declare function assertSessionRoot(context: TaskArtifactOwnerStorageContext): void;
|
|
89
|
+
export declare function freezeTreeSnapshot(snapshot: NativeDirectoryTreeSnapshot): NativeDirectoryTreeSnapshot;
|
|
90
|
+
export declare function retainedTreeDoesNotExpandAuthority(expected: NativeDirectoryTreeSnapshot, retained: NativeDirectoryTreeSnapshot): boolean;
|
|
91
|
+
export declare function sameTreeContents(left: NativeDirectoryTreeSnapshot, right: NativeDirectoryTreeSnapshot): boolean;
|
|
92
|
+
export declare function sameOwnerParentIdentity(left: TaskArtifactOwnerParentIdentity, right: TaskArtifactOwnerParentIdentity): boolean;
|
|
93
|
+
export declare function immutableDeletionEvidence(sessionId: string, locatorValue: TaskArtifactOwnerLocator, parentIdentityValue: TaskArtifactOwnerParentIdentity, treeSnapshotValue: NativeDirectoryTreeSnapshot): TaskArtifactOwnerDeletionEvidence;
|
|
94
|
+
/** Parse a persisted locator. Missing metadata returns undefined; malformed metadata fails closed. */
|
|
95
|
+
export declare function parseTaskArtifactOwnerLocator(value: unknown): TaskArtifactOwnerLocator | undefined;
|
|
96
|
+
/** Validate JSON-restored tombstone evidence before it is used for exact retirement. */
|
|
97
|
+
export declare function parseTaskArtifactOwnerDeletionEvidence(value: unknown): TaskArtifactOwnerDeletionEvidence;
|
|
98
|
+
export declare function ownerAbsolutePath(context: TaskArtifactOwnerStorageContext, ownerId: string): string;
|
|
99
|
+
export declare function isOwnerRetainedRoot(context: TaskArtifactOwnerStorageContext, ownerId: string, pathname: string): boolean;
|
|
100
|
+
export declare function isKnownNativeSidePath(context: TaskArtifactOwnerStorageContext, ownerId: string, pathname: string): boolean;
|
|
101
|
+
/** Validate JSON-restored native continuation data against immutable owner authorization. */
|
|
102
|
+
export declare function parseTaskArtifactOwnerRetirementContinuation(context: TaskArtifactOwnerStorageContext, evidenceValue: TaskArtifactOwnerDeletionEvidence, value: unknown): TaskArtifactOwnerRetirementContinuation;
|
|
103
|
+
/**
|
|
104
|
+
* Strictly decode persisted managed-journal data. Parsing does not establish current physical retirement,
|
|
105
|
+
* payload destruction, or writer quiescence.
|
|
106
|
+
*/
|
|
107
|
+
export declare function parseTaskArtifactOwnerRetirementOutcome(context: TaskArtifactOwnerStorageContext, evidence: TaskArtifactOwnerDeletionEvidence, value: unknown): TaskArtifactOwnerRetirementOutcome;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { type TaskArtifactOwnerDeletionEvidence, type TaskArtifactOwnerRetirementContinuation, type TaskArtifactOwnerRetirementOutcome, type TaskArtifactOwnerStorageContext } from "./task-artifact-owner-codec";
|
|
2
|
+
/** Confirm physical completion from a managed native proof, never from canonical absence alone. */
|
|
3
|
+
export declare function verifyTaskArtifactOwnerPhysicalRetirement(context: TaskArtifactOwnerStorageContext, evidence: TaskArtifactOwnerDeletionEvidence, value: unknown): void;
|
|
4
|
+
/** Revalidate a persisted remnant through managed authority without mutation or new payload proof. */
|
|
5
|
+
export declare function verifyTaskArtifactOwnerRetirementContinuation(context: TaskArtifactOwnerStorageContext, evidenceValue: TaskArtifactOwnerDeletionEvidence, value: unknown): TaskArtifactOwnerRetirementContinuation;
|
|
6
|
+
/** Continue exact native removal without widening the original owner-tree authority. */
|
|
7
|
+
export declare function retireTaskArtifactOwner(context: TaskArtifactOwnerStorageContext, evidenceValue: TaskArtifactOwnerDeletionEvidence, continuationValue?: unknown): TaskArtifactOwnerRetirementOutcome;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { ArtifactManager } from "./artifacts";
|
|
2
|
+
import { type TaskArtifactOwnerLocator, type TaskArtifactOwnerStorageContext } from "./task-artifact-owner-codec";
|
|
3
|
+
export interface ManagedTaskArtifactOwner {
|
|
4
|
+
readonly locator: TaskArtifactOwnerLocator;
|
|
5
|
+
readonly manager: ArtifactManager;
|
|
6
|
+
}
|
|
7
|
+
/** Reopen an owner only beneath the captured managed sessions-root authority. */
|
|
8
|
+
export declare function restoreManagedTaskArtifactOwner(context: TaskArtifactOwnerStorageContext, sessionId: string, locatorValue: unknown): ManagedTaskArtifactOwner;
|
|
9
|
+
/** Establish or restore the logical-session owner under the captured managed sessions authority. */
|
|
10
|
+
export declare function ensureManagedTaskArtifactOwner(context: TaskArtifactOwnerStorageContext, sessionId: string, locatorValue: unknown, legacyArtifactRelativePath?: string): Promise<ManagedTaskArtifactOwner>;
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"type": "module",
|
|
3
3
|
"name": "@gajae-code/coding-agent",
|
|
4
|
-
"version": "0.18.
|
|
4
|
+
"version": "0.18.7",
|
|
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",
|
|
@@ -57,12 +57,12 @@
|
|
|
57
57
|
"@agentclientprotocol/sdk": "1.3.0",
|
|
58
58
|
"@babel/parser": "^7.29.3",
|
|
59
59
|
"@mozilla/readability": "^0.6.0",
|
|
60
|
-
"@gajae-code/stats": "0.18.
|
|
61
|
-
"@gajae-code/agent-core": "0.18.
|
|
62
|
-
"@gajae-code/ai": "0.18.
|
|
63
|
-
"@gajae-code/natives": "0.18.
|
|
64
|
-
"@gajae-code/tui": "0.18.
|
|
65
|
-
"@gajae-code/utils": "0.18.
|
|
60
|
+
"@gajae-code/stats": "0.18.7",
|
|
61
|
+
"@gajae-code/agent-core": "0.18.7",
|
|
62
|
+
"@gajae-code/ai": "0.18.7",
|
|
63
|
+
"@gajae-code/natives": "0.18.7",
|
|
64
|
+
"@gajae-code/tui": "0.18.7",
|
|
65
|
+
"@gajae-code/utils": "0.18.7",
|
|
66
66
|
"@puppeteer/browsers": "^2.13.0",
|
|
67
67
|
"@types/turndown": "5.0.6",
|
|
68
68
|
"@xterm/headless": "^6.0.0",
|