@timurproko/a1 0.2.7-dev.1232 → 0.2.7-dev.1234

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (103) hide show
  1. package/dist/composition/owned-ui.js +13 -79
  2. package/dist/composition/release-update-observation.d.ts +22 -0
  3. package/dist/composition/release-update-observation.js +91 -0
  4. package/dist/composition/resident-tab-bridge.d.ts +16 -0
  5. package/dist/composition/resident-tab-bridge.js +45 -16
  6. package/dist/composition/startup-route.d.ts +8 -0
  7. package/dist/composition/startup-route.js +20 -0
  8. package/dist/contracts/owned-ui/session-workflows.d.ts +3 -0
  9. package/dist/foundation/release/bootstrap.js +46 -36
  10. package/dist/foundation/release/progress-palette.generated.d.ts +1 -1
  11. package/dist/foundation/release/progress-palette.generated.js +1 -1
  12. package/dist/foundation/release/update-activation.js +8 -2
  13. package/dist/foundation/resident-tabs/bridge-client.d.ts +3 -0
  14. package/dist/foundation/resident-tabs/bridge-client.js +7 -1
  15. package/dist/foundation/resident-tabs/continuity.d.ts +12 -0
  16. package/dist/foundation/resident-tabs/continuity.js +55 -0
  17. package/dist/foundation/resident-tabs/index.d.ts +3 -0
  18. package/dist/foundation/resident-tabs/index.js +4 -0
  19. package/dist/foundation/resident-tabs/maintenance.d.ts +1 -1
  20. package/dist/foundation/resident-tabs/release-holds.js +11 -8
  21. package/dist/foundation/resident-tabs/runtime-control.d.ts +38 -0
  22. package/dist/foundation/resident-tabs/runtime-control.js +73 -0
  23. package/dist/foundation/startup/startup-descriptor.js +2 -2
  24. package/dist/integrations/pi/components/resources/builtin-themes.d.ts +2 -2
  25. package/dist/integrations/pi/components/resources/builtin-themes.js +2 -2
  26. package/dist/integrations/pi/components/upstream/adjacent/core/keybindings.d.ts +1 -1
  27. package/dist/integrations/pi/components/upstream/adjacent/core/keybindings.js +1 -1
  28. package/dist/integrations/pi/components/upstream/assets/earendil-image.json +2 -2
  29. package/dist/integrations/pi/components/upstream/components/countdown-timer.d.ts +1 -1
  30. package/dist/integrations/pi/components/upstream/components/earendil-announcement.js +1 -1
  31. package/dist/integrations/pi/components/upstream/components/extension-editor.d.ts +3 -3
  32. package/dist/integrations/pi/components/upstream/components/extension-editor.js +4 -1
  33. package/dist/integrations/pi/components/upstream/components/extension-input.js +1 -1
  34. package/dist/integrations/pi/components/upstream/components/extension-selector.js +1 -1
  35. package/dist/integrations/pi/components/upstream/components/mermaid.js +1 -1
  36. package/dist/integrations/pi/components/upstream/components/owned-editor.d.ts +1 -1
  37. package/dist/integrations/pi/components/upstream/components/owned-editor.js +8 -1
  38. package/dist/integrations/pi/components/upstream/components/pi-logo.js +1 -1
  39. package/dist/integrations/pi/components/upstream/components/scoped-models-selector.d.ts +2 -1
  40. package/dist/integrations/pi/components/upstream/components/scoped-models-selector.js +14 -3
  41. package/dist/integrations/pi/components/upstream/components/session-footer.js +1 -1
  42. package/dist/integrations/pi/components/upstream/components/session-selector-search.d.ts +4 -0
  43. package/dist/integrations/pi/components/upstream/components/session-selector-search.js +87 -23
  44. package/dist/integrations/pi/components/upstream/components/session-selector.d.ts +3 -2
  45. package/dist/integrations/pi/components/upstream/components/session-selector.js +18 -13
  46. package/dist/integrations/pi/components/upstream/components/skill-invocation-message.d.ts +1 -1
  47. package/dist/integrations/pi/components/upstream/components/skill-invocation-message.js +1 -1
  48. package/dist/integrations/pi/components/upstream/components/status-indicator.d.ts +1 -1
  49. package/dist/integrations/pi/components/upstream/components/status-indicator.js +1 -1
  50. package/dist/integrations/pi/components/upstream/components/themed-text.d.ts +1 -1
  51. package/dist/integrations/pi/components/upstream/components/themed-text.js +1 -1
  52. package/dist/integrations/pi/components/upstream/components/thinking-selector.d.ts +1 -1
  53. package/dist/integrations/pi/components/upstream/components/thinking-selector.js +1 -1
  54. package/dist/integrations/pi/components/upstream/components/tool-execution.d.ts +6 -0
  55. package/dist/integrations/pi/components/upstream/components/tool-execution.js +14 -2
  56. package/dist/integrations/pi/components/upstream/components/tree-selector.d.ts +2 -1
  57. package/dist/integrations/pi/components/upstream/components/tree-selector.js +5 -4
  58. package/dist/integrations/pi/components/upstream/components/trust-selector.js +1 -1
  59. package/dist/integrations/pi/components/upstream/external-editor.d.ts +1 -0
  60. package/dist/integrations/pi/components/upstream/external-editor.js +13 -6
  61. package/dist/integrations/pi/components/upstream/history/editor-core.d.ts +3 -1
  62. package/dist/integrations/pi/components/upstream/history/editor-core.js +9 -2
  63. package/dist/integrations/pi/components/upstream/history/kill-ring.d.ts +1 -1
  64. package/dist/integrations/pi/components/upstream/history/kill-ring.js +1 -1
  65. package/dist/integrations/pi/components/upstream/history/printable-key.js +1 -1
  66. package/dist/integrations/pi/components/upstream/history/text-helpers.js +1 -1
  67. package/dist/integrations/pi/components/upstream/history/undo-stack.d.ts +1 -1
  68. package/dist/integrations/pi/components/upstream/history/undo-stack.js +1 -1
  69. package/dist/integrations/pi/components/upstream/history/word-navigation.js +1 -1
  70. package/dist/integrations/pi/components/upstream/model-search.d.ts +11 -1
  71. package/dist/integrations/pi/components/upstream/model-search.js +21 -0
  72. package/dist/integrations/pi/components/upstream/program-status-reporter.d.ts +1 -1
  73. package/dist/integrations/pi/components/upstream/theme/theme-controller.d.ts +1 -1
  74. package/dist/integrations/pi/components/upstream/theme/theme.js +1 -1
  75. package/dist/integrations/pi/engine/adapter.js +6 -1
  76. package/dist/integrations/pi/engine/diagnostics-state.d.ts +9 -0
  77. package/dist/integrations/pi/engine/diagnostics-state.js +34 -0
  78. package/dist/integrations/pi/engine/resources/changelog.json +4 -4
  79. package/dist/integrations/pi/engine/view-state.d.ts +2 -1
  80. package/dist/integrations/pi/engine/view-state.js +4 -16
  81. package/dist/integrations/pi/startup-public.js +324 -309
  82. package/dist/integrations/pi/startup-public.manifest.json +1156 -846
  83. package/dist/integrations/pi/tui-runtime/damage-aware-terminal.d.ts +1 -1
  84. package/dist/integrations/pi/tui-runtime/damage-aware-terminal.js +1 -1
  85. package/dist/native/darwin-arm64/manifest.json +1 -1
  86. package/dist/native/darwin-arm64/terminal-host.manifest.json +3 -3
  87. package/dist/native/darwin-arm64/terminal-host.node +0 -0
  88. package/dist/native/darwin-x64/manifest.json +1 -1
  89. package/dist/native/darwin-x64/terminal-host.manifest.json +3 -3
  90. package/dist/native/darwin-x64/terminal-host.node +0 -0
  91. package/dist/native/linux-x64/manifest.json +1 -1
  92. package/dist/native/linux-x64/terminal-host.manifest.json +3 -3
  93. package/dist/native/linux-x64/terminal-host.node +0 -0
  94. package/dist/native/win32-x64/manifest.json +2 -2
  95. package/dist/native/win32-x64/process-guardian.node +0 -0
  96. package/dist/native/win32-x64/terminal-host.manifest.json +3 -3
  97. package/dist/native/win32-x64/terminal-host.node +0 -0
  98. package/dist/runtime-payload-inventory.json +8178 -5237
  99. package/dist/ui/settings/progress-palette.generated.d.ts +1 -1
  100. package/dist/ui/settings/progress-palette.generated.js +1 -1
  101. package/docs/architecture/native-fixture-isolation.md +23 -0
  102. package/docs/architecture/resident-tabs.md +23 -4
  103. package/package.json +10 -5
@@ -0,0 +1,55 @@
1
+ import { readdir, readFile } from "node:fs/promises";
2
+ import { resolve } from "node:path";
3
+ import { RUNTIME_CONTROL_API } from "./runtime-control.js";
4
+ import { runBoundedHostCommand } from "./bounded-host-command.js";
5
+ import { resolveTerminalHostEntryPath, resolveTerminalHostPath } from "./ensure-terminal-host.js";
6
+ import { verifyTerminalHostArtifact } from "./terminal-host-artifact.js";
7
+ /** Activation authority requires a stable authenticated source-contract set, never an idle Agent. */
8
+ export async function assertResidentContinuity(options) {
9
+ const { inspect = inspectResidentContinuity, ...context } = options;
10
+ const first = await inspect(context);
11
+ const second = await inspect(context);
12
+ if (first !== second && second !== await inspect(context)) {
13
+ throw new Error("Resident workspace changed during update readiness; the prior client remains selected.");
14
+ }
15
+ }
16
+ /** Native inspection/import is read-only toward execution and never starts or stops a source. */
17
+ export async function inspectResidentContinuity(options) {
18
+ let hasRecords = false;
19
+ for (const directory of ["tabs", "resident-workspaces"]) {
20
+ try {
21
+ hasRecords ||= (await readdir(resolve(options.dataDir, directory))).length > 0;
22
+ }
23
+ catch (error) {
24
+ if (!(error instanceof Error && "code" in error && error.code === "ENOENT")) {
25
+ throw new Error("Resident workspace discovery is unavailable; update activation was refused.");
26
+ }
27
+ }
28
+ }
29
+ if (!hasRecords)
30
+ return "empty";
31
+ const manifest = JSON.parse(await readFile(resolve(options.releaseRoot, "package.json"), "utf8"));
32
+ const contracts = manifest.residentControlContracts;
33
+ if (!Array.isArray(contracts)
34
+ || ![RUNTIME_CONTROL_API, "resident-workspace-v1"].every(contract => contracts.includes(contract))) {
35
+ throw new Error("Candidate does not preserve the stable resident control and workspace contracts; activation was refused.");
36
+ }
37
+ const addon = resolveTerminalHostPath(options.releaseRoot, {}, process.platform, process.arch);
38
+ await verifyTerminalHostArtifact(addon, process.platform, process.arch);
39
+ const result = await runBoundedHostCommand({ executable: process.execPath, entry: resolveTerminalHostEntryPath(options.releaseRoot) }, [
40
+ "workspace-check", "--profile", options.profileRoot,
41
+ "--data-dir", options.dataDir, "--runtime-dir", options.runtimeDir,
42
+ ], { label: "resident continuity check", maxStdoutBytes: 4096, timeoutMs: 8_000, environment: options.environment });
43
+ let report;
44
+ try {
45
+ report = JSON.parse(result.stdout.trim());
46
+ }
47
+ catch {
48
+ throw new Error("Resident control compatibility could not be verified; the prior client remains selected.");
49
+ }
50
+ if (result.code !== 0 || report.schema !== "resident-workspace-check-v1" || report.compatible !== true
51
+ || typeof report.fingerprint !== "string" || !/^[a-f0-9]{64}$/u.test(report.fingerprint)) {
52
+ throw new Error("Resident control compatibility could not be verified; the prior client remains selected.");
53
+ }
54
+ return report.fingerprint;
55
+ }
@@ -10,3 +10,6 @@ export { runTerminalHostMaintenance } from "./maintenance.js";
10
10
  export type { MaintenanceAction, MaintenanceHostState, MaintenanceOptions, MaintenanceReport } from "./maintenance.js";
11
11
  export { DOCTOR_MAX_BYTES, writeDoctorBundle } from "./doctor.js";
12
12
  export type { DoctorBundle, DoctorOptions } from "./doctor.js";
13
+ export type { ContinuityOptions } from "./continuity.js";
14
+ /** Load native continuity inspection only when a caller is preparing client activation. */
15
+ export declare function assertResidentContinuity(options: import("./continuity.js").ContinuityOptions): Promise<void>;
@@ -4,3 +4,7 @@ export { selectResidentHost } from "./routing.js";
4
4
  export { readResidentReleaseHolds } from "./release-holds.js";
5
5
  export { runTerminalHostMaintenance } from "./maintenance.js";
6
6
  export { DOCTOR_MAX_BYTES, writeDoctorBundle } from "./doctor.js";
7
+ /** Load native continuity inspection only when a caller is preparing client activation. */
8
+ export async function assertResidentContinuity(options) {
9
+ await (await import("./continuity.js")).assertResidentContinuity(options);
10
+ }
@@ -1,5 +1,5 @@
1
1
  import { type TerminalHostCommand } from "./ensure-terminal-host.js";
2
- export type MaintenanceAction = "list" | "stop" | "stop-all" | "host-status" | "host-stop";
2
+ export type MaintenanceAction = "list" | "stop" | "stop-all" | "host-status" | "host-stop" | "runtime-control";
3
3
  export type MaintenanceHostState = "none" | "running" | "stopped" | "unresponsive" | "incompatible" | "refused" | "unverifiable" | "unavailable";
4
4
  /** The versioned `a1 tabs` report: `a1-tabs-maintenance-v1`, as printed by the terminal host. */
5
5
  export interface MaintenanceReport {
@@ -44,15 +44,18 @@ export async function readResidentReleaseHolds(options) {
44
44
  }
45
45
  }
46
46
  async function hasResidentRecords(dataDir) {
47
- let profiles;
48
- try {
49
- profiles = await readdir(resolve(dataDir, "tabs"));
50
- }
51
- catch (error) {
52
- return !(error instanceof Error && "code" in error && error.code === "ENOENT");
47
+ for (const directory of ["tabs", "resident-workspaces"]) {
48
+ try {
49
+ // Invariant: native inspection, not a following stat, judges unknown or linked entries.
50
+ if ((await readdir(resolve(dataDir, directory))).length > 0)
51
+ return true;
52
+ }
53
+ catch (error) {
54
+ if (!(error instanceof Error && "code" in error && error.code === "ENOENT"))
55
+ return true;
56
+ }
53
57
  }
54
- // Invariant: native inspection, not a following stat, judges unknown or linked namespace entries.
55
- return profiles.length > 0;
58
+ return false;
56
59
  }
57
60
  function incomplete(reason) {
58
61
  return { complete: false, releaseRoots: [], uncertain: [reason] };
@@ -0,0 +1,38 @@
1
+ import { type MaintenanceOptions, type MaintenanceReport } from "./maintenance.js";
2
+ /** Mandatory native control semantics; optional methods never establish source authority. */
3
+ export declare const RUNTIME_CONTROL_API = "resident-control-v1";
4
+ export declare const RUNTIME_CONTROL_CORE: readonly ["attach", "tab.list", "tab.view", "input", "resize", "detach", "controller-boundary"];
5
+ export interface RuntimeControlIdentity {
6
+ readonly releaseId: string;
7
+ readonly scope: string;
8
+ readonly epoch: number;
9
+ readonly bootId: string;
10
+ readonly osSessionId: string;
11
+ }
12
+ export interface RuntimeControlDescription extends RuntimeControlIdentity {
13
+ readonly api: typeof RUNTIME_CONTROL_API;
14
+ readonly generation: 1;
15
+ readonly core: readonly string[];
16
+ readonly frameLimit: number;
17
+ readonly inputLimit: number;
18
+ readonly retryInput: false;
19
+ }
20
+ export type RuntimeControlVerdict = {
21
+ readonly status: "compatible";
22
+ readonly contract: RuntimeControlDescription;
23
+ } | {
24
+ readonly status: "blocked";
25
+ readonly reason: "unavailable" | "invalid-contract" | "unsupported-api" | "source-mismatch" | "stale-epoch" | "missing-core";
26
+ };
27
+ /**
28
+ * Validates an authenticated source's descriptor against separately verified source custody.
29
+ * This is not an activation verdict: the caller must also reconcile every live tab and fence
30
+ * changes to that topology before committing a client selection.
31
+ */
32
+ export declare function assessRuntimeControl(value: unknown, expected: RuntimeControlIdentity): RuntimeControlVerdict;
33
+ export interface ReadRuntimeControlOptions extends Omit<MaintenanceOptions, "action" | "tabId"> {
34
+ readonly expected: RuntimeControlIdentity;
35
+ readonly maintain?: (options: MaintenanceOptions) => Promise<MaintenanceReport>;
36
+ }
37
+ /** A bounded read-only authenticated exchange; it never starts a host or substitutes a release. */
38
+ export declare function readRuntimeControl(options: ReadRuntimeControlOptions): Promise<RuntimeControlVerdict>;
@@ -0,0 +1,73 @@
1
+ import { runTerminalHostMaintenance } from "./maintenance.js";
2
+ /** Mandatory native control semantics; optional methods never establish source authority. */
3
+ export const RUNTIME_CONTROL_API = "resident-control-v1";
4
+ export const RUNTIME_CONTROL_CORE = Object.freeze([
5
+ "attach", "tab.list", "tab.view", "input", "resize", "detach", "controller-boundary",
6
+ ]);
7
+ /**
8
+ * Validates an authenticated source's descriptor against separately verified source custody.
9
+ * This is not an activation verdict: the caller must also reconcile every live tab and fence
10
+ * changes to that topology before committing a client selection.
11
+ */
12
+ export function assessRuntimeControl(value, expected) {
13
+ if (!isRecord(value))
14
+ return blocked("invalid-contract");
15
+ if (value.api !== RUNTIME_CONTROL_API || value.generation !== 1)
16
+ return blocked("unsupported-api");
17
+ if (!identityValid(value) || !identityValid(expected)
18
+ || !boundedStrings(value.core) || typeof value.retryInput !== "boolean"
19
+ || !positiveInteger(value.frameLimit, 2 * 1024 * 1024)
20
+ || !positiveInteger(value.inputLimit, 1024 * 1024) || value.inputLimit > value.frameLimit) {
21
+ return blocked("invalid-contract");
22
+ }
23
+ if (value.releaseId !== expected.releaseId || value.scope !== expected.scope
24
+ || value.bootId !== expected.bootId || value.osSessionId !== expected.osSessionId)
25
+ return blocked("source-mismatch");
26
+ if (value.epoch !== expected.epoch)
27
+ return blocked("stale-epoch");
28
+ const core = value.core;
29
+ if (value.retryInput || RUNTIME_CONTROL_CORE.some(method => !core.includes(method)))
30
+ return blocked("missing-core");
31
+ // Security: retain only allowlisted metadata, never arbitrary optional source data.
32
+ return { status: "compatible", contract: Object.freeze({
33
+ api: RUNTIME_CONTROL_API, generation: 1, releaseId: value.releaseId, scope: value.scope,
34
+ epoch: value.epoch, bootId: value.bootId, osSessionId: value.osSessionId,
35
+ core: Object.freeze([...value.core]), frameLimit: value.frameLimit, inputLimit: value.inputLimit,
36
+ retryInput: false,
37
+ }) };
38
+ }
39
+ /** A bounded read-only authenticated exchange; it never starts a host or substitutes a release. */
40
+ export async function readRuntimeControl(options) {
41
+ const { expected, maintain = runTerminalHostMaintenance, ...maintenance } = options;
42
+ try {
43
+ const report = await maintain({ ...maintenance, action: "runtime-control" });
44
+ if (report.schema !== "a1-tabs-maintenance-v1" || report.exitCode !== 0
45
+ || report.host !== "running" || report.command !== "runtime-control")
46
+ return blocked("unavailable");
47
+ return assessRuntimeControl(report.result, expected);
48
+ }
49
+ catch {
50
+ return blocked("unavailable");
51
+ }
52
+ }
53
+ function blocked(reason) {
54
+ return { status: "blocked", reason };
55
+ }
56
+ function isRecord(value) {
57
+ return value !== null && typeof value === "object" && !Array.isArray(value);
58
+ }
59
+ function positiveInteger(value, maximum = Number.MAX_SAFE_INTEGER) {
60
+ return typeof value === "number" && Number.isSafeInteger(value) && value > 0 && value <= maximum;
61
+ }
62
+ function boundedStrings(value) {
63
+ return Array.isArray(value) && value.length <= 64 && new Set(value).size === value.length
64
+ && value.every(entry => typeof entry === "string" && entry.length > 0 && entry.length <= 64);
65
+ }
66
+ function identityValid(value) {
67
+ const record = value;
68
+ return typeof record.releaseId === "string" && /^[a-f0-9]{64}$/u.test(record.releaseId)
69
+ && typeof record.scope === "string" && /^[a-f0-9]{20}$/u.test(record.scope)
70
+ && positiveInteger(record.epoch)
71
+ && [record.bootId, record.osSessionId].every(entry => typeof entry === "string" && entry.length > 0
72
+ && entry.length <= 256 && !/[\x00-\x1f\x7f]/u.test(entry));
73
+ }
@@ -10,7 +10,7 @@ export const STARTUP_DESCRIPTOR = Object.freeze({
10
10
  ],
11
11
  "generatedArtifact": {
12
12
  "path": "dist/integrations/pi/startup-public.js",
13
- "sha256": "e065933fe374d7953c5aac0ff1735fa47d119ab97551e955c2a65e8c2df667eb"
13
+ "sha256": "97a7715b6a24a7449ecb61d3581e27396ebde40d3d2d0b6f701415c82e74f6b2"
14
14
  },
15
15
  "dependencyLayerIdentity": {
16
16
  "source": "A1_RELEASE_LAYERS",
@@ -19,7 +19,7 @@ export const STARTUP_DESCRIPTOR = Object.freeze({
19
19
  "compileCacheNamespace": {
20
20
  "strategy": "node-abi-version-and-ordered-layer-sha256-v1"
21
21
  },
22
- "identity": "5c1afab4657c251b840e042279290bd1fa03ce608bc81bc6e7eaf8d332486eef"
22
+ "identity": "c1f84ec1184782905d628eba21b4c0e62c643e0a37481d4bb42e47e768d5d48f"
23
23
  });
24
24
 
25
25
  export function loadDeclaredStartupGraph() {
@@ -1,6 +1,6 @@
1
1
  /**
2
- * Attributed owned theme resources adapted from @earendil-works/pi-coding-agent 1.4.0 (MIT),
3
- * commit 4a080252f06caf63a525d7873c5d94d3c23887e0.
2
+ * Attributed owned theme resources adapted from @earendil-works/pi-coding-agent 1.5.0 (MIT),
3
+ * commit f9a26365568127461c47a07a37dcb42c140a3ac5.
4
4
  * Upstream dark.json SHA-256: e1f96982f8cb7d2a48eca7db03c9cb282cb1e14a243680cd855638ecd6a251b6
5
5
  * Upstream light.json SHA-256: 2dee6a4be7f765e7fd7728166b7ebf8c29e4ce313f8ec6b38ae50699e3abc2f3
6
6
  * Modifications: removed upstream schema/export metadata; runtime color data is unchanged.
@@ -1,6 +1,6 @@
1
1
  /**
2
- * Attributed owned theme resources adapted from @earendil-works/pi-coding-agent 1.4.0 (MIT),
3
- * commit 4a080252f06caf63a525d7873c5d94d3c23887e0.
2
+ * Attributed owned theme resources adapted from @earendil-works/pi-coding-agent 1.5.0 (MIT),
3
+ * commit f9a26365568127461c47a07a37dcb42c140a3ac5.
4
4
  * Upstream dark.json SHA-256: e1f96982f8cb7d2a48eca7db03c9cb282cb1e14a243680cd855638ecd6a251b6
5
5
  * Upstream light.json SHA-256: 2dee6a4be7f765e7fd7728166b7ebf8c29e4ce313f8ec6b38ae50699e3abc2f3
6
6
  * Modifications: removed upstream schema/export metadata; runtime color data is unchanged.
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Provenance: @earendil-works/pi-coding-agent 1.4.0 (MIT), commit 4a080252f06caf63a525d7873c5d94d3c23887e0,
2
+ * Provenance: @earendil-works/pi-coding-agent 1.5.0 (MIT), commit f9a26365568127461c47a07a37dcb42c140a3ac5,
3
3
  * packages/coding-agent/src/core/keybindings.ts.
4
4
  * Modifications: Mechanical source port with Node import prefixes, public package-root agent-directory
5
5
  * resolution, and an opt-in bare-A1 input profile including Ctrl+L level cycling, unbound model
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Provenance: @earendil-works/pi-coding-agent 1.4.0 (MIT), commit 4a080252f06caf63a525d7873c5d94d3c23887e0,
2
+ * Provenance: @earendil-works/pi-coding-agent 1.5.0 (MIT), commit f9a26365568127461c47a07a37dcb42c140a3ac5,
3
3
  * packages/coding-agent/src/core/keybindings.ts.
4
4
  * Modifications: Mechanical source port with Node import prefixes, public package-root agent-directory
5
5
  * resolution, and an opt-in bare-A1 input profile including Ctrl+L level cycling, unbound model
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "sourcePackage": "@earendil-works/pi-coding-agent",
3
- "sourceVersion": "1.4.0",
3
+ "sourceVersion": "1.5.0",
4
4
  "upstreamRepository": "https://github.com/earendil-works/pi.git",
5
- "upstreamCommit": "4a080252f06caf63a525d7873c5d94d3c23887e0",
5
+ "upstreamCommit": "f9a26365568127461c47a07a37dcb42c140a3ac5",
6
6
  "sourcePath": "dist/modes/interactive/assets/clankolas.png",
7
7
  "sourceSha256": "169acd0dfe6fbb8d8742ed24a3fc654fd0b2e2d4223c733249c5493723f1b72d",
8
8
  "license": "MIT",
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Provenance: @earendil-works/pi-coding-agent 1.4.0 (MIT), commit 4a080252f06caf63a525d7873c5d94d3c23887e0,
2
+ * Provenance: @earendil-works/pi-coding-agent 1.5.0 (MIT), commit f9a26365568127461c47a07a37dcb42c140a3ac5,
3
3
  * packages/coding-agent/src/modes/interactive/components/countdown-timer.ts.
4
4
  * Modifications: Mechanical source port with ECMAScript private fields; imports remain on the public
5
5
  * Pi TUI package root.
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Provenance: @earendil-works/pi-coding-agent 1.4.0 (MIT), commit 4a080252f06caf63a525d7873c5d94d3c23887e0,
2
+ * Provenance: @earendil-works/pi-coding-agent 1.5.0 (MIT), commit f9a26365568127461c47a07a37dcb42c140a3ac5,
3
3
  * packages/coding-agent/src/modes/interactive/components/earendil-announcement.ts.
4
4
  * Modifications: Mechanical pinned source port with private imports remapped to public package-root
5
5
  * types/APIs and A1-owned theme boundaries. The unchanged image is loaded lazily from its attributed,
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Provenance: @earendil-works/pi-coding-agent 1.4.0 (MIT), commit 4a080252f06caf63a525d7873c5d94d3c23887e0,
2
+ * Provenance: @earendil-works/pi-coding-agent 1.5.0 (MIT), commit f9a26365568127461c47a07a37dcb42c140a3ac5,
3
3
  * packages/coding-agent/src/modes/interactive/components/extension-editor.ts.
4
4
  * Modifications: Mechanical port: remap pi-tui to the root public singleton, use owned
5
5
  * keybindings/theme and external-editor seams, preserve editor layout, hints, focus, submission,
@@ -7,9 +7,9 @@
7
7
  * compact padded modal frame.
8
8
  * Deviations: owned-modal-shortcut-hints.
9
9
  */
10
- import { Container, type TUI } from "@earendil-works/pi-tui";
10
+ import { Container, type Focusable, type TUI } from "@earendil-works/pi-tui";
11
11
  import type { KeybindingsManager } from "../adjacent/core/keybindings.js";
12
- export declare class ExtensionEditorComponent extends Container {
12
+ export declare class ExtensionEditorComponent extends Container implements Focusable {
13
13
  #private;
14
14
  get focused(): boolean;
15
15
  set focused(value: boolean);
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Provenance: @earendil-works/pi-coding-agent 1.4.0 (MIT), commit 4a080252f06caf63a525d7873c5d94d3c23887e0,
2
+ * Provenance: @earendil-works/pi-coding-agent 1.5.0 (MIT), commit f9a26365568127461c47a07a37dcb42c140a3ac5,
3
3
  * packages/coding-agent/src/modes/interactive/components/extension-editor.ts.
4
4
  * Modifications: Mechanical port: remap pi-tui to the root public singleton, use owned
5
5
  * keybindings/theme and external-editor seams, preserve editor layout, hints, focus, submission,
@@ -18,6 +18,7 @@ export class ExtensionEditorComponent extends Container {
18
18
  #keybindings;
19
19
  #externalEditorCommand;
20
20
  #onCancel;
21
+ #externalEditorStatus = new Text("", 0, 0);
21
22
  #focused = false;
22
23
  get focused() {
23
24
  return this.#focused;
@@ -50,6 +51,7 @@ export class ExtensionEditorComponent extends Container {
50
51
  this.#editor.setText(prefill);
51
52
  this.#editor.onSubmit = onSubmit;
52
53
  this.addChild(this.#editor);
54
+ this.addChild(this.#externalEditorStatus);
53
55
  this.addChild(new Spacer(1));
54
56
  const hint = renderPiModalShortcutHints([
55
57
  { key: this.#keybindings.getKeys("tui.select.confirm").join("/"), action: "submit" },
@@ -78,6 +80,7 @@ export class ExtensionEditorComponent extends Container {
78
80
  this.#tui.stop();
79
81
  try {
80
82
  const result = await editInExternalEditor({ command: this.#externalEditorCommand, content });
83
+ this.#externalEditorStatus.setText(result.status === "failed" ? piTheme().fg("warning", result.message) : "");
81
84
  if (result.status === "complete")
82
85
  this.#editor.setText(result.content);
83
86
  }
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Provenance: @earendil-works/pi-coding-agent 1.4.0 (MIT), commit 4a080252f06caf63a525d7873c5d94d3c23887e0,
2
+ * Provenance: @earendil-works/pi-coding-agent 1.5.0 (MIT), commit f9a26365568127461c47a07a37dcb42c140a3ac5,
3
3
  * packages/coding-agent/src/modes/interactive/components/extension-input.ts.
4
4
  * Modifications: Mechanical port: remap public imports, use ECMAScript private fields, and route the
5
5
  * bare-A1 instruction row and chrome through the shared semantic shortcut and compact padded
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Provenance: @earendil-works/pi-coding-agent 1.4.0 (MIT), commit 4a080252f06caf63a525d7873c5d94d3c23887e0,
2
+ * Provenance: @earendil-works/pi-coding-agent 1.5.0 (MIT), commit f9a26365568127461c47a07a37dcb42c140a3ac5,
3
3
  * packages/coding-agent/src/modes/interactive/components/extension-selector.ts.
4
4
  * Modifications: Mechanical port: remap public imports, use ECMAScript private fields, and route the
5
5
  * bare-A1 instruction row and chrome through the shared semantic shortcut and compact padded
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Provenance: @earendil-works/pi-coding-agent 1.4.0 (MIT), commit 4a080252f06caf63a525d7873c5d94d3c23887e0,
2
+ * Provenance: @earendil-works/pi-coding-agent 1.5.0 (MIT), commit f9a26365568127461c47a07a37dcb42c140a3ac5,
3
3
  * packages/coding-agent/src/modes/interactive/components/mermaid.ts.
4
4
  * Modifications: Mechanical pinned source port with private imports remapped to public package-root
5
5
  * types/APIs and A1-owned theme boundaries; behavior remains acceptance-tested.
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Provenance: @earendil-works/pi-coding-agent 1.4.0 (MIT), commit 4a080252f06caf63a525d7873c5d94d3c23887e0,
2
+ * Provenance: @earendil-works/pi-coding-agent 1.5.0 (MIT), commit f9a26365568127461c47a07a37dcb42c140a3ac5,
3
3
  * packages/coding-agent/src/modes/interactive/components/custom-editor.ts.
4
4
  * Modifications: A1-owned class name and synchronized A1 keybinding contract replace the nominal
5
5
  * private upstream keybinding constructor dependency; bare A1 injects the shared Settings/agent input
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Provenance: @earendil-works/pi-coding-agent 1.4.0 (MIT), commit 4a080252f06caf63a525d7873c5d94d3c23887e0,
2
+ * Provenance: @earendil-works/pi-coding-agent 1.5.0 (MIT), commit f9a26365568127461c47a07a37dcb42c140a3ac5,
3
3
  * packages/coding-agent/src/modes/interactive/components/custom-editor.ts.
4
4
  * Modifications: A1-owned class name and synchronized A1 keybinding contract replace the nominal
5
5
  * private upstream keybinding constructor dependency; bare A1 injects the shared Settings/agent input
@@ -108,6 +108,13 @@ export function createOwnedEditorClass(Base) {
108
108
  this.onPromptSuggestionAccepted?.(accepted);
109
109
  return;
110
110
  }
111
+ // Selection page keys move an open autocomplete menu before app actions run.
112
+ // This lets users bind Ctrl+V even though it pastes images by default.
113
+ if (this.isShowingAutocomplete()
114
+ && (this.keybindings.matches(data, "tui.select.pageUp") || this.keybindings.matches(data, "tui.select.pageDown"))) {
115
+ super.handleInput(data);
116
+ return;
117
+ }
111
118
  if (this.keybindings.matches(data, "app.clipboard.pasteImage")) {
112
119
  this.onPasteImage?.();
113
120
  return;
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Provenance: @earendil-works/pi-coding-agent 1.4.0 (MIT), commit 4a080252f06caf63a525d7873c5d94d3c23887e0,
2
+ * Provenance: @earendil-works/pi-coding-agent 1.5.0 (MIT), commit f9a26365568127461c47a07a37dcb42c140a3ac5,
3
3
  * packages/coding-agent/src/modes/interactive/components/pi-logo.ts.
4
4
  * Modifications: Remapped the private theme import to A1's public-backed adapter and composed the
5
5
  * fixed-color logo into the owned startup header.
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Provenance: @earendil-works/pi-coding-agent 1.4.0 (MIT), commit 4a080252f06caf63a525d7873c5d94d3c23887e0,
2
+ * Provenance: @earendil-works/pi-coding-agent 1.5.0 (MIT), commit f9a26365568127461c47a07a37dcb42c140a3ac5,
3
3
  * packages/coding-agent/src/modes/interactive/components/scoped-models-selector.ts.
4
4
  * Modifications: Source-synchronized scoped-model selector port: preserve session-only toggles,
5
5
  * search, bulk/provider/reorder actions, dirty state, Ctrl+S persistence, refresh status,
@@ -32,6 +32,7 @@ export interface ModelsCallbacks {
32
32
  * Changes are session-only until explicitly persisted with Ctrl+S.
33
33
  */
34
34
  export declare class ScopedModelsSelectorComponent extends Container implements Focusable {
35
+ readonly capturesViewportInput: boolean;
35
36
  private modelsById;
36
37
  private allIds;
37
38
  private enabledIds;
@@ -1,6 +1,6 @@
1
- import { Container, fuzzyFilter, getKeybindings, Input, Spacer, Text, } from "@earendil-works/pi-tui";
1
+ import { Container, fuzzyFilter, getKeybindings, getSelectPageIndex, Input, Spacer, Text, } from "@earendil-works/pi-tui";
2
2
  import { DynamicBorder } from "../../../startup-public.js";
3
- import { getModelSearchText } from "../model-search.js";
3
+ import { getDistinctModelName, getModelSearchText } from "../model-search.js";
4
4
  import { addPiModalHeader, addPiModalSearchInput, adoptPiModalFrame } from "../../modal-frame.js";
5
5
  import { DIALOG_CLOSE_SHORTCUT_HINT, paintPiBorder, piTheme, renderPiModalShortcutHints } from "../../theme.js";
6
6
  // Rationale: upstream's capitalized hint formatter is private to the package; the same mapping lives here.
@@ -79,6 +79,7 @@ function getSortedIds(enabledIds, allIds) {
79
79
  * Changes are session-only until explicitly persisted with Ctrl+S.
80
80
  */
81
81
  export class ScopedModelsSelectorComponent extends Container {
82
+ capturesViewportInput = true;
82
83
  modelsById = new Map();
83
84
  allIds = [];
84
85
  enabledIds = null;
@@ -217,9 +218,11 @@ export class ScopedModelsSelectorComponent extends Container {
217
218
  const id = item.model?.id ?? item.fullId;
218
219
  const styledId = item.model ? id : theme.strikethrough(id);
219
220
  const modelText = isSelected ? theme.fg("accent", styledId) : styledId;
221
+ const name = item.model ? getDistinctModelName(item.model) : undefined;
222
+ const nameText = name ? theme.fg("muted", ` (${name})`) : "";
220
223
  const providerBadge = theme.fg("muted", item.model ? ` [${item.model.provider}]` : " [unavailable]");
221
224
  const status = item.model && item.enabled ? theme.fg("accent", "✓ ") : " ";
222
- this.listContainer.addChild(new Text(`${prefix}${status}${modelText}${providerBadge}`, 0, 0));
225
+ this.listContainer.addChild(new Text(`${prefix}${status}${modelText}${nameText}${providerBadge}`, 0, 0));
223
226
  }
224
227
  // Add scroll indicator if needed
225
228
  if (startIndex > 0 || endIndex < this.filteredItems.length) {
@@ -248,6 +251,14 @@ export class ScopedModelsSelectorComponent extends Container {
248
251
  this.updateList();
249
252
  return;
250
253
  }
254
+ const pageIndex = getSelectPageIndex(kb, data, this.selectedIndex, this.filteredItems.length, this.maxVisible);
255
+ if (pageIndex !== undefined) {
256
+ if (this.filteredItems.length === 0)
257
+ return;
258
+ this.selectedIndex = pageIndex;
259
+ this.updateList();
260
+ return;
261
+ }
251
262
  // Reorder enabled models
252
263
  const reorderUp = kb.matches(data, "app.models.reorderUp");
253
264
  const reorderDown = kb.matches(data, "app.models.reorderDown");
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Provenance: @earendil-works/pi-coding-agent 1.4.0 (MIT), commit 4a080252f06caf63a525d7873c5d94d3c23887e0,
2
+ * Provenance: @earendil-works/pi-coding-agent 1.5.0 (MIT), commit f9a26365568127461c47a07a37dcb42c140a3ac5,
3
3
  * packages/coding-agent/src/modes/interactive/components/footer.ts.
4
4
  * Modifications: Owned UI/routing; A1 level color, linked PRs, resident names, dim ellipsis and model
5
5
  * priority; Pi unchanged.
@@ -18,5 +18,9 @@ export interface MatchResult {
18
18
  }
19
19
  export declare function hasSessionName(session: SessionInfo): boolean;
20
20
  export declare function parseSearchQuery(query: string): ParsedSearchQuery;
21
+ /**
22
+ * Each field is matched separately, so a token never matches across field boundaries.
23
+ * Different tokens may match different fields.
24
+ */
21
25
  export declare function matchSession(session: SessionInfo, parsed: ParsedSearchQuery): MatchResult;
22
26
  export declare function filterAndSortSessions(sessions: SessionInfo[], query: string, sortMode: SortMode, nameFilter?: NameFilter): SessionInfo[];