@pmndrs/pine 0.0.0-stage → 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/LICENSE +21 -0
- package/README.md +180 -2
- package/bin/pine.js +27 -0
- package/docs/SKILL.md +189 -0
- package/docs/references/agents.md +368 -0
- package/docs/references/coding.md +126 -0
- package/docs/references/configuration.md +229 -0
- package/docs/references/events.md +263 -0
- package/docs/references/mcp.md +257 -0
- package/docs/references/operations.md +280 -0
- package/docs/references/overview.md +186 -0
- package/docs/references/security.md +489 -0
- package/docs/references/setup.md +181 -0
- package/docs/references/sources.md +768 -0
- package/docs/references/stack.md +105 -0
- package/docs/references/tui.md +348 -0
- package/examples/home/.env.example +5 -0
- package/examples/home/USER.md +4 -0
- package/examples/home/agents/main/agent.json +4 -0
- package/examples/home/agents/main/workspace/AGENTS.md +14 -0
- package/examples/home/agents/main/workspace/MEMORY.md +4 -0
- package/examples/home/agents/main/workspace/SOUL.md +4 -0
- package/examples/home/models.json +62 -0
- package/examples/home/pine.json +30 -0
- package/examples/home/skills/README.txt +7 -0
- package/examples/launchd/com.pine.daemon.plist +32 -0
- package/mcp/browser.d.ts +34 -0
- package/mcp/browser.js +228 -0
- package/mcp/commands.d.ts +20 -0
- package/mcp/commands.js +88 -0
- package/mcp/lib.d.ts +13 -0
- package/mcp/lib.js +50 -0
- package/mcp/web.d.ts +6 -0
- package/mcp/web.js +140 -0
- package/package.json +32 -4
- package/src/agent-admin.d.ts +24 -0
- package/src/agent-admin.js +55 -0
- package/src/agents.d.ts +343 -0
- package/src/agents.js +1587 -0
- package/src/cli.d.ts +2 -0
- package/src/cli.js +526 -0
- package/src/config.d.ts +351 -0
- package/src/config.js +514 -0
- package/src/dev/claude-model.d.ts +28 -0
- package/src/dev/claude-model.js +174 -0
- package/src/env-file.d.ts +4 -0
- package/src/env-file.js +40 -0
- package/src/http.d.ts +46 -0
- package/src/http.js +407 -0
- package/src/limiter.d.ts +32 -0
- package/src/limiter.js +84 -0
- package/src/login.d.ts +21 -0
- package/src/login.js +126 -0
- package/src/manual.d.ts +61 -0
- package/src/manual.js +425 -0
- package/src/mcp-config.d.ts +40 -0
- package/src/mcp-config.js +132 -0
- package/src/net.d.ts +36 -0
- package/src/net.js +122 -0
- package/src/pine.d.ts +32 -0
- package/src/pine.js +142 -0
- package/src/router.d.ts +56 -0
- package/src/router.js +164 -0
- package/src/sandbox-fs.d.ts +27 -0
- package/src/sandbox-fs.js +172 -0
- package/src/security.d.ts +121 -0
- package/src/security.js +363 -0
- package/src/skills.d.ts +67 -0
- package/src/skills.js +163 -0
- package/src/source-types.d.ts +61 -0
- package/src/source-types.js +1 -0
- package/src/sources/command.d.ts +4 -0
- package/src/sources/command.js +77 -0
- package/src/sources/folder.d.ts +6 -0
- package/src/sources/folder.js +116 -0
- package/src/sources/ftp.d.ts +4 -0
- package/src/sources/ftp.js +307 -0
- package/src/sources/http.d.ts +4 -0
- package/src/sources/http.js +201 -0
- package/src/sources/mqtt.d.ts +18 -0
- package/src/sources/mqtt.js +97 -0
- package/src/sources/telegram.d.ts +22 -0
- package/src/sources/telegram.js +269 -0
- package/src/sources/webhook.d.ts +4 -0
- package/src/sources/webhook.js +52 -0
- package/src/sources.d.ts +339 -0
- package/src/sources.js +955 -0
- package/src/store.d.ts +89 -0
- package/src/store.js +251 -0
- package/src/timers.d.ts +83 -0
- package/src/timers.js +318 -0
- package/src/tools.d.ts +6 -0
- package/src/tools.js +777 -0
- package/src/tui/app.d.ts +209 -0
- package/src/tui/app.js +2223 -0
- package/src/tui/client.d.ts +178 -0
- package/src/tui/client.js +116 -0
- package/src/tui/code-pane.d.ts +51 -0
- package/src/tui/code-pane.js +398 -0
- package/src/tui/highlight.d.ts +8 -0
- package/src/tui/highlight.js +86 -0
- package/src/tui/picture.d.ts +141 -0
- package/src/tui/picture.js +571 -0
- package/src/tui/run.d.ts +8 -0
- package/src/tui/run.js +97 -0
- package/src/tui/theme.d.ts +32 -0
- package/src/tui/theme.js +128 -0
- package/src/types.d.ts +124 -0
- package/src/types.js +1 -0
- package/src/update.d.ts +25 -0
- package/src/update.js +110 -0
- package/src/util.d.ts +32 -0
- package/src/util.js +116 -0
- package/src/watching.d.ts +20 -0
- package/src/watching.js +68 -0
- package/src/workspace-view.d.ts +38 -0
- package/src/workspace-view.js +160 -0
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import fs from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { loadConfig, PINE_ROOT, WORKSPACE_FILES } from "./config.js";
|
|
4
|
+
import { errText } from "./util.js";
|
|
5
|
+
/** The built-in tools an agent can be given. */
|
|
6
|
+
export const AGENT_TOOLS = ["read", "bash", "edit", "write", "grep", "find", "ls"];
|
|
7
|
+
/**
|
|
8
|
+
* Create an agent while the daemon runs: its folder with agent.json, and a workspace with its
|
|
9
|
+
* instructions (AGENTS.md) and the other files it keeps itself, as they come with a new home. The files are written first and then read back through the normal loader, so a new
|
|
10
|
+
* agent is checked exactly like one that was there at start; if it does not pass, the folder is
|
|
11
|
+
* taken away again. Nothing but these few lines goes into its agent.json.
|
|
12
|
+
*/
|
|
13
|
+
/** What is wrong with a proposed agent, as an error; nothing is written. Returns the cleaned-up values. */
|
|
14
|
+
export function checkNewAgent(cfg, spec) {
|
|
15
|
+
if (!/^[a-z][a-z0-9_-]{1,30}$/.test(spec.id))
|
|
16
|
+
throw new Error(`"${spec.id}" is not a usable agent id: lowercase letters, digits, - and _, starting with a letter, at least two characters`);
|
|
17
|
+
if (cfg.agents[spec.id])
|
|
18
|
+
throw new Error(`an agent called ${spec.id} exists already`);
|
|
19
|
+
const description = spec.description.replace(/\s+/g, " ").trim();
|
|
20
|
+
if (!description)
|
|
21
|
+
throw new Error("an agent needs a description: one line on what it is for");
|
|
22
|
+
if (!spec.instructions.trim())
|
|
23
|
+
throw new Error("an agent needs instructions: who it is and how it works");
|
|
24
|
+
const tools = spec.tools ?? AGENT_TOOLS;
|
|
25
|
+
const unknown = tools.filter((t) => !AGENT_TOOLS.includes(t));
|
|
26
|
+
if (unknown.length)
|
|
27
|
+
throw new Error(`unknown tool${unknown.length === 1 ? "" : "s"} ${unknown.join(", ")}. An agent can have: ${AGENT_TOOLS.join(", ")}`);
|
|
28
|
+
if (fs.existsSync(path.join(cfg.home, "agents", spec.id)))
|
|
29
|
+
throw new Error(`the folder agents/${spec.id} exists already`);
|
|
30
|
+
return { description, tools };
|
|
31
|
+
}
|
|
32
|
+
export function createAgent(cfg, spec) {
|
|
33
|
+
const { description, tools } = checkNewAgent(cfg, spec);
|
|
34
|
+
const dir = path.join(cfg.home, "agents", spec.id);
|
|
35
|
+
fs.mkdirSync(path.join(dir, "workspace"), { recursive: true, mode: 0o700 });
|
|
36
|
+
try {
|
|
37
|
+
fs.writeFileSync(path.join(dir, "agent.json"), `${JSON.stringify({ description, ...(spec.model ? { model: spec.model } : {}), tools }, null, 2)}\n`, { mode: 0o600 });
|
|
38
|
+
fs.writeFileSync(path.join(dir, "workspace", "AGENTS.md"), `${spec.instructions.trim()}\n`, { mode: 0o600 });
|
|
39
|
+
// The rest starts as the stubs a new home has.
|
|
40
|
+
for (const name of WORKSPACE_FILES.slice(1)) {
|
|
41
|
+
const stub = path.join(PINE_ROOT, "examples", "home", "agents", "main", "workspace", name);
|
|
42
|
+
if (fs.existsSync(stub))
|
|
43
|
+
fs.copyFileSync(stub, path.join(dir, "workspace", name)), fs.chmodSync(path.join(dir, "workspace", name), 0o600);
|
|
44
|
+
}
|
|
45
|
+
const made = loadConfig(cfg.home).agents[spec.id];
|
|
46
|
+
if (!made)
|
|
47
|
+
throw new Error("the new agent was not found after writing it");
|
|
48
|
+
cfg.agents[spec.id] = made;
|
|
49
|
+
return made;
|
|
50
|
+
}
|
|
51
|
+
catch (e) {
|
|
52
|
+
fs.rmSync(dir, { recursive: true, force: true });
|
|
53
|
+
throw new Error(`the agent could not be created: ${errText(e)}`);
|
|
54
|
+
}
|
|
55
|
+
}
|
package/src/agents.d.ts
ADDED
|
@@ -0,0 +1,343 @@
|
|
|
1
|
+
import { ModelRuntime } from "@earendil-works/pi-coding-agent";
|
|
2
|
+
import { type AgentConfig, type McpServerConfig, type Mode, type PineConfig } from "./config.ts";
|
|
3
|
+
import { Limiter, type Slot } from "./limiter.ts";
|
|
4
|
+
import { type Approvals, type SandboxVariant } from "./security.ts";
|
|
5
|
+
import type { Bus, Kv, State, TaskStore } from "./store.ts";
|
|
6
|
+
import type { SourceHost } from "./sources.ts";
|
|
7
|
+
import type { Scheduler } from "./timers.ts";
|
|
8
|
+
import type { ContextUse, ImageRef, PineEvent, ReplyTarget, Task, TaskKind, TaskResult, TranscriptEntry, Trust } from "./types.ts";
|
|
9
|
+
import { type Logger } from "./util.ts";
|
|
10
|
+
export declare const THINKING_LEVELS: string[];
|
|
11
|
+
export interface SubmitOptions {
|
|
12
|
+
agent: string;
|
|
13
|
+
prompt: string;
|
|
14
|
+
/** Session key. Default "main". "new" runs in a fresh session that is closed afterwards. */
|
|
15
|
+
session?: string;
|
|
16
|
+
kind?: TaskKind;
|
|
17
|
+
priority?: number;
|
|
18
|
+
event?: PineEvent;
|
|
19
|
+
reply?: ReplyTarget;
|
|
20
|
+
parent?: Task;
|
|
21
|
+
images?: ImageRef[];
|
|
22
|
+
/** Files the owner hands over with the message. They are saved to inbox/ in the workspace. */
|
|
23
|
+
attachments?: Array<{
|
|
24
|
+
name: string;
|
|
25
|
+
data: string;
|
|
26
|
+
}>;
|
|
27
|
+
notify?: {
|
|
28
|
+
agent: string;
|
|
29
|
+
session: string;
|
|
30
|
+
};
|
|
31
|
+
whenBusy?: "queue" | "steer";
|
|
32
|
+
trust?: Trust;
|
|
33
|
+
tainted?: string;
|
|
34
|
+
leaf?: boolean;
|
|
35
|
+
tools?: string[];
|
|
36
|
+
label?: string;
|
|
37
|
+
}
|
|
38
|
+
/** Capabilities of one run, decided by who started it. */
|
|
39
|
+
export interface Profile {
|
|
40
|
+
tools: string[];
|
|
41
|
+
mcp: Record<string, McpServerConfig>;
|
|
42
|
+
delegates: string[];
|
|
43
|
+
subagents: boolean;
|
|
44
|
+
publish: string[];
|
|
45
|
+
stateWrite: boolean;
|
|
46
|
+
/** A sub-agent: a copy doing one job. */
|
|
47
|
+
leaf: boolean;
|
|
48
|
+
}
|
|
49
|
+
export interface RunContext {
|
|
50
|
+
task: Task;
|
|
51
|
+
slot: Slot;
|
|
52
|
+
cancelled?: boolean;
|
|
53
|
+
timedOut?: boolean;
|
|
54
|
+
}
|
|
55
|
+
export interface Live {
|
|
56
|
+
agent: AgentConfig;
|
|
57
|
+
key: string;
|
|
58
|
+
ephemeral: boolean;
|
|
59
|
+
trust: Trust;
|
|
60
|
+
runtime: any;
|
|
61
|
+
session: any;
|
|
62
|
+
current?: RunContext;
|
|
63
|
+
tainted?: string;
|
|
64
|
+
taint(reason: string): void;
|
|
65
|
+
/** True when the run must not change instructions or act without checks: untrusted start or tainted session. */
|
|
66
|
+
restricted(): boolean;
|
|
67
|
+
/** The mode in force for the call that is about to run (see effectiveMode). */
|
|
68
|
+
mode(): Mode;
|
|
69
|
+
/** Which sandbox the next shell or file call runs in. */
|
|
70
|
+
variant(): SandboxVariant;
|
|
71
|
+
/**
|
|
72
|
+
* The conversation whose permissions apply here ("agent:session"). A sub-agent is a copy of its
|
|
73
|
+
* conversation doing part of that conversation's job, so it has that conversation's key: what the
|
|
74
|
+
* owner allowed there (access, "always" answers) holds for it, and what it is allowed holds there.
|
|
75
|
+
*/
|
|
76
|
+
perm: string;
|
|
77
|
+
/** Access the owner granted to this conversation beyond the agent's own folders. Holds until the conversation is reset or the daemon restarts. */
|
|
78
|
+
grant(kind: "read" | "write" | "network", target?: string): string | undefined;
|
|
79
|
+
/** Take over what the conversation has been granted since this session's sandbox was written. */
|
|
80
|
+
syncGrants(): void;
|
|
81
|
+
/** Whether this session's shell can use the network right now. */
|
|
82
|
+
network(): boolean;
|
|
83
|
+
/** The folder the owner opened for this conversation, if any: where its tools start, and readable and writable for it. */
|
|
84
|
+
folder?: string;
|
|
85
|
+
sandboxed: boolean;
|
|
86
|
+
idleTimer?: NodeJS.Timeout;
|
|
87
|
+
/** The last "[pine]" note this session was sent, without its time. A new one goes out when this changes. */
|
|
88
|
+
noteKey?: string;
|
|
89
|
+
/** The configuration changed under this session; close it when it is idle so the next task starts it anew. */
|
|
90
|
+
stale?: boolean;
|
|
91
|
+
contextStamp: string;
|
|
92
|
+
lastUsed: number;
|
|
93
|
+
}
|
|
94
|
+
export interface AgentManagerDeps {
|
|
95
|
+
cfg: PineConfig;
|
|
96
|
+
bus: Bus;
|
|
97
|
+
state: State;
|
|
98
|
+
kv: Kv;
|
|
99
|
+
tasks: TaskStore;
|
|
100
|
+
approvals: Approvals;
|
|
101
|
+
log: Logger;
|
|
102
|
+
}
|
|
103
|
+
export declare class AgentManager {
|
|
104
|
+
cfg: PineConfig;
|
|
105
|
+
bus: Bus;
|
|
106
|
+
state: State;
|
|
107
|
+
kv: Kv;
|
|
108
|
+
tasks: TaskStore;
|
|
109
|
+
approvals: Approvals;
|
|
110
|
+
limiter: Limiter;
|
|
111
|
+
private log;
|
|
112
|
+
/** Event sources and subscriptions. Set by the daemon once both exist. */
|
|
113
|
+
sources?: SourceHost;
|
|
114
|
+
/** Set by the daemon once the scheduler exists. */
|
|
115
|
+
schedules?: Scheduler;
|
|
116
|
+
private modelRuntime;
|
|
117
|
+
private lives;
|
|
118
|
+
private creating;
|
|
119
|
+
private lanes;
|
|
120
|
+
private running;
|
|
121
|
+
private waiters;
|
|
122
|
+
private taints;
|
|
123
|
+
private stopping;
|
|
124
|
+
private warnedNoSandbox;
|
|
125
|
+
/** Conversations ("agent:session") where the owner chose bypass although they have read outside content. */
|
|
126
|
+
private bypassAnyway;
|
|
127
|
+
/**
|
|
128
|
+
* What the owner allowed "always" in a conversation ("agent:session" -> "server:<name>" or
|
|
129
|
+
* "tool:<name>"), with the state the conversation was in. A yes given before the conversation
|
|
130
|
+
* read outside content does not cover it afterwards. Gone with a reset or a restart.
|
|
131
|
+
*/
|
|
132
|
+
private allowed;
|
|
133
|
+
/** Access granted to a conversation with request_access, by the same key. Its sub-agents share it. */
|
|
134
|
+
private grants;
|
|
135
|
+
constructor(deps: AgentManagerDeps);
|
|
136
|
+
init(): Promise<void>;
|
|
137
|
+
get models(): ModelRuntime;
|
|
138
|
+
modelFor(agent: AgentConfig): any;
|
|
139
|
+
resolveModel(ref: string): any;
|
|
140
|
+
/** Models that have credentials (or need none), as "provider/id". */
|
|
141
|
+
availableModels(): Promise<string[]>;
|
|
142
|
+
/**
|
|
143
|
+
* Switch an agent to another model and save the choice in its agent.json, so it is still the
|
|
144
|
+
* agent's model after a restart. Sessions pick it up with their next task and keep their history.
|
|
145
|
+
*/
|
|
146
|
+
setModel(agentId: string, ref: string): Promise<void>;
|
|
147
|
+
submit(o: SubmitOptions): Task;
|
|
148
|
+
/** Write attached files into <workspace>/inbox and say which of them are images. */
|
|
149
|
+
private saveAttachments;
|
|
150
|
+
wait(id: number): Promise<TaskResult>;
|
|
151
|
+
/** Submit and wait. */
|
|
152
|
+
run(o: SubmitOptions): Promise<TaskResult>;
|
|
153
|
+
/** Wait for child tasks while lending this run's model slot to them. Aborting cancels the children. */
|
|
154
|
+
awaitChildren(run: RunContext, ids: number[], signal?: AbortSignal): Promise<TaskResult[]>;
|
|
155
|
+
cancel(id: number): boolean;
|
|
156
|
+
/**
|
|
157
|
+
* What a task did, step by step, read from the session file pi keeps for it: the text it was
|
|
158
|
+
* given, what it wrote and thought, and every tool call with the start of its result. This is how
|
|
159
|
+
* a sub-agent's work can be looked at, during the run and afterwards; its session folder
|
|
160
|
+
* (sessions/_tasks/<task id>) stays on disk. For a task in a named session, only that task's part
|
|
161
|
+
* of the conversation is returned.
|
|
162
|
+
*/
|
|
163
|
+
/** The folder a UI shows beside a conversation: the one opened for it, else the agent's workspace. */
|
|
164
|
+
viewRoot(agentId: string, session: string): string | undefined;
|
|
165
|
+
/** What a task did, step by step. `full` keeps each tool's whole output (for reading it), not just its start. */
|
|
166
|
+
transcript(id: number, full?: boolean): {
|
|
167
|
+
task: Task;
|
|
168
|
+
entries: TranscriptEntry[];
|
|
169
|
+
} | undefined;
|
|
170
|
+
/** Save the pictures in a tool result under data/media/tool, so a UI can fetch them by id. */
|
|
171
|
+
private keepToolImages;
|
|
172
|
+
/** A picture a tool returned (see keepToolImages). */
|
|
173
|
+
toolImage(id: string): Picture | undefined;
|
|
174
|
+
/** The n-th picture that came with a task: an attachment, or an image an adapter passed along. */
|
|
175
|
+
taskImage(taskId: number, n: number): Picture | undefined;
|
|
176
|
+
/**
|
|
177
|
+
* A picture or video in an agent's workspace, which the agent refers to in an answer. Only real
|
|
178
|
+
* image and video files inside the workspace are served: the path comes from model output, and this endpoint
|
|
179
|
+
* must not become a way to read other files.
|
|
180
|
+
*/
|
|
181
|
+
workspaceImage(agentId: string, file: string, session?: string): Picture | undefined;
|
|
182
|
+
/** A picture at a web address, fetched because the owner asked for it. Https and public addresses only. */
|
|
183
|
+
fetchImage(url: string): Promise<Picture | undefined>;
|
|
184
|
+
/** Remove kept tool pictures that are older than the event log reaches back. */
|
|
185
|
+
pruneMedia(olderThanMs: number): void;
|
|
186
|
+
status(): {
|
|
187
|
+
limiter: {
|
|
188
|
+
active: number;
|
|
189
|
+
waiting: number;
|
|
190
|
+
max: number;
|
|
191
|
+
};
|
|
192
|
+
running: {
|
|
193
|
+
task: number;
|
|
194
|
+
agent: string;
|
|
195
|
+
session: string;
|
|
196
|
+
kind: TaskKind;
|
|
197
|
+
}[];
|
|
198
|
+
sessions: {
|
|
199
|
+
agent: string;
|
|
200
|
+
session: string;
|
|
201
|
+
busy: boolean;
|
|
202
|
+
tainted: string | undefined;
|
|
203
|
+
trust: Trust;
|
|
204
|
+
mode: Mode;
|
|
205
|
+
context: ContextUse | undefined;
|
|
206
|
+
}[];
|
|
207
|
+
modes: {
|
|
208
|
+
[k: string]: Mode;
|
|
209
|
+
};
|
|
210
|
+
};
|
|
211
|
+
/** Forget a session's history (and its taint). The next task with this key starts fresh. */
|
|
212
|
+
resetSession(agentId: string, session?: string): Promise<boolean>;
|
|
213
|
+
folderOf(agentId: string, session: string): string | undefined;
|
|
214
|
+
/** Every conversation of an agent that has a folder, also one nothing was said in yet. */
|
|
215
|
+
folders(agentId: string): Array<{
|
|
216
|
+
session: string;
|
|
217
|
+
folder: string;
|
|
218
|
+
}>;
|
|
219
|
+
/** Why a folder cannot be opened for an agent, or undefined when it can. */
|
|
220
|
+
private folderProblem;
|
|
221
|
+
/** Open a folder for a conversation, or with `null` go back to the agent's own workspace. Takes effect with its next message. */
|
|
222
|
+
setFolder(agentId: string, session: string, wanted: string | null): Promise<{
|
|
223
|
+
folder?: string;
|
|
224
|
+
}>;
|
|
225
|
+
/** The session keys a conversation's name stands for: its own and the one outside content is handled in. */
|
|
226
|
+
private keysOf;
|
|
227
|
+
private pinned;
|
|
228
|
+
/** The tabs a UI had open, to open them again, and so that an open conversation is not removed. */
|
|
229
|
+
uiTabs(): {
|
|
230
|
+
tabs: Array<{
|
|
231
|
+
agent: string;
|
|
232
|
+
session: string;
|
|
233
|
+
}>;
|
|
234
|
+
active: number;
|
|
235
|
+
code: boolean;
|
|
236
|
+
};
|
|
237
|
+
/** `code`: whether the pane beside the conversation was open. Left as it was when not given. */
|
|
238
|
+
saveUiTabs(tabs: unknown, active: unknown, code?: unknown): void;
|
|
239
|
+
/**
|
|
240
|
+
* An agent's conversations: pinned ones first, then the most recently used. `expires` is when
|
|
241
|
+
* one is removed by itself if nothing more is said in it; one without it stays.
|
|
242
|
+
*/
|
|
243
|
+
conversations(agentId: string): Array<{
|
|
244
|
+
session: string;
|
|
245
|
+
tasks: number;
|
|
246
|
+
last: number;
|
|
247
|
+
pinned: boolean;
|
|
248
|
+
open: boolean;
|
|
249
|
+
expires?: number;
|
|
250
|
+
folder?: string;
|
|
251
|
+
}>;
|
|
252
|
+
/** Pin a conversation, so that it stays however long it is not used, or take the pin off. */
|
|
253
|
+
pinSession(agentId: string, session: string, on: boolean): boolean;
|
|
254
|
+
/** Remove a conversation for good: what was said in it, what it may do without asking, what it listens to. */
|
|
255
|
+
removeSession(agentId: string, session: string): Promise<{
|
|
256
|
+
removed: boolean;
|
|
257
|
+
unsubscribed: string[];
|
|
258
|
+
sources: string[];
|
|
259
|
+
servers: string[];
|
|
260
|
+
}>;
|
|
261
|
+
/** Give a conversation another name. Everything stays with it: its history, its pin, what it listens to. */
|
|
262
|
+
renameSession(agentId: string, from: string, wanted: string): Promise<{
|
|
263
|
+
session: string;
|
|
264
|
+
}>;
|
|
265
|
+
/**
|
|
266
|
+
* The daily tidying: conversations that have reached their time, and the copies kept of reset
|
|
267
|
+
* conversations once they are older than the event log reaches back.
|
|
268
|
+
*/
|
|
269
|
+
pruneConversations(): Promise<number>;
|
|
270
|
+
stop(): Promise<void>;
|
|
271
|
+
private enqueue;
|
|
272
|
+
private execute;
|
|
273
|
+
private causeOf;
|
|
274
|
+
private resultOf;
|
|
275
|
+
private finish;
|
|
276
|
+
profileFor(agent: AgentConfig, trust: Trust, task?: Task): Profile;
|
|
277
|
+
private live;
|
|
278
|
+
private createLive;
|
|
279
|
+
/** The session whose permissions a task runs under: its own, or for a sub-agent the one that started it. */
|
|
280
|
+
private permSession;
|
|
281
|
+
/** Everything pine itself adds to a session: MCP servers, the sandboxed shell, the policy gate, and context. */
|
|
282
|
+
/**
|
|
283
|
+
* The mode that applies right now. A run started by an outside event never gets more than
|
|
284
|
+
* "auto", and bypass is suspended in a session that has read outside content unless the
|
|
285
|
+
* configuration says otherwise: those are the two situations in which someone else may be steering.
|
|
286
|
+
*/
|
|
287
|
+
effectiveMode(agent: AgentConfig, live: Pick<Live, "trust" | "tainted" | "key"> & {
|
|
288
|
+
perm?: string;
|
|
289
|
+
}): Mode;
|
|
290
|
+
/**
|
|
291
|
+
* Set how much an agent's model reasons before it answers, and save it in agent.json. Applies
|
|
292
|
+
* from the next model call. A model that cannot reason ignores it; pi lowers a level the model
|
|
293
|
+
* does not offer to the nearest one it does.
|
|
294
|
+
*/
|
|
295
|
+
setThinking(agentId: string, level: string): void;
|
|
296
|
+
/**
|
|
297
|
+
* Tools or servers of some agents changed. Idle sessions are closed now and busy ones when their
|
|
298
|
+
* task ends; each continues from its history with the new set when it is next used.
|
|
299
|
+
*/
|
|
300
|
+
refreshSessions(agentIds?: string[]): Promise<void>;
|
|
301
|
+
/**
|
|
302
|
+
* Change an agent's mode until the daemon restarts. Takes effect on its next tool call.
|
|
303
|
+
* `anyway` names a conversation in which the owner, knowing it has read outside content,
|
|
304
|
+
* wants bypass to apply all the same.
|
|
305
|
+
*/
|
|
306
|
+
setMode(agentId: string, mode: Mode, anyway?: string): void;
|
|
307
|
+
private coreExtension;
|
|
308
|
+
/**
|
|
309
|
+
* Can this agent move information out of the machine: web or remote MCP tools, or a shell with
|
|
310
|
+
* network? A tainted session that hands such an agent a task could be leaking through it.
|
|
311
|
+
*/
|
|
312
|
+
canSendOut(agentId: string): boolean;
|
|
313
|
+
/**
|
|
314
|
+
* The part of the system prompt that pine adds. Everything here is fixed for the life of a
|
|
315
|
+
* session. A model server reuses its work only for a prompt whose beginning is unchanged, and
|
|
316
|
+
* the system prompt is the very beginning: one changing word here would make a local model
|
|
317
|
+
* read the whole conversation again on every turn. What changes goes into contextNote().
|
|
318
|
+
*/
|
|
319
|
+
private contextBlock;
|
|
320
|
+
/**
|
|
321
|
+
* What is true right now: the time, the mode, trust, shared state. It is put in front of the
|
|
322
|
+
* incoming message, at the end of the conversation, and only when something other than the
|
|
323
|
+
* clock has changed since the last note, so the conversation so far stays byte for byte what
|
|
324
|
+
* the model server has already seen. `key` is the note without the time.
|
|
325
|
+
*/
|
|
326
|
+
private contextNote;
|
|
327
|
+
private sizeOf;
|
|
328
|
+
/**
|
|
329
|
+
* The files that make up an agent's instructions, in the order they enter its prompt; those
|
|
330
|
+
* that exist. First what the owner alone can change, then what the agent keeps itself, the
|
|
331
|
+
* one that changes most often last.
|
|
332
|
+
*/
|
|
333
|
+
private instructionFiles;
|
|
334
|
+
private stamp;
|
|
335
|
+
/** pi reads instruction files once per session; pick up edits made since. */
|
|
336
|
+
private refresh;
|
|
337
|
+
private armIdle;
|
|
338
|
+
private dispose;
|
|
339
|
+
}
|
|
340
|
+
export interface Picture {
|
|
341
|
+
mime: string;
|
|
342
|
+
bytes: Buffer;
|
|
343
|
+
}
|