@zetaloop/chappie 0.5.0 → 1.0.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.
@@ -0,0 +1,13 @@
1
+ Chappie connects this conversation to coding-agent sessions across devices. Native tools run on the selected session's device, using its working directory.
2
+
3
+ Select the intended session with init. Resume existing work with the task's sessionId, including from another chat or branch. Use sessions to identify the target by agent, device, directory, or name when its ID is unknown.
4
+
5
+ init sets this conversation's default target. A sessionId on another tool selects that operation's target. Read the file at globalAgents.path when returned, and follow initialization.instructions for participation in the task.
6
+
7
+ Read recent history to recover progress. Use tools to obtain native definitions before constructing call arguments.
8
+
9
+ Use chat for progress, explanations, and completion in the selected session. Use transfer to exchange files and images with ChatGPT or another session. For questions in the agent interface, call its installed interactive tool.
10
+
11
+ Address new local user input delivered with results. Check delivered results before repeating interrupted operations. Use the session's persistent process facilities for long-running commands and read their saved output as needed.
12
+
13
+ ChatGPT removes the middle of tool responses exceeding 10,000 tokens. Use history pagination or limit native tool output when needed.
package/dist/omp.js ADDED
@@ -0,0 +1,240 @@
1
+ import { createRequire } from "node:module"; const require = createRequire(import.meta.url);
2
+ import {
3
+ journalHistory
4
+ } from "./chunk-OWAAWZNT.js";
5
+ import {
6
+ ProviderOutput,
7
+ Session,
8
+ createMessage
9
+ } from "./chunk-5CKVVDZ2.js";
10
+ import {
11
+ localTools
12
+ } from "./chunk-DM523QRR.js";
13
+ import {
14
+ ipcEndpoint
15
+ } from "./chunk-EIPDEA3I.js";
16
+ import "./chunk-GX4JWLHH.js";
17
+ import {
18
+ getDirectory,
19
+ readConfig,
20
+ toJSONSchema
21
+ } from "./chunk-GWYP7B66.js";
22
+ import "./chunk-UOFCCHBS.js";
23
+
24
+ // src/omp.ts
25
+ import { access } from "node:fs/promises";
26
+ import { hostname } from "node:os";
27
+ import { resolve } from "node:path";
28
+ import { createAssistantMessageEventStream } from "@oh-my-pi/pi-ai/utils/event-stream";
29
+ import { toolWireSchema } from "@oh-my-pi/pi-ai/utils/schema/wire";
30
+ import { getAgentDir } from "@oh-my-pi/pi-utils";
31
+ async function chappie(omp) {
32
+ const config = await readConfig();
33
+ let context;
34
+ let inputCursor = null;
35
+ let manager;
36
+ let unsubscribe;
37
+ const current = () => {
38
+ if (!context) throw new Error("Session has not started");
39
+ return context;
40
+ };
41
+ const host = {
42
+ describe() {
43
+ const ctx = current();
44
+ const name = ctx.sessionManager.getSessionName();
45
+ return {
46
+ id: ctx.sessionManager.getSessionId(),
47
+ agent: "omp",
48
+ cwd: ctx.cwd,
49
+ device: hostname(),
50
+ ...ctx.model ? { model: `${ctx.model.provider}/${ctx.model.id}` } : {},
51
+ ...name ? { name } : {}
52
+ };
53
+ },
54
+ active: () => context?.model?.provider === "chappie",
55
+ isIdle: () => current().isIdle(),
56
+ async inspect() {
57
+ const active = new Set(omp.getActiveTools());
58
+ const path = resolve(getAgentDir(), "AGENTS.md");
59
+ let globalAgents;
60
+ try {
61
+ await access(path);
62
+ globalAgents = { path };
63
+ } catch (error) {
64
+ if (error.code !== "ENOENT") throw error;
65
+ }
66
+ return {
67
+ tools: omp.getAllTools().filter((tool) => active.has(tool.name)).map((tool) => ({ ...tool, parameters: toolWireSchema(tool) })),
68
+ skills: omp.getCommands().filter((command) => command.source === "skill"),
69
+ ...globalAgents ? { globalAgents } : {}
70
+ };
71
+ },
72
+ async history(range) {
73
+ const ctx = current();
74
+ return journalHistory(
75
+ ctx.sessionManager.getBranch(),
76
+ ctx.sessionManager.getSessionId(),
77
+ range
78
+ );
79
+ },
80
+ inputs() {
81
+ const store = current().sessionManager;
82
+ const leafId = store.getLeafId();
83
+ if (leafId === inputCursor) return [];
84
+ const entries = [];
85
+ let entry = store.getLeafEntry();
86
+ while (entry && entry.id !== inputCursor) {
87
+ entries.push(entry);
88
+ entry = entry.parentId ? store.getEntry(entry.parentId) : void 0;
89
+ }
90
+ const changedBranch = inputCursor !== null && !entry;
91
+ inputCursor = leafId;
92
+ if (changedBranch) {
93
+ session.resetInputs();
94
+ return [];
95
+ }
96
+ const inputs = [];
97
+ for (const entry2 of entries.reverse()) {
98
+ if (entry2.type !== "message" || entry2.message.role !== "user") continue;
99
+ const message = entry2.message;
100
+ inputs.push({ id: entry2.id, sessionId: store.getSessionId(), message });
101
+ }
102
+ return inputs;
103
+ },
104
+ resetInputs() {
105
+ inputCursor = context?.sessionManager.getLeafId() ?? null;
106
+ },
107
+ wake() {
108
+ omp.sendMessage(
109
+ { customType: "chappie.request", content: "", display: false },
110
+ { triggerTurn: true, deliverAs: "nextTurn" }
111
+ );
112
+ },
113
+ abort: () => current().abort(),
114
+ notify(message, type, activity) {
115
+ omp.appendEntry("chappie.notice", { message, type, ...activity });
116
+ context?.ui.notify(message, type);
117
+ }
118
+ };
119
+ const session = new Session(host, config);
120
+ const tools = localTools(session);
121
+ const names = new Set(tools.map((tool) => tool.name));
122
+ async function updateTools() {
123
+ const desired = session.active ? ["transfer"] : session.localTools ? [...names] : [];
124
+ const active = omp.getActiveTools();
125
+ const enabled = active.filter((name) => names.has(name));
126
+ if (enabled.length === desired.length && enabled.every((name) => desired.includes(name)))
127
+ return;
128
+ await omp.setActiveTools([
129
+ ...active.filter((name) => !names.has(name)),
130
+ ...desired
131
+ ]);
132
+ }
133
+ async function update(ctx) {
134
+ context = ctx;
135
+ if (manager !== ctx.sessionManager) {
136
+ unsubscribe?.();
137
+ manager = ctx.sessionManager;
138
+ const store = manager;
139
+ const append = store.appendModelChange;
140
+ const record = function(...args) {
141
+ const result = append.apply(this, args);
142
+ if (session.update()) void updateTools();
143
+ return result;
144
+ };
145
+ store.appendModelChange = record;
146
+ const renamed = store.onSessionNameChanged(() => session.update());
147
+ unsubscribe = () => {
148
+ renamed();
149
+ if (store.appendModelChange === record)
150
+ store.appendModelChange = append;
151
+ };
152
+ }
153
+ if (session.update()) await updateTools();
154
+ }
155
+ omp.on("session_start", (_event, ctx) => update(ctx));
156
+ omp.on("session_switch", (_event, ctx) => update(ctx));
157
+ omp.on("session_branch", (_event, ctx) => update(ctx));
158
+ omp.on("session_tree", async (_event, ctx) => {
159
+ await update(ctx);
160
+ session.resetInputs();
161
+ session.historyChanged();
162
+ });
163
+ omp.on("context", (event) => ({
164
+ messages: host.active() ? [] : event.messages.filter(
165
+ (message) => message.role !== "custom" || message.customType !== "chappie.request"
166
+ )
167
+ }));
168
+ omp.on("message_start", (_event, ctx) => {
169
+ context = ctx;
170
+ session.historyChanged();
171
+ });
172
+ omp.on("message_end", (_event, ctx) => {
173
+ context = ctx;
174
+ session.historyChanged();
175
+ });
176
+ omp.on("session_compact", (_event, ctx) => {
177
+ context = ctx;
178
+ session.historyChanged();
179
+ });
180
+ omp.on("turn_end", (event, ctx) => {
181
+ context = ctx;
182
+ session.complete(event.message, event.toolResults);
183
+ });
184
+ omp.on("agent_end", async (_event, ctx) => {
185
+ context = ctx;
186
+ await session.settled();
187
+ });
188
+ omp.on("session_shutdown", () => {
189
+ unsubscribe?.();
190
+ session.close();
191
+ });
192
+ for (const tool of tools) {
193
+ omp.registerTool({
194
+ name: tool.name,
195
+ label: tool.name,
196
+ description: tool.description,
197
+ parameters: toJSONSchema(tool.parameters),
198
+ async execute(_id, args, signal, update2) {
199
+ const result = await tool.execute(
200
+ args,
201
+ signal,
202
+ (result2) => update2?.({ ...result2, details: result2.details })
203
+ );
204
+ return { ...result, details: result.details };
205
+ }
206
+ });
207
+ }
208
+ const provider = {
209
+ api: "chappie",
210
+ baseUrl: config.connect ?? ipcEndpoint(getDirectory()),
211
+ apiKey: "chappie",
212
+ models: [
213
+ {
214
+ id: "chatgpt",
215
+ name: "ChatGPT",
216
+ reasoning: false,
217
+ input: ["text", "image"],
218
+ cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
219
+ contextWindow: 1e9,
220
+ maxTokens: 1e9
221
+ }
222
+ ],
223
+ streamSimple(model, context2, options) {
224
+ const stream = createAssistantMessageEventStream();
225
+ const output = new ProviderOutput(
226
+ createMessage(model, "stop"),
227
+ stream,
228
+ options?.signal
229
+ );
230
+ queueMicrotask(() => {
231
+ void (options?.codexCompaction ? session.generate(output, { kind: "compaction", input: context2 }) : session.start(output)).catch((error) => output.fail(error));
232
+ });
233
+ return stream;
234
+ }
235
+ };
236
+ omp.registerProvider("chappie", provider);
237
+ }
238
+ export {
239
+ chappie as default
240
+ };