@danypops/pi-lector 0.9.5 → 0.10.0

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 (42) hide show
  1. package/extension/src/{apply-patch-operations.ts → apply-patch/operations.ts} +3 -3
  2. package/extension/src/{apply-patch-rendering.ts → apply-patch/rendering.ts} +1 -1
  3. package/extension/src/{code-intelligence-operations.ts → code-intelligence/operations.ts} +2 -2
  4. package/extension/src/{code-intelligence-rendering.ts → code-intelligence/rendering.ts} +1 -1
  5. package/extension/src/cross-workspace-search/operations.ts +88 -0
  6. package/extension/src/{cross-workspace-search-rendering.ts → cross-workspace-search/rendering.ts} +37 -13
  7. package/extension/src/{edit-operations.ts → edit/operations.ts} +2 -2
  8. package/extension/src/editor/editor-state.ts +317 -0
  9. package/extension/src/editor/neovim-editor-component.ts +199 -0
  10. package/extension/src/editor/operations.ts +36 -0
  11. package/extension/src/{external-search-operations.ts → external-search/operations.ts} +1 -1
  12. package/extension/src/{external-search-rendering.ts → external-search/rendering.ts} +1 -1
  13. package/extension/src/{find-files-operations.ts → find-files/operations.ts} +1 -1
  14. package/extension/src/{find-files-rendering.ts → find-files/rendering.ts} +1 -1
  15. package/extension/src/{find-symbols-operations.ts → find-symbols/operations.ts} +1 -1
  16. package/extension/src/{find-symbols-rendering.ts → find-symbols/rendering.ts} +1 -1
  17. package/extension/src/{git-operations.ts → git/operations.ts} +1 -1
  18. package/extension/src/{git-rendering.ts → git/rendering.ts} +1 -1
  19. package/extension/src/index.ts +76 -39
  20. package/extension/src/lector-client.ts +25 -0
  21. package/extension/src/{line-edit-operations.ts → line-edit/operations.ts} +4 -4
  22. package/extension/src/{line-edit-rendering.ts → line-edit/rendering.ts} +1 -1
  23. package/extension/src/{mutation-history-operations.ts → mutation-history/operations.ts} +2 -2
  24. package/extension/src/{package-source-operations.ts → package-source/operations.ts} +1 -1
  25. package/extension/src/{package-source-rendering.ts → package-source/rendering.ts} +35 -28
  26. package/extension/src/{read-operations.ts → read/operations.ts} +2 -2
  27. package/extension/src/{reference-based-rename-operations.ts → reference-based-rename/operations.ts} +1 -1
  28. package/extension/src/{rename-operations.ts → rename/operations.ts} +1 -1
  29. package/extension/src/{repo-cache-evict-operations.ts → repo-cache/evict-operations.ts} +2 -2
  30. package/extension/src/{repo-cache-list-operations.ts → repo-cache/list-operations.ts} +2 -2
  31. package/extension/src/{repo-cache-rendering.ts → repo-cache/rendering.ts} +1 -1
  32. package/extension/src/{repo-fetch-operations.ts → repo-fetch/operations.ts} +1 -1
  33. package/extension/src/{search-operations.ts → search/operations.ts} +1 -1
  34. package/extension/src/{search-rendering.ts → search/rendering.ts} +1 -1
  35. package/extension/src/{symbol-annotation-operations.ts → symbol-annotation/operations.ts} +1 -1
  36. package/extension/src/{symbol-annotation-rendering.ts → symbol-annotation/rendering.ts} +1 -1
  37. package/extension/src/{workspace-cache-operations.ts → workspace-cache/operations.ts} +1 -1
  38. package/extension/src/{workspace-cache-rendering.ts → workspace-cache/rendering.ts} +1 -1
  39. package/extension/src/{write-operations.ts → write/operations.ts} +2 -2
  40. package/package.json +2 -2
  41. package/extension/src/cross-workspace-search-operations.ts +0 -43
  42. /package/extension/src/{code-intelligence-hints.ts → code-intelligence/hints.ts} +0 -0
@@ -1,7 +1,7 @@
1
1
  import type { PackageSourceListEntry, PackageSourceOperationResult } from "@danypops/lector";
2
2
  import { keyHint } from "@earendil-works/pi-coding-agent";
3
3
  import { renderTruncatedList, type TableColumn } from "malevich-tui-components";
4
- import type { LectorTheme } from "./lector-tui-theme.ts";
4
+ import type { LectorTheme } from "../lector-tui-theme.ts";
5
5
 
6
6
  const DEFAULT_VISIBLE_CANDIDATES = 5;
7
7
 
@@ -36,33 +36,40 @@ export function formatPackageSourceCall(
36
36
  export function formatPackageSourceResult(result: PackageSourceOperationResult | undefined, expanded: boolean, theme: LectorTheme): string {
37
37
  if (!result) return theme.fg("dim", "No package-source result.");
38
38
  const { outcome } = result;
39
- if (outcome.status === "verified") {
40
- return [
41
- `${theme.fg("accent", result.workspaceId ?? "unregistered")} ${theme.fg("success", `${outcome.coordinate.name}@${outcome.coordinate.resolvedVersion}`)}`,
42
- `${outcome.workspace.cachePath}`,
43
- `${outcome.repository.url ?? "local source"}@${outcome.repository.resolvedRef ?? "local"} ${outcome.repository.commit ?? outcome.verification.integrity}`,
44
- ].join("\n");
39
+ switch (outcome.status) {
40
+ case "verified":
41
+ return [
42
+ `${theme.fg("accent", result.workspaceId ?? "unregistered")} ${theme.fg("success", `${outcome.coordinate.name}@${outcome.coordinate.resolvedVersion}`)}`,
43
+ `${outcome.workspace.cachePath}`,
44
+ `${outcome.repository.url ?? "local source"}@${outcome.repository.resolvedRef ?? "local"} ${outcome.repository.commit ?? outcome.verification.integrity}`,
45
+ ].join("\n");
46
+ case "ambiguous": {
47
+ const lines = [
48
+ theme.fg("warning", `Ambiguous package source (${outcome.code})`),
49
+ ...renderTruncatedList({
50
+ items: outcome.candidates,
51
+ expanded,
52
+ visibleCount: DEFAULT_VISIBLE_CANDIDATES,
53
+ formatItem: (candidate) => `${candidate.version} -- ${candidate.source}`,
54
+ moreLine: (hidden) => theme.fg("dim", `… ${hidden} more`),
55
+ truncationWarning: outcome.truncated ? theme.fg("dim", "More candidates were truncated by the daemon.") : undefined,
56
+ }),
57
+ ];
58
+ return lines.join("\n");
59
+ }
60
+ case "unauthenticated":
61
+ return theme.fg("warning", `Authentication required (${outcome.code}): configure ${outcome.requiredCredentialNames.join(", ")}`);
62
+ case "oversized":
63
+ return theme.fg("warning", `Source resolution exceeded ${outcome.resource} limit ${outcome.limit}.`);
64
+ case "mismatched":
65
+ return theme.fg("error", `Source mismatch (${outcome.code}): expected ${outcome.expected}, got ${outcome.actual}.`);
66
+ case "unavailable":
67
+ return theme.fg("warning", `Source unavailable (${outcome.code}).`);
68
+ default: {
69
+ const exhaustive: never = outcome;
70
+ throw new Error(`unhandled package source outcome status: ${JSON.stringify(exhaustive)}`);
71
+ }
45
72
  }
46
- if (outcome.status === "ambiguous") {
47
- const lines = [
48
- theme.fg("warning", `Ambiguous package source (${outcome.code})`),
49
- ...renderTruncatedList({
50
- items: outcome.candidates,
51
- expanded,
52
- visibleCount: DEFAULT_VISIBLE_CANDIDATES,
53
- formatItem: (candidate) => `${candidate.version} -- ${candidate.source}`,
54
- moreLine: (hidden) => theme.fg("dim", `… ${hidden} more`),
55
- truncationWarning: outcome.truncated ? theme.fg("dim", "More candidates were truncated by the daemon.") : undefined,
56
- }),
57
- ];
58
- return lines.join("\n");
59
- }
60
- if (outcome.status === "unauthenticated") {
61
- return theme.fg("warning", `Authentication required (${outcome.code}): configure ${outcome.requiredCredentialNames.join(", ")}`);
62
- }
63
- if (outcome.status === "oversized") return theme.fg("warning", `Source resolution exceeded ${outcome.resource} limit ${outcome.limit}.`);
64
- if (outcome.status === "mismatched") return theme.fg("error", `Source mismatch (${outcome.code}): expected ${outcome.expected}, got ${outcome.actual}.`);
65
- return theme.fg("warning", `Source unavailable (${outcome.code}).`);
66
73
  }
67
74
 
68
75
  /** Empty-state fallback only -- a non-empty page renders as a real Table (see buildPackageSourceListTableRows) so the human channel actually shows what's resolved, not just a bare count. Mirrors formatRepoCacheListResult. */
@@ -74,7 +81,7 @@ export function formatPackageSourceListResult(
74
81
  return count === 0 ? theme.fg("dim", "no resolved package sources") : theme.fg("success", `${count} resolved package source${count === 1 ? "" : "s"}`);
75
82
  }
76
83
 
77
- /** Powers of 1024, one decimal past the first. Mirrors repo-cache-rendering.ts's own formatCacheSize -- kept as a small local duplicate rather than a shared export, matching that file's own precedent. */
84
+ /** Powers of 1024, one decimal past the first. Mirrors repo-cache/rendering.ts's own formatCacheSize -- kept as a small local duplicate rather than a shared export, matching that file's own precedent. */
78
85
  function formatCacheSize(bytes: number): string {
79
86
  const units = ["B", "KB", "MB", "GB", "TB"] as const;
80
87
  let value = bytes;
@@ -1,8 +1,8 @@
1
1
  import { constants } from "node:fs";
2
2
  import { access as fsAccess, readFile as fsReadFile } from "node:fs/promises";
3
3
  import type { ReadOperations } from "@earendil-works/pi-coding-agent";
4
- import { lectorClient, withWorkspace, workspaceForPath } from "./lector-client.ts";
5
- import { toWorkspaceRelativePath } from "./workspace-relative-path.ts";
4
+ import { lectorClient, withWorkspace, workspaceForPath } from "../lector-client.ts";
5
+ import { toWorkspaceRelativePath } from "../workspace-relative-path.ts";
6
6
 
7
7
  /**
8
8
  * Lector's core domain (RawRead/ExpectedHashEdit) is deliberately text-only
@@ -1,5 +1,5 @@
1
1
  import type { OperationOutputs } from "@danypops/lector";
2
- import { lectorClient, withWorkspace, workspaceForCodeIntelligencePath } from "./lector-client.ts";
2
+ import { lectorClient, withWorkspace, workspaceForCodeIntelligencePath } from "../lector-client.ts";
3
3
 
4
4
  /**
5
5
  * Thin wrapper over Lector's non-LSP reference-based rename: moves a file and rewrites every
@@ -1,5 +1,5 @@
1
1
  import type { OperationOutputs } from "@danypops/lector";
2
- import { lectorClient, withWorkspace, workspaceForCodeIntelligencePath } from "./lector-client.ts";
2
+ import { lectorClient, withWorkspace, workspaceForCodeIntelligencePath } from "../lector-client.ts";
3
3
 
4
4
  /**
5
5
  * Thin wrappers over Lector's LSP-driven prepareRename/rename -- position-based (path + 1-indexed
@@ -1,8 +1,8 @@
1
- import { lectorClient } from "./lector-client.ts";
1
+ import { lectorClient } from "../lector-client.ts";
2
2
 
3
3
  /**
4
4
  * Thin wrapper over repo.evictCache -- no `directory`/workspaceForDirectory resolution (matching
5
- * repo-fetch-operations.ts and repo-cache-list-operations.ts: this targets the daemon-wide fetch
5
+ * repo-fetch/operations.ts and repo-cache/list-operations.ts: this targets the daemon-wide fetch
6
6
  * cache, not a workspace-scoped concept).
7
7
  */
8
8
  export interface RepoCacheEvictOperations {
@@ -1,9 +1,9 @@
1
1
  import type { CachedRepositoryPage } from "@danypops/lector";
2
- import { lectorClient } from "./lector-client.ts";
2
+ import { lectorClient } from "../lector-client.ts";
3
3
 
4
4
  /**
5
5
  * Thin wrapper over repo.listCache -- no network, no cache mutation, no `directory`/
6
- * workspaceForDirectory resolution (matching repo-fetch-operations.ts: this queries the
6
+ * workspaceForDirectory resolution (matching repo-fetch/operations.ts: this queries the
7
7
  * daemon-wide fetch cache, not a workspace-scoped concept).
8
8
  */
9
9
  export interface RepoCacheListOperations {
@@ -1,7 +1,7 @@
1
1
  import type { CachedRepositoryEntry, CachedRepositoryPage, RepoFetchResult } from "@danypops/lector";
2
2
  import { keyHint } from "@earendil-works/pi-coding-agent";
3
3
  import type { TableColumn } from "malevich-tui-components";
4
- import type { LectorTheme } from "./lector-tui-theme.ts";
4
+ import type { LectorTheme } from "../lector-tui-theme.ts";
5
5
 
6
6
  /** Table has no row-count bound of its own; a cache can grow arbitrarily large even though repo_cache's own `maxResults` bounds any one page, so the display itself still needs a cap independent of that. */
7
7
  export const REPO_CACHE_VISIBLE_ROWS = 20;
@@ -1,5 +1,5 @@
1
1
  import type { RepoFetchResult } from "@danypops/lector";
2
- import { lectorClient } from "./lector-client.ts";
2
+ import { lectorClient } from "../lector-client.ts";
3
3
 
4
4
  /**
5
5
  * Thin wrapper over repo.fetch. No `directory`/workspaceForDirectory resolution here -- unlike
@@ -1,5 +1,5 @@
1
1
  import type { TextSearchResult } from "@danypops/lector";
2
- import { lectorClient, withWorkspace, workspaceForDirectory } from "./lector-client.ts";
2
+ import { lectorClient, withWorkspace, workspaceForDirectory } from "../lector-client.ts";
3
3
 
4
4
  /**
5
5
  * Thin wrapper over workspace.searchText. `directory` is required, same convention as
@@ -1,7 +1,7 @@
1
1
  import type { TextSearchResult } from "@danypops/lector";
2
2
  import { keyHint } from "@earendil-works/pi-coding-agent";
3
3
  import { renderTruncatedList } from "malevich-tui-components";
4
- import type { LectorTheme } from "./lector-tui-theme.ts";
4
+ import type { LectorTheme } from "../lector-tui-theme.ts";
5
5
 
6
6
  const DEFAULT_VISIBLE_MATCHES = 20;
7
7
 
@@ -1,5 +1,5 @@
1
1
  import type { OperationInputs, OperationOutputs } from "@danypops/lector";
2
- import { lectorClient, withWorkspace, workspaceForCodeIntelligencePath } from "./lector-client.ts";
2
+ import { lectorClient, withWorkspace, workspaceForCodeIntelligencePath } from "../lector-client.ts";
3
3
 
4
4
  /** A bare symbol position an anchor is given as -- symbolNodeId and the anchor's baseline file hash are derived server-side, never supplied by the caller. */
5
5
  export interface AnnotationAnchorInput {
@@ -1,5 +1,5 @@
1
1
  import type { SymbolAnnotation } from "@danypops/lector";
2
- import type { LectorTheme } from "./lector-tui-theme.ts";
2
+ import type { LectorTheme } from "../lector-tui-theme.ts";
3
3
 
4
4
  const STATUS_COLOR: Record<SymbolAnnotation["status"], "success" | "warning" | "dim"> = {
5
5
  fresh: "success",
@@ -1,5 +1,5 @@
1
1
  import type { JobSnapshot, PopulateSymbolGraphResult, WorkspaceCacheStatus } from "@danypops/lector";
2
- import { lectorClient, withWorkspace, workspaceForDirectory } from "./lector-client.ts";
2
+ import { lectorClient, withWorkspace, workspaceForDirectory } from "../lector-client.ts";
3
3
 
4
4
  export interface WorkspaceCacheOperations {
5
5
  status(directory: string, maxFiles: number, maxSymbolsPerFile: number): Promise<WorkspaceCacheStatus>;
@@ -1,5 +1,5 @@
1
1
  import type { JobSnapshot, PopulateSymbolGraphResult, WorkspaceCacheStatus } from "@danypops/lector";
2
- import type { LectorTheme } from "./lector-tui-theme.ts";
2
+ import type { LectorTheme } from "../lector-tui-theme.ts";
3
3
 
4
4
  type WorkspaceCacheAction = "status" | "populate" | "job_status";
5
5
 
@@ -1,7 +1,7 @@
1
1
  import { type ContentHash, remoteErrorIs } from "@danypops/lector";
2
2
  import type { WriteOperations } from "@earendil-works/pi-coding-agent";
3
- import { lectorClient, withWorkspace, workspaceForPath } from "./lector-client.ts";
4
- import { toWorkspaceRelativePath } from "./workspace-relative-path.ts";
3
+ import { lectorClient, withWorkspace, workspaceForPath } from "../lector-client.ts";
4
+ import { toWorkspaceRelativePath } from "../workspace-relative-path.ts";
5
5
 
6
6
  const MAX_STALE_HASH_RETRIES = 3;
7
7
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@danypops/pi-lector",
3
- "version": "0.9.5",
3
+ "version": "0.10.0",
4
4
  "description": "Pi host adapter for Lector: overrides read/write/edit with a daemon-backed, hash-guarded filesystem",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -19,7 +19,7 @@
19
19
  },
20
20
  "dependencies": {
21
21
  "@danypops/vehicle-client": "^0.2.0",
22
- "@danypops/lector": "^0.12.0",
22
+ "@danypops/lector": "^0.14.0",
23
23
  "malevich-tui-components": "^0.19.0"
24
24
  },
25
25
  "devDependencies": {
@@ -1,43 +0,0 @@
1
- import type { SymbolSearchResult, TextSearchResult, WorkspaceQueryOutcome } from "@danypops/lector";
2
- import { lectorClient, workspaceForDirectory } from "./lector-client.ts";
3
-
4
- /**
5
- * Fans out across explicitly-named directories only -- never the daemon's own "every registered
6
- * workspace" default. Lector's daemon is a shared, system-wide service: leaving workspaceIds
7
- * unset would search every project any other concurrent Pi session has ever registered against
8
- * it, not just this session's own (confirmed live, not assumed -- a real fetched jittor workspace
9
- * from an unrelated session showed up in an early test of this exact feature). `directories` is
10
- * required, same "no implicit fallback" convention as find_symbols/search_code.
11
- */
12
- export interface CrossWorkspaceSearchOperations {
13
- findSymbols(query: string, directories: readonly string[], timeoutMs?: number): Promise<readonly WorkspaceQueryOutcome<SymbolSearchResult>[]>;
14
- searchText(
15
- query: string,
16
- directories: readonly string[],
17
- maxMatches: number,
18
- maxBytes: number,
19
- timeoutMs?: number,
20
- ): Promise<readonly WorkspaceQueryOutcome<TextSearchResult>[]>;
21
- }
22
-
23
- async function resolveWorkspaceIds(directories: readonly string[]): Promise<readonly string[]> {
24
- const resolved = await Promise.all(directories.map((directory) => workspaceForDirectory(directory)));
25
- return resolved.map((r) => r.workspaceId);
26
- }
27
-
28
- export function createLectorCrossWorkspaceSearchOperations(): CrossWorkspaceSearchOperations {
29
- return {
30
- async findSymbols(query, directories, timeoutMs) {
31
- const workspaceIds = await resolveWorkspaceIds(directories);
32
- const client = await lectorClient();
33
- const { results } = await client.call("search.symbols", { query, workspaceIds, timeoutMs });
34
- return results;
35
- },
36
- async searchText(query, directories, maxMatches, maxBytes, timeoutMs) {
37
- const workspaceIds = await resolveWorkspaceIds(directories);
38
- const client = await lectorClient();
39
- const { results } = await client.call("search.text", { query, maxMatches, maxBytes, workspaceIds, timeoutMs });
40
- return results;
41
- },
42
- };
43
- }