@sayknow-cli/coding-agent 0.5.1 → 0.5.6
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 +185 -14
- package/dist/types/cli/update-cli.d.ts +8 -1
- package/dist/types/commands/session.d.ts +7 -0
- package/dist/types/config/atomic-yaml-patch.d.ts +20 -1
- package/dist/types/config/keybindings.d.ts +10 -0
- package/dist/types/config/model-registry.d.ts +1 -1
- package/dist/types/config/models-config-schema.d.ts +4 -0
- package/dist/types/config/settings-schema.d.ts +9 -0
- package/dist/types/config/telegram-autostart.d.ts +9 -1
- package/dist/types/dap/client.d.ts +1 -0
- package/dist/types/lsp/client.d.ts +5 -0
- package/dist/types/modes/components/pet-capability.d.ts +8 -7
- package/dist/types/modes/components/pet-selector.d.ts +1 -1
- package/dist/types/modes/components/sayknow-pet-widget.d.ts +1 -1
- package/dist/types/modes/components/welcome.d.ts +1 -0
- package/dist/types/modes/controllers/selector-controller.d.ts +3 -1
- package/dist/types/modes/interactive-mode.d.ts +13 -1
- package/dist/types/modes/shared/agent-wire/unattended-session.d.ts +7 -0
- package/dist/types/modes/shared/agent-wire/workflow-gate-broker.d.ts +2 -0
- package/dist/types/modes/types.d.ts +7 -1
- package/dist/types/runtime-mcp/transports/stdio.d.ts +2 -0
- package/dist/types/session/agent-session.d.ts +9 -0
- package/dist/types/session/internal/managed-session-scope.d.ts +3 -1
- package/dist/types/session/internal/managed-session-storage.d.ts +2 -0
- package/dist/types/session/session-manager.d.ts +9 -0
- package/dist/types/session/session-storage.d.ts +17 -0
- package/dist/types/session-import/claude.d.ts +26 -0
- package/dist/types/session-import/codex.d.ts +22 -0
- package/dist/types/session-import/command.d.ts +20 -0
- package/dist/types/session-import/detect.d.ts +22 -0
- package/dist/types/session-import/index.d.ts +7 -0
- package/dist/types/session-import/redact.d.ts +23 -0
- package/dist/types/session-import/service.d.ts +28 -0
- package/dist/types/session-import/types.d.ts +125 -0
- package/dist/types/skc-runtime/boot-generation.d.ts +59 -0
- package/dist/types/skc-runtime/launch-tmux.d.ts +10 -2
- package/dist/types/skc-runtime/launch-worktree.d.ts +17 -1
- package/dist/types/skc-runtime/session-restore-runtime.d.ts +41 -0
- package/dist/types/skc-runtime/session-restore.d.ts +99 -0
- package/dist/types/skc-runtime/tmux-owner-isolation.d.ts +160 -0
- package/dist/types/skc-runtime/tmux-sessions.d.ts +26 -1
- package/dist/types/slash-commands/builtin-registry.d.ts +4 -0
- package/dist/types/slash-commands/types.d.ts +5 -0
- package/dist/types/tools/ask.d.ts +169 -4
- package/package.json +16 -7
- package/scripts/generate-sdk-operation-inventory.ts +5 -6
- package/src/cli/config-cli.ts +23 -8
- package/src/cli/update-cli.ts +265 -21
- package/src/commands/session.ts +88 -2
- package/src/config/atomic-yaml-patch.ts +167 -30
- package/src/config/keybindings.ts +10 -0
- package/src/config/model-profiles.ts +69 -1
- package/src/config/model-registry.ts +72 -38
- package/src/config/models-config-schema.ts +1 -1
- package/src/config/settings-schema.ts +9 -0
- package/src/config/settings.ts +13 -2
- package/src/config/telegram-autostart.ts +11 -4
- package/src/dap/client.ts +78 -30
- package/src/defaults/skc/skills/deep-interview/SKILL.md +29 -3
- package/src/internal-urls/docs-index.generated.ts +5 -4
- package/src/lsp/client.ts +17 -29
- package/src/main.ts +1 -1
- package/src/modes/action-registry.ts +2 -0
- package/src/modes/components/pet-capability.ts +22 -13
- package/src/modes/components/pet-selector.ts +1 -1
- package/src/modes/components/sayknow-pet-widget.ts +41 -7
- package/src/modes/components/welcome.ts +5 -0
- package/src/modes/controllers/event-controller.ts +1 -1
- package/src/modes/controllers/goal-mode-controller.ts +7 -2
- package/src/modes/controllers/input-controller.ts +71 -6
- package/src/modes/controllers/plan-mode-controller.ts +8 -1
- package/src/modes/controllers/runtime-mcp-command-controller.ts +14 -0
- package/src/modes/controllers/selector-controller.ts +47 -19
- package/src/modes/interactive-mode.ts +54 -4
- package/src/modes/shared/agent-wire/unattended-session.ts +40 -9
- package/src/modes/shared/agent-wire/workflow-gate-broker.ts +2 -0
- package/src/modes/types.ts +5 -1
- package/src/notifications/lifecycle-control-runtime.ts +258 -179
- package/src/prompts/system/eager-todo.md +2 -0
- package/src/prompts/system/plan-mode-approved.md +1 -1
- package/src/prompts/system/system-prompt.md +4 -2
- package/src/runtime-mcp/transports/stdio.ts +96 -33
- package/src/sdk/broker/lifecycle.ts +6 -5
- package/src/sdk/bus/lifecycle-control-runtime.ts +189 -110
- package/src/sdk/protocol/operation-inventory.generated.json +33 -0
- package/src/sdk/session.ts +25 -18
- package/src/session/agent-session.ts +120 -25
- package/src/session/internal/managed-session-scope.ts +41 -6
- package/src/session/internal/managed-session-storage.ts +14 -0
- package/src/session/session-manager.ts +113 -11
- package/src/session/session-storage.ts +70 -0
- package/src/session-import/claude.ts +382 -0
- package/src/session-import/codex.ts +458 -0
- package/src/session-import/command.ts +61 -0
- package/src/session-import/detect.ts +133 -0
- package/src/session-import/index.ts +27 -0
- package/src/session-import/redact.ts +125 -0
- package/src/session-import/service.ts +749 -0
- package/src/session-import/types.ts +163 -0
- package/src/skc-runtime/boot-generation.ts +172 -0
- package/src/skc-runtime/launch-tmux.ts +219 -41
- package/src/skc-runtime/launch-worktree.ts +277 -4
- package/src/skc-runtime/session-restore-runtime.ts +120 -0
- package/src/skc-runtime/session-restore.ts +296 -0
- package/src/skc-runtime/session-state-sidecar.ts +41 -0
- package/src/skc-runtime/tmux-owner-isolation.ts +665 -0
- package/src/skc-runtime/tmux-sessions.ts +284 -108
- package/src/slash-commands/acp-builtins.ts +5 -1
- package/src/slash-commands/builtin-registry.ts +109 -5
- package/src/slash-commands/types.ts +5 -0
- package/src/tools/ask.ts +188 -10
- package/src/tools/eval.ts +2 -2
- package/src/export/html/template.css +0 -1060
- package/src/export/html/template.html +0 -47
- package/src/export/html/template.js +0 -2348
- package/vendor/insane-search/engine/tests/test_hardening.py +0 -57
- package/vendor/insane-search/engine/tests/test_smoke.py +0 -152
- package/vendor/insane-search/engine/tests/test_u1.py +0 -200
- package/vendor/insane-search/engine/tests/test_u4.py +0 -131
- package/vendor/insane-search/engine/tests/test_u5.py +0 -163
- package/vendor/insane-search/engine/tests/test_u7.py +0 -124
- package/vendor/insane-search/engine/tests/test_u8.py +0 -216
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import { type BootGeneration, type RecordedBootGeneration } from "./boot-generation";
|
|
2
|
+
export declare const RESTORE_POINTER_SCHEMA_VERSION = 1;
|
|
3
|
+
export interface RestorePointer {
|
|
4
|
+
schema_version: number;
|
|
5
|
+
/** Coordinator identity: what the create fence and the sidecar are keyed by. */
|
|
6
|
+
coordinator_session_id: string;
|
|
7
|
+
state_file: string;
|
|
8
|
+
/** SKC session id whose transcript `skc --resume` would reopen. */
|
|
9
|
+
skc_session_id: string;
|
|
10
|
+
session_file: string;
|
|
11
|
+
cwd: string;
|
|
12
|
+
branch: string | null;
|
|
13
|
+
boot: RecordedBootGeneration;
|
|
14
|
+
updated_at: string;
|
|
15
|
+
}
|
|
16
|
+
/** Pointers live under SKC's own root so they are discoverable without scanning projects. */
|
|
17
|
+
export declare function restorePointerDirectory(): string;
|
|
18
|
+
export declare function restorePointerFile(coordinatorSessionId: string, stateFile: string): string;
|
|
19
|
+
export declare function isRestorePointer(value: unknown): value is RestorePointer;
|
|
20
|
+
/**
|
|
21
|
+
* The session id `skc --resume` resolves is the transcript header id, which is
|
|
22
|
+
* NOT the coordinator id: a normal `skc --tmux` child inherits only the
|
|
23
|
+
* coordinator identity and then mints its own session id. Reading it from the
|
|
24
|
+
* transcript is the only way a pointer can name the conversation that will
|
|
25
|
+
* actually be reopened.
|
|
26
|
+
*/
|
|
27
|
+
export declare function readTranscriptSessionId(sessionFile: string): string | null;
|
|
28
|
+
export interface PublishRestorePointerInput {
|
|
29
|
+
coordinatorSessionId: string;
|
|
30
|
+
stateFile: string;
|
|
31
|
+
skcSessionId: string;
|
|
32
|
+
sessionFile: string;
|
|
33
|
+
cwd: string;
|
|
34
|
+
branch?: string | null;
|
|
35
|
+
bootGeneration?: BootGeneration;
|
|
36
|
+
now?: () => Date;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Publishes (or refreshes) the pointer for a live session.
|
|
40
|
+
*
|
|
41
|
+
* Returns false without writing when the platform cannot produce boot evidence:
|
|
42
|
+
* a pointer whose boot value is unusable could never be judged `changed`, so
|
|
43
|
+
* writing one would only add noise. Never throws — losing a pointer must not
|
|
44
|
+
* break the session that was trying to publish it.
|
|
45
|
+
*/
|
|
46
|
+
export declare function publishRestorePointer(input: PublishRestorePointerInput): boolean;
|
|
47
|
+
/** Lists candidate pointers. Unreadable or malformed entries are skipped, never guessed at. */
|
|
48
|
+
export declare function listRestorePointers(): RestorePointer[];
|
|
49
|
+
/**
|
|
50
|
+
* Exact reference to one candidate, for `skc session restore --reference`.
|
|
51
|
+
*
|
|
52
|
+
* base64url of the identity pair, so a reference cannot be confused with a
|
|
53
|
+
* session id, a path, or a prefix. It selects a candidate; it never overrides
|
|
54
|
+
* any eligibility check.
|
|
55
|
+
*/
|
|
56
|
+
export declare function encodeRestoreReference(coordinatorSessionId: string, stateFile: string): string;
|
|
57
|
+
export declare function decodeRestoreReference(reference: string): {
|
|
58
|
+
coordinatorSessionId: string;
|
|
59
|
+
stateFile: string;
|
|
60
|
+
} | null;
|
|
61
|
+
export type RestoreIneligibleReason = "same_boot" | "boot_unknown" | "sidecar_missing" | "sidecar_identity_mismatch" | "sidecar_terminal" | "transcript_missing" | "cwd_missing" | "live_identity_collision" | "transcript_identity_mismatch" | "unsupported_owner_proof";
|
|
62
|
+
export type RestoreCandidateVerdict = {
|
|
63
|
+
eligible: true;
|
|
64
|
+
pointer: RestorePointer;
|
|
65
|
+
} | {
|
|
66
|
+
eligible: false;
|
|
67
|
+
pointer: RestorePointer;
|
|
68
|
+
reason: RestoreIneligibleReason;
|
|
69
|
+
detail?: string;
|
|
70
|
+
};
|
|
71
|
+
/** The sidecar fields restore is allowed to trust, read fresh at decision time. */
|
|
72
|
+
export interface RestoreSidecarFacts {
|
|
73
|
+
sessionId: string;
|
|
74
|
+
stateFile: string;
|
|
75
|
+
sessionFile: string | null;
|
|
76
|
+
cwd: string | null;
|
|
77
|
+
terminal: boolean;
|
|
78
|
+
}
|
|
79
|
+
export interface RestoreCandidateDeps {
|
|
80
|
+
currentBoot: BootGeneration;
|
|
81
|
+
/** Strict re-read of the referenced sidecar. Null when absent or unparseable. */
|
|
82
|
+
readSidecar: (pointer: RestorePointer) => RestoreSidecarFacts | null;
|
|
83
|
+
pathExists: (target: string) => boolean;
|
|
84
|
+
/** True when a live tmux session already owns this identity. */
|
|
85
|
+
hasLiveIdentity: (pointer: RestorePointer) => boolean;
|
|
86
|
+
/** Header id of the transcript the pointer names, re-read at decision time. */
|
|
87
|
+
readTranscriptSessionId: (pointer: RestorePointer) => string | null;
|
|
88
|
+
/** False when this host cannot produce the owner proof restore requires (psmux). */
|
|
89
|
+
ownerProofAvailable: () => boolean;
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Decides whether one candidate may be restored.
|
|
93
|
+
*
|
|
94
|
+
* Order matters: the reboot proof comes first because it is the cheapest and the
|
|
95
|
+
* most restrictive gate, and the pointer's own contents are never trusted beyond
|
|
96
|
+
* naming what to re-read.
|
|
97
|
+
*/
|
|
98
|
+
export declare function evaluateRestoreCandidate(pointer: RestorePointer, deps: RestoreCandidateDeps): RestoreCandidateVerdict;
|
|
99
|
+
export declare function evaluateRestoreCandidates(pointers: readonly RestorePointer[], deps: RestoreCandidateDeps): RestoreCandidateVerdict[];
|
|
@@ -302,6 +302,166 @@ export declare function replaceOwnerGenerationSync(stateDir: string, sessionId:
|
|
|
302
302
|
/** Publishes a raw-owner generation through the canonical SQLite-serialized CAS path. */
|
|
303
303
|
export declare function publishOwnerGenerationSync(request: PublishGenerationRequest): PublishGenerationResult;
|
|
304
304
|
export declare function createOwnerIntent(stateDir: string, input: Omit<OwnerIntent, "schema_version" | "intent_id" | "state">): Promise<OwnerIntent>;
|
|
305
|
+
/**
|
|
306
|
+
* Shared identity create fence (frozen contract F1'-F9''', architect-approved).
|
|
307
|
+
*
|
|
308
|
+
* Concurrent creators of the SAME canonical `(stateDir, sessionId)` identity must
|
|
309
|
+
* not both spawn a child: `SessionManager` opens transcripts with append flags and
|
|
310
|
+
* has no inter-process single-writer lock, so two owners on one transcript is a
|
|
311
|
+
* data-integrity failure rather than a recoverable skip.
|
|
312
|
+
*
|
|
313
|
+
* The fence deliberately does NOT hold the SQLite writer transaction across the
|
|
314
|
+
* spawn. `bootstrapTmuxOwnerIsolation()` runs in a separate process and acquires
|
|
315
|
+
* this very database twice itself, and the synchronous creator blocks on that
|
|
316
|
+
* helper through `Bun.spawnSync`, so a held transaction would deadlock the helper
|
|
317
|
+
* against its own parent. A long hold would also starve the 250 ms verdict path
|
|
318
|
+
* that shares this database. Instead each transition takes a short (target 50 ms)
|
|
319
|
+
* transaction that only reads and writes a durable reservation row; mutual
|
|
320
|
+
* exclusion outlives the transaction as row state, not as a held lock.
|
|
321
|
+
*/
|
|
322
|
+
export type IdentityCreatePhase = "reserved" | "helper_invoked" | "spawned" | "tagged" | "published";
|
|
323
|
+
/** Phases at or beyond which an untagged child may already exist on the server. */
|
|
324
|
+
export declare function identityCreatePhaseMayHaveChild(phase: IdentityCreatePhase): boolean;
|
|
325
|
+
export interface IdentityCreateKey {
|
|
326
|
+
stateDir: string;
|
|
327
|
+
sessionId: string;
|
|
328
|
+
stateFile: string;
|
|
329
|
+
}
|
|
330
|
+
export interface IdentityCreateReservation {
|
|
331
|
+
reservationId: string;
|
|
332
|
+
stateDir: string;
|
|
333
|
+
sessionId: string;
|
|
334
|
+
stateFile: string;
|
|
335
|
+
ownerPid: number;
|
|
336
|
+
ownerIncarnation: string;
|
|
337
|
+
phase: IdentityCreatePhase;
|
|
338
|
+
attemptSessionName: string | null;
|
|
339
|
+
nativeSessionId: string | null;
|
|
340
|
+
serverPid: number | null;
|
|
341
|
+
serverStartTime: string | null;
|
|
342
|
+
claimedAt: string;
|
|
343
|
+
updatedAt: string;
|
|
344
|
+
leaseDeadline: string;
|
|
345
|
+
}
|
|
346
|
+
export type IdentityCreateReservationResult = {
|
|
347
|
+
ok: true;
|
|
348
|
+
reservation: IdentityCreateReservation;
|
|
349
|
+
recovered: IdentityCreateReservation | null;
|
|
350
|
+
} | {
|
|
351
|
+
ok: false;
|
|
352
|
+
code: "identity_reserved_live" | "identity_reserved_unknown" | "identity_fence_contended" | "identity_incarnation_unavailable" | "identity_orphan_unresolved" | "identity_existing_owner";
|
|
353
|
+
existing: IdentityCreateReservation | null;
|
|
354
|
+
diagnostic: string;
|
|
355
|
+
};
|
|
356
|
+
/** Owner liveness is tri-state: only a proven-dead owner may be displaced. */
|
|
357
|
+
export type OwnerLiveness = "alive" | "dead" | "unknown";
|
|
358
|
+
/**
|
|
359
|
+
* `processIncarnation()` returns `undefined` both for a vanished process and for a
|
|
360
|
+
* failed probe, so existence is resolved first. Signal 0 distinguishes them:
|
|
361
|
+
* `ESRCH` proves absence, `EPERM` proves a live process owned by another user, and
|
|
362
|
+
* anything else is unknown. Only then does the incarnation discriminate PID reuse.
|
|
363
|
+
*/
|
|
364
|
+
export declare function probeOwnerLiveness(pid: number, recordedIncarnation: string, deps?: {
|
|
365
|
+
readIncarnation?: (pid: number) => string | undefined;
|
|
366
|
+
signal?: (pid: number) => void;
|
|
367
|
+
}): OwnerLiveness;
|
|
368
|
+
/** @internal Test seam for the incarnation reader. */
|
|
369
|
+
export declare function __setOwnerIncarnationReaderForTests(reader: ((pid: number) => string | undefined) | null): void;
|
|
370
|
+
export declare function canonicalIdentityCreateKey(key: IdentityCreateKey): IdentityCreateKey;
|
|
371
|
+
/**
|
|
372
|
+
* Ends the attempt while KEEPING the durable row.
|
|
373
|
+
*
|
|
374
|
+
* Used when cleanup after a spawn was uncertain: a child may survive that we
|
|
375
|
+
* could not remove, so the evidence must outlive the attempt. Unlike
|
|
376
|
+
* `releaseIdentityCreate` this leaves the row for authority-first recovery.
|
|
377
|
+
*/
|
|
378
|
+
export declare function abandonIdentityCreate(reservation: IdentityCreateReservation): void;
|
|
379
|
+
export interface ReserveIdentityCreateOptions {
|
|
380
|
+
ttlMs?: number;
|
|
381
|
+
ownerPid?: number;
|
|
382
|
+
ownerIncarnation?: string;
|
|
383
|
+
now?: () => Date;
|
|
384
|
+
probeLiveness?: (pid: number, incarnation: string) => OwnerLiveness;
|
|
385
|
+
}
|
|
386
|
+
/**
|
|
387
|
+
* Claims the identity when it is free, and otherwise reports why not.
|
|
388
|
+
*
|
|
389
|
+
* A dead previous owner is deliberately NOT displaced here: authority-first
|
|
390
|
+
* recovery has to census live tmux, which shells out and must never run inside
|
|
391
|
+
* the fence window. The caller performs that census and then calls
|
|
392
|
+
* {@link reclaimIdentityCreate}.
|
|
393
|
+
*
|
|
394
|
+
* The lease deadline is diagnostic only. Expiry never authorizes takeover; only a
|
|
395
|
+
* proven-dead owner does, because real creator paths block in unbounded
|
|
396
|
+
* `Bun.spawnSync` and cannot heartbeat while blocked.
|
|
397
|
+
*/
|
|
398
|
+
export declare function reserveIdentityCreate(rawKey: IdentityCreateKey, options?: ReserveIdentityCreateOptions): IdentityCreateReservationResult;
|
|
399
|
+
/**
|
|
400
|
+
* Completes authority-first recovery after the caller proved, outside the fence
|
|
401
|
+
* window, that the abandoned reservation left no authoritative child behind.
|
|
402
|
+
*
|
|
403
|
+
* `expectedReservationId` pins the exact abandoned row: if another process already
|
|
404
|
+
* recovered it, the row no longer matches and this fails closed rather than
|
|
405
|
+
* producing a second child.
|
|
406
|
+
*/
|
|
407
|
+
export declare function reclaimIdentityCreate(rawKey: IdentityCreateKey, expectedReservationId: string, options?: ReserveIdentityCreateOptions): IdentityCreateReservationResult;
|
|
408
|
+
/**
|
|
409
|
+
* What a live-tmux census concluded about the child an abandoned reservation may
|
|
410
|
+
* have left behind. `unknown` is not a soft failure: it is the fail-closed case.
|
|
411
|
+
*/
|
|
412
|
+
export type AbandonedIdentityVerdict = {
|
|
413
|
+
kind: "authoritative";
|
|
414
|
+
nativeSessionId: string;
|
|
415
|
+
} | {
|
|
416
|
+
kind: "orphan";
|
|
417
|
+
nativeSessionId: string;
|
|
418
|
+
} | {
|
|
419
|
+
kind: "absent";
|
|
420
|
+
} | {
|
|
421
|
+
kind: "unknown";
|
|
422
|
+
reason: string;
|
|
423
|
+
};
|
|
424
|
+
/**
|
|
425
|
+
* Injected so this module never imports the tmux session helpers (which already
|
|
426
|
+
* depend on it). The census shells out and therefore runs OUTSIDE the fence
|
|
427
|
+
* window, by construction.
|
|
428
|
+
*/
|
|
429
|
+
export interface AbandonedIdentityCensus {
|
|
430
|
+
inspect(evidence: {
|
|
431
|
+
stateDir: string;
|
|
432
|
+
sessionId: string;
|
|
433
|
+
attemptSessionName: string | null;
|
|
434
|
+
nativeSessionId: string | null;
|
|
435
|
+
}): AbandonedIdentityVerdict;
|
|
436
|
+
cleanupOrphan(nativeSessionId: string, attemptSessionName: string | null): void;
|
|
437
|
+
}
|
|
438
|
+
/**
|
|
439
|
+
* Authority-first recovery for a reservation whose owner is proven dead and that
|
|
440
|
+
* reached at least `helper_invoked`, so an untagged child may exist.
|
|
441
|
+
*
|
|
442
|
+
* The reservation's own `phase` is a hint, never the authority: a creator can
|
|
443
|
+
* publish its generation and die before recording `published`. The census reads
|
|
444
|
+
* the live canonical tags and the current published generation instead, so a
|
|
445
|
+
* valid child is preserved rather than killed — which is what keeps a
|
|
446
|
+
* tag-before-report crash from producing a successor.
|
|
447
|
+
*/
|
|
448
|
+
export declare function recoverAbandonedIdentityCreate(key: IdentityCreateKey, existing: IdentityCreateReservation, census: AbandonedIdentityCensus, options?: ReserveIdentityCreateOptions): IdentityCreateReservationResult;
|
|
449
|
+
export interface IdentityCreatePhasePatch {
|
|
450
|
+
attemptSessionName?: string | null;
|
|
451
|
+
nativeSessionId?: string | null;
|
|
452
|
+
serverPid?: number | null;
|
|
453
|
+
serverStartTime?: string | null;
|
|
454
|
+
}
|
|
455
|
+
/**
|
|
456
|
+
* Records a create-progress transition and renews the lease.
|
|
457
|
+
*
|
|
458
|
+
* Returns `null` when the reservation is no longer ours. The caller MUST treat
|
|
459
|
+
* that as a lost fence and perform no tmux mutation: another process has already
|
|
460
|
+
* recovered this identity.
|
|
461
|
+
*/
|
|
462
|
+
export declare function advanceIdentityCreatePhase(reservation: IdentityCreateReservation, phase: IdentityCreatePhase, patch?: IdentityCreatePhasePatch, options?: Pick<ReserveIdentityCreateOptions, "ttlMs" | "now">): IdentityCreateReservation | null;
|
|
463
|
+
/** Releases the reservation. Idempotent, and never deletes a successor's row. */
|
|
464
|
+
export declare function releaseIdentityCreate(reservation: IdentityCreateReservation): void;
|
|
305
465
|
/** Publish exactly one terminal verdict. Existing valid verdicts always win. */
|
|
306
466
|
export declare function observeOwnerTerminal(request: ObserveTerminalRequest): Promise<OwnerVerdict>;
|
|
307
467
|
/** Strictly validate the persisted authorization, optionally against its terminal observation. */
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type OwnerIsolationProbeSync, type PlanResponse, type TmuxOwnerIsolationExecutionDependencies, type TmuxOwnerIsolationExecutionResult } from "./tmux-owner-isolation";
|
|
1
|
+
import { type AbandonedIdentityCensus, type IdentityCreateKey, type IdentityCreateReservationResult, type OwnerIsolationProbeSync, type PlanResponse, type TmuxOwnerIsolationExecutionDependencies, type TmuxOwnerIsolationExecutionResult } from "./tmux-owner-isolation";
|
|
2
2
|
export interface SkcTmuxSessionStatus {
|
|
3
3
|
name: string;
|
|
4
4
|
attached: boolean;
|
|
@@ -67,6 +67,17 @@ export interface ForceCloseOwnerDependencies {
|
|
|
67
67
|
}
|
|
68
68
|
export interface CreateSkcTmuxSessionOptions {
|
|
69
69
|
platform?: NodeJS.Platform;
|
|
70
|
+
/**
|
|
71
|
+
* Restore only: run the child in the session's recorded directory instead of
|
|
72
|
+
* this process's cwd.
|
|
73
|
+
*/
|
|
74
|
+
cwd?: string;
|
|
75
|
+
/**
|
|
76
|
+
* Restore only: argv appended to the `skc` child, e.g. `["--resume", "<id>"]`.
|
|
77
|
+
* Restore reuses this creator verbatim so it inherits the same identity fence
|
|
78
|
+
* and owner-isolation proof as an ordinary create.
|
|
79
|
+
*/
|
|
80
|
+
childArgs?: string[];
|
|
70
81
|
}
|
|
71
82
|
export type CreateOwnerIsolationTestDependencies = {
|
|
72
83
|
probe?: Partial<OwnerIsolationProbeSync>;
|
|
@@ -83,6 +94,20 @@ export declare function findSkcTmuxSessionByBranch(branch: string, env?: NodeJS.
|
|
|
83
94
|
export declare function findSkcTmuxSessionByName(sessionName: string, env?: NodeJS.ProcessEnv): SkcTmuxSessionStatus | undefined;
|
|
84
95
|
export declare function findSkcTmuxSessionByScope(project: string, branch: string | null | undefined, env?: NodeJS.ProcessEnv): SkcTmuxSessionStatus | undefined;
|
|
85
96
|
export declare function statusSkcTmuxSession(sessionName: string, env?: NodeJS.ProcessEnv): SkcTmuxSessionStatus;
|
|
97
|
+
/**
|
|
98
|
+
* Live-tmux census for authority-first recovery of an abandoned reservation.
|
|
99
|
+
*
|
|
100
|
+
* Authority is the CURRENT published generation on disk compared against the
|
|
101
|
+
* live session's canonical tags — never the reservation's own `phase`, because a
|
|
102
|
+
* creator can publish and then die before recording that it published.
|
|
103
|
+
*/
|
|
104
|
+
/**
|
|
105
|
+
* Resolves a reservation refused because its previous owner died after reaching
|
|
106
|
+
* the helper. Shared by every producer so none of them can brick an identity by
|
|
107
|
+
* treating an abandoned row as a permanent collision.
|
|
108
|
+
*/
|
|
109
|
+
export declare function settleAbandonedIdentity(reserved: IdentityCreateReservationResult, identityKey: IdentityCreateKey, census: AbandonedIdentityCensus): IdentityCreateReservationResult;
|
|
110
|
+
export declare function abandonedIdentityCensus(tmuxCommand: string, env: NodeJS.ProcessEnv, stateFile: string): AbandonedIdentityCensus;
|
|
86
111
|
export declare function createSkcTmuxSession(env?: NodeJS.ProcessEnv, options?: CreateSkcTmuxSessionOptions): SkcTmuxSessionStatus;
|
|
87
112
|
/** Proves a managed reusable name still resolves to one immutable session on one server. */
|
|
88
113
|
export declare function proveSkcTmuxSessionMutationTarget(sessionName: string, env?: NodeJS.ProcessEnv): ProvenTmuxSessionIdentity;
|
|
@@ -1,10 +1,14 @@
|
|
|
1
1
|
import { type ComposerSubmissionOptions } from "../modes/types";
|
|
2
|
+
import { runSessionImportCommand } from "../session-import";
|
|
2
3
|
import type { BuiltinSlashCommand, ParsedSlashCommand, SlashCommandResult, SlashCommandRuntime, SlashCommandSpec, TuiSlashCommandRuntime } from "./types";
|
|
3
4
|
export type { BuiltinSlashCommand, SubcommandDef } from "./types";
|
|
4
5
|
/** TUI-specific runtime accepted by `executeBuiltinSlashCommand`. */
|
|
5
6
|
export type BuiltinSlashCommandRuntime = TuiSlashCommandRuntime & {
|
|
6
7
|
composer?: ComposerSubmissionOptions;
|
|
7
8
|
};
|
|
9
|
+
type SessionImportRunner = typeof runSessionImportCommand;
|
|
10
|
+
export declare function handleImportSessionCommand(command: ParsedSlashCommand, runtime: SlashCommandRuntime, importer?: SessionImportRunner): Promise<SlashCommandResult>;
|
|
11
|
+
export declare function handleImportSessionTuiCommand(command: ParsedSlashCommand, runtime: TuiSlashCommandRuntime, importer?: SessionImportRunner): Promise<SlashCommandResult>;
|
|
8
12
|
export declare function formatUnknownBuiltinSlashCommandDiagnostic(commandName: string): string | undefined;
|
|
9
13
|
/** Builtin command metadata used for slash-command autocomplete and help text. */
|
|
10
14
|
export declare const BUILTIN_SLASH_COMMAND_DEFS: ReadonlyArray<BuiltinSlashCommand>;
|
|
@@ -81,6 +81,11 @@ export interface SlashCommandSpec extends BuiltinSlashCommand {
|
|
|
81
81
|
aliases?: string[];
|
|
82
82
|
/** When false, the dispatcher refuses to handle invocations that include arguments. */
|
|
83
83
|
allowArgs?: boolean;
|
|
84
|
+
/**
|
|
85
|
+
* Whether ACP may advertise and execute this command. Commands that read
|
|
86
|
+
* caller-selected local paths must set this to false.
|
|
87
|
+
*/
|
|
88
|
+
acp?: boolean;
|
|
84
89
|
/**
|
|
85
90
|
* ACP-specific override for `description`. Used by `ACP_BUILTIN_SLASH_COMMANDS`
|
|
86
91
|
* when building `available_commands_update` payloads so the client receives
|
|
@@ -29,13 +29,92 @@ export declare const askSchema: z.ZodObject<{
|
|
|
29
29
|
}, z.core.$strip>>;
|
|
30
30
|
multi: z.ZodOptional<z.ZodBoolean>;
|
|
31
31
|
recommended: z.ZodOptional<z.ZodNumber>;
|
|
32
|
-
|
|
32
|
+
workflowGate: z.ZodOptional<z.ZodObject<{
|
|
33
|
+
stage: z.ZodEnum<{
|
|
34
|
+
"deep-interview": "deep-interview";
|
|
35
|
+
ralplan: "ralplan";
|
|
36
|
+
ultragoal: "ultragoal";
|
|
37
|
+
}>;
|
|
38
|
+
kind: z.ZodEnum<{
|
|
39
|
+
question: "question";
|
|
40
|
+
approval: "approval";
|
|
41
|
+
execution: "execution";
|
|
42
|
+
}>;
|
|
43
|
+
}, z.core.$strip>>;
|
|
44
|
+
deepInterview: z.ZodOptional<z.ZodUnion<readonly [z.ZodObject<{
|
|
45
|
+
round: z.ZodLiteral<0>;
|
|
46
|
+
component: z.ZodLiteral<"review-topology">;
|
|
47
|
+
intent_contract: z.ZodObject<{
|
|
48
|
+
items: z.ZodArray<z.ZodObject<{
|
|
49
|
+
id: z.ZodString;
|
|
50
|
+
category: z.ZodEnum<{
|
|
51
|
+
surface: "surface";
|
|
52
|
+
artifact: "artifact";
|
|
53
|
+
integration: "integration";
|
|
54
|
+
constraint: "constraint";
|
|
55
|
+
}>;
|
|
56
|
+
statement: z.ZodString;
|
|
57
|
+
}, z.core.$strict>>;
|
|
58
|
+
confirmation_options: z.ZodArray<z.ZodString>;
|
|
59
|
+
}, z.core.$strict>;
|
|
33
60
|
round_id: z.ZodOptional<z.ZodString>;
|
|
61
|
+
dimension: z.ZodString;
|
|
62
|
+
ambiguity: z.ZodNumber;
|
|
63
|
+
confused_terms: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
64
|
+
references: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
65
|
+
reference_id: z.ZodString;
|
|
66
|
+
label: z.ZodString;
|
|
67
|
+
origin: z.ZodString;
|
|
68
|
+
url: z.ZodOptional<z.ZodString>;
|
|
69
|
+
excerpt: z.ZodOptional<z.ZodString>;
|
|
70
|
+
}, z.core.$strict>>>;
|
|
71
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
34
72
|
round: z.ZodNumber;
|
|
73
|
+
intent_review: z.ZodObject<{
|
|
74
|
+
observed_items: z.ZodArray<z.ZodObject<{
|
|
75
|
+
id: z.ZodString;
|
|
76
|
+
category: z.ZodEnum<{
|
|
77
|
+
surface: "surface";
|
|
78
|
+
artifact: "artifact";
|
|
79
|
+
integration: "integration";
|
|
80
|
+
constraint: "constraint";
|
|
81
|
+
}>;
|
|
82
|
+
statement: z.ZodString;
|
|
83
|
+
}, z.core.$strict>>;
|
|
84
|
+
supporting_substitutions: z.ZodArray<z.ZodObject<{
|
|
85
|
+
removed_id: z.ZodString;
|
|
86
|
+
replacement_ids: z.ZodArray<z.ZodString>;
|
|
87
|
+
rationale: z.ZodString;
|
|
88
|
+
}, z.core.$strict>>;
|
|
89
|
+
approval_options: z.ZodArray<z.ZodString>;
|
|
90
|
+
}, z.core.$strict>;
|
|
91
|
+
round_id: z.ZodOptional<z.ZodString>;
|
|
35
92
|
component: z.ZodString;
|
|
36
93
|
dimension: z.ZodString;
|
|
37
94
|
ambiguity: z.ZodNumber;
|
|
38
|
-
|
|
95
|
+
confused_terms: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
96
|
+
references: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
97
|
+
reference_id: z.ZodString;
|
|
98
|
+
label: z.ZodString;
|
|
99
|
+
origin: z.ZodString;
|
|
100
|
+
url: z.ZodOptional<z.ZodString>;
|
|
101
|
+
excerpt: z.ZodOptional<z.ZodString>;
|
|
102
|
+
}, z.core.$strict>>>;
|
|
103
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
104
|
+
round_id: z.ZodOptional<z.ZodString>;
|
|
105
|
+
round: z.ZodNumber;
|
|
106
|
+
component: z.ZodString;
|
|
107
|
+
dimension: z.ZodString;
|
|
108
|
+
ambiguity: z.ZodNumber;
|
|
109
|
+
confused_terms: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
110
|
+
references: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
111
|
+
reference_id: z.ZodString;
|
|
112
|
+
label: z.ZodString;
|
|
113
|
+
origin: z.ZodString;
|
|
114
|
+
url: z.ZodOptional<z.ZodString>;
|
|
115
|
+
excerpt: z.ZodOptional<z.ZodString>;
|
|
116
|
+
}, z.core.$strict>>>;
|
|
117
|
+
}, z.core.$strict>]>>;
|
|
39
118
|
}, z.core.$strip>>;
|
|
40
119
|
}, z.core.$strip>;
|
|
41
120
|
export type AskToolInput = z.infer<typeof askSchema>;
|
|
@@ -54,6 +133,8 @@ export interface AskToolDetails {
|
|
|
54
133
|
multi?: boolean;
|
|
55
134
|
selectedOptions?: string[];
|
|
56
135
|
customInput?: string;
|
|
136
|
+
/** Set when the user answered with a clarification question instead of a choice. */
|
|
137
|
+
clarificationQuestion?: string;
|
|
57
138
|
/** Multi-part question mode */
|
|
58
139
|
results?: QuestionResult[];
|
|
59
140
|
}
|
|
@@ -80,16 +161,100 @@ export declare class AskTool implements AgentTool<typeof askSchema, AskToolDetai
|
|
|
80
161
|
}, z.core.$strip>>;
|
|
81
162
|
multi: z.ZodOptional<z.ZodBoolean>;
|
|
82
163
|
recommended: z.ZodOptional<z.ZodNumber>;
|
|
83
|
-
|
|
164
|
+
workflowGate: z.ZodOptional<z.ZodObject<{
|
|
165
|
+
stage: z.ZodEnum<{
|
|
166
|
+
"deep-interview": "deep-interview";
|
|
167
|
+
ralplan: "ralplan";
|
|
168
|
+
ultragoal: "ultragoal";
|
|
169
|
+
}>;
|
|
170
|
+
kind: z.ZodEnum<{
|
|
171
|
+
question: "question";
|
|
172
|
+
approval: "approval";
|
|
173
|
+
execution: "execution";
|
|
174
|
+
}>;
|
|
175
|
+
}, z.core.$strip>>;
|
|
176
|
+
deepInterview: z.ZodOptional<z.ZodUnion<readonly [z.ZodObject<{
|
|
177
|
+
round: z.ZodLiteral<0>;
|
|
178
|
+
component: z.ZodLiteral<"review-topology">;
|
|
179
|
+
intent_contract: z.ZodObject<{
|
|
180
|
+
items: z.ZodArray<z.ZodObject<{
|
|
181
|
+
id: z.ZodString;
|
|
182
|
+
category: z.ZodEnum<{
|
|
183
|
+
surface: "surface";
|
|
184
|
+
artifact: "artifact";
|
|
185
|
+
integration: "integration";
|
|
186
|
+
constraint: "constraint";
|
|
187
|
+
}>;
|
|
188
|
+
statement: z.ZodString;
|
|
189
|
+
}, z.core.$strict>>;
|
|
190
|
+
confirmation_options: z.ZodArray<z.ZodString>;
|
|
191
|
+
}, z.core.$strict>;
|
|
84
192
|
round_id: z.ZodOptional<z.ZodString>;
|
|
193
|
+
dimension: z.ZodString;
|
|
194
|
+
ambiguity: z.ZodNumber;
|
|
195
|
+
confused_terms: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
196
|
+
references: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
197
|
+
reference_id: z.ZodString;
|
|
198
|
+
label: z.ZodString;
|
|
199
|
+
origin: z.ZodString;
|
|
200
|
+
url: z.ZodOptional<z.ZodString>;
|
|
201
|
+
excerpt: z.ZodOptional<z.ZodString>;
|
|
202
|
+
}, z.core.$strict>>>;
|
|
203
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
85
204
|
round: z.ZodNumber;
|
|
205
|
+
intent_review: z.ZodObject<{
|
|
206
|
+
observed_items: z.ZodArray<z.ZodObject<{
|
|
207
|
+
id: z.ZodString;
|
|
208
|
+
category: z.ZodEnum<{
|
|
209
|
+
surface: "surface";
|
|
210
|
+
artifact: "artifact";
|
|
211
|
+
integration: "integration";
|
|
212
|
+
constraint: "constraint";
|
|
213
|
+
}>;
|
|
214
|
+
statement: z.ZodString;
|
|
215
|
+
}, z.core.$strict>>;
|
|
216
|
+
supporting_substitutions: z.ZodArray<z.ZodObject<{
|
|
217
|
+
removed_id: z.ZodString;
|
|
218
|
+
replacement_ids: z.ZodArray<z.ZodString>;
|
|
219
|
+
rationale: z.ZodString;
|
|
220
|
+
}, z.core.$strict>>;
|
|
221
|
+
approval_options: z.ZodArray<z.ZodString>;
|
|
222
|
+
}, z.core.$strict>;
|
|
223
|
+
round_id: z.ZodOptional<z.ZodString>;
|
|
86
224
|
component: z.ZodString;
|
|
87
225
|
dimension: z.ZodString;
|
|
88
226
|
ambiguity: z.ZodNumber;
|
|
89
|
-
|
|
227
|
+
confused_terms: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
228
|
+
references: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
229
|
+
reference_id: z.ZodString;
|
|
230
|
+
label: z.ZodString;
|
|
231
|
+
origin: z.ZodString;
|
|
232
|
+
url: z.ZodOptional<z.ZodString>;
|
|
233
|
+
excerpt: z.ZodOptional<z.ZodString>;
|
|
234
|
+
}, z.core.$strict>>>;
|
|
235
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
236
|
+
round_id: z.ZodOptional<z.ZodString>;
|
|
237
|
+
round: z.ZodNumber;
|
|
238
|
+
component: z.ZodString;
|
|
239
|
+
dimension: z.ZodString;
|
|
240
|
+
ambiguity: z.ZodNumber;
|
|
241
|
+
confused_terms: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
242
|
+
references: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
243
|
+
reference_id: z.ZodString;
|
|
244
|
+
label: z.ZodString;
|
|
245
|
+
origin: z.ZodString;
|
|
246
|
+
url: z.ZodOptional<z.ZodString>;
|
|
247
|
+
excerpt: z.ZodOptional<z.ZodString>;
|
|
248
|
+
}, z.core.$strict>>>;
|
|
249
|
+
}, z.core.$strict>]>>;
|
|
90
250
|
}, z.core.$strip>>;
|
|
91
251
|
}, z.core.$strip>;
|
|
92
252
|
readonly strict = true;
|
|
253
|
+
/**
|
|
254
|
+
* These fields are rendered to the user and carry no executable or durable
|
|
255
|
+
* meaning. IDs and workflow/deep-interview metadata remain fail-closed.
|
|
256
|
+
*/
|
|
257
|
+
readonly displaySafeEscapedArgFields: readonly ["questions.question", "questions.options.label"];
|
|
93
258
|
readonly loadMode = "discoverable";
|
|
94
259
|
constructor(session: ToolSession);
|
|
95
260
|
static createIf(session: ToolSession): AskTool | null;
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"type": "module",
|
|
3
3
|
"name": "@sayknow-cli/coding-agent",
|
|
4
|
-
"version": "0.5.
|
|
4
|
+
"version": "0.5.6",
|
|
5
5
|
"description": "Sayknow-CLI CLI with read, bash, edit, write tools and session management",
|
|
6
6
|
"homepage": "https://sayknow-cli.com",
|
|
7
7
|
"author": "jaybeyond",
|
|
@@ -33,6 +33,7 @@
|
|
|
33
33
|
"scripts": {
|
|
34
34
|
"build": "bun scripts/build-binary.ts",
|
|
35
35
|
"check": "biome check . && bun run check:types",
|
|
36
|
+
"check:runtime": "bun run generate-hotkeys-docs --check",
|
|
36
37
|
"check:types": "tsgo -p tsconfig.json --noEmit",
|
|
37
38
|
"lint": "biome lint .",
|
|
38
39
|
"test": "bun test --isolate",
|
|
@@ -43,6 +44,7 @@
|
|
|
43
44
|
"fmt": "biome format --write . && bun run format-prompts",
|
|
44
45
|
"format-prompts": "bun scripts/format-prompts.ts",
|
|
45
46
|
"generate-docs-index": "bun scripts/generate-docs-index.ts",
|
|
47
|
+
"generate-hotkeys-docs": "bun scripts/generate-hotkeys-docs.ts",
|
|
46
48
|
"prepack": "bun scripts/generate-docs-index.ts",
|
|
47
49
|
"generate-template": "bun scripts/generate-template.ts",
|
|
48
50
|
"install:defaults": "bun src/cli.ts setup defaults",
|
|
@@ -52,12 +54,12 @@
|
|
|
52
54
|
"@agentclientprotocol/sdk": "1.3.0",
|
|
53
55
|
"@babel/parser": "^7.29.3",
|
|
54
56
|
"@mozilla/readability": "^0.6.0",
|
|
55
|
-
"@sayknow-cli/stats": "0.5.
|
|
56
|
-
"@sayknow-cli/agent-core": "0.5.
|
|
57
|
-
"@sayknow-cli/ai": "0.5.
|
|
58
|
-
"@sayknow-cli/natives": "0.5.
|
|
59
|
-
"@sayknow-cli/tui": "0.5.
|
|
60
|
-
"@sayknow-cli/utils": "0.5.
|
|
57
|
+
"@sayknow-cli/stats": "0.5.6",
|
|
58
|
+
"@sayknow-cli/agent-core": "0.5.6",
|
|
59
|
+
"@sayknow-cli/ai": "0.5.6",
|
|
60
|
+
"@sayknow-cli/natives": "0.5.6",
|
|
61
|
+
"@sayknow-cli/tui": "0.5.6",
|
|
62
|
+
"@sayknow-cli/utils": "0.5.6",
|
|
61
63
|
"@puppeteer/browsers": "^2.13.0",
|
|
62
64
|
"@types/turndown": "5.0.6",
|
|
63
65
|
"@xterm/headless": "^6.0.0",
|
|
@@ -88,6 +90,10 @@
|
|
|
88
90
|
"README.md",
|
|
89
91
|
"CHANGELOG.md",
|
|
90
92
|
"vendor",
|
|
93
|
+
"!vendor/insane-search/engine/tests/**",
|
|
94
|
+
"!src/export/html/template.html",
|
|
95
|
+
"!src/export/html/template.css",
|
|
96
|
+
"!src/export/html/template.js",
|
|
91
97
|
"dist/types"
|
|
92
98
|
],
|
|
93
99
|
"exports": {
|
|
@@ -124,6 +130,9 @@
|
|
|
124
130
|
"./commands/skc-runtime-bridge": null,
|
|
125
131
|
"./capability/mcp": null,
|
|
126
132
|
"./config/mcp-schema": null,
|
|
133
|
+
"./config/model-auth": null,
|
|
134
|
+
"./config/model-bindings-applier": null,
|
|
135
|
+
"./config/model-discovery-manager": null,
|
|
127
136
|
"./discovery/mcp-json": null,
|
|
128
137
|
"./exa": null,
|
|
129
138
|
"./exa/*": null,
|
|
@@ -34,6 +34,8 @@ const LOCKED_EXCLUSIONS: Readonly<Record<string, string>> = {
|
|
|
34
34
|
"slash_command:pet": "visual/local-only command, not a user-facing SDK control seam",
|
|
35
35
|
"slash_command:transcript": "visual/local-only transcript viewer, not a user-facing SDK control seam",
|
|
36
36
|
"slash_command:sessions": "visual/local-only sessions dashboard, not a user-facing SDK control seam",
|
|
37
|
+
"slash_command:import-session":
|
|
38
|
+
"local transcript-file import into a new session; ACP is explicitly disabled and no SDK operation reads caller-selected host paths",
|
|
37
39
|
"agent_session:constructor": "internal accessor/plumbing, not a user-facing control seam",
|
|
38
40
|
"agent_session:nextToolChoice": "internal accessor/plumbing, not a user-facing control seam",
|
|
39
41
|
"agent_session:setForcedToolChoice": "internal accessor/plumbing, not a user-facing control seam",
|
|
@@ -51,6 +53,7 @@ const LOCKED_EXCLUSIONS: Readonly<Record<string, string>> = {
|
|
|
51
53
|
"agent_session:clearPlanCompactAbortPending": "internal accessor/plumbing, not a user-facing control seam",
|
|
52
54
|
"agent_session:enqueueCustomMessageDisplay": "internal accessor/plumbing, not a user-facing control seam",
|
|
53
55
|
"agent_session:runMidRunMaintenanceForTests": "test-only maintenance seam, not a user-facing SDK control seam",
|
|
56
|
+
"agent_session:runPrePromptContextCheckForTests": "test-only context check seam, not a user-facing SDK control seam",
|
|
54
57
|
"agent_session:estimateMidRunContextTokensForTests": "test-only estimator seam, not a user-facing SDK control seam",
|
|
55
58
|
"agent_session:activeMidRunBarrierCountForTests": "read-only test seam, not a user-facing SDK control seam",
|
|
56
59
|
"agent_session:activeMidRunMaintenanceCountForTests": "read-only test seam, not a user-facing SDK control seam",
|
|
@@ -58,6 +61,8 @@ const LOCKED_EXCLUSIONS: Readonly<Record<string, string>> = {
|
|
|
58
61
|
"agent_session:setCancelAndSubmitAbortOutcomeProviderForTests":
|
|
59
62
|
"test-only cancellation seam, not a user-facing SDK control seam",
|
|
60
63
|
"agent_session:getAgentId": "internal accessor/plumbing, not a user-facing control seam",
|
|
64
|
+
"agent_session:hasExplicitlyDisabledTools":
|
|
65
|
+
"internal automatic-tool-selection predicate, not a user-facing SDK control seam",
|
|
61
66
|
"agent_session:emitNotice": "internal accessor/plumbing, not a user-facing control seam",
|
|
62
67
|
"agent_session:subscribe": "internal accessor/plumbing, not a user-facing control seam",
|
|
63
68
|
"agent_session:dispose": "internal accessor/plumbing, not a user-facing control seam",
|
|
@@ -275,9 +280,6 @@ const SEAM_TO_SDK: Readonly<Record<string, string>> = {
|
|
|
275
280
|
"slash_command:move": "session.cwd.move",
|
|
276
281
|
};
|
|
277
282
|
|
|
278
|
-
/** Genuine action seams awaiting a reviewed registry mapping or exclusion. */
|
|
279
|
-
const PENDING_REVIEW: Readonly<Record<string, string>> = {};
|
|
280
|
-
|
|
281
283
|
function lockedExclusion(sourceId: string): string | undefined {
|
|
282
284
|
return LOCKED_EXCLUSIONS[sourceId];
|
|
283
285
|
}
|
|
@@ -812,7 +814,6 @@ function generatedRecords(seams: Awaited<ReturnType<typeof scanSeams>>): Invento
|
|
|
812
814
|
for (const seam of seams) {
|
|
813
815
|
const sdkId = SEAM_TO_SDK[seam.sourceId];
|
|
814
816
|
const rationale = lockedExclusion(seam.sourceId);
|
|
815
|
-
if (!sdkId && !rationale) continue;
|
|
816
817
|
if (!sdkId) {
|
|
817
818
|
if (!rationale) continue;
|
|
818
819
|
records.push({
|
|
@@ -877,8 +878,6 @@ export function pendingReviewErrors(seams: readonly Pick<SourceSeam, "sourceId">
|
|
|
877
878
|
|
|
878
879
|
async function check(records: InventoryRecord[], seams: Awaited<ReturnType<typeof scanSeams>>): Promise<void> {
|
|
879
880
|
const errors = [...validateRegistry(records), ...pendingReviewErrors(seams)];
|
|
880
|
-
for (const sourceId of Object.keys(PENDING_REVIEW))
|
|
881
|
-
errors.push(`Pending review source seam: ${sourceId}. ${PENDING_REVIEW[sourceId]}`);
|
|
882
881
|
let checkedIn: InventoryRecord[];
|
|
883
882
|
try {
|
|
884
883
|
checkedIn = await Bun.file(inventoryPath).json();
|