pi.lock 0.0.0-stage → 0.1.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 (49) hide show
  1. package/README.md +183 -2
  2. package/dist/bridge.d.ts +7 -0
  3. package/dist/bridge.js +18 -0
  4. package/dist/bridge.js.map +1 -0
  5. package/dist/cli.d.ts +2 -0
  6. package/dist/cli.js +82 -0
  7. package/dist/cli.js.map +1 -0
  8. package/dist/commands.d.ts +1 -0
  9. package/dist/commands.js +114 -0
  10. package/dist/commands.js.map +1 -0
  11. package/dist/common.d.ts +17 -0
  12. package/dist/common.js +87 -0
  13. package/dist/common.js.map +1 -0
  14. package/dist/definition.d.ts +32 -0
  15. package/dist/definition.js +379 -0
  16. package/dist/definition.js.map +1 -0
  17. package/dist/index.d.ts +5 -0
  18. package/dist/index.js +5 -0
  19. package/dist/index.js.map +1 -0
  20. package/dist/init.d.ts +6 -0
  21. package/dist/init.js +39 -0
  22. package/dist/init.js.map +1 -0
  23. package/dist/loader.d.ts +48 -0
  24. package/dist/loader.js +141 -0
  25. package/dist/loader.js.map +1 -0
  26. package/dist/lock.d.ts +17 -0
  27. package/dist/lock.js +92 -0
  28. package/dist/lock.js.map +1 -0
  29. package/dist/mcp.d.ts +8 -0
  30. package/dist/mcp.js +113 -0
  31. package/dist/mcp.js.map +1 -0
  32. package/dist/model.d.ts +14 -0
  33. package/dist/model.js +74 -0
  34. package/dist/model.js.map +1 -0
  35. package/dist/runtime.d.ts +37 -0
  36. package/dist/runtime.js +258 -0
  37. package/dist/runtime.js.map +1 -0
  38. package/docs/acceptance.md +54 -0
  39. package/docs/acceptance.tap +178 -0
  40. package/docs/architecture.md +47 -0
  41. package/examples/demo/.pi/SYSTEM.md +1 -0
  42. package/examples/demo/.pi/extensions/demo.ts +13 -0
  43. package/examples/demo/.pi/models.json +26 -0
  44. package/examples/demo/.pi/prompts/hello.md +4 -0
  45. package/examples/demo/.pi/settings.json +15 -0
  46. package/examples/demo/.pi/skills/explain/SKILL.md +5 -0
  47. package/examples/demo/pi.lock +473 -0
  48. package/npm-shrinkwrap.json +1880 -0
  49. package/package.json +46 -4
package/README.md CHANGED
@@ -1,3 +1,184 @@
1
- # Temporary Holding Version
1
+ # pi.lock
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ Use the same Pi agent from a local terminal, RPC, or the SDK with the same configuration, instructions, skills, extensions, and tools. Deploy and roll it back with Git.
4
+
5
+ Supported Pi version: **1.3.0** (verified as the npm `latest` release on 2026-10-18). Requires Node.js **22.19.0+**.
6
+
7
+ pi.lock uses Pi's native `.pi/settings.json`, `SYSTEM.md`, `extensions/`, `skills/`, `prompts/`, TUI, and RPC protocol. The main addition is `pi-lock lock`, which captures a tuned agent. Use the project-local `pi-lock` command in place of `pi`; import `createAgentSession` from `pi.lock` in the SDK.
8
+
9
+ ## Name and package
10
+
11
+ The project is named **pi.lock**. One npm package provides both its CLI and SDK:
12
+
13
+ | Purpose | Name |
14
+ |---|---|
15
+ | Project name | pi.lock |
16
+ | Agent lockfile | `pi.lock` |
17
+ | npm package and SDK import | `pi.lock` |
18
+ | CLI command | `pi-lock` |
19
+ | Local snapshots, credentials, and sessions | `.pi-lock/` (excluded from Git) |
20
+
21
+ The current version is `0.1.0`. Install the published package with `npm install pi.lock`. The CLI command remains `pi-lock`.
22
+
23
+ ## Try it without an API key
24
+
25
+ Run these commands from the source checkout:
26
+
27
+ ```sh
28
+ npm ci
29
+ npm run build
30
+ node dist/cli.js --project examples/demo lock
31
+ node dist/cli.js --project examples/demo -p /hello
32
+ node dist/cli.js --project examples/demo
33
+ ```
34
+
35
+ The last command opens Pi's native TUI. The demo uses a deterministic local provider and an echo tool; it makes no model-service requests. It also includes a skill and a `/hello` prompt template.
36
+
37
+ ## Use it in your project
38
+
39
+ Install the npm package as a project dependency:
40
+
41
+ ```sh
42
+ npm install pi.lock
43
+ npx --no-install pi-lock init --provider deepseek --model deepseek-chat
44
+ ```
45
+
46
+ If your project already has `.pi/settings.json`, keep it and skip `init`.
47
+
48
+ Set the API-key environment variable for your provider. For example, DeepSeek uses `DEEPSEEK_API_KEY`. After changing `.pi/SYSTEM.md`, skills, or extensions, tune the agent in development mode:
49
+
50
+ ```sh
51
+ npx --no-install pi-lock --dev
52
+ ```
53
+
54
+ Development mode supports Pi's `/model`, `/settings`, and `/reload` commands. Behavior settings are written to this agent's `.pi/settings.json`. Restart the development session after changing provider definitions.
55
+
56
+ When you are done tuning, lock the agent and run it in the default frozen mode:
57
+
58
+ ```sh
59
+ npx --no-install pi-lock lock
60
+ npx --no-install pi-lock
61
+ npx --no-install pi-lock -p "Help me with this task"
62
+ npx --no-install pi-lock --mode rpc
63
+ ```
64
+
65
+ Frozen mode is the default. Changes to files, missing dependencies, model changes, and tool-schema differences produce explicit errors. The runtime does not supplement resources from global configuration, switch models, or update dependencies automatically. Use `--dev` to make changes, then run `lock` again.
66
+
67
+ ## SDK: the same agent
68
+
69
+ ```ts
70
+ import { createAgentSession } from "pi.lock";
71
+
72
+ const agent = await createAgentSession({
73
+ projectRoot: "/app/my-agent", // Contains .pi/ and pi.lock
74
+ cwd: "/data/current-task", // Working directory for the agent's task
75
+ apiKey: process.env.DEEPSEEK_API_KEY,
76
+ });
77
+
78
+ try {
79
+ await agent.session.prompt("Help me with this task");
80
+ console.log(agent.session.getLastAssistantText());
81
+ console.log(agent.agentDigest);
82
+ } finally {
83
+ await agent.dispose();
84
+ }
85
+ ```
86
+
87
+ When run from the agent project directory, you can omit both `projectRoot` and `cwd`. `projectRoot` selects the agent definition; `cwd` selects the task data location. Instructions and `.pi` configuration in the working directory or its parents are not merged into an explicitly selected agent.
88
+
89
+ The returned `session` is Pi's `AgentSession`, with native streaming events, cancellation, and history support. `agent.runtime` provides `newSession()`, `fork()`, and `switchSession()`. After replacing a session, read the current session through `agent.session` and subscribe to its events again. `agent.dispose()` runs extension cleanup and releases the session.
90
+
91
+ To manage history yourself, pass Pi's native `SessionManager`:
92
+
93
+ ```ts
94
+ import { createAgentSession, SessionManager } from "pi.lock";
95
+
96
+ const agent = await createAgentSession({
97
+ projectRoot: "/app/my-agent",
98
+ cwd: "/data/current-task",
99
+ sessionManager: SessionManager.inMemory("/data/current-task"),
100
+ });
101
+ ```
102
+
103
+ The SDK also accepts `credentials` (Pi's native `CredentialStore`), `env` (named credential bindings), `uiContext`, `sessionFile`, and `sessionDir`. Model, tool, and resource configuration lives in `.pi`; the SDK does not have a second configuration surface. Unsupported behavior overrides return an error.
104
+
105
+ ## Project files and local state
106
+
107
+ ```text
108
+ my-agent/
109
+ ├── .pi/
110
+ │ ├── settings.json
111
+ │ ├── SYSTEM.md
112
+ │ ├── models.json # Optional: native Pi custom-provider definitions
113
+ │ ├── mcp.json # Optional: native Pi MCP configuration
114
+ │ ├── extensions/
115
+ │ ├── skills/
116
+ │ └── prompts/
117
+ ├── pi.lock # Commit to Git
118
+ ├── package.json # Commit when using npm dependencies
119
+ ├── package-lock.json # Commit when using npm dependencies
120
+ └── .pi-lock/ # Created automatically; excluded from Git
121
+ ├── releases/<digest>/ # Immutable code and resource snapshots
122
+ └── state/ # Local sessions, TUI state, and CLI credentials
123
+ ```
124
+
125
+ The project root's `AGENTS.md` or `AGENTS.override.md` and project-local `.agents/skills/` are included in the lock. Parent directories, `~/.pi`, and `~/.agents` are not searched.
126
+
127
+ `pi.lock` records the resource inventory and load order, file hashes, npm dependency versions and integrity, model metadata, tool schemas, the initialized configuration fingerprint, and fingerprints for the Pi/pi-lock runtime code. Managed paths are relative to the project root.
128
+
129
+ The CLI's `/login` stores credentials in `.pi-lock/state/auth.json`. SDK applications can inject their own credential store. Credentials and sessions are not written to the lockfile. Do not copy a user-level `auth.json`, `models-store.json`, or entire sessions directory into `.pi`.
130
+
131
+ ## Deployment and rollback
132
+
133
+ Commit `.pi/`, `pi.lock`, and the npm manifests and lockfiles you use. A recommended approach is to deploy each Git commit into its own directory:
134
+
135
+ ```sh
136
+ npm ci
137
+ npx --no-install pi-lock sync --frozen
138
+ npx --no-install pi-lock verify
139
+ ```
140
+
141
+ You do not need `npm ci` if the agent has no additional npm dependencies. `sync --frozen` restores npm-locked dependencies in the project root and `.pi/npm/`, then verifies the agent without rewriting `pi.lock`.
142
+
143
+ To roll back, restore the earlier Git commit and the matching pi-lock npm package version, then start that runtime. New sessions use that version. Older sessions carry their own `agentDigest` and are explicitly rejected if the version does not match. A running runtime continues to use its own snapshot, so a Git checkout change cannot mix another version's skills into it.
144
+
145
+ Keep each release's dependency packages or a reproducible source for them. A lockfile cannot recover a package that has been removed from its remote source. Local npm tarballs must also be stored and committed within the project.
146
+
147
+ Inspect the current lock:
148
+
149
+ ```sh
150
+ npx --no-install pi-lock inspect
151
+ ```
152
+
153
+ ## Extensions, npm packages, and MCP
154
+
155
+ The standard Pi TypeScript/JavaScript extension API remains unchanged. Relative helper imports for local extensions are included in the snapshot. Install external npm dependencies in the current project and pin them with an npm lockfile. Pi host packages and TypeBox use the same host instance instead of being duplicated. TypeScript compilation caches are disabled, and path mappings from another project's `tsconfig` are not read.
156
+
157
+ Use the `packages` declaration in `.pi/settings.json` to load local resource packages, packages in the project's `node_modules`, or packages installed by `pi install -l` into `.pi/npm/node_modules`. Pi package manifests, globs, and resource filters are supported. If you specify a version, it must match the exact installed version; you can also omit the version and let `pi.lock` record the installed version.
158
+
159
+ Vendor Git-based resource packages into the project or distribute them as npm packages pinned by integrity. The first release does not manage Pi's remote Git package installer. External symlinks, global npm packages, and API keys generated by shell commands are not part of frozen execution.
160
+
161
+ MCP uses `mcpServers` from `.pi/mcp.json`. It supports stdio and Streamable HTTP, with direct, codemode, deferred, and hidden tool exposure. Tool-call adaptation, codemode, and `tool_search` use Pi 1.3.0 implementations. Server instructions, capabilities, and tool schemas are recorded at lock time and checked at startup and when making requests.
162
+
163
+ Stdio MCP servers must use `node` or a project-relative executable; relative script paths in their configuration are included in the snapshot. Put any additional runner in the project dependencies. HTTP authentication uses explicit `${VARIABLE}` bindings. The first release does not read global MCP OAuth credentials automatically. A stdio child process receives only the configured environment variables and the Node executable's PATH; it does not inherit the entire user environment. Use `${WORKSPACE}` in arguments for the task directory and `${AGENT_ROOT}` for the current resource snapshot.
164
+
165
+ ## Guarantees and compatibility boundaries
166
+
167
+ - Resource discovery uses only the locked inventory and supported entry points. The original global `pi` command and SDK do not automatically recognize `pi.lock`; use this project's CLI or SDK entry points.
168
+ - Extensions that read user directories, dynamically import arbitrary external code, or change business logic based on `ctx.mode` need adaptation. pi-lock checks initialized configuration and rejects detectable differences, but it is not an OS sandbox for arbitrary JavaScript. Direct mutation of Pi internals by an SDK host is also outside the freeze contract.
169
+ - Task files, session history, external-service responses, credentials, and the clock are runtime inputs. Programs launched by filesystem tools still require a compatible host environment. A locked configuration cannot make a macOS-only command run on Linux.
170
+ - The SDK does not modify `process.env`, `HOME`, or the process working directory. The CLI sets project-local Pi state paths in its own process and disables Pi's automatic downloads and updates. Native TUI colors and key bindings affect presentation, not the agent definition.
171
+ - A headless call that needs user interaction reports `INTERACTION_REQUIRED` by default; it does not approve automatically. The SDK can receive native `uiContext` callbacks. RPC and TUI use Pi's own interaction channels.
172
+ - Session metadata is bound to an agent version. Applications must explicitly handle version and data migrations, and reversal of side effects already performed by external tools.
173
+ - See the [acceptance report](docs/acceptance.md) for the tested environment. Tests in temporary directories on one machine are not presented as proof of cross-platform operation or compatibility with every third-party extension.
174
+
175
+ ## Development and acceptance
176
+
177
+ ```sh
178
+ npm ci
179
+ npm test
180
+ ```
181
+
182
+ Acceptance uses Pi's real `AgentSession`, native TUI (through a PTY), native RPC, native OpenAI-compatible HTTP streaming, and a local MCP server. Model responses come from deterministic local fixtures, so no real account or paid request is required.
183
+
184
+ See the [architecture notes](docs/architecture.md) for implementation details and trade-offs.
@@ -0,0 +1,7 @@
1
+ import type { ExtensionFactory, LoadExtensionsResult, ExtensionRuntime, EventBus } from "@earendil-works/pi-coding-agent";
2
+ export declare function assertEngine(): void;
3
+ export declare function explicitExtensionLoader(): Promise<{
4
+ loadExtensions: (paths: string[], cwd: string, events?: EventBus, runtime?: ExtensionRuntime) => Promise<LoadExtensionsResult>;
5
+ loadExtensionFromFactory: (factory: ExtensionFactory, cwd: string, events: EventBus, runtime: ExtensionRuntime, name?: string) => Promise<LoadExtensionsResult["extensions"][number]>;
6
+ }>;
7
+ export declare function internalModule(path: string): Promise<any>;
package/dist/bridge.js ADDED
@@ -0,0 +1,18 @@
1
+ // Pi 1.3.0 exposes ResourceLoader publicly but not its explicit-only extension loader.
2
+ // Keep these version-specific imports in one audited bridge; never call discovery.
3
+ import { VERSION } from "@earendil-works/pi-coding-agent";
4
+ import { PI_VERSION, fail } from "./common.js";
5
+ const entry = import.meta.resolve("@earendil-works/pi-coding-agent");
6
+ export function assertEngine() {
7
+ if (VERSION !== PI_VERSION)
8
+ fail("ENGINE_MISMATCH", `pi-lock supports Pi ${PI_VERSION}; installed Pi is ${VERSION}. Run npm ci.`);
9
+ }
10
+ export async function explicitExtensionLoader() {
11
+ assertEngine();
12
+ return import(new URL("./core/extensions/loader.js", entry).href);
13
+ }
14
+ export async function internalModule(path) {
15
+ assertEngine();
16
+ return import(new URL(path, entry).href);
17
+ }
18
+ //# sourceMappingURL=bridge.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bridge.js","sourceRoot":"","sources":["../src/bridge.ts"],"names":[],"mappings":"AAAA,uFAAuF;AACvF,mFAAmF;AACnF,OAAO,EAAE,OAAO,EAAE,MAAM,iCAAiC,CAAC;AAE1D,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,aAAa,CAAC;AAE/C,MAAM,KAAK,GAAG,OAAO,IAAI,CAAC,OAAO,CAAC,iCAAiC,CAAC,CAAC;AACrE,MAAM,UAAU,YAAY;IAC1B,IAAI,OAAO,KAAK,UAAU;QAAE,IAAI,CAAC,iBAAiB,EAAE,uBAAuB,UAAU,qBAAqB,OAAO,eAAe,CAAC,CAAC;AACpI,CAAC;AACD,MAAM,CAAC,KAAK,UAAU,uBAAuB;IAI3C,YAAY,EAAE,CAAC;IACf,OAAO,MAAM,CAAC,IAAI,GAAG,CAAC,6BAA6B,EAAE,KAAK,CAAC,CAAC,IAAI,CAAC,CAAC;AACpE,CAAC;AACD,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,IAAY;IAC/C,YAAY,EAAE,CAAC;IACf,OAAO,MAAM,CAAC,IAAI,GAAG,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC,IAAI,CAAC,CAAC;AAC3C,CAAC"}
package/dist/cli.d.ts ADDED
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
package/dist/cli.js ADDED
@@ -0,0 +1,82 @@
1
+ #!/usr/bin/env node
2
+ // This entry intentionally imports no Pi code until its per-process paths are bound locally.
3
+ import { mkdirSync } from "node:fs";
4
+ import { resolve } from "node:path";
5
+ import { fail, findProject, LockError, PI_VERSION } from "./common.js";
6
+ const help = `pi-lock — Pi ${PI_VERSION}, project-local and reproducible
7
+
8
+ pi-lock init [--demo] Create ordinary .pi settings and resources
9
+ pi-lock lock Generate/update pi.lock after editing
10
+ pi-lock Open Pi's native TUI (frozen by default)
11
+ pi-lock -p "prompt" Print a response and exit
12
+ pi-lock --mode rpc Use Pi's JSONL RPC protocol
13
+ pi-lock --mode json "prompt" Stream Pi JSON events
14
+ pi-lock inspect Show the locked resources and fingerprint
15
+ pi-lock verify Verify source/dependencies against pi.lock
16
+ pi-lock sync --frozen npm ci, then verify; never rewrite pi.lock
17
+
18
+ --project <dir> Agent definition root (auto-detected)
19
+ --cwd <dir> Task workspace (does not change the agent)
20
+ --dev Edit/tune before locking; /reload reads local edits
21
+ --provider <id> --model <id> init/--dev only; saves local Pi settings
22
+ --thinking <level> --tools <list> --dev only; saves local Pi settings
23
+ --session <file> Resume a matching locked session
24
+ --session-dir <dir> Explicit application-owned session directory
25
+ --no-session Use an in-memory session
26
+ -c, --continue Continue latest session of this Agent version
27
+ `;
28
+ async function main() {
29
+ const args = process.argv.slice(2);
30
+ if (args.includes("--help") || args.includes("-h")) {
31
+ console.log(help);
32
+ return;
33
+ }
34
+ if (args.includes("--version") || args.includes("-v")) {
35
+ console.log(`pi-lock 0.1.0 (Pi ${PI_VERSION})`);
36
+ return;
37
+ }
38
+ const commands = new Set(["init", "lock", "inspect", "verify", "sync"]);
39
+ let command = commands.has(args[0]) ? args.shift() : "run";
40
+ const flags = {};
41
+ const messages = [];
42
+ const booleanFlags = new Set(["--demo", "--dev", "--no-session", "--frozen", "--continue", "-c", "-p", "--print"]);
43
+ const valueFlags = new Set(["--project", "--cwd", "--mode", "--provider", "--model", "--thinking", "--tools", "--session", "--session-dir"]);
44
+ while (args.length) {
45
+ const arg = args.shift();
46
+ if (arg === "--") {
47
+ messages.push(...args);
48
+ break;
49
+ }
50
+ if (booleanFlags.has(arg))
51
+ flags[arg] = true;
52
+ else if (valueFlags.has(arg)) {
53
+ const value = args.shift();
54
+ if (!value || value.startsWith("--"))
55
+ fail("ARGUMENT", `${arg} needs a value.`);
56
+ flags[arg] = value;
57
+ }
58
+ else if (arg.startsWith("-"))
59
+ fail("ARGUMENT", `Unknown option ${arg}. Run pi-lock --help.`);
60
+ else if (command === "run" && !messages.length && !flags["-p"] && !flags["--print"] && !flags["--mode"] && commands.has(arg))
61
+ command = arg;
62
+ else
63
+ messages.push(arg);
64
+ }
65
+ const cwd = resolve(String(flags["--cwd"] ?? process.cwd()));
66
+ const root = command === "init" ? resolve(String(flags["--project"] ?? cwd)) : findProject(cwd, flags["--project"]);
67
+ // Pi TUI helpers still use getAgentDir(); set it before importing Pi, inside this CLI process only.
68
+ const uiRoot = resolve(root, ".pi-lock/state/ui");
69
+ mkdirSync(uiRoot, { recursive: true });
70
+ process.env.PI_CODING_AGENT_DIR = uiRoot;
71
+ process.env.PI_CODING_AGENT_SESSION_DIR = resolve(root, ".pi-lock/state/sessions");
72
+ process.env.PI_OFFLINE = "1";
73
+ process.env.PI_SKIP_VERSION_CHECK = "1";
74
+ process.env.PI_TELEMETRY = "0";
75
+ const { execute } = await import("./commands.js");
76
+ await execute(command, root, cwd, flags, messages);
77
+ }
78
+ main().catch(error => {
79
+ console.error(`${error instanceof LockError ? error.code : "PI_LOCK_ERROR"}: ${error.message}`);
80
+ process.exitCode = 1;
81
+ });
82
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export declare function execute(command: string, root: string, cwd: string, flags: Record<string, string | boolean>, messages: string[]): Promise<void>;
@@ -0,0 +1,114 @@
1
+ import { copyFileSync, existsSync, mkdirSync, rmSync } from "node:fs";
2
+ import { resolve } from "node:path";
3
+ import { spawn } from "node:child_process";
4
+ import { InteractiveMode, initTheme, runPrintMode, runRpcMode, SessionManager } from "@earendil-works/pi-coding-agent";
5
+ import { atomicJson, digest, fail, json } from "./common.js";
6
+ import { internalModule } from "./bridge.js";
7
+ import { initialize } from "./init.js";
8
+ import { createLockedRuntime, lockProject } from "./runtime.js";
9
+ import { materialize, readLock, verifyDefinition, verifySourcesBeforeInstall } from "./lock.js";
10
+ async function npmCi(cwd) {
11
+ await new Promise((done, reject) => {
12
+ const child = spawn("npm", ["ci", "--no-audit", "--no-fund"], { cwd, stdio: "inherit", shell: false });
13
+ child.on("error", reject);
14
+ child.on("close", code => code === 0 ? done() : reject(new Error(`npm ci failed (${code}) in ${cwd}`)));
15
+ });
16
+ }
17
+ export async function execute(command, root, cwd, flags, messages) {
18
+ if (command === "init") {
19
+ initialize(root, { demo: Boolean(flags["--demo"]), provider: flags["--provider"], model: flags["--model"] });
20
+ console.log(`Created .pi/settings.json${flags["--demo"] ? " and offline demo" : ""}. Run pi-lock --dev to tune, then pi-lock lock.`);
21
+ return;
22
+ }
23
+ if (command === "lock") {
24
+ const lock = await lockProject(root);
25
+ console.log(`Locked Pi ${lock.runtime.pi}: ${lock.agentDigest}\nCommit .pi/ and pi.lock to Git.`);
26
+ return;
27
+ }
28
+ if (command === "sync") {
29
+ if (!flags["--frozen"])
30
+ fail("ARGUMENT", "Use pi-lock sync --frozen to restore dependencies without changing pi.lock.");
31
+ const lock = readLock(root);
32
+ verifySourcesBeforeInstall(root, lock);
33
+ for (const path of [root, resolve(root, ".pi/npm")])
34
+ if (existsSync(resolve(path, "package-lock.json")))
35
+ await npmCi(path);
36
+ }
37
+ if (["verify", "inspect", "sync"].includes(command)) {
38
+ const lock = readLock(root);
39
+ verifyDefinition(root, lock);
40
+ materialize(root, lock);
41
+ if (command === "inspect")
42
+ console.log(JSON.stringify({ agentDigest: lock.agentDigest, pi: lock.runtime.pi, configuration: lock.effective, resources: lock.definition.resources, dependencies: lock.definition.dependencies }, null, 2));
43
+ else
44
+ console.log(`Verified ${lock.agentDigest}`);
45
+ return;
46
+ }
47
+ const edits = { "--model": "defaultModel", "--provider": "defaultProvider", "--thinking": "defaultThinkingLevel", "--tools": "defaultTools" };
48
+ for (const [flag, field] of Object.entries(edits))
49
+ if (flags[flag] !== undefined) {
50
+ if (!flags["--dev"])
51
+ fail("FROZEN_SETTING", `${flag} changes locked behavior. Start --dev to tune, then pi-lock lock.`);
52
+ const path = resolve(root, ".pi/settings.json");
53
+ const config = json(path);
54
+ config[field] = flag === "--tools" ? String(flags[flag]).split(",") : flags[flag];
55
+ atomicJson(path, config);
56
+ }
57
+ const mode = flags["--mode"] ?? ((flags["-p"] || flags["--print"]) ? "print" : "tui");
58
+ if (!["tui", "rpc", "json", "print", "text"].includes(String(mode)))
59
+ fail("ARGUMENT", `Unknown mode ${mode}.`);
60
+ const state = resolve(root, ".pi-lock/state");
61
+ mkdirSync(state, { recursive: true });
62
+ const { AuthStorage } = await internalModule("./core/auth-storage.js");
63
+ const credentials = AuthStorage.create(resolve(state, "auth.json"));
64
+ const opts = { projectRoot: root, cwd, credentials, dev: Boolean(flags["--dev"]), sessionFile: flags["--session"], sessionDir: flags["--session-dir"] };
65
+ if (flags["--no-session"])
66
+ opts.sessionManager = SessionManager.inMemory(cwd);
67
+ if (flags["--continue"] || flags["-c"]) {
68
+ if (opts.dev)
69
+ fail("ARGUMENT", "Continue a frozen version, or use --session explicitly while developing.");
70
+ const lock = readLock(root);
71
+ const dir = resolve(String(flags["--session-dir"] ?? resolve(state, "sessions", lock.agentDigest, digest(cwd).slice(0, 12))));
72
+ opts.sessionManager = SessionManager.continueRecent(cwd, dir);
73
+ }
74
+ if (mode !== "tui")
75
+ (await internalModule("./core/output-guard.js")).takeOverStdout();
76
+ const locked = await createLockedRuntime(opts);
77
+ const themeModule = await internalModule("./modes/interactive/theme/theme.js");
78
+ themeModule.setRegisteredThemes(locked.runtime.services.resourceLoader.getThemes().themes);
79
+ initTheme(locked.runtime.services.settingsManager.getTheme(), false);
80
+ const keys = resolve(locked.releaseRoot, ".pi/keybindings.json");
81
+ if (existsSync(keys))
82
+ copyFileSync(keys, resolve(state, "ui/keybindings.json"));
83
+ else
84
+ rmSync(resolve(state, "ui/keybindings.json"), { force: true });
85
+ try {
86
+ if (mode === "rpc") {
87
+ await runRpcMode(locked.runtime);
88
+ }
89
+ else if (mode === "tui") {
90
+ if (!process.stdin.isTTY || !process.stdout.isTTY)
91
+ fail("TTY_REQUIRED", "TUI requires a terminal. Use -p or --mode rpc for non-interactive execution.");
92
+ const tui = new InteractiveMode(locked.runtime, { initialMessage: messages.join(" ") || undefined, initialImages: [], initialMessages: [], migratedProviders: [], verbose: false });
93
+ await tui.run();
94
+ }
95
+ else {
96
+ let prompt = messages.join(" ");
97
+ if (!process.stdin.isTTY) {
98
+ const chunks = [];
99
+ for await (const chunk of process.stdin)
100
+ chunks.push(Buffer.from(chunk));
101
+ const input = Buffer.concat(chunks).toString("utf8").trim();
102
+ if (input)
103
+ prompt = [input, prompt].filter(Boolean).join("\n\n");
104
+ }
105
+ if (!prompt)
106
+ fail("PROMPT_REQUIRED", "Pass a prompt or pipe input into pi-lock -p.");
107
+ process.exitCode = await runPrintMode(locked.runtime, { mode: mode === "json" ? "json" : "text", initialMessage: prompt, initialImages: [], messages: [] });
108
+ }
109
+ }
110
+ finally {
111
+ await locked.dispose();
112
+ }
113
+ }
114
+ //# sourceMappingURL=commands.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"commands.js","sourceRoot":"","sources":["../src/commands.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ export declare const PI_VERSION = "1.3.0";
2
+ export declare const FORMAT = 1;
3
+ export declare class LockError extends Error {
4
+ code: string;
5
+ constructor(code: string, message: string);
6
+ }
7
+ export declare function fail(code: string, message: string): never;
8
+ export declare function canonical(value: unknown): string;
9
+ export declare function hash(value: string | Buffer): string;
10
+ export declare function digest(value: unknown): string;
11
+ export declare function json<T = any>(path: string): T;
12
+ export declare function atomicJson(path: string, value: unknown): void;
13
+ export declare function inside(root: string, path: string): string;
14
+ export declare function portablePath(root: string, full: string): string;
15
+ export declare function walk(root: string, path: string, skip?: Set<string>): string[];
16
+ export declare function findProject(start: string, explicit?: string): string;
17
+ export declare function replaceRoots(value: unknown, roots: Array<[string, string]>): unknown;
package/dist/common.js ADDED
@@ -0,0 +1,87 @@
1
+ import { createHash } from "node:crypto";
2
+ import { existsSync, lstatSync, readFileSync, realpathSync, readdirSync, statSync, mkdirSync, renameSync, writeFileSync } from "node:fs";
3
+ import { dirname, isAbsolute, relative, resolve, sep } from "node:path";
4
+ export const PI_VERSION = "1.3.0";
5
+ export const FORMAT = 1;
6
+ export class LockError extends Error {
7
+ code;
8
+ constructor(code, message) {
9
+ super(message);
10
+ this.code = code;
11
+ this.name = "LockError";
12
+ }
13
+ }
14
+ export function fail(code, message) { throw new LockError(code, message); }
15
+ export function canonical(value) {
16
+ if (Array.isArray(value))
17
+ return `[${value.map(canonical).join(",")}]`;
18
+ if (value && typeof value === "object") {
19
+ return `{${Object.keys(value).filter(k => value[k] !== undefined).sort().map(k => `${JSON.stringify(k)}:${canonical(value[k])}`).join(",")}}`;
20
+ }
21
+ return JSON.stringify(value);
22
+ }
23
+ export function hash(value) { return createHash("sha256").update(value).digest("hex"); }
24
+ export function digest(value) { return hash(canonical(value)); }
25
+ export function json(path) {
26
+ try {
27
+ return JSON.parse(readFileSync(path, "utf8"));
28
+ }
29
+ catch (e) {
30
+ return fail("INVALID_JSON", `${path}: ${e.message}`);
31
+ }
32
+ }
33
+ export function atomicJson(path, value) {
34
+ mkdirSync(dirname(path), { recursive: true });
35
+ const temp = `${path}.${process.pid}.${Math.random().toString(36).slice(2)}.tmp`;
36
+ writeFileSync(temp, JSON.stringify(value, null, 2) + "\n", { mode: 0o600 });
37
+ renameSync(temp, path);
38
+ }
39
+ export function inside(root, path) {
40
+ const full = resolve(root, path);
41
+ const rel = relative(root, full);
42
+ if (isAbsolute(rel) || rel === ".." || rel.startsWith(`..${sep}`))
43
+ fail("OUTSIDE_PROJECT", `Resource must be inside the agent project: ${path}`);
44
+ if (existsSync(full)) {
45
+ const actual = relative(realpathSync(root), realpathSync(full));
46
+ if (isAbsolute(actual) || actual === ".." || actual.startsWith(`..${sep}`))
47
+ fail("OUTSIDE_PROJECT", `Symlink leaves agent project: ${path}`);
48
+ }
49
+ return full;
50
+ }
51
+ export function portablePath(root, full) { return relative(root, full).split(sep).join("/"); }
52
+ export function walk(root, path, skip = new Set()) {
53
+ if (!existsSync(path))
54
+ return [];
55
+ inside(root, path);
56
+ if (lstatSync(path).isSymbolicLink())
57
+ fail("SYMLINK_RESOURCE", `Use ordinary project files instead of symlinks: ${path}`);
58
+ if (!statSync(path).isDirectory())
59
+ return [path];
60
+ return readdirSync(path).sort().filter(name => !skip.has(name)).flatMap(name => walk(root, resolve(path, name), skip));
61
+ }
62
+ export function findProject(start, explicit) {
63
+ if (explicit)
64
+ return realpathSync(resolve(explicit));
65
+ let path = realpathSync(resolve(start));
66
+ while (true) {
67
+ if (existsSync(resolve(path, "pi.lock")) || existsSync(resolve(path, ".pi/settings.json")))
68
+ return path;
69
+ const parent = dirname(path);
70
+ if (parent === path)
71
+ fail("NO_PROJECT", "No pi.lock or .pi/settings.json found. Run pi-lock init in the agent project.");
72
+ path = parent;
73
+ }
74
+ }
75
+ export function replaceRoots(value, roots) {
76
+ if (typeof value === "string") {
77
+ for (const [root, label] of [...roots].sort((a, b) => b[0].length - a[0].length))
78
+ value = value.split(root).join(label);
79
+ return value;
80
+ }
81
+ if (Array.isArray(value))
82
+ return value.map(v => replaceRoots(v, roots));
83
+ if (value && typeof value === "object")
84
+ return Object.fromEntries(Object.entries(value).map(([k, v]) => [k, replaceRoots(v, roots)]));
85
+ return value;
86
+ }
87
+ //# sourceMappingURL=common.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"common.js","sourceRoot":"","sources":["../src/common.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,32 @@
1
+ export interface FileRecord {
2
+ path: string;
3
+ sha256: string;
4
+ executable: boolean;
5
+ }
6
+ export interface Resources {
7
+ extensions: string[];
8
+ skills: string[];
9
+ prompts: string[];
10
+ themes: string[];
11
+ context: string[];
12
+ system?: string;
13
+ append?: string;
14
+ }
15
+ export interface Definition {
16
+ settings: Record<string, any>;
17
+ files: FileRecord[];
18
+ resources: Resources;
19
+ dependencies: Array<{
20
+ path: string;
21
+ name: string;
22
+ version: string;
23
+ integrity?: string;
24
+ }>;
25
+ modelConfig: Record<string, any>;
26
+ }
27
+ export declare function readDefinition(root: string): Definition;
28
+ export declare function runtimeIdentity(): {
29
+ pi: string;
30
+ adapter: string;
31
+ sha256: string;
32
+ };