remote-pi 0.2.0 → 0.4.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.
- package/README.md +44 -0
- package/dist/actions/handlers.d.ts +116 -0
- package/dist/actions/handlers.js +152 -0
- package/dist/actions/handlers.js.map +1 -0
- package/dist/actions/registry.d.ts +25 -0
- package/dist/actions/registry.js +34 -0
- package/dist/actions/registry.js.map +1 -0
- package/dist/bin/supervisord.js +43 -1
- package/dist/bin/supervisord.js.map +1 -1
- package/dist/commands/builtin_mirror.d.ts +58 -0
- package/dist/commands/builtin_mirror.js +71 -0
- package/dist/commands/builtin_mirror.js.map +1 -0
- package/dist/commands/list_commands.d.ts +60 -0
- package/dist/commands/list_commands.js +73 -0
- package/dist/commands/list_commands.js.map +1 -0
- package/dist/daemon/control_protocol.d.ts +8 -0
- package/dist/daemon/control_protocol.js.map +1 -1
- package/dist/daemon/rpc_child.d.ts +24 -0
- package/dist/daemon/rpc_child.js +41 -2
- package/dist/daemon/rpc_child.js.map +1 -1
- package/dist/daemon/supervisor.d.ts +11 -0
- package/dist/daemon/supervisor.js +56 -4
- package/dist/daemon/supervisor.js.map +1 -1
- package/dist/index.d.ts +6 -0
- package/dist/index.js +753 -209
- package/dist/index.js.map +1 -1
- package/dist/mcp/mesh_server.d.ts +16 -0
- package/dist/mcp/mesh_server.js +207 -0
- package/dist/mcp/mesh_server.js.map +1 -0
- package/dist/pairing/storage.js +12 -10
- package/dist/pairing/storage.js.map +1 -1
- package/dist/protocol/types.d.ts +103 -0
- package/dist/session/bridge.d.ts +39 -0
- package/dist/session/bridge.js +41 -0
- package/dist/session/bridge.js.map +1 -0
- package/dist/session/mesh_node.d.ts +123 -0
- package/dist/session/mesh_node.js +203 -0
- package/dist/session/mesh_node.js.map +1 -0
- package/dist/session/setup_wizard.d.ts +6 -23
- package/dist/session/setup_wizard.js +6 -15
- package/dist/session/setup_wizard.js.map +1 -1
- package/dist/session/tools.js +0 -6
- package/dist/session/tools.js.map +1 -1
- package/dist/transport/relay_client.d.ts +8 -0
- package/dist/transport/relay_client.js +50 -2
- package/dist/transport/relay_client.js.map +1 -1
- package/package.json +4 -2
- package/skills/claude-agent-network/SKILL.md +239 -0
package/README.md
CHANGED
|
@@ -111,6 +111,50 @@ direct builds while public releases roll out):
|
|
|
111
111
|
|
|
112
112
|
---
|
|
113
113
|
|
|
114
|
+
## Mobile app actions
|
|
115
|
+
|
|
116
|
+
Beyond the chat, the app surfaces a small set of typed actions you can run
|
|
117
|
+
on the paired Pi session. Tap the ⚙ button next to the message input (visible
|
|
118
|
+
when the input is empty) to open the Quick Actions sheet:
|
|
119
|
+
|
|
120
|
+
| Action | What it does |
|
|
121
|
+
|---|---|
|
|
122
|
+
| **Compact context** | Runs `ctx.compact()` — same as `/compact` in the TUI. |
|
|
123
|
+
| **New session** | Runs `ctx.newSession()` — equivalent to `/new`, asks for confirmation first. |
|
|
124
|
+
| **Model** | Opens a model picker fed by your authenticated providers (same source the TUI uses) and switches via `pi.setModel(model)`. |
|
|
125
|
+
| **Thinking** | Segmented control with the 6 SDK levels (`off` · `minimal` · `low` · `medium` · `high` · `xhigh`). Changes via `pi.setThinkingLevel(level)`. |
|
|
126
|
+
|
|
127
|
+
Each action gets a structured `action_ok` / `action_error` reply so the app
|
|
128
|
+
can show a SnackBar on failure. Visible side-effects (chat output, model
|
|
129
|
+
change broadcasts, compaction notice) still flow through the normal chat
|
|
130
|
+
channels. The wire schema is documented in [`PROTOCOL.md`](../PROTOCOL.md)
|
|
131
|
+
under "App actions".
|
|
132
|
+
|
|
133
|
+
It is **not** a generic slash-command picker. The Pi SDK does not expose
|
|
134
|
+
programmatic invocation for most builtins (those live in the TUI's
|
|
135
|
+
interactive loop), so the app exposes only the actions that have a clean
|
|
136
|
+
SDK call. The [`pi-telegram`](https://github.com/llblab/pi-telegram) adapter
|
|
137
|
+
follows the same pattern.
|
|
138
|
+
|
|
139
|
+
### Images
|
|
140
|
+
|
|
141
|
+
The app can attach **one image** (camera or gallery) to a message. It's
|
|
142
|
+
compressed on the device and rides **inline** in the `user_message` — the
|
|
143
|
+
optional `images` field carries `{ data: <base64>, mime }`. The pi-extension
|
|
144
|
+
turns it into the SDK's multimodal content (an `ImageContent` followed by the
|
|
145
|
+
caption `TextContent`) and calls `sendUserMessage(content)`, so the model sees
|
|
146
|
+
the picture plus your text.
|
|
147
|
+
|
|
148
|
+
Whether a model accepts images is surfaced as a `vision` flag on each
|
|
149
|
+
`WireModel` (derived from the SDK's `Model.input` including `"image"`); the app
|
|
150
|
+
greys out the attach button when the active model is text-only.
|
|
151
|
+
|
|
152
|
+
The **relay is unchanged** — the image travels inside the same opaque `ct` blob
|
|
153
|
+
as the rest of the message, so there's no binary channel (large files are a
|
|
154
|
+
future track). Text-only messages are unaffected.
|
|
155
|
+
|
|
156
|
+
---
|
|
157
|
+
|
|
114
158
|
## Install
|
|
115
159
|
|
|
116
160
|
Requirements: Node 20+, Pi (the host coding agent).
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Plan/28 Wave B — typed action handlers.
|
|
3
|
+
*
|
|
4
|
+
* Each handler maps one `ClientMessage` action to a public Pi SDK call,
|
|
5
|
+
* and replies with `action_ok` or `action_error`. Handlers take their
|
|
6
|
+
* dependencies as parameters so the index.ts wiring is one-liner and
|
|
7
|
+
* unit tests can pass fakes without touching global state.
|
|
8
|
+
*
|
|
9
|
+
* `models_list` lives next door because it shares the `ModelRegistry`
|
|
10
|
+
* helper and the same wire vocabulary.
|
|
11
|
+
*
|
|
12
|
+
* SDK API surface used (see plan/28 Wave 0 for the full table):
|
|
13
|
+
*
|
|
14
|
+
* - `ctx.compact()` — non-blocking, fires `session_compact`
|
|
15
|
+
* event when done
|
|
16
|
+
* - `ctx.newSession()` — only on `ExtensionCommandContext`;
|
|
17
|
+
* resolves with `{cancelled}` flag
|
|
18
|
+
* - `pi.setModel(model)` — returns `false` if no auth configured
|
|
19
|
+
* - `pi.setThinkingLevel(lvl)` — synchronous
|
|
20
|
+
* - `ctx.getModel()` — optional, undefined before first turn
|
|
21
|
+
* - `ModelRegistry.{refresh,getAvailable,find}` — see `registry.ts`
|
|
22
|
+
*/
|
|
23
|
+
import type { ClientMessage, ServerMessage, WireModel } from "../protocol/types.js";
|
|
24
|
+
/**
|
|
25
|
+
* Structural subset of the SDK's `Model<Api>` interface (defined in
|
|
26
|
+
* `@mariozechner/pi-ai`, which is a transitive dep — not re-exported by
|
|
27
|
+
* `@mariozechner/pi-coding-agent`'s main entry). Capturing just the
|
|
28
|
+
* fields we touch keeps the handler decoupled from the SDK's full Model
|
|
29
|
+
* surface and avoids a direct dep on `pi-ai`.
|
|
30
|
+
*/
|
|
31
|
+
export interface SdkModelLike {
|
|
32
|
+
id: string;
|
|
33
|
+
name: string;
|
|
34
|
+
provider: string;
|
|
35
|
+
reasoning: boolean;
|
|
36
|
+
contextWindow: number;
|
|
37
|
+
/** Plan/30: accepted input modalities. The SDK's `Model.input` is
|
|
38
|
+
* `("text" | "image")[]`; we read `includes("image")` for the `vision`
|
|
39
|
+
* flag. Optional here so tests can omit it (treated as text-only). */
|
|
40
|
+
input?: ("text" | "image")[];
|
|
41
|
+
}
|
|
42
|
+
type Model<_TApi = unknown> = SdkModelLike;
|
|
43
|
+
/**
|
|
44
|
+
* Minimal channel surface needed to reply. Mirrors `PlainPeerChannel`'s
|
|
45
|
+
* `.send` signature; tests pass an array-backed fake.
|
|
46
|
+
*/
|
|
47
|
+
export interface ActionReplySender {
|
|
48
|
+
send(msg: ServerMessage): void;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Narrow shape of the `ExtensionAPI` surface action handlers actually
|
|
52
|
+
* call. Lets the test layer stub just these without rebuilding the full
|
|
53
|
+
* SDK type (which has 30+ methods we don't use here).
|
|
54
|
+
*/
|
|
55
|
+
export interface ActionPi {
|
|
56
|
+
setModel(model: Model<any>): Promise<boolean>;
|
|
57
|
+
setThinkingLevel(level: import("../protocol/types.js").ThinkingLevel): void;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Narrow shape of the per-call context. Drawn from the union of
|
|
61
|
+
* `ExtensionContextActions` (compact, getModel) and
|
|
62
|
+
* `ExtensionCommandContextActions` (newSession), since index.ts caches
|
|
63
|
+
* the most-recent ctx and that's typically the command one.
|
|
64
|
+
*
|
|
65
|
+
* All fields are optional so a missing method (e.g. when only a plain
|
|
66
|
+
* `ExtensionContext` was seen) becomes a typed `action_error` instead of
|
|
67
|
+
* a runtime TypeError.
|
|
68
|
+
*/
|
|
69
|
+
export interface ActionCtx {
|
|
70
|
+
compact?: (options?: object) => void;
|
|
71
|
+
/**
|
|
72
|
+
* Starts a new session. `withSession` is the SDK's blessed hook for
|
|
73
|
+
* post-replacement work: it receives a FRESH, command-capable ctx bound to
|
|
74
|
+
* the new session. The SDK marks any ctx captured BEFORE this call stale, so
|
|
75
|
+
* callers must re-capture via `withSession` rather than reuse the old ctx.
|
|
76
|
+
*/
|
|
77
|
+
newSession?: (options?: {
|
|
78
|
+
withSession?: (ctx: ActionCtx) => Promise<void>;
|
|
79
|
+
}) => Promise<{
|
|
80
|
+
cancelled: boolean;
|
|
81
|
+
}>;
|
|
82
|
+
getModel?: () => Model<any> | undefined;
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Minimal shape of the registry surface. Maps 1:1 onto `ModelRegistry`
|
|
86
|
+
* but lets tests fake catalogs without instantiating the real one.
|
|
87
|
+
*/
|
|
88
|
+
export interface ActionModelRegistry {
|
|
89
|
+
refresh(): void;
|
|
90
|
+
getAvailable(): Model<any>[];
|
|
91
|
+
find(provider: string, modelId: string): Model<any> | undefined;
|
|
92
|
+
}
|
|
93
|
+
/** Project a SDK `Model<Api>` onto the wire schema. Shared by list_models
|
|
94
|
+
* and the `current` echo, so both stay in lockstep. */
|
|
95
|
+
export declare function wireFromModel(model: Model<any>): WireModel;
|
|
96
|
+
type SessionCompactMsg = Extract<ClientMessage, {
|
|
97
|
+
type: "session_compact";
|
|
98
|
+
}>;
|
|
99
|
+
type SessionNewMsg = Extract<ClientMessage, {
|
|
100
|
+
type: "session_new";
|
|
101
|
+
}>;
|
|
102
|
+
type ModelSetMsg = Extract<ClientMessage, {
|
|
103
|
+
type: "model_set";
|
|
104
|
+
}>;
|
|
105
|
+
type ThinkingSetMsg = Extract<ClientMessage, {
|
|
106
|
+
type: "thinking_set";
|
|
107
|
+
}>;
|
|
108
|
+
type ListModelsMsg = Extract<ClientMessage, {
|
|
109
|
+
type: "list_models";
|
|
110
|
+
}>;
|
|
111
|
+
export declare function handleSessionCompact(ctx: ActionCtx | null, sender: ActionReplySender, msg: SessionCompactMsg): void;
|
|
112
|
+
export declare function handleSessionNew(ctx: ActionCtx | null, sender: ActionReplySender, msg: SessionNewMsg, onReplaced?: (freshCtx: ActionCtx) => void): Promise<boolean>;
|
|
113
|
+
export declare function handleThinkingSet(pi: ActionPi, sender: ActionReplySender, msg: ThinkingSetMsg): void;
|
|
114
|
+
export declare function handleModelSet(pi: ActionPi, reg: ActionModelRegistry, sender: ActionReplySender, msg: ModelSetMsg, onPersist?: (provider: string, modelId: string) => void): Promise<void>;
|
|
115
|
+
export declare function handleListModels(ctx: ActionCtx | null, reg: ActionModelRegistry, sender: ActionReplySender, msg: ListModelsMsg): void;
|
|
116
|
+
export {};
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Plan/28 Wave B — typed action handlers.
|
|
3
|
+
*
|
|
4
|
+
* Each handler maps one `ClientMessage` action to a public Pi SDK call,
|
|
5
|
+
* and replies with `action_ok` or `action_error`. Handlers take their
|
|
6
|
+
* dependencies as parameters so the index.ts wiring is one-liner and
|
|
7
|
+
* unit tests can pass fakes without touching global state.
|
|
8
|
+
*
|
|
9
|
+
* `models_list` lives next door because it shares the `ModelRegistry`
|
|
10
|
+
* helper and the same wire vocabulary.
|
|
11
|
+
*
|
|
12
|
+
* SDK API surface used (see plan/28 Wave 0 for the full table):
|
|
13
|
+
*
|
|
14
|
+
* - `ctx.compact()` — non-blocking, fires `session_compact`
|
|
15
|
+
* event when done
|
|
16
|
+
* - `ctx.newSession()` — only on `ExtensionCommandContext`;
|
|
17
|
+
* resolves with `{cancelled}` flag
|
|
18
|
+
* - `pi.setModel(model)` — returns `false` if no auth configured
|
|
19
|
+
* - `pi.setThinkingLevel(lvl)` — synchronous
|
|
20
|
+
* - `ctx.getModel()` — optional, undefined before first turn
|
|
21
|
+
* - `ModelRegistry.{refresh,getAvailable,find}` — see `registry.ts`
|
|
22
|
+
*/
|
|
23
|
+
/** Project a SDK `Model<Api>` onto the wire schema. Shared by list_models
|
|
24
|
+
* and the `current` echo, so both stay in lockstep. */
|
|
25
|
+
export function wireFromModel(model) {
|
|
26
|
+
return {
|
|
27
|
+
id: model.id,
|
|
28
|
+
name: model.name,
|
|
29
|
+
provider: model.provider,
|
|
30
|
+
reasoning: model.reasoning,
|
|
31
|
+
context_window: model.contextWindow,
|
|
32
|
+
// Plan/30: vision = model accepts image input. `Model.input` is
|
|
33
|
+
// `("text" | "image")[]` at runtime (confirmed against pi-ai). `?.` guards
|
|
34
|
+
// a fake/partial model in tests → treated as text-only.
|
|
35
|
+
vision: model.input?.includes("image") ?? false,
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
// ── ack helpers ────────────────────────────────────────────────────────────
|
|
39
|
+
function ok(sender, msg, action) {
|
|
40
|
+
sender.send({ type: "action_ok", in_reply_to: msg.id, action });
|
|
41
|
+
}
|
|
42
|
+
function fail(sender, msg, action, err) {
|
|
43
|
+
const error = err instanceof Error ? err.message : String(err);
|
|
44
|
+
sender.send({ type: "action_error", in_reply_to: msg.id, action, error });
|
|
45
|
+
}
|
|
46
|
+
/** Run a synchronous action with uniform success/failure replies. */
|
|
47
|
+
function runSync(sender, msg, action, body) {
|
|
48
|
+
try {
|
|
49
|
+
body();
|
|
50
|
+
ok(sender, msg, action);
|
|
51
|
+
}
|
|
52
|
+
catch (e) {
|
|
53
|
+
fail(sender, msg, action, e);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
/** Run an async action with uniform success/failure replies. */
|
|
57
|
+
async function runAsync(sender, msg, action, body) {
|
|
58
|
+
try {
|
|
59
|
+
await body();
|
|
60
|
+
ok(sender, msg, action);
|
|
61
|
+
return true;
|
|
62
|
+
}
|
|
63
|
+
catch (e) {
|
|
64
|
+
fail(sender, msg, action, e);
|
|
65
|
+
return false;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
export function handleSessionCompact(ctx, sender, msg) {
|
|
69
|
+
runSync(sender, msg, "session_compact", () => {
|
|
70
|
+
if (!ctx?.compact)
|
|
71
|
+
throw new Error("compact unavailable (no active session ctx)");
|
|
72
|
+
// Force the summary to English regardless of the conversation language —
|
|
73
|
+
// the summary is surfaced to the app via the `compaction` message, which
|
|
74
|
+
// is an English-only surface. `customInstructions` is appended to the SDK's
|
|
75
|
+
// compaction prompt (best-effort: the model writes the summary).
|
|
76
|
+
ctx.compact({
|
|
77
|
+
customInstructions: "Always write the compaction summary in English, even if the conversation is in another language.",
|
|
78
|
+
});
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
export async function handleSessionNew(ctx, sender, msg, onReplaced) {
|
|
82
|
+
// Returns true only when a fresh session was actually created. index.ts
|
|
83
|
+
// keys the Pi-side reset (clear _messageBuffer, restamp _sessionStartedAt,
|
|
84
|
+
// fan out an empty session_history) off this signal — a `cancelled`/errored
|
|
85
|
+
// new-session must NOT reset, so we return runAsync's success boolean.
|
|
86
|
+
return runAsync(sender, msg, "session_new", async () => {
|
|
87
|
+
if (!ctx?.newSession)
|
|
88
|
+
throw new Error("newSession unavailable (no command ctx yet)");
|
|
89
|
+
// newSession marks the caller's captured ctx (index.ts's `_lastCtx`) STALE
|
|
90
|
+
// — reusing it later throws "stale after session replacement" (the
|
|
91
|
+
// compact-after-New-session crash). `withSession` hands back a fresh,
|
|
92
|
+
// command-capable ctx bound to the new session; forward it via onReplaced
|
|
93
|
+
// so the caller re-captures and keeps later actions off the stale ctx.
|
|
94
|
+
const result = await ctx.newSession({
|
|
95
|
+
withSession: async (freshCtx) => { onReplaced?.(freshCtx); },
|
|
96
|
+
});
|
|
97
|
+
// `cancelled: true` happens when the SDK's hook chain vetoes the new
|
|
98
|
+
// session (e.g. an extension's `session_before_switch` returned a
|
|
99
|
+
// refusal). Surface as a typed error rather than silent success.
|
|
100
|
+
if (result.cancelled)
|
|
101
|
+
throw new Error("cancelled by extension hook");
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
export function handleThinkingSet(pi, sender, msg) {
|
|
105
|
+
runSync(sender, msg, "thinking_set", () => {
|
|
106
|
+
pi.setThinkingLevel(msg.level);
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
export async function handleModelSet(pi, reg, sender, msg, onPersist) {
|
|
110
|
+
await runAsync(sender, msg, "model_set", async () => {
|
|
111
|
+
// Refresh first so a model just-added via `/login` is visible.
|
|
112
|
+
reg.refresh();
|
|
113
|
+
const model = reg.find(msg.provider, msg.model_id);
|
|
114
|
+
if (!model) {
|
|
115
|
+
throw new Error(`model "${msg.provider}/${msg.model_id}" not in registry`);
|
|
116
|
+
}
|
|
117
|
+
const success = await pi.setModel(model);
|
|
118
|
+
if (!success)
|
|
119
|
+
throw new Error("no auth configured for this model");
|
|
120
|
+
// `pi.setModel` only sets the LIVE model — it does NOT persist. Without
|
|
121
|
+
// this, a model picked from the app reverts to the saved default on the
|
|
122
|
+
// next Pi/daemon restart (the TUI persists because AgentSession.setModel
|
|
123
|
+
// writes the default; this path doesn't). `onPersist` writes the new
|
|
124
|
+
// default so the app's choice survives. Best-effort — the caller's writer
|
|
125
|
+
// must not throw, so a failed settings write never fails the model change.
|
|
126
|
+
onPersist?.(model.provider, model.id);
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
export function handleListModels(ctx, reg, sender, msg) {
|
|
130
|
+
// refresh() can throw if `models.json` is malformed — wrap in try so the
|
|
131
|
+
// app gets an explicit error reply instead of a silent drop.
|
|
132
|
+
try {
|
|
133
|
+
reg.refresh();
|
|
134
|
+
const models = reg.getAvailable().map(wireFromModel);
|
|
135
|
+
const current = ctx?.getModel?.();
|
|
136
|
+
sender.send({
|
|
137
|
+
type: "models_list",
|
|
138
|
+
in_reply_to: msg.id,
|
|
139
|
+
models,
|
|
140
|
+
current: current ? wireFromModel(current) : undefined,
|
|
141
|
+
});
|
|
142
|
+
}
|
|
143
|
+
catch (e) {
|
|
144
|
+
sender.send({
|
|
145
|
+
type: "error",
|
|
146
|
+
in_reply_to: msg.id,
|
|
147
|
+
code: "internal_error",
|
|
148
|
+
message: e instanceof Error ? e.message : String(e),
|
|
149
|
+
});
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
//# sourceMappingURL=handlers.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"handlers.js","sourceRoot":"","sources":["../../src/actions/handlers.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAqFH;wDACwD;AACxD,MAAM,UAAU,aAAa,CAAC,KAAiB;IAC7C,OAAO;QACL,EAAE,EAAE,KAAK,CAAC,EAAE;QACZ,IAAI,EAAE,KAAK,CAAC,IAAI;QAChB,QAAQ,EAAE,KAAK,CAAC,QAAQ;QACxB,SAAS,EAAE,KAAK,CAAC,SAAS;QAC1B,cAAc,EAAE,KAAK,CAAC,aAAa;QACnC,gEAAgE;QAChE,2EAA2E;QAC3E,wDAAwD;QACxD,MAAM,EAAE,KAAK,CAAC,KAAK,EAAE,QAAQ,CAAC,OAAO,CAAC,IAAI,KAAK;KAChD,CAAC;AACJ,CAAC;AAED,8EAA8E;AAE9E,SAAS,EAAE,CAAC,MAAyB,EAAE,GAAmB,EAAE,MAAkB;IAC5E,MAAM,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,WAAW,EAAE,WAAW,EAAE,GAAG,CAAC,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC;AAClE,CAAC;AAED,SAAS,IAAI,CACX,MAAyB,EACzB,GAAmB,EACnB,MAAkB,EAClB,GAAY;IAEZ,MAAM,KAAK,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IAC/D,MAAM,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,cAAc,EAAE,WAAW,EAAE,GAAG,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC;AAC5E,CAAC;AAED,qEAAqE;AACrE,SAAS,OAAO,CACd,MAAyB,EACzB,GAAmB,EACnB,MAAkB,EAClB,IAAgB;IAEhB,IAAI,CAAC;QACH,IAAI,EAAE,CAAC;QACP,EAAE,CAAC,MAAM,EAAE,GAAG,EAAE,MAAM,CAAC,CAAC;IAC1B,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,IAAI,CAAC,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC;IAC/B,CAAC;AACH,CAAC;AAED,gEAAgE;AAChE,KAAK,UAAU,QAAQ,CACrB,MAAyB,EACzB,GAAmB,EACnB,MAAkB,EAClB,IAAyB;IAEzB,IAAI,CAAC;QACH,MAAM,IAAI,EAAE,CAAC;QACb,EAAE,CAAC,MAAM,EAAE,GAAG,EAAE,MAAM,CAAC,CAAC;QACxB,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,IAAI,CAAC,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC;QAC7B,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAUD,MAAM,UAAU,oBAAoB,CAClC,GAAqB,EACrB,MAAyB,EACzB,GAAsB;IAEtB,OAAO,CAAC,MAAM,EAAE,GAAG,EAAE,iBAAiB,EAAE,GAAG,EAAE;QAC3C,IAAI,CAAC,GAAG,EAAE,OAAO;YAAE,MAAM,IAAI,KAAK,CAAC,6CAA6C,CAAC,CAAC;QAClF,yEAAyE;QACzE,yEAAyE;QACzE,4EAA4E;QAC5E,iEAAiE;QACjE,GAAG,CAAC,OAAO,CAAC;YACV,kBAAkB,EAChB,kGAAkG;SACrG,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,GAAqB,EACrB,MAAyB,EACzB,GAAkB,EAClB,UAA0C;IAE1C,wEAAwE;IACxE,2EAA2E;IAC3E,4EAA4E;IAC5E,uEAAuE;IACvE,OAAO,QAAQ,CAAC,MAAM,EAAE,GAAG,EAAE,aAAa,EAAE,KAAK,IAAI,EAAE;QACrD,IAAI,CAAC,GAAG,EAAE,UAAU;YAAE,MAAM,IAAI,KAAK,CAAC,6CAA6C,CAAC,CAAC;QACrF,2EAA2E;QAC3E,mEAAmE;QACnE,sEAAsE;QACtE,0EAA0E;QAC1E,uEAAuE;QACvE,MAAM,MAAM,GAAG,MAAM,GAAG,CAAC,UAAU,CAAC;YAClC,WAAW,EAAE,KAAK,EAAE,QAAQ,EAAE,EAAE,GAAG,UAAU,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;SAC7D,CAAC,CAAC;QACH,qEAAqE;QACrE,kEAAkE;QAClE,iEAAiE;QACjE,IAAI,MAAM,CAAC,SAAS;YAAE,MAAM,IAAI,KAAK,CAAC,6BAA6B,CAAC,CAAC;IACvE,CAAC,CAAC,CAAC;AACL,CAAC;AAED,MAAM,UAAU,iBAAiB,CAC/B,EAAY,EACZ,MAAyB,EACzB,GAAmB;IAEnB,OAAO,CAAC,MAAM,EAAE,GAAG,EAAE,cAAc,EAAE,GAAG,EAAE;QACxC,EAAE,CAAC,gBAAgB,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;IACjC,CAAC,CAAC,CAAC;AACL,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,EAAY,EACZ,GAAwB,EACxB,MAAyB,EACzB,GAAgB,EAChB,SAAuD;IAEvD,MAAM,QAAQ,CAAC,MAAM,EAAE,GAAG,EAAE,WAAW,EAAE,KAAK,IAAI,EAAE;QAClD,+DAA+D;QAC/D,GAAG,CAAC,OAAO,EAAE,CAAC;QACd,MAAM,KAAK,GAAG,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,QAAQ,EAAE,GAAG,CAAC,QAAQ,CAAC,CAAC;QACnD,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,MAAM,IAAI,KAAK,CAAC,UAAU,GAAG,CAAC,QAAQ,IAAI,GAAG,CAAC,QAAQ,mBAAmB,CAAC,CAAC;QAC7E,CAAC;QACD,MAAM,OAAO,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;QACzC,IAAI,CAAC,OAAO;YAAE,MAAM,IAAI,KAAK,CAAC,mCAAmC,CAAC,CAAC;QACnE,wEAAwE;QACxE,wEAAwE;QACxE,yEAAyE;QACzE,qEAAqE;QACrE,0EAA0E;QAC1E,2EAA2E;QAC3E,SAAS,EAAE,CAAC,KAAK,CAAC,QAAQ,EAAE,KAAK,CAAC,EAAE,CAAC,CAAC;IACxC,CAAC,CAAC,CAAC;AACL,CAAC;AAED,MAAM,UAAU,gBAAgB,CAC9B,GAAqB,EACrB,GAAwB,EACxB,MAAyB,EACzB,GAAkB;IAElB,yEAAyE;IACzE,6DAA6D;IAC7D,IAAI,CAAC;QACH,GAAG,CAAC,OAAO,EAAE,CAAC;QACd,MAAM,MAAM,GAAG,GAAG,CAAC,YAAY,EAAE,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC;QACrD,MAAM,OAAO,GAAG,GAAG,EAAE,QAAQ,EAAE,EAAE,CAAC;QAClC,MAAM,CAAC,IAAI,CAAC;YACV,IAAI,EAAE,aAAa;YACnB,WAAW,EAAE,GAAG,CAAC,EAAE;YACnB,MAAM;YACN,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,SAAS;SACtD,CAAC,CAAC;IACL,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,MAAM,CAAC,IAAI,CAAC;YACV,IAAI,EAAE,OAAO;YACb,WAAW,EAAE,GAAG,CAAC,EAAE;YACnB,IAAI,EAAE,gBAAgB;YACtB,OAAO,EAAE,CAAC,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC;SACpD,CAAC,CAAC;IACL,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Plan/28 — ModelRegistry instance shared by the action handlers.
|
|
3
|
+
*
|
|
4
|
+
* pi-extension creates its **own** `ModelRegistry` instance alongside the
|
|
5
|
+
* one `AgentSession` instantiates internally. Both read the same on-disk
|
|
6
|
+
* sources (`~/.pi/auth/*`, `~/.pi/models.json`), so they stay in sync —
|
|
7
|
+
* we just call `refresh()` before each `list_models` request to capture
|
|
8
|
+
* changes the user makes via `/login` or `/scoped-models` in the TUI.
|
|
9
|
+
*
|
|
10
|
+
* Why a fresh instance instead of accessing Pi's: the `ExtensionAPI`
|
|
11
|
+
* surface does not expose `AgentSession`'s registry, and the public
|
|
12
|
+
* factories (`ModelRegistry.create`, `AuthStorage.create`) are the
|
|
13
|
+
* documented way for extensions to read the same catalog. No deep
|
|
14
|
+
* imports, no internal-state coupling — see the probe note in
|
|
15
|
+
* `plan/28-pi-commands.md` Wave 0.
|
|
16
|
+
*/
|
|
17
|
+
import { ModelRegistry } from "@mariozechner/pi-coding-agent";
|
|
18
|
+
/**
|
|
19
|
+
* Lazily instantiate the shared `ModelRegistry`. Subsequent calls return
|
|
20
|
+
* the same instance — keep it cached so `refresh()` cycles are cheap and
|
|
21
|
+
* the underlying `models.json` parse is amortized across requests.
|
|
22
|
+
*/
|
|
23
|
+
export declare function ensureModelRegistry(): ModelRegistry;
|
|
24
|
+
/** Test seam — drop the cached registry so tests can rebuild with fakes. */
|
|
25
|
+
export declare function _resetModelRegistryForTests(): void;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Plan/28 — ModelRegistry instance shared by the action handlers.
|
|
3
|
+
*
|
|
4
|
+
* pi-extension creates its **own** `ModelRegistry` instance alongside the
|
|
5
|
+
* one `AgentSession` instantiates internally. Both read the same on-disk
|
|
6
|
+
* sources (`~/.pi/auth/*`, `~/.pi/models.json`), so they stay in sync —
|
|
7
|
+
* we just call `refresh()` before each `list_models` request to capture
|
|
8
|
+
* changes the user makes via `/login` or `/scoped-models` in the TUI.
|
|
9
|
+
*
|
|
10
|
+
* Why a fresh instance instead of accessing Pi's: the `ExtensionAPI`
|
|
11
|
+
* surface does not expose `AgentSession`'s registry, and the public
|
|
12
|
+
* factories (`ModelRegistry.create`, `AuthStorage.create`) are the
|
|
13
|
+
* documented way for extensions to read the same catalog. No deep
|
|
14
|
+
* imports, no internal-state coupling — see the probe note in
|
|
15
|
+
* `plan/28-pi-commands.md` Wave 0.
|
|
16
|
+
*/
|
|
17
|
+
import { ModelRegistry, AuthStorage } from "@mariozechner/pi-coding-agent";
|
|
18
|
+
let _registry = null;
|
|
19
|
+
/**
|
|
20
|
+
* Lazily instantiate the shared `ModelRegistry`. Subsequent calls return
|
|
21
|
+
* the same instance — keep it cached so `refresh()` cycles are cheap and
|
|
22
|
+
* the underlying `models.json` parse is amortized across requests.
|
|
23
|
+
*/
|
|
24
|
+
export function ensureModelRegistry() {
|
|
25
|
+
if (!_registry) {
|
|
26
|
+
_registry = ModelRegistry.create(AuthStorage.create());
|
|
27
|
+
}
|
|
28
|
+
return _registry;
|
|
29
|
+
}
|
|
30
|
+
/** Test seam — drop the cached registry so tests can rebuild with fakes. */
|
|
31
|
+
export function _resetModelRegistryForTests() {
|
|
32
|
+
_registry = null;
|
|
33
|
+
}
|
|
34
|
+
//# sourceMappingURL=registry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registry.js","sourceRoot":"","sources":["../../src/actions/registry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,+BAA+B,CAAC;AAE3E,IAAI,SAAS,GAAyB,IAAI,CAAC;AAE3C;;;;GAIG;AACH,MAAM,UAAU,mBAAmB;IACjC,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,SAAS,GAAG,aAAa,CAAC,MAAM,CAAC,WAAW,CAAC,MAAM,EAAE,CAAC,CAAC;IACzD,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,4EAA4E;AAC5E,MAAM,UAAU,2BAA2B;IACzC,SAAS,GAAG,IAAI,CAAC;AACnB,CAAC"}
|
package/dist/bin/supervisord.js
CHANGED
|
@@ -18,8 +18,43 @@
|
|
|
18
18
|
*/
|
|
19
19
|
import { fileURLToPath } from "node:url";
|
|
20
20
|
import { dirname, join } from "node:path";
|
|
21
|
-
import { Supervisor } from "../daemon/supervisor.js";
|
|
21
|
+
import { Supervisor, SupervisorAlreadyRunningError } from "../daemon/supervisor.js";
|
|
22
|
+
const HELP_TEXT = `pi-supervisord — Remote Pi daemon supervisor
|
|
23
|
+
|
|
24
|
+
Usage: pi-supervisord
|
|
25
|
+
|
|
26
|
+
Runs the long-lived supervisor: reads ~/.pi/remote/daemons.json, spawns one
|
|
27
|
+
\`pi --mode rpc\` child per entry, and listens on ~/.pi/remote/supervisor.sock
|
|
28
|
+
for control requests from the \`remote-pi\` CLI.
|
|
29
|
+
|
|
30
|
+
This binary takes NO arguments — it is normally launched by systemd/launchd
|
|
31
|
+
(via \`remote-pi install\`), not by hand. Manage the fleet with:
|
|
32
|
+
remote-pi daemon start | stop | restart | status
|
|
33
|
+
remote-pi daemons
|
|
34
|
+
|
|
35
|
+
Options:
|
|
36
|
+
-h, --help Show this help and exit
|
|
37
|
+
-v, --version Print version and exit
|
|
38
|
+
`;
|
|
22
39
|
async function main() {
|
|
40
|
+
// Guard: any stray argument used to fall through and start a FULL
|
|
41
|
+
// supervisor (a `pi-supervisord --help` once ran for days). Handle the
|
|
42
|
+
// conventional flags explicitly and reject unknown args instead of
|
|
43
|
+
// silently spawning the daemon fleet.
|
|
44
|
+
const args = process.argv.slice(2);
|
|
45
|
+
if (args.includes("-h") || args.includes("--help")) {
|
|
46
|
+
process.stdout.write(HELP_TEXT);
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
if (args.includes("-v") || args.includes("--version")) {
|
|
50
|
+
process.stdout.write("pi-supervisord (remote-pi)\n");
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
if (args.length > 0) {
|
|
54
|
+
process.stderr.write(`pi-supervisord: unexpected argument(s): ${args.join(" ")}\n` +
|
|
55
|
+
"This binary takes no arguments. Run `pi-supervisord --help`.\n");
|
|
56
|
+
process.exit(2);
|
|
57
|
+
}
|
|
23
58
|
// The supervisor needs to point each spawned Pi at the extension
|
|
24
59
|
// entry it's bundled with. We're at `dist/bin/supervisord.js` after
|
|
25
60
|
// build; the extension is the sibling `dist/index.js`.
|
|
@@ -38,6 +73,13 @@ async function main() {
|
|
|
38
73
|
process.on("SIGINT", () => void shutdown("SIGINT"));
|
|
39
74
|
}
|
|
40
75
|
main().catch((err) => {
|
|
76
|
+
// "Already running" is a normal, expected condition (systemd/launchd may
|
|
77
|
+
// race a manual start, or the user double-launches) — not a crash. Report
|
|
78
|
+
// it calmly and exit 0 so service managers don't flag a failure loop.
|
|
79
|
+
if (err instanceof SupervisorAlreadyRunningError) {
|
|
80
|
+
process.stderr.write(`[pi-supervisord] ${err.message}\n`);
|
|
81
|
+
process.exit(0);
|
|
82
|
+
}
|
|
41
83
|
process.stderr.write(`[pi-supervisord] fatal: ${String(err)}\n`);
|
|
42
84
|
process.exit(1);
|
|
43
85
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"supervisord.js","sourceRoot":"","sources":["../../src/bin/supervisord.ts"],"names":[],"mappings":";AACA;;;;;;;;;;;;;;;;GAgBG;AACH,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;
|
|
1
|
+
{"version":3,"file":"supervisord.js","sourceRoot":"","sources":["../../src/bin/supervisord.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Plan/28 — Mirror of the Pi SDK's built-in slash commands.
|
|
3
|
+
*
|
|
4
|
+
* The SDK `@mariozechner/pi-coding-agent` defines `BUILTIN_SLASH_COMMANDS`
|
|
5
|
+
* in `dist/core/slash-commands.js` but does NOT re-export it from the main
|
|
6
|
+
* package entry, and the `exports` field of its `package.json` blocks deep
|
|
7
|
+
* imports. So pi-extension carries this manually-maintained mirror until
|
|
8
|
+
* an upstream PR exposes the constant publicly.
|
|
9
|
+
*
|
|
10
|
+
* **Maintenance**: when bumping `@mariozechner/pi-coding-agent`, diff the
|
|
11
|
+
* runtime's `BUILTIN_SLASH_COMMANDS` against this file and update names,
|
|
12
|
+
* descriptions, and the invokable / takes_args flags. The Wave 0 scout of
|
|
13
|
+
* plan/28 captured the 0.73.1 baseline; later bumps should leave a
|
|
14
|
+
* one-liner note here documenting which SDK version was synced.
|
|
15
|
+
*
|
|
16
|
+
* Synced from SDK version: **0.73.1**.
|
|
17
|
+
*
|
|
18
|
+
* **Invokability**: a builtin is `invokable: true` only when an entry in
|
|
19
|
+
* `ExtensionContextActions` lets the extension run it without simulating
|
|
20
|
+
* keyboard input in the TUI. The full mapping lives in `dispatcher.ts`
|
|
21
|
+
* (Wave B Slice 2). When more upstream APIs land, flip more flags to
|
|
22
|
+
* `true` here and add the corresponding dispatch in `dispatcher.ts`.
|
|
23
|
+
*/
|
|
24
|
+
import type { WireCommand } from "../protocol/types.js";
|
|
25
|
+
/**
|
|
26
|
+
* A built-in slash command as exposed by the Pi TUI. Mirror of the SDK's
|
|
27
|
+
* `BuiltinSlashCommand` interface, kept local to avoid the deep-import.
|
|
28
|
+
*/
|
|
29
|
+
export interface BuiltinMirrorEntry {
|
|
30
|
+
/** Slash name without the leading `/`. */
|
|
31
|
+
name: string;
|
|
32
|
+
/** One-line description shown in the app picker. */
|
|
33
|
+
description: string;
|
|
34
|
+
/**
|
|
35
|
+
* Whether the extension API can invoke this builtin programmatically
|
|
36
|
+
* via `ExtensionContextActions`. Stays `false` until plan/28 Wave B
|
|
37
|
+
* Slice 2 wires the dispatcher AND the underlying SDK action exists.
|
|
38
|
+
*/
|
|
39
|
+
invokable: boolean;
|
|
40
|
+
/**
|
|
41
|
+
* Whether the builtin meaningfully accepts free-text arguments after
|
|
42
|
+
* its name (e.g. `/model claude-opus-4-7`, `/name <session-name>`).
|
|
43
|
+
* Used by the app to decide whether to keep the input editable after
|
|
44
|
+
* the chip is placed.
|
|
45
|
+
*/
|
|
46
|
+
takes_args: boolean;
|
|
47
|
+
}
|
|
48
|
+
export declare const BUILTIN_SLASH_COMMANDS_MIRROR: readonly BuiltinMirrorEntry[];
|
|
49
|
+
/**
|
|
50
|
+
* Lookup helper used by the dispatcher. Returns the mirror entry for a
|
|
51
|
+
* builtin name, or `undefined` if `name` is not a known builtin.
|
|
52
|
+
*/
|
|
53
|
+
export declare function findBuiltin(name: string): BuiltinMirrorEntry | undefined;
|
|
54
|
+
/**
|
|
55
|
+
* Project a mirror entry to the wire schema. Shared by the list_commands
|
|
56
|
+
* handler so the mirror and the wire stay in lockstep.
|
|
57
|
+
*/
|
|
58
|
+
export declare function builtinToWire(entry: BuiltinMirrorEntry): WireCommand;
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Plan/28 — Mirror of the Pi SDK's built-in slash commands.
|
|
3
|
+
*
|
|
4
|
+
* The SDK `@mariozechner/pi-coding-agent` defines `BUILTIN_SLASH_COMMANDS`
|
|
5
|
+
* in `dist/core/slash-commands.js` but does NOT re-export it from the main
|
|
6
|
+
* package entry, and the `exports` field of its `package.json` blocks deep
|
|
7
|
+
* imports. So pi-extension carries this manually-maintained mirror until
|
|
8
|
+
* an upstream PR exposes the constant publicly.
|
|
9
|
+
*
|
|
10
|
+
* **Maintenance**: when bumping `@mariozechner/pi-coding-agent`, diff the
|
|
11
|
+
* runtime's `BUILTIN_SLASH_COMMANDS` against this file and update names,
|
|
12
|
+
* descriptions, and the invokable / takes_args flags. The Wave 0 scout of
|
|
13
|
+
* plan/28 captured the 0.73.1 baseline; later bumps should leave a
|
|
14
|
+
* one-liner note here documenting which SDK version was synced.
|
|
15
|
+
*
|
|
16
|
+
* Synced from SDK version: **0.73.1**.
|
|
17
|
+
*
|
|
18
|
+
* **Invokability**: a builtin is `invokable: true` only when an entry in
|
|
19
|
+
* `ExtensionContextActions` lets the extension run it without simulating
|
|
20
|
+
* keyboard input in the TUI. The full mapping lives in `dispatcher.ts`
|
|
21
|
+
* (Wave B Slice 2). When more upstream APIs land, flip more flags to
|
|
22
|
+
* `true` here and add the corresponding dispatch in `dispatcher.ts`.
|
|
23
|
+
*/
|
|
24
|
+
export const BUILTIN_SLASH_COMMANDS_MIRROR = [
|
|
25
|
+
// Session lifecycle
|
|
26
|
+
{ name: "compact", description: "Manually compact the session context", invokable: true, takes_args: false },
|
|
27
|
+
{ name: "new", description: "Start a new session", invokable: false, takes_args: false },
|
|
28
|
+
{ name: "resume", description: "Resume a different session", invokable: false, takes_args: false },
|
|
29
|
+
{ name: "fork", description: "Create a new fork from a previous user message", invokable: false, takes_args: false },
|
|
30
|
+
{ name: "clone", description: "Duplicate the current session at the current position", invokable: false, takes_args: false },
|
|
31
|
+
{ name: "tree", description: "Navigate session tree (switch branches)", invokable: false, takes_args: false },
|
|
32
|
+
{ name: "name", description: "Set session display name", invokable: false, takes_args: true },
|
|
33
|
+
{ name: "session", description: "Show session info and stats", invokable: false, takes_args: false },
|
|
34
|
+
// Model / providers
|
|
35
|
+
{ name: "model", description: "Select model", invokable: true, takes_args: true },
|
|
36
|
+
{ name: "scoped-models", description: "Enable/disable models for Ctrl+P cycling", invokable: false, takes_args: false },
|
|
37
|
+
{ name: "login", description: "Configure provider authentication", invokable: false, takes_args: false },
|
|
38
|
+
{ name: "logout", description: "Remove provider authentication", invokable: false, takes_args: false },
|
|
39
|
+
// Import / export / share
|
|
40
|
+
{ name: "export", description: "Export session (HTML default, or specify path)", invokable: false, takes_args: true },
|
|
41
|
+
{ name: "import", description: "Import and resume a session from a JSONL file", invokable: false, takes_args: true },
|
|
42
|
+
{ name: "share", description: "Share session as a secret GitHub gist", invokable: false, takes_args: false },
|
|
43
|
+
{ name: "copy", description: "Copy last agent message to clipboard", invokable: false, takes_args: false },
|
|
44
|
+
// UI / settings
|
|
45
|
+
{ name: "settings", description: "Open settings menu", invokable: false, takes_args: false },
|
|
46
|
+
{ name: "hotkeys", description: "Show all keyboard shortcuts", invokable: false, takes_args: false },
|
|
47
|
+
{ name: "changelog", description: "Show changelog entries", invokable: false, takes_args: false },
|
|
48
|
+
{ name: "reload", description: "Reload keybindings, extensions, skills, prompts, themes", invokable: false, takes_args: false },
|
|
49
|
+
{ name: "quit", description: "Quit pi", invokable: true, takes_args: false },
|
|
50
|
+
];
|
|
51
|
+
/**
|
|
52
|
+
* Lookup helper used by the dispatcher. Returns the mirror entry for a
|
|
53
|
+
* builtin name, or `undefined` if `name` is not a known builtin.
|
|
54
|
+
*/
|
|
55
|
+
export function findBuiltin(name) {
|
|
56
|
+
return BUILTIN_SLASH_COMMANDS_MIRROR.find((c) => c.name === name);
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Project a mirror entry to the wire schema. Shared by the list_commands
|
|
60
|
+
* handler so the mirror and the wire stay in lockstep.
|
|
61
|
+
*/
|
|
62
|
+
export function builtinToWire(entry) {
|
|
63
|
+
return {
|
|
64
|
+
name: entry.name,
|
|
65
|
+
description: entry.description,
|
|
66
|
+
source: "builtin",
|
|
67
|
+
invokable: entry.invokable,
|
|
68
|
+
takes_args: entry.takes_args,
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
//# sourceMappingURL=builtin_mirror.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"builtin_mirror.js","sourceRoot":"","sources":["../../src/commands/builtin_mirror.ts"],"names":[],"mappings":"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"}
|