pi-tinychat 0.1.0 → 0.1.1

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/src/pi-path.js CHANGED
@@ -1,70 +1,70 @@
1
- import { statSync } from "node:fs";
2
- import { delimiter, dirname, join } from "node:path";
3
-
4
- const PI_PACKAGE = "@earendil-works/pi-coding-agent";
5
- const CLI_CANDIDATES = [
6
- ["dist", "bundle", "cli.js"],
7
- ["dist", "cli.js"],
8
- ];
9
-
10
- function isFile(path) {
11
- try {
12
- return statSync(path).isFile();
13
- } catch {
14
- return false;
15
- }
16
- }
17
-
18
- function nodeCli(reference) {
19
- for (const segments of CLI_CANDIDATES) {
20
- const candidate = join(reference, ...segments);
21
- if (isFile(candidate)) return candidate;
22
- }
23
- return undefined;
24
- }
25
-
26
- /**
27
- * Turn a path to a `pi` launcher into something spawn() can execute directly.
28
- * npm shims are avoided on Windows (and are slower everywhere), so the real
29
- * CLI entry point is preferred when it can be located.
30
- */
31
- function fromLauncher(path) {
32
- if (/\.(c|m)?js$/i.test(path)) {
33
- return { command: process.execPath, args: [path], source: path };
34
- }
35
-
36
- const dir = dirname(path);
37
- const packageRoots = [
38
- join(dir, "node_modules", ...PI_PACKAGE.split("/")),
39
- join(dir, "..", "lib", "node_modules", ...PI_PACKAGE.split("/")),
40
- join(dir, "..", "..", "lib", "node_modules", ...PI_PACKAGE.split("/")),
41
- ];
42
- for (const root of packageRoots) {
43
- const cli = nodeCli(root);
44
- if (cli) return { command: process.execPath, args: [cli], source: cli };
45
- }
46
-
47
- return {
48
- command: path,
49
- args: [],
50
- shell: process.platform === "win32" && /\.(cmd|bat)$/i.test(path),
51
- source: path,
52
- };
53
- }
54
-
55
- /** Locate the installed Pi CLI without installing or copying it. */
56
- export function locatePi(env = process.env) {
57
- const explicit = env.PI_TINYCHAT_PI?.trim();
58
- if (explicit) return fromLauncher(explicit);
59
-
60
- const names =
61
- process.platform === "win32" ? ["pi.cmd", "pi.exe", "pi.bat", "pi"] : ["pi"];
62
- for (const dir of (env.PATH ?? "").split(delimiter).filter(Boolean)) {
63
- for (const name of names) {
64
- const candidate = join(dir, name);
65
- if (isFile(candidate)) return fromLauncher(candidate);
66
- }
67
- }
68
-
69
- return { command: "pi", args: [], source: "pi (PATH)" };
70
- }
1
+ import { statSync } from "node:fs";
2
+ import { delimiter, dirname, join } from "node:path";
3
+
4
+ const PI_PACKAGE = "@earendil-works/pi-coding-agent";
5
+ const CLI_CANDIDATES = [
6
+ ["dist", "bundle", "cli.js"],
7
+ ["dist", "cli.js"],
8
+ ];
9
+
10
+ function isFile(path) {
11
+ try {
12
+ return statSync(path).isFile();
13
+ } catch {
14
+ return false;
15
+ }
16
+ }
17
+
18
+ function nodeCli(reference) {
19
+ for (const segments of CLI_CANDIDATES) {
20
+ const candidate = join(reference, ...segments);
21
+ if (isFile(candidate)) return candidate;
22
+ }
23
+ return undefined;
24
+ }
25
+
26
+ /**
27
+ * Turn a path to a `pi` launcher into something spawn() can execute directly.
28
+ * npm shims are avoided on Windows (and are slower everywhere), so the real
29
+ * CLI entry point is preferred when it can be located.
30
+ */
31
+ function fromLauncher(path) {
32
+ if (/\.(c|m)?js$/i.test(path)) {
33
+ return { command: process.execPath, args: [path], source: path };
34
+ }
35
+
36
+ const dir = dirname(path);
37
+ const packageRoots = [
38
+ join(dir, "node_modules", ...PI_PACKAGE.split("/")),
39
+ join(dir, "..", "lib", "node_modules", ...PI_PACKAGE.split("/")),
40
+ join(dir, "..", "..", "lib", "node_modules", ...PI_PACKAGE.split("/")),
41
+ ];
42
+ for (const root of packageRoots) {
43
+ const cli = nodeCli(root);
44
+ if (cli) return { command: process.execPath, args: [cli], source: cli };
45
+ }
46
+
47
+ return {
48
+ command: path,
49
+ args: [],
50
+ shell: process.platform === "win32" && /\.(cmd|bat)$/i.test(path),
51
+ source: path,
52
+ };
53
+ }
54
+
55
+ /** Locate the installed Pi CLI without installing or copying it. */
56
+ export function locatePi(env = process.env) {
57
+ const explicit = env.PI_TINYCHAT_PI?.trim();
58
+ if (explicit) return fromLauncher(explicit);
59
+
60
+ const names =
61
+ process.platform === "win32" ? ["pi.cmd", "pi.exe", "pi.bat", "pi"] : ["pi"];
62
+ for (const dir of (env.PATH ?? "").split(delimiter).filter(Boolean)) {
63
+ for (const name of names) {
64
+ const candidate = join(dir, name);
65
+ if (isFile(candidate)) return fromLauncher(candidate);
66
+ }
67
+ }
68
+
69
+ return { command: "pi", args: [], source: "pi (PATH)" };
70
+ }
package/src/pi-types.d.ts CHANGED
@@ -1,85 +1,85 @@
1
- /**
2
- * Pi types consumed by Pi TinyChat, derived from the official packages.
3
- *
4
- * The Pi packages are devDependencies only: no runtime dependency is added,
5
- * but the RPC wire protocol, session JSONL, and extension API are checked
6
- * against the same declarations Pi ships. When Pi changes, bump the
7
- * devDependencies and let `npm run typecheck` point at every consumer.
8
- */
9
-
10
- import type {
11
- AssistantMessage,
12
- ImageContent,
13
- Message,
14
- Model,
15
- TextContent,
16
- ThinkingContent,
17
- ToolCall,
18
- ToolResultMessage,
19
- Usage,
20
- UserMessage,
21
- } from "@earendil-works/pi-ai";
22
- import type {
23
- JsonAgentSessionEvent,
24
- RpcCommand,
25
- RpcCommandType,
26
- RpcExtensionUIRequest,
27
- RpcResponse,
28
- RpcSessionState,
29
- RpcSlashCommand,
30
- SessionEntry,
31
- SessionHeader,
32
- SessionStats,
33
- SessionTreeNode,
34
- } from "@earendil-works/pi-coding-agent";
35
-
36
- export type PiThinkingLevel = RpcSessionState["thinkingLevel"];
37
- export type PiModel = Model<string>;
38
-
39
- export type PiTextBlock = TextContent;
40
- export type PiThinkingBlock = ThinkingContent;
41
- export type PiImageBlock = ImageContent;
42
- export type PiToolCallBlock = ToolCall;
43
- export type PiContentBlock = TextContent | ThinkingContent | ImageContent | ToolCall;
44
- export type PiUserContent = UserMessage["content"];
45
- export type PiContent = string | readonly (TextContent | ImageContent)[];
46
- export type PiUsage = Usage;
47
-
48
- export type PiMessage = Message;
49
- export type PiAgentMessage = PiSessionEntry extends infer _ ? Extract<SessionEntry, { type: "message" }>["message"] : never;
50
- export type PiUserMessage = UserMessage;
51
- export type PiAssistantMessage = AssistantMessage;
52
- export type PiToolResultMessage = ToolResultMessage;
53
-
54
- export type PiSessionState = RpcSessionState;
55
- export type PiSessionStats = SessionStats;
56
- export type PiSlashCommand = RpcSlashCommand;
57
- export type PiSessionEntry = SessionEntry;
58
- export type PiSessionHeader = SessionHeader;
59
- export type PiSessionLine = PiSessionHeader | PiSessionEntry;
60
- export type PiTreeNode = SessionTreeNode;
61
-
62
- export type PiRecord = JsonAgentSessionEvent | RpcExtensionUIRequest;
63
- export type PiAssistantMessageEvent = Extract<
64
- JsonAgentSessionEvent,
65
- { type: "message_update" }
66
- >["assistantMessageEvent"];
67
- export type PiToolOutput = Extract<JsonAgentSessionEvent, { type: "tool_execution_end" }>["result"];
68
- export type PiExtensionUIRequest = RpcExtensionUIRequest;
69
- export type PiCommand = RpcCommand;
70
- export type PiCommandType = RpcCommandType;
71
- export type PiResponse = RpcResponse;
72
-
73
- /** `data` payload of a successful response, keyed by command type. */
74
- export type PiCommandData<Type extends PiCommandType> = Extract<
75
- RpcResponse,
76
- { command: Type; success: true }
77
- > extends { data: infer Data }
78
- ? Data
79
- : undefined;
80
-
81
- export interface PiExitInfo {
82
- reason: string;
83
- stderr: string;
84
- stopping: boolean;
85
- }
1
+ /**
2
+ * Pi types consumed by Pi TinyChat, derived from the official packages.
3
+ *
4
+ * The Pi packages are devDependencies only: no runtime dependency is added,
5
+ * but the RPC wire protocol, session JSONL, and extension API are checked
6
+ * against the same declarations Pi ships. When Pi changes, bump the
7
+ * devDependencies and let `npm run typecheck` point at every consumer.
8
+ */
9
+
10
+ import type {
11
+ AssistantMessage,
12
+ ImageContent,
13
+ Message,
14
+ Model,
15
+ TextContent,
16
+ ThinkingContent,
17
+ ToolCall,
18
+ ToolResultMessage,
19
+ Usage,
20
+ UserMessage,
21
+ } from "@earendil-works/pi-ai";
22
+ import type {
23
+ JsonAgentSessionEvent,
24
+ RpcCommand,
25
+ RpcCommandType,
26
+ RpcExtensionUIRequest,
27
+ RpcResponse,
28
+ RpcSessionState,
29
+ RpcSlashCommand,
30
+ SessionEntry,
31
+ SessionHeader,
32
+ SessionStats,
33
+ SessionTreeNode,
34
+ } from "@earendil-works/pi-coding-agent";
35
+
36
+ export type PiThinkingLevel = RpcSessionState["thinkingLevel"];
37
+ export type PiModel = Model<string>;
38
+
39
+ export type PiTextBlock = TextContent;
40
+ export type PiThinkingBlock = ThinkingContent;
41
+ export type PiImageBlock = ImageContent;
42
+ export type PiToolCallBlock = ToolCall;
43
+ export type PiContentBlock = TextContent | ThinkingContent | ImageContent | ToolCall;
44
+ export type PiUserContent = UserMessage["content"];
45
+ export type PiContent = string | readonly (TextContent | ImageContent)[];
46
+ export type PiUsage = Usage;
47
+
48
+ export type PiMessage = Message;
49
+ export type PiAgentMessage = PiSessionEntry extends infer _ ? Extract<SessionEntry, { type: "message" }>["message"] : never;
50
+ export type PiUserMessage = UserMessage;
51
+ export type PiAssistantMessage = AssistantMessage;
52
+ export type PiToolResultMessage = ToolResultMessage;
53
+
54
+ export type PiSessionState = RpcSessionState;
55
+ export type PiSessionStats = SessionStats;
56
+ export type PiSlashCommand = RpcSlashCommand;
57
+ export type PiSessionEntry = SessionEntry;
58
+ export type PiSessionHeader = SessionHeader;
59
+ export type PiSessionLine = PiSessionHeader | PiSessionEntry;
60
+ export type PiTreeNode = SessionTreeNode;
61
+
62
+ export type PiRecord = JsonAgentSessionEvent | RpcExtensionUIRequest;
63
+ export type PiAssistantMessageEvent = Extract<
64
+ JsonAgentSessionEvent,
65
+ { type: "message_update" }
66
+ >["assistantMessageEvent"];
67
+ export type PiToolOutput = Extract<JsonAgentSessionEvent, { type: "tool_execution_end" }>["result"];
68
+ export type PiExtensionUIRequest = RpcExtensionUIRequest;
69
+ export type PiCommand = RpcCommand;
70
+ export type PiCommandType = RpcCommandType;
71
+ export type PiResponse = RpcResponse;
72
+
73
+ /** `data` payload of a successful response, keyed by command type. */
74
+ export type PiCommandData<Type extends PiCommandType> = Extract<
75
+ RpcResponse,
76
+ { command: Type; success: true }
77
+ > extends { data: infer Data }
78
+ ? Data
79
+ : undefined;
80
+
81
+ export interface PiExitInfo {
82
+ reason: string;
83
+ stderr: string;
84
+ stopping: boolean;
85
+ }