@herbertgao/pi-extensions 2026.8.8 → 2026.8.10
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/README.md +6 -3
- package/node_modules/@czottmann/pi-automode/CHANGELOG.md +24 -0
- package/node_modules/@czottmann/pi-automode/README.md +78 -112
- package/node_modules/@czottmann/pi-automode/docs/GLOSSARY.md +18 -14
- package/node_modules/@czottmann/pi-automode/docs/adr/ADR-001-permission-precedence-and-trust-boundaries.md +44 -0
- package/node_modules/@czottmann/pi-automode/docs/adr/INDEX.md +5 -0
- package/node_modules/@czottmann/pi-automode/docs/automode-classifier-flow.md +198 -104
- package/node_modules/@czottmann/pi-automode/docs/configuration.md +155 -0
- package/node_modules/@czottmann/pi-automode/docs/defaults.md +55 -14
- package/node_modules/@czottmann/pi-automode/docs/diagnostics.md +90 -0
- package/node_modules/@czottmann/pi-automode/docs/observability-logging.md +61 -26
- package/node_modules/@czottmann/pi-automode/examples/automode.local.json +5 -0
- package/node_modules/@czottmann/pi-automode/extensions/auto-mode/classifier.ts +172 -18
- package/node_modules/@czottmann/pi-automode/extensions/auto-mode/config.ts +127 -30
- package/node_modules/@czottmann/pi-automode/extensions/auto-mode/constants.ts +3 -0
- package/node_modules/@czottmann/pi-automode/extensions/auto-mode/extension.ts +273 -31
- package/node_modules/@czottmann/pi-automode/extensions/auto-mode/log.ts +60 -5
- package/node_modules/@czottmann/pi-automode/extensions/auto-mode/paths.ts +92 -8
- package/node_modules/@czottmann/pi-automode/extensions/auto-mode/permissions.ts +203 -13
- package/node_modules/@czottmann/pi-automode/extensions/auto-mode/state.ts +1 -0
- package/node_modules/@czottmann/pi-automode/extensions/auto-mode/types.ts +11 -0
- package/node_modules/@czottmann/pi-automode/extensions/auto-mode/utils.ts +9 -1
- package/node_modules/@czottmann/pi-automode/package.json +9 -2
- package/node_modules/@czottmann/pi-automode/skills/automode-diagnostics/SKILL.md +63 -0
- package/node_modules/@herbertgao/pi-cc-extensions/README.en.md +3 -3
- package/node_modules/@herbertgao/pi-cc-extensions/README.md +3 -3
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/config/panel.ts +8 -3
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/context.ts +56 -29
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/message-display.ts +1 -1
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/mouse/interaction.ts +15 -13
- package/node_modules/@herbertgao/pi-cc-extensions/package.json +3 -3
- package/node_modules/@herbertgao/pi-handoff/CHANGELOG.md +29 -0
- package/node_modules/@herbertgao/pi-handoff/README.md +15 -18
- package/node_modules/@herbertgao/pi-handoff/package.json +11 -4
- package/node_modules/@herbertgao/pi-handoff/src/complete-text.ts +33 -0
- package/node_modules/@herbertgao/pi-handoff/src/index.ts +127 -232
- package/node_modules/@herbertgao/pi-handoff/src/session-query.ts +15 -30
- package/node_modules/@herbertgao/pi-mermaid-open/CHANGELOG.md +14 -0
- package/node_modules/@herbertgao/pi-mermaid-open/README.md +21 -4
- package/node_modules/@herbertgao/pi-mermaid-open/herdr-plugin/herdr-plugin.toml +11 -0
- package/node_modules/@herbertgao/pi-mermaid-open/herdr-plugin/viewer.mjs +305 -0
- package/node_modules/@herbertgao/pi-mermaid-open/package.json +15 -4
- package/node_modules/@herbertgao/pi-mermaid-open/src/index.ts +351 -101
- package/node_modules/@herbertgao/pi-preferred-thinking/CHANGELOG.md +12 -0
- package/node_modules/@herbertgao/pi-preferred-thinking/README.md +30 -14
- package/node_modules/@herbertgao/pi-preferred-thinking/package.json +7 -4
- package/node_modules/@herbertgao/pi-preferred-thinking/src/index.ts +140 -85
- package/node_modules/@herbertgao/pi-recap/CHANGELOG.md +12 -0
- package/node_modules/@herbertgao/pi-recap/README.md +5 -3
- package/node_modules/@herbertgao/pi-recap/package.json +9 -3
- package/node_modules/@herbertgao/pi-recap/src/index.ts +3 -7
- package/node_modules/@herbertgao/pi-recap/src/model-picker.ts +6 -19
- package/node_modules/@herbertgao/pi-recap/src/models.ts +9 -21
- package/node_modules/@herbertgao/pi-recap/src/tui.ts +1 -1
- package/node_modules/@herbertgao/pi-rename/CHANGELOG.md +49 -0
- package/node_modules/@herbertgao/pi-rename/README.md +13 -11
- package/node_modules/@herbertgao/pi-rename/package.json +13 -3
- package/node_modules/@herbertgao/pi-rename/src/index.ts +135 -59
- package/node_modules/@herbertgao/pi-rename/src/models.ts +5 -13
- package/node_modules/@herbertgao/pi-rename/src/naming.ts +2 -6
- package/node_modules/@herbertgao/pi-stash/package.json +3 -3
- package/node_modules/@herbertgao/pi-subagents/CHANGELOG.md +8 -0
- package/node_modules/@herbertgao/pi-subagents/README.md +16 -3
- package/node_modules/@herbertgao/pi-subagents/package.json +1 -1
- package/node_modules/@herbertgao/pi-subagents/src/cross-extension-rpc.ts +15 -4
- package/node_modules/@herbertgao/pi-subagents/src/index.ts +16 -0
- package/node_modules/@herbertgao/pi-subagents/src/ui/conversation-viewer.ts +5 -1
- package/node_modules/pi-web-access/CHANGELOG.md +13 -0
- package/node_modules/pi-web-access/README.md +2 -2
- package/node_modules/pi-web-access/chrome-cookies.ts +12 -7
- package/node_modules/pi-web-access/gemini-search.ts +28 -10
- package/node_modules/pi-web-access/index.ts +24 -10
- package/node_modules/pi-web-access/package.json +1 -1
- package/node_modules/resume-from/LICENSE +21 -0
- package/node_modules/resume-from/README.md +161 -0
- package/node_modules/resume-from/dist/adapters/claude-code/adapter.d.ts +25 -0
- package/node_modules/resume-from/dist/adapters/claude-code/adapter.js +60 -0
- package/node_modules/resume-from/dist/adapters/claude-code/contract.d.ts +8 -0
- package/node_modules/resume-from/dist/adapters/claude-code/contract.js +4 -0
- package/node_modules/resume-from/dist/adapters/claude-code/entries.d.ts +30 -0
- package/node_modules/resume-from/dist/adapters/claude-code/entries.js +107 -0
- package/node_modules/resume-from/dist/adapters/claude-code/index.d.ts +3 -0
- package/node_modules/resume-from/dist/adapters/claude-code/index.js +2 -0
- package/node_modules/resume-from/dist/adapters/claude-code/layout.d.ts +29 -0
- package/node_modules/resume-from/dist/adapters/claude-code/layout.js +80 -0
- package/node_modules/resume-from/dist/adapters/claude-code/readback.d.ts +9 -0
- package/node_modules/resume-from/dist/adapters/claude-code/readback.js +39 -0
- package/node_modules/resume-from/dist/adapters/claude-code/reader.d.ts +37 -0
- package/node_modules/resume-from/dist/adapters/claude-code/reader.js +415 -0
- package/node_modules/resume-from/dist/adapters/claude-code/redaction.d.ts +26 -0
- package/node_modules/resume-from/dist/adapters/claude-code/redaction.js +132 -0
- package/node_modules/resume-from/dist/adapters/claude-code/validation.d.ts +4 -0
- package/node_modules/resume-from/dist/adapters/claude-code/validation.js +39 -0
- package/node_modules/resume-from/dist/adapters/claude-code/writer.d.ts +23 -0
- package/node_modules/resume-from/dist/adapters/claude-code/writer.js +306 -0
- package/node_modules/resume-from/dist/adapters/codex/contract.d.ts +15 -0
- package/node_modules/resume-from/dist/adapters/codex/contract.js +4 -0
- package/node_modules/resume-from/dist/adapters/codex/index.d.ts +6 -0
- package/node_modules/resume-from/dist/adapters/codex/index.js +44 -0
- package/node_modules/resume-from/dist/adapters/codex/read.d.ts +28 -0
- package/node_modules/resume-from/dist/adapters/codex/read.js +270 -0
- package/node_modules/resume-from/dist/adapters/codex/readback.d.ts +9 -0
- package/node_modules/resume-from/dist/adapters/codex/readback.js +47 -0
- package/node_modules/resume-from/dist/adapters/codex/redaction.d.ts +26 -0
- package/node_modules/resume-from/dist/adapters/codex/redaction.js +132 -0
- package/node_modules/resume-from/dist/adapters/codex/rollout.d.ts +75 -0
- package/node_modules/resume-from/dist/adapters/codex/rollout.js +185 -0
- package/node_modules/resume-from/dist/adapters/codex/validation.d.ts +7 -0
- package/node_modules/resume-from/dist/adapters/codex/validation.js +78 -0
- package/node_modules/resume-from/dist/adapters/codex/write.d.ts +17 -0
- package/node_modules/resume-from/dist/adapters/codex/write.js +141 -0
- package/node_modules/resume-from/dist/adapters/contract.d.ts +74 -0
- package/node_modules/resume-from/dist/adapters/contract.js +4 -0
- package/node_modules/resume-from/dist/adapters/pi/adapter.d.ts +15 -0
- package/node_modules/resume-from/dist/adapters/pi/adapter.js +209 -0
- package/node_modules/resume-from/dist/adapters/pi/contract.d.ts +24 -0
- package/node_modules/resume-from/dist/adapters/pi/contract.js +4 -0
- package/node_modules/resume-from/dist/adapters/pi/format.d.ts +162 -0
- package/node_modules/resume-from/dist/adapters/pi/format.js +223 -0
- package/node_modules/resume-from/dist/adapters/pi/index.d.ts +7 -0
- package/node_modules/resume-from/dist/adapters/pi/index.js +10 -0
- package/node_modules/resume-from/dist/adapters/pi/parse.d.ts +41 -0
- package/node_modules/resume-from/dist/adapters/pi/parse.js +371 -0
- package/node_modules/resume-from/dist/adapters/pi/redaction.d.ts +26 -0
- package/node_modules/resume-from/dist/adapters/pi/redaction.js +132 -0
- package/node_modules/resume-from/dist/adapters/pi/serialize.d.ts +22 -0
- package/node_modules/resume-from/dist/adapters/pi/serialize.js +87 -0
- package/node_modules/resume-from/dist/adapters/pi/validate.d.ts +14 -0
- package/node_modules/resume-from/dist/adapters/pi/validate.js +134 -0
- package/node_modules/resume-from/dist/bin.d.ts +35 -0
- package/node_modules/resume-from/dist/bin.js +135 -0
- package/node_modules/resume-from/dist/contract.d.ts +10 -0
- package/node_modules/resume-from/dist/contract.js +4 -0
- package/node_modules/resume-from/dist/host/agents.d.ts +29 -0
- package/node_modules/resume-from/dist/host/agents.js +20 -0
- package/node_modules/resume-from/dist/host/cli/args.d.ts +21 -0
- package/node_modules/resume-from/dist/host/cli/args.js +187 -0
- package/node_modules/resume-from/dist/host/cli/contract.d.ts +27 -0
- package/node_modules/resume-from/dist/host/cli/contract.js +4 -0
- package/node_modules/resume-from/dist/host/cli/index.d.ts +2 -0
- package/node_modules/resume-from/dist/host/cli/index.js +1 -0
- package/node_modules/resume-from/dist/host/cli/presentation.d.ts +2 -0
- package/node_modules/resume-from/dist/host/cli/presentation.js +11 -0
- package/node_modules/resume-from/dist/host/cli/render.d.ts +3 -0
- package/node_modules/resume-from/dist/host/cli/render.js +70 -0
- package/node_modules/resume-from/dist/host/cli/runner.d.ts +8 -0
- package/node_modules/resume-from/dist/host/cli/runner.js +125 -0
- package/node_modules/resume-from/dist/host/contract.d.ts +42 -0
- package/node_modules/resume-from/dist/host/contract.js +4 -0
- package/node_modules/resume-from/dist/host/entry.d.ts +52 -0
- package/node_modules/resume-from/dist/host/entry.js +91 -0
- package/node_modules/resume-from/dist/host/index.d.ts +11 -0
- package/node_modules/resume-from/dist/host/index.js +10 -0
- package/node_modules/resume-from/dist/host/pi-extension/command.d.ts +18 -0
- package/node_modules/resume-from/dist/host/pi-extension/command.js +103 -0
- package/node_modules/resume-from/dist/host/pi-extension/contract.d.ts +34 -0
- package/node_modules/resume-from/dist/host/pi-extension/contract.js +4 -0
- package/node_modules/resume-from/dist/host/pi-extension/index.d.ts +6 -0
- package/node_modules/resume-from/dist/host/pi-extension/index.js +4 -0
- package/node_modules/resume-from/dist/host/pi-extension/picker.d.ts +16 -0
- package/node_modules/resume-from/dist/host/pi-extension/picker.js +35 -0
- package/node_modules/resume-from/dist/host/pi-extension/presentation.d.ts +2 -0
- package/node_modules/resume-from/dist/host/pi-extension/presentation.js +11 -0
- package/node_modules/resume-from/dist/host/pi-extension/register.d.ts +25 -0
- package/node_modules/resume-from/dist/host/pi-extension/register.js +11 -0
- package/node_modules/resume-from/dist/host/pi-extension/ui.d.ts +20 -0
- package/node_modules/resume-from/dist/host/pi-extension/ui.js +1 -0
- package/node_modules/resume-from/dist/host/profile.d.ts +8 -0
- package/node_modules/resume-from/dist/host/profile.js +31 -0
- package/node_modules/resume-from/dist/host/registry.d.ts +8 -0
- package/node_modules/resume-from/dist/host/registry.js +33 -0
- package/node_modules/resume-from/dist/host/wiring.d.ts +41 -0
- package/node_modules/resume-from/dist/host/wiring.js +67 -0
- package/node_modules/resume-from/dist/import/confirmation.d.ts +6 -0
- package/node_modules/resume-from/dist/import/confirmation.js +27 -0
- package/node_modules/resume-from/dist/import/contract.d.ts +41 -0
- package/node_modules/resume-from/dist/import/contract.js +4 -0
- package/node_modules/resume-from/dist/import/discovery/contract.d.ts +58 -0
- package/node_modules/resume-from/dist/import/discovery/contract.js +4 -0
- package/node_modules/resume-from/dist/import/discovery/errors.d.ts +9 -0
- package/node_modules/resume-from/dist/import/discovery/errors.js +12 -0
- package/node_modules/resume-from/dist/import/discovery/finder.d.ts +10 -0
- package/node_modules/resume-from/dist/import/discovery/finder.js +129 -0
- package/node_modules/resume-from/dist/import/discovery/homes.d.ts +23 -0
- package/node_modules/resume-from/dist/import/discovery/homes.js +83 -0
- package/node_modules/resume-from/dist/import/discovery/index.d.ts +2 -0
- package/node_modules/resume-from/dist/import/discovery/index.js +2 -0
- package/node_modules/resume-from/dist/import/discovery/ordering.d.ts +3 -0
- package/node_modules/resume-from/dist/import/discovery/ordering.js +21 -0
- package/node_modules/resume-from/dist/import/errors.d.ts +22 -0
- package/node_modules/resume-from/dist/import/errors.js +20 -0
- package/node_modules/resume-from/dist/import/index.d.ts +3 -0
- package/node_modules/resume-from/dist/import/index.js +5 -0
- package/node_modules/resume-from/dist/import/landing/contract.d.ts +44 -0
- package/node_modules/resume-from/dist/import/landing/contract.js +4 -0
- package/node_modules/resume-from/dist/import/landing/errors.d.ts +15 -0
- package/node_modules/resume-from/dist/import/landing/errors.js +15 -0
- package/node_modules/resume-from/dist/import/landing/handover.d.ts +5 -0
- package/node_modules/resume-from/dist/import/landing/handover.js +12 -0
- package/node_modules/resume-from/dist/import/landing/index.d.ts +4 -0
- package/node_modules/resume-from/dist/import/landing/index.js +4 -0
- package/node_modules/resume-from/dist/import/landing/lander.d.ts +7 -0
- package/node_modules/resume-from/dist/import/landing/lander.js +133 -0
- package/node_modules/resume-from/dist/import/landing/marker.d.ts +9 -0
- package/node_modules/resume-from/dist/import/landing/marker.js +46 -0
- package/node_modules/resume-from/dist/import/pipeline.d.ts +17 -0
- package/node_modules/resume-from/dist/import/pipeline.js +134 -0
- package/node_modules/resume-from/dist/import/preview/builder.d.ts +6 -0
- package/node_modules/resume-from/dist/import/preview/builder.js +76 -0
- package/node_modules/resume-from/dist/import/preview/contract.d.ts +39 -0
- package/node_modules/resume-from/dist/import/preview/contract.js +4 -0
- package/node_modules/resume-from/dist/import/preview/format.d.ts +19 -0
- package/node_modules/resume-from/dist/import/preview/format.js +45 -0
- package/node_modules/resume-from/dist/import/preview/index.d.ts +2 -0
- package/node_modules/resume-from/dist/import/preview/index.js +1 -0
- package/node_modules/resume-from/dist/import/preview/warnings.d.ts +11 -0
- package/node_modules/resume-from/dist/import/preview/warnings.js +80 -0
- package/node_modules/resume-from/dist/import/transfer/contract.d.ts +48 -0
- package/node_modules/resume-from/dist/import/transfer/contract.js +4 -0
- package/node_modules/resume-from/dist/import/transfer/index.d.ts +2 -0
- package/node_modules/resume-from/dist/import/transfer/index.js +1 -0
- package/node_modules/resume-from/dist/import/transfer/rules.d.ts +3 -0
- package/node_modules/resume-from/dist/import/transfer/rules.js +228 -0
- package/node_modules/resume-from/dist/import/wiring.d.ts +24 -0
- package/node_modules/resume-from/dist/import/wiring.js +27 -0
- package/node_modules/resume-from/dist/index.d.ts +36 -0
- package/node_modules/resume-from/dist/index.js +36 -0
- package/node_modules/resume-from/dist/platform/config/contract.d.ts +35 -0
- package/node_modules/resume-from/dist/platform/config/contract.js +4 -0
- package/node_modules/resume-from/dist/platform/config/defaults.d.ts +16 -0
- package/node_modules/resume-from/dist/platform/config/defaults.js +22 -0
- package/node_modules/resume-from/dist/platform/config/errors.d.ts +9 -0
- package/node_modules/resume-from/dist/platform/config/errors.js +12 -0
- package/node_modules/resume-from/dist/platform/config/index.d.ts +5 -0
- package/node_modules/resume-from/dist/platform/config/index.js +6 -0
- package/node_modules/resume-from/dist/platform/config/loader.d.ts +10 -0
- package/node_modules/resume-from/dist/platform/config/loader.js +47 -0
- package/node_modules/resume-from/dist/platform/config/paths.d.ts +13 -0
- package/node_modules/resume-from/dist/platform/config/paths.js +37 -0
- package/node_modules/resume-from/dist/platform/config/validate.d.ts +9 -0
- package/node_modules/resume-from/dist/platform/config/validate.js +117 -0
- package/node_modules/resume-from/dist/platform/repo/contract.d.ts +30 -0
- package/node_modules/resume-from/dist/platform/repo/contract.js +4 -0
- package/node_modules/resume-from/dist/platform/repo/git.d.ts +21 -0
- package/node_modules/resume-from/dist/platform/repo/git.js +74 -0
- package/node_modules/resume-from/dist/platform/repo/index.d.ts +2 -0
- package/node_modules/resume-from/dist/platform/repo/index.js +1 -0
- package/node_modules/resume-from/dist/platform/repo/reader.d.ts +8 -0
- package/node_modules/resume-from/dist/platform/repo/reader.js +130 -0
- package/node_modules/resume-from/dist/platform/store/contract.d.ts +31 -0
- package/node_modules/resume-from/dist/platform/store/contract.js +4 -0
- package/node_modules/resume-from/dist/platform/store/file-committer.d.ts +3 -0
- package/node_modules/resume-from/dist/platform/store/file-committer.js +391 -0
- package/node_modules/resume-from/dist/platform/store/index.d.ts +2 -0
- package/node_modules/resume-from/dist/platform/store/index.js +2 -0
- package/node_modules/resume-from/dist/platform/tokens/contract.d.ts +12 -0
- package/node_modules/resume-from/dist/platform/tokens/contract.js +4 -0
- package/node_modules/resume-from/dist/platform/tokens/estimator.d.ts +12 -0
- package/node_modules/resume-from/dist/platform/tokens/estimator.js +111 -0
- package/node_modules/resume-from/dist/platform/tokens/index.d.ts +2 -0
- package/node_modules/resume-from/dist/platform/tokens/index.js +1 -0
- package/node_modules/resume-from/dist/session/contract.d.ts +109 -0
- package/node_modules/resume-from/dist/session/contract.js +4 -0
- package/node_modules/resume-from/package.json +80 -0
- package/node_modules/resume-from/shims/pi/extensions/resume-from.js +118 -0
- package/package.json +19 -14
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import type { AdapterRole, AgentAdapter, AgentCapabilities, LandingLevel, ProvenanceSupport, SelectionLevel } from "../../adapters/contract.js";
|
|
2
|
+
export type { AdapterRole, AgentAdapter, AgentCapabilities, LandingLevel, ProvenanceSupport, SelectionLevel, };
|
|
3
|
+
import type { HomeEntry, ImportConfig } from "../../platform/config/contract.js";
|
|
4
|
+
export type { HomeEntry, ImportConfig };
|
|
5
|
+
import type { RepoIdentity, RepoReader } from "../../platform/repo/contract.js";
|
|
6
|
+
export type { RepoIdentity, RepoReader };
|
|
7
|
+
import type { AgentId, CanonicalSession, CanonicalTurn, HomePath, RepoSnapshot, SessionDescriptor, SessionId, SessionRef, SourceProvenance, ToolCallRecord, ToolEffect, TurnKind, TurnRole } from "../../session/contract.js";
|
|
8
|
+
export type { AgentId, CanonicalSession, CanonicalTurn, HomePath, RepoSnapshot, SessionDescriptor, SessionId, SessionRef, SourceProvenance, ToolCallRecord, ToolEffect, TurnKind, TurnRole, };
|
|
9
|
+
/** How the user named the session to import (FR-12). */
|
|
10
|
+
export type SelectionInput = {
|
|
11
|
+
by: "row";
|
|
12
|
+
row: number;
|
|
13
|
+
} | {
|
|
14
|
+
by: "session-id";
|
|
15
|
+
id: SessionId;
|
|
16
|
+
} | {
|
|
17
|
+
by: "file-path";
|
|
18
|
+
path: string;
|
|
19
|
+
};
|
|
20
|
+
/** Which homes to search (FR-2, FR-5, FR-13, FR-15). */
|
|
21
|
+
export interface SearchScope {
|
|
22
|
+
/** Absolute path of the repository the listing is filtered to (FR-13). */
|
|
23
|
+
repoRoot: string;
|
|
24
|
+
/** When set, only this agent is searched (FR-15). */
|
|
25
|
+
onlyAgent: AgentId | null;
|
|
26
|
+
/** When set, only this home is searched (FR-2). */
|
|
27
|
+
onlyHome: HomePath | null;
|
|
28
|
+
}
|
|
29
|
+
/** Why a selection could not be resolved (FR-56). */
|
|
30
|
+
export interface SelectionError {
|
|
31
|
+
/** What the user gave: the row, the session ID, or the path. */
|
|
32
|
+
input: string;
|
|
33
|
+
/** What failed, and what the user can do next. */
|
|
34
|
+
message: string;
|
|
35
|
+
}
|
|
36
|
+
/** One home that could not be searched. The listing continues without it. */
|
|
37
|
+
export interface HomeFailure {
|
|
38
|
+
home: HomePath;
|
|
39
|
+
agent: AgentId;
|
|
40
|
+
/** Why the home was skipped, in one line. */
|
|
41
|
+
message: string;
|
|
42
|
+
}
|
|
43
|
+
/** What a listing produced, including what it could not read. */
|
|
44
|
+
export interface Listing {
|
|
45
|
+
/** Newest first, across every agent and home (FR-14, FR-15). */
|
|
46
|
+
rows: SessionDescriptor[];
|
|
47
|
+
/** Homes that were skipped. Reported to the user, never silent. */
|
|
48
|
+
failures: HomeFailure[];
|
|
49
|
+
}
|
|
50
|
+
/** Finds, filters, orders and loads source sessions. It never writes. */
|
|
51
|
+
export interface SessionFinder {
|
|
52
|
+
/** Newest first (FR-14), only sessions of the current repository (FR-13). */
|
|
53
|
+
list(scope: SearchScope): Promise<Listing>;
|
|
54
|
+
/** Resolves a choice against the same ordering list() produced. Rejects with SelectionError. */
|
|
55
|
+
resolve(scope: SearchScope, input: SelectionInput): Promise<SessionDescriptor>;
|
|
56
|
+
/** Reads one session into the neutral vocabulary, through its source adapter. */
|
|
57
|
+
load(descriptor: SessionDescriptor): Promise<CanonicalSession>;
|
|
58
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { SelectionError } from "./contract.js";
|
|
2
|
+
/**
|
|
3
|
+
* What `resolve` rejects with. It is an `Error` so a stack survives, and a `SelectionError`
|
|
4
|
+
* so the host can print what the user gave and what to do next (FR-56).
|
|
5
|
+
*/
|
|
6
|
+
export declare class SessionSelectionError extends Error implements SelectionError {
|
|
7
|
+
readonly input: string;
|
|
8
|
+
constructor(input: string, message: string);
|
|
9
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What `resolve` rejects with. It is an `Error` so a stack survives, and a `SelectionError`
|
|
3
|
+
* so the host can print what the user gave and what to do next (FR-56).
|
|
4
|
+
*/
|
|
5
|
+
export class SessionSelectionError extends Error {
|
|
6
|
+
input;
|
|
7
|
+
constructor(input, message) {
|
|
8
|
+
super(message);
|
|
9
|
+
this.name = "SessionSelectionError";
|
|
10
|
+
this.input = input;
|
|
11
|
+
}
|
|
12
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { ImportConfig, SessionFinder } from "./contract.js";
|
|
2
|
+
import { type SourceAdapter } from "./homes.js";
|
|
3
|
+
export type { SourceAdapter };
|
|
4
|
+
/** Everything the finder needs. The adapter list arrives from `src/import/`; it holds none. */
|
|
5
|
+
export interface DiscoveryDeps {
|
|
6
|
+
adapters: readonly SourceAdapter[];
|
|
7
|
+
/** Only `extraHomes` is read. */
|
|
8
|
+
config: Pick<ImportConfig, "extraHomes">;
|
|
9
|
+
}
|
|
10
|
+
export declare function createSessionFinder(deps: DiscoveryDeps): SessionFinder;
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
// The source side of the tool: find the sessions of this repository, order them, resolve the
|
|
2
|
+
// user's choice, and load it. It never writes and never calls a model (NG-1, AC-4, FR-8).
|
|
3
|
+
import { SessionSelectionError } from "./errors.js";
|
|
4
|
+
import { buildSearchList, canonicalPath, isDirectory, } from "./homes.js";
|
|
5
|
+
import { compareDescriptors } from "./ordering.js";
|
|
6
|
+
const NEXT_STEP = "Run the list again to see the sessions available in this repository.";
|
|
7
|
+
function reasonLine(reason) {
|
|
8
|
+
const text = reason instanceof Error ? reason.message : String(reason);
|
|
9
|
+
return text.split("\n")[0] ?? "unknown error";
|
|
10
|
+
}
|
|
11
|
+
export function createSessionFinder(deps) {
|
|
12
|
+
async function collect(target, repoRoot) {
|
|
13
|
+
// A home the user named must never fail silently: adapters swallow a missing
|
|
14
|
+
// directory (an absent default home is normal), but a typo'd --home is not (FR-2).
|
|
15
|
+
if (target.named === true && !(await isDirectory(target.home))) {
|
|
16
|
+
return {
|
|
17
|
+
rows: [],
|
|
18
|
+
failures: [
|
|
19
|
+
{
|
|
20
|
+
home: target.home,
|
|
21
|
+
agent: target.agent,
|
|
22
|
+
message: "home not searched: no such directory",
|
|
23
|
+
},
|
|
24
|
+
],
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
let found;
|
|
28
|
+
try {
|
|
29
|
+
found = await target.adapter.listSessions(target.home);
|
|
30
|
+
}
|
|
31
|
+
catch (reason) {
|
|
32
|
+
// One bad home never empties the listing.
|
|
33
|
+
return {
|
|
34
|
+
rows: [],
|
|
35
|
+
failures: [
|
|
36
|
+
{
|
|
37
|
+
home: target.home,
|
|
38
|
+
agent: target.agent,
|
|
39
|
+
message: `home not searched: ${reasonLine(reason)}`,
|
|
40
|
+
},
|
|
41
|
+
],
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
const rows = [];
|
|
45
|
+
const failures = [];
|
|
46
|
+
for (const descriptor of found) {
|
|
47
|
+
if (descriptor.repoPath === null) {
|
|
48
|
+
// Out of scope, but never silent: the tool cannot show that it belongs here.
|
|
49
|
+
failures.push({
|
|
50
|
+
home: target.home,
|
|
51
|
+
agent: target.agent,
|
|
52
|
+
message: `session ${descriptor.ref.id} records no repository, so it cannot be listed here`,
|
|
53
|
+
});
|
|
54
|
+
continue;
|
|
55
|
+
}
|
|
56
|
+
if ((await canonicalPath(descriptor.repoPath)) === repoRoot)
|
|
57
|
+
rows.push(descriptor); // FR-13
|
|
58
|
+
}
|
|
59
|
+
return { rows, failures };
|
|
60
|
+
}
|
|
61
|
+
/** The single listing both `list` and `resolve` use, so the two always agree (FR-10). */
|
|
62
|
+
async function buildListing(scope) {
|
|
63
|
+
const targets = await buildSearchList(deps.adapters, deps.config, scope);
|
|
64
|
+
const repoRoot = await canonicalPath(scope.repoRoot);
|
|
65
|
+
const collected = await Promise.all(targets.map((target) => collect(target, repoRoot)));
|
|
66
|
+
const rows = [];
|
|
67
|
+
const failures = [];
|
|
68
|
+
for (const part of collected) {
|
|
69
|
+
rows.push(...part.rows);
|
|
70
|
+
failures.push(...part.failures);
|
|
71
|
+
}
|
|
72
|
+
rows.sort(compareDescriptors);
|
|
73
|
+
return { rows, failures };
|
|
74
|
+
}
|
|
75
|
+
async function resolveRow(rows, row) {
|
|
76
|
+
const chosen = Number.isInteger(row) && row >= 1 ? rows[row - 1] : undefined;
|
|
77
|
+
if (!chosen) {
|
|
78
|
+
throw new SessionSelectionError(String(row), `Row ${row} is not in this repository's session list, which has ${rows.length} row(s). ${NEXT_STEP}`);
|
|
79
|
+
}
|
|
80
|
+
return chosen;
|
|
81
|
+
}
|
|
82
|
+
return {
|
|
83
|
+
async list(scope) {
|
|
84
|
+
return await buildListing(scope);
|
|
85
|
+
},
|
|
86
|
+
async resolve(scope, input) {
|
|
87
|
+
const { rows } = await buildListing(scope);
|
|
88
|
+
switch (input.by) {
|
|
89
|
+
case "row":
|
|
90
|
+
return await resolveRow(rows, input.row);
|
|
91
|
+
case "session-id": {
|
|
92
|
+
const matches = rows.filter((row) => row.ref.id === input.id);
|
|
93
|
+
const found = matches[0];
|
|
94
|
+
if (!found) {
|
|
95
|
+
throw new SessionSelectionError(input.id, `No session "${input.id}" belongs to this repository. ${NEXT_STEP}`);
|
|
96
|
+
}
|
|
97
|
+
if (matches.length > 1) {
|
|
98
|
+
const locations = matches
|
|
99
|
+
.map((row) => `${row.ref.agent} at "${row.ref.home}" (${row.filePath})`)
|
|
100
|
+
.join("; ");
|
|
101
|
+
throw new SessionSelectionError(input.id, `Session ID "${input.id}" matches ${matches.length} sessions: ${locations}. ` +
|
|
102
|
+
"Select a numbered row or exact file path, or narrow the search with an agent and --home.");
|
|
103
|
+
}
|
|
104
|
+
return found;
|
|
105
|
+
}
|
|
106
|
+
case "file-path": {
|
|
107
|
+
const wanted = await canonicalPath(input.path);
|
|
108
|
+
for (const row of rows) {
|
|
109
|
+
if ((await canonicalPath(row.filePath)) === wanted)
|
|
110
|
+
return row;
|
|
111
|
+
}
|
|
112
|
+
// Selection by path is a convenience, not a way around the repository filter (NG-9).
|
|
113
|
+
throw new SessionSelectionError(input.path, `"${input.path}" is not a session of this repository. ${NEXT_STEP}`);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
},
|
|
117
|
+
async load(descriptor) {
|
|
118
|
+
const adapter = deps.adapters.find((candidate) => {
|
|
119
|
+
const capabilities = candidate.capabilities();
|
|
120
|
+
return capabilities.agent === descriptor.ref.agent && capabilities.roles.includes("source");
|
|
121
|
+
});
|
|
122
|
+
if (!adapter) {
|
|
123
|
+
throw new Error(`no source adapter for agent "${descriptor.ref.agent}"`);
|
|
124
|
+
}
|
|
125
|
+
// Returned unchanged: the rules of sections D and E belong to src/import/transfer/.
|
|
126
|
+
return await adapter.loadSession(descriptor);
|
|
127
|
+
},
|
|
128
|
+
};
|
|
129
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { AgentAdapter, AgentId, HomePath, ImportConfig, SearchScope } from "./contract.js";
|
|
2
|
+
/**
|
|
3
|
+
* The source-role subset of `AgentAdapter` this module uses. The target-role methods
|
|
4
|
+
* exist on the port but are never called here (module.md, Public Contract).
|
|
5
|
+
*/
|
|
6
|
+
export type SourceAdapter = Pick<AgentAdapter, "capabilities" | "listSessions" | "loadSession">;
|
|
7
|
+
/** One home to search, with the adapter that can read it. */
|
|
8
|
+
export interface SearchTarget {
|
|
9
|
+
agent: AgentId;
|
|
10
|
+
/** Resolved absolute path. */
|
|
11
|
+
home: HomePath;
|
|
12
|
+
adapter: SourceAdapter;
|
|
13
|
+
/** Set when the user named this home and no configuration lists it (FR-2). */
|
|
14
|
+
named?: boolean;
|
|
15
|
+
}
|
|
16
|
+
/** True when the path exists and is a directory. Symlinks are followed. */
|
|
17
|
+
export declare function isDirectory(target: string): Promise<boolean>;
|
|
18
|
+
/** Expands a leading `~` and makes the path absolute. */
|
|
19
|
+
export declare function expandHome(value: string): string;
|
|
20
|
+
/** Absolute path with symlinks resolved. A path that does not exist keeps its expanded form. */
|
|
21
|
+
export declare function canonicalPath(value: string): Promise<string>;
|
|
22
|
+
/** Every source adapter's default home (FR-3), plus every configured extra home (FR-5). */
|
|
23
|
+
export declare function buildSearchList(adapters: readonly SourceAdapter[], config: Pick<ImportConfig, "extraHomes">, scope: SearchScope): Promise<SearchTarget[]>;
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
// Which homes are searched, and in what form. A home reached twice is searched once,
|
|
2
|
+
// and two spellings of the same directory are one home.
|
|
3
|
+
import { realpath, stat } from "node:fs/promises";
|
|
4
|
+
import { homedir } from "node:os";
|
|
5
|
+
import path from "node:path";
|
|
6
|
+
/** True when the path exists and is a directory. Symlinks are followed. */
|
|
7
|
+
export async function isDirectory(target) {
|
|
8
|
+
try {
|
|
9
|
+
return (await stat(target)).isDirectory();
|
|
10
|
+
}
|
|
11
|
+
catch {
|
|
12
|
+
return false;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
/** Expands a leading `~` and makes the path absolute. */
|
|
16
|
+
export function expandHome(value) {
|
|
17
|
+
if (value === "~")
|
|
18
|
+
return homedir();
|
|
19
|
+
if (value.startsWith("~/") || value.startsWith(`~${path.sep}`)) {
|
|
20
|
+
return path.resolve(homedir(), value.slice(2));
|
|
21
|
+
}
|
|
22
|
+
return path.resolve(value);
|
|
23
|
+
}
|
|
24
|
+
/** Absolute path with symlinks resolved. A path that does not exist keeps its expanded form. */
|
|
25
|
+
export async function canonicalPath(value) {
|
|
26
|
+
const expanded = expandHome(value);
|
|
27
|
+
try {
|
|
28
|
+
return await realpath(expanded);
|
|
29
|
+
}
|
|
30
|
+
catch {
|
|
31
|
+
return expanded;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
/** Every source adapter's default home (FR-3), plus every configured extra home (FR-5). */
|
|
35
|
+
export async function buildSearchList(adapters, config, scope) {
|
|
36
|
+
const sources = new Map();
|
|
37
|
+
const candidates = [];
|
|
38
|
+
for (const adapter of adapters) {
|
|
39
|
+
const capabilities = adapter.capabilities();
|
|
40
|
+
if (!capabilities.roles.includes("source"))
|
|
41
|
+
continue; // FR-59
|
|
42
|
+
if (sources.has(capabilities.agent))
|
|
43
|
+
continue;
|
|
44
|
+
sources.set(capabilities.agent, adapter);
|
|
45
|
+
candidates.push({
|
|
46
|
+
agent: capabilities.agent,
|
|
47
|
+
home: capabilities.defaultHome,
|
|
48
|
+
adapter,
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
for (const entry of config.extraHomes) {
|
|
52
|
+
const adapter = sources.get(entry.agent);
|
|
53
|
+
if (!adapter)
|
|
54
|
+
continue; // no source adapter for that agent: nothing could read the home
|
|
55
|
+
candidates.push({ agent: entry.agent, home: entry.home, adapter });
|
|
56
|
+
}
|
|
57
|
+
const onlyHome = scope.onlyHome === null ? null : await canonicalPath(scope.onlyHome);
|
|
58
|
+
const seen = new Set();
|
|
59
|
+
const targets = [];
|
|
60
|
+
for (const candidate of candidates) {
|
|
61
|
+
if (scope.onlyAgent !== null && candidate.agent !== scope.onlyAgent)
|
|
62
|
+
continue; // FR-15
|
|
63
|
+
const home = await canonicalPath(candidate.home);
|
|
64
|
+
if (onlyHome !== null && home !== onlyHome)
|
|
65
|
+
continue; // FR-2
|
|
66
|
+
const key = `${candidate.agent}\u0000${home}`;
|
|
67
|
+
if (seen.has(key))
|
|
68
|
+
continue;
|
|
69
|
+
seen.add(key);
|
|
70
|
+
targets.push({ agent: candidate.agent, home, adapter: candidate.adapter });
|
|
71
|
+
}
|
|
72
|
+
// FR-2 names a home, not a filter: a home outside the defaults and extraHomes would
|
|
73
|
+
// otherwise silently empty the list. Every source adapter (narrowed by FR-15) searches
|
|
74
|
+
// it; an adapter whose layout is absent there simply finds no sessions.
|
|
75
|
+
if (onlyHome !== null && targets.length === 0) {
|
|
76
|
+
for (const [agent, adapter] of sources) {
|
|
77
|
+
if (scope.onlyAgent !== null && agent !== scope.onlyAgent)
|
|
78
|
+
continue;
|
|
79
|
+
targets.push({ agent, home: onlyHome, adapter, named: true });
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
return targets;
|
|
83
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
// The listing order. It is a total order, because FR-10 lets the user see the rows in one
|
|
2
|
+
// invocation and name row 3 in the next one.
|
|
3
|
+
/** An unreadable timestamp sorts last rather than making the comparison unstable. */
|
|
4
|
+
function timeOf(iso) {
|
|
5
|
+
const parsed = Date.parse(iso);
|
|
6
|
+
return Number.isNaN(parsed) ? Number.NEGATIVE_INFINITY : parsed;
|
|
7
|
+
}
|
|
8
|
+
function compareText(a, b) {
|
|
9
|
+
return a < b ? -1 : a > b ? 1 : 0;
|
|
10
|
+
}
|
|
11
|
+
function compareRef(a, b) {
|
|
12
|
+
return compareText(a.agent, b.agent) || compareText(a.home, b.home) || compareText(a.id, b.id);
|
|
13
|
+
}
|
|
14
|
+
/** Newest first across every agent and home (FR-14, FR-15); ties broken by `SessionRef`. */
|
|
15
|
+
export function compareDescriptors(a, b) {
|
|
16
|
+
const left = timeOf(a.updatedAt);
|
|
17
|
+
const right = timeOf(b.updatedAt);
|
|
18
|
+
if (left !== right)
|
|
19
|
+
return right > left ? 1 : -1;
|
|
20
|
+
return compareRef(a.ref, b.ref);
|
|
21
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { ValidationDefect } from "./contract.js";
|
|
2
|
+
/**
|
|
3
|
+
* Which part of the import failed. One shape for every host, whatever stage raised it
|
|
4
|
+
* (FR-56): a discovery failure, a blocked plan and a landing failure are all this.
|
|
5
|
+
*/
|
|
6
|
+
export type ImportStage = "target" | "discovery" | "plan" | "preview" | "blocked" | "confirmation" | "source-changed" | "landing";
|
|
7
|
+
export interface ImportFailureDetail {
|
|
8
|
+
defects?: ValidationDefect[];
|
|
9
|
+
cause?: unknown;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* What every operation of the pipeline rejects with. It is an `Error` so a host that only
|
|
13
|
+
* prints the throwable still shows what failed and what to do next (FR-56).
|
|
14
|
+
*/
|
|
15
|
+
export declare class ImportFailure extends Error {
|
|
16
|
+
readonly stage: ImportStage;
|
|
17
|
+
/** The structural defects, when a target adapter refused the new session (FR-50). */
|
|
18
|
+
readonly defects: ValidationDefect[];
|
|
19
|
+
constructor(stage: ImportStage, message: string, detail?: ImportFailureDetail);
|
|
20
|
+
}
|
|
21
|
+
/** The first line of whatever a stage threw. Never the raw throwable (FR-56). */
|
|
22
|
+
export declare function reasonOf(cause: unknown): string;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What every operation of the pipeline rejects with. It is an `Error` so a host that only
|
|
3
|
+
* prints the throwable still shows what failed and what to do next (FR-56).
|
|
4
|
+
*/
|
|
5
|
+
export class ImportFailure extends Error {
|
|
6
|
+
stage;
|
|
7
|
+
/** The structural defects, when a target adapter refused the new session (FR-50). */
|
|
8
|
+
defects;
|
|
9
|
+
constructor(stage, message, detail = {}) {
|
|
10
|
+
super(message, detail.cause === undefined ? undefined : { cause: detail.cause });
|
|
11
|
+
this.name = "ImportFailure";
|
|
12
|
+
this.stage = stage;
|
|
13
|
+
this.defects = detail.defects ?? [];
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
/** The first line of whatever a stage threw. Never the raw throwable (FR-56). */
|
|
17
|
+
export function reasonOf(cause) {
|
|
18
|
+
const text = cause instanceof Error ? cause.message : String(cause);
|
|
19
|
+
return text.split("\n")[0] ?? "unknown error";
|
|
20
|
+
}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
export type { AgentAdapter, AgentId, AgentRuntime, HandoverInstruction, HomeFailure, HomePath, ImportPipeline, ImportRequest, LandingResult, Listing, ListRequest, PreviewReport, PreviewWarning, SelectionInput, SessionDescriptor, SessionId, SessionRef, TargetProfile, WarningKind, } from "./contract.js";
|
|
2
|
+
export { ImportFailure, type ImportStage } from "./errors.js";
|
|
3
|
+
export { createImportPipeline, type ImportPipelineDeps } from "./wiring.js";
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
// The import pipeline: list, preview, commit. A host drives these three calls and nothing
|
|
2
|
+
// deeper — the four stages behind them are this module's internal design, and none of them
|
|
3
|
+
// is exported, so no host can land a session it did not preview.
|
|
4
|
+
export { ImportFailure } from "./errors.js";
|
|
5
|
+
export { createImportPipeline } from "./wiring.js";
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import type { AdapterRole, AgentAdapter, AgentCapabilities, AgentRuntime, LandingLevel, ProvenanceSupport, SelectionLevel, SerializedSession, StoredSessionFacts, SwitchOutcome, ValidationDefect } from "../../adapters/contract.js";
|
|
2
|
+
export type { AdapterRole, AgentAdapter, AgentCapabilities, AgentRuntime, LandingLevel, ProvenanceSupport, SelectionLevel, SerializedSession, StoredSessionFacts, SwitchOutcome, ValidationDefect, };
|
|
3
|
+
import type { DropReason, PinReason, TransferPlan, TurnDrop, TurnPin } from "../transfer/contract.js";
|
|
4
|
+
export type { DropReason, PinReason, TransferPlan, TurnDrop, TurnPin };
|
|
5
|
+
import type { Bytes, CommitError, CommitHandle, CommitRefusal, FileCommitter, PendingFile } from "../../platform/store/contract.js";
|
|
6
|
+
export type { Bytes, CommitError, CommitHandle, CommitRefusal, FileCommitter, PendingFile };
|
|
7
|
+
import type { AgentId, CanonicalSession, CanonicalTurn, HomePath, ProvenanceMarker, RepoSnapshot, SessionId, SessionRef, SourceProvenance, TargetProfile, ToolCallRecord, ToolEffect, TurnKind, TurnRole } from "../../session/contract.js";
|
|
8
|
+
export type { AgentId, CanonicalSession, CanonicalTurn, HomePath, ProvenanceMarker, RepoSnapshot, SessionId, SessionRef, SourceProvenance, TargetProfile, ToolCallRecord, ToolEffect, TurnKind, TurnRole, };
|
|
9
|
+
/** What the user must do next when the adapter cannot switch (FR-45). */
|
|
10
|
+
export interface HandoverInstruction {
|
|
11
|
+
sessionId: SessionId;
|
|
12
|
+
/** The native command that opens the new session, for example "claude --resume <id>". */
|
|
13
|
+
command: string;
|
|
14
|
+
}
|
|
15
|
+
/** What the landing produced (FR-40 to FR-47, FR-52). */
|
|
16
|
+
export interface LandingResult {
|
|
17
|
+
ref: SessionRef;
|
|
18
|
+
switched: boolean;
|
|
19
|
+
/** Set when the adapter could only create (FR-43, FR-45). */
|
|
20
|
+
handover: HandoverInstruction | null;
|
|
21
|
+
itemsSent: number;
|
|
22
|
+
itemsStored: number;
|
|
23
|
+
marker: ProvenanceMarker;
|
|
24
|
+
}
|
|
25
|
+
/** Which step of the landing failed (FR-56). */
|
|
26
|
+
export type LandingStage = "serialize" | "validate" | "commit" | "read-back" | "switch";
|
|
27
|
+
/** A landing that failed. Nothing remains in the target home (FR-53). */
|
|
28
|
+
export interface LandingError {
|
|
29
|
+
stage: LandingStage;
|
|
30
|
+
/** What failed, and what the user can do next (FR-56). */
|
|
31
|
+
message: string;
|
|
32
|
+
/** The structural defects, when the stage is "validate" (FR-50). */
|
|
33
|
+
defects: ValidationDefect[];
|
|
34
|
+
/** True when a commit was made and then undone. */
|
|
35
|
+
rolledBack: boolean;
|
|
36
|
+
}
|
|
37
|
+
/** Places a plan in the target home. Adds only, all or nothing (FR-49, FR-53). */
|
|
38
|
+
export interface SessionLander {
|
|
39
|
+
/**
|
|
40
|
+
* Runs after the user confirmed the preview (FR-20).
|
|
41
|
+
* Rejects with a LandingError, leaving the target home unchanged.
|
|
42
|
+
*/
|
|
43
|
+
land(plan: TransferPlan, adapter: AgentAdapter, committer: FileCommitter, runtime: AgentRuntime, importedAt: string): Promise<LandingResult>;
|
|
44
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { LandingError, LandingStage, ValidationDefect } from "./contract.js";
|
|
2
|
+
interface FailureDetail {
|
|
3
|
+
defects?: ValidationDefect[];
|
|
4
|
+
}
|
|
5
|
+
/**
|
|
6
|
+
* The rejection value of `land`. It is an Error so a host that only logs the
|
|
7
|
+
* throwable still shows the stage and the next step (FR-56).
|
|
8
|
+
*/
|
|
9
|
+
export declare class LandingFailure extends Error implements LandingError {
|
|
10
|
+
readonly stage: LandingStage;
|
|
11
|
+
readonly defects: ValidationDefect[];
|
|
12
|
+
readonly rolledBack = false;
|
|
13
|
+
constructor(stage: LandingStage, message: string, detail?: FailureDetail);
|
|
14
|
+
}
|
|
15
|
+
export {};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The rejection value of `land`. It is an Error so a host that only logs the
|
|
3
|
+
* throwable still shows the stage and the next step (FR-56).
|
|
4
|
+
*/
|
|
5
|
+
export class LandingFailure extends Error {
|
|
6
|
+
stage;
|
|
7
|
+
defects;
|
|
8
|
+
rolledBack = false;
|
|
9
|
+
constructor(stage, message, detail = {}) {
|
|
10
|
+
super(message);
|
|
11
|
+
this.name = "LandingFailure";
|
|
12
|
+
this.stage = stage;
|
|
13
|
+
this.defects = detail.defects ?? [];
|
|
14
|
+
}
|
|
15
|
+
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { AgentId, HandoverInstruction, SessionId } from "./contract.js";
|
|
2
|
+
/** Renders the native command that opens a landed session (FR-45). */
|
|
3
|
+
export type HandoverCommandBuilder = (agent: AgentId, sessionId: SessionId) => string;
|
|
4
|
+
export declare const describeSession: HandoverCommandBuilder;
|
|
5
|
+
export declare function buildHandover(build: HandoverCommandBuilder, agent: AgentId, sessionId: SessionId): HandoverInstruction;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Ceiling: no contract restated by this module carries an agent's own resume
|
|
3
|
+
* command — neither AgentCapabilities nor the target half of AgentAdapter — and
|
|
4
|
+
* this module must never name an agent (FR-60). The default therefore names the
|
|
5
|
+
* session and the agent instead of printing a command that would not run. The
|
|
6
|
+
* host injects the real one. Upgrade trigger: when the adapter contract carries
|
|
7
|
+
* a resume-command template, this default and the injection point are deleted.
|
|
8
|
+
*/
|
|
9
|
+
export const describeSession = (agent, sessionId) => `open session ${sessionId} with ${agent}`;
|
|
10
|
+
export function buildHandover(build, agent, sessionId) {
|
|
11
|
+
return { sessionId, command: build(agent, sessionId) };
|
|
12
|
+
}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export { LandingFailure } from "./errors.js";
|
|
2
|
+
export { buildHandover, describeSession, type HandoverCommandBuilder } from "./handover.js";
|
|
3
|
+
export { createSessionLander, type SessionLanderOptions } from "./lander.js";
|
|
4
|
+
export { buildMarker, summariseDrops } from "./marker.js";
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { SessionLander } from "./contract.js";
|
|
2
|
+
import { type HandoverCommandBuilder } from "./handover.js";
|
|
3
|
+
export interface SessionLanderOptions {
|
|
4
|
+
/** Overrides the placeholder resume command. See handover.ts for the ceiling. */
|
|
5
|
+
handoverCommand?: HandoverCommandBuilder;
|
|
6
|
+
}
|
|
7
|
+
export declare function createSessionLander(options?: SessionLanderOptions): SessionLander;
|