@kingcrab/pi-imessage 0.0.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/README.md +120 -0
- package/dist/agent.d.ts +22 -0
- package/dist/agent.d.ts.map +1 -0
- package/dist/agent.js +341 -0
- package/dist/agent.js.map +1 -0
- package/dist/cli.d.ts +15 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +179 -0
- package/dist/cli.js.map +1 -0
- package/dist/imessage.d.ts +32 -0
- package/dist/imessage.d.ts.map +1 -0
- package/dist/imessage.js +65 -0
- package/dist/imessage.js.map +1 -0
- package/dist/logger.d.ts +33 -0
- package/dist/logger.d.ts.map +1 -0
- package/dist/logger.js +103 -0
- package/dist/logger.js.map +1 -0
- package/dist/main.d.ts +5 -0
- package/dist/main.d.ts.map +1 -0
- package/dist/main.js +66 -0
- package/dist/main.js.map +1 -0
- package/dist/pipeline.d.ts +26 -0
- package/dist/pipeline.d.ts.map +1 -0
- package/dist/pipeline.js +48 -0
- package/dist/pipeline.js.map +1 -0
- package/dist/queue.d.ts +16 -0
- package/dist/queue.d.ts.map +1 -0
- package/dist/queue.js +47 -0
- package/dist/queue.js.map +1 -0
- package/dist/self-echo.d.ts +19 -0
- package/dist/self-echo.d.ts.map +1 -0
- package/dist/self-echo.js +54 -0
- package/dist/self-echo.js.map +1 -0
- package/dist/send.d.ts +17 -0
- package/dist/send.d.ts.map +1 -0
- package/dist/send.js +107 -0
- package/dist/send.js.map +1 -0
- package/dist/settings.d.ts +39 -0
- package/dist/settings.d.ts.map +1 -0
- package/dist/settings.js +74 -0
- package/dist/settings.js.map +1 -0
- package/dist/store.d.ts +41 -0
- package/dist/store.d.ts.map +1 -0
- package/dist/store.js +72 -0
- package/dist/store.js.map +1 -0
- package/dist/tasks.d.ts +88 -0
- package/dist/tasks.d.ts.map +1 -0
- package/dist/tasks.js +260 -0
- package/dist/tasks.js.map +1 -0
- package/dist/types.d.ts +77 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +24 -0
- package/dist/types.js.map +1 -0
- package/dist/watch.d.ts +21 -0
- package/dist/watch.d.ts.map +1 -0
- package/dist/watch.js +137 -0
- package/dist/watch.js.map +1 -0
- package/dist/web/data.d.ts +11 -0
- package/dist/web/data.d.ts.map +1 -0
- package/dist/web/data.js +56 -0
- package/dist/web/data.js.map +1 -0
- package/dist/web/html.d.ts +5 -0
- package/dist/web/html.d.ts.map +1 -0
- package/dist/web/html.js +16 -0
- package/dist/web/html.js.map +1 -0
- package/dist/web/index.d.ts +15 -0
- package/dist/web/index.d.ts.map +1 -0
- package/dist/web/index.js +116 -0
- package/dist/web/index.js.map +1 -0
- package/dist/web/render.d.ts +5 -0
- package/dist/web/render.d.ts.map +1 -0
- package/dist/web/render.js +50 -0
- package/dist/web/render.js.map +1 -0
- package/dist/web/templates/page.eta +85 -0
- package/package.json +42 -0
package/README.md
ADDED
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
# pi-imessage
|
|
2
|
+
|
|
3
|
+
An self-managing iMessage bot — powered by [pi](https://github.com/badlogic/pi-mono).
|
|
4
|
+
|
|
5
|
+

|
|
6
|
+
|
|
7
|
+
## Features
|
|
8
|
+
|
|
9
|
+
- **Transparent**: tool calls and reasoning are sent to your iMessage chat, so you can see exactly what it's doing and why
|
|
10
|
+
- **Web UI**: browse chat history, toggle replies on/off, live updates
|
|
11
|
+
- **Working memory & custom tools**: remembers context across sessions and creates workflow-specific CLI tools (aka "skills") for your tasks
|
|
12
|
+
- **Group chat aware**: distinguishes DMs, SMS, and group chats; identifies who sent each message
|
|
13
|
+
|
|
14
|
+
## Quick Start
|
|
15
|
+
|
|
16
|
+
Prerequisites: macOS with Messages.app, Full Disk Access for the terminal, [Pi Coding Agent](https://github.com/badlogic/pi-mono/tree/main/packages/coding-agent#quick-start) authenticated
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
npm install -g @kingcrab/pi-imessage
|
|
20
|
+
|
|
21
|
+
pi-imessage # run in foreground
|
|
22
|
+
pi-imessage install # install as launchd service (auto-start on boot, restart on crash)
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## Usage
|
|
26
|
+
|
|
27
|
+
### Web UI
|
|
28
|
+
|
|
29
|
+
Available at `http://localhost:7750` (configurable via `WEB_PORT`).
|
|
30
|
+
|
|
31
|
+
- Displays chat logs from the last 7 days, sorted by most recent activity
|
|
32
|
+
- Toggle reply on/off per chat
|
|
33
|
+
- Live updates via SSE when new messages arrive
|
|
34
|
+
|
|
35
|
+
### Commands
|
|
36
|
+
|
|
37
|
+
Send these as iMessage to interact with the bot:
|
|
38
|
+
|
|
39
|
+
| Command | Description | Example Reply |
|
|
40
|
+
|---|---|---|
|
|
41
|
+
| `/new` | Reset the session, starting a fresh conversation | `✓ New session started` |
|
|
42
|
+
| `/status` | Show session stats: tokens, context, model | `💬 3 msgs - ↑7.2k ↓505 1.1%/128k`<br>`🤖 anthropic/claude-sonnet-4 • 💭 minimal` |
|
|
43
|
+
|
|
44
|
+
### Settings (`WORKING_DIR/settings.json`)
|
|
45
|
+
|
|
46
|
+
All fields are optional.
|
|
47
|
+
|
|
48
|
+
```json
|
|
49
|
+
{
|
|
50
|
+
"chatAllowlist": {
|
|
51
|
+
"whitelist": ["*"],
|
|
52
|
+
"blacklist": ["iMessage;-;+11234567890"]
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
**Chat allowlist** controls which chats receive replies (messages are always logged). Resolution priority: `blacklist[guid]` > `whitelist[guid]` > `blacklist["*"]` > `whitelist["*"]`.
|
|
58
|
+
|
|
59
|
+
### Environment Variables
|
|
60
|
+
|
|
61
|
+
| Variable | Required | Default | Description |
|
|
62
|
+
|---|---|---|---|
|
|
63
|
+
| `WEB_HOST` | no | `localhost` | Web UI host |
|
|
64
|
+
| `WEB_PORT` | no | `7750` | Web UI port |
|
|
65
|
+
| `WORKING_DIR` | no | `~/.pi/imessage` | Workspace directory |
|
|
66
|
+
|
|
67
|
+
## Development
|
|
68
|
+
|
|
69
|
+
```bash
|
|
70
|
+
npm run check # typecheck + lint (run after code changes)
|
|
71
|
+
npm test # run tests
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
## How It Works
|
|
75
|
+
|
|
76
|
+
```
|
|
77
|
+
~/Library/Messages/chat.db
|
|
78
|
+
│
|
|
79
|
+
(poll every 2s for new rows)
|
|
80
|
+
│
|
|
81
|
+
▼
|
|
82
|
+
┌──────────────────────────────────────────────────┐
|
|
83
|
+
│ pi-imessage │
|
|
84
|
+
│ │
|
|
85
|
+
│ Watcher (chat.db polling) │
|
|
86
|
+
│ │ │
|
|
87
|
+
│ ├─ Filter: is_from_me=0, no reactions │
|
|
88
|
+
│ ├─ Deduplicate via seenRowIds │
|
|
89
|
+
│ ├─ Read attachments from local disk │
|
|
90
|
+
│ │ │
|
|
91
|
+
│ ▼ │
|
|
92
|
+
│ AsyncQueue<IncomingMessage> │
|
|
93
|
+
│ │ │
|
|
94
|
+
│ ▼ │
|
|
95
|
+
│ SessionManager (pi-coding-agent) │
|
|
96
|
+
│ │ per chatGuid, persistent on disk │
|
|
97
|
+
│ │ └─ data/<chatGuid>/ │
|
|
98
|
+
│ │ ├─ log.jsonl (full history) │
|
|
99
|
+
│ │ └─ context.jsonl (LLM context) │
|
|
100
|
+
│ │ │
|
|
101
|
+
│ ▼ │
|
|
102
|
+
│ Agent loop (pi-agent-core) │
|
|
103
|
+
│ │ │
|
|
104
|
+
│ │ ┌─ outer: follow-up messages ────┐ │
|
|
105
|
+
│ │ │ ┌─ inner: tool calls + ┐ │ │
|
|
106
|
+
│ │ │ │ steering messages │ │ │
|
|
107
|
+
│ │ │ └───────────────────────────┘ │ │
|
|
108
|
+
│ │ └────────────────────────────────┘ │
|
|
109
|
+
│ │ │
|
|
110
|
+
│ ▼ │
|
|
111
|
+
│ Collect assistant reply text │
|
|
112
|
+
│ │ │
|
|
113
|
+
│ ├─ sendMessage (AppleScript → Messages.app) │
|
|
114
|
+
│ └─ save logs (messages, digests) │
|
|
115
|
+
│ │
|
|
116
|
+
└──────────────────────────────────────────────────┘
|
|
117
|
+
│
|
|
118
|
+
▼
|
|
119
|
+
iMessage (user receives reply via Messages.app)
|
|
120
|
+
```
|
package/dist/agent.d.ts
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Agent module — text-in / text-out AI processor per iMessage chat.
|
|
3
|
+
*
|
|
4
|
+
* Each chat gets a lazily-created AgentSession with persistent context
|
|
5
|
+
* (context.jsonl per chat directory).
|
|
6
|
+
*
|
|
7
|
+
* Reply delivery: each tool or assistant event enqueues an onReply call
|
|
8
|
+
* through replyChain, so iMessages arrive in order.
|
|
9
|
+
*
|
|
10
|
+
* Model: uses ~/.pi/agent/ defaults (via createAgentSession).
|
|
11
|
+
*/
|
|
12
|
+
import type { AgentReply, IncomingMessage } from "./types.js";
|
|
13
|
+
export interface AgentManagerConfig {
|
|
14
|
+
workingDir: string;
|
|
15
|
+
}
|
|
16
|
+
export declare function createAgentManager(config: AgentManagerConfig): Promise<{
|
|
17
|
+
processMessage: (msg: IncomingMessage, onReply: (reply: AgentReply) => Promise<void>) => Promise<void>;
|
|
18
|
+
newSession: (chatGuid: string) => Promise<void>;
|
|
19
|
+
getSessionStatus: (chatGuid: string) => Promise<string>;
|
|
20
|
+
}>;
|
|
21
|
+
export type AgentManager = Pick<Awaited<ReturnType<typeof createAgentManager>>, "processMessage" | "newSession" | "getSessionStatus">;
|
|
22
|
+
//# sourceMappingURL=agent.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agent.d.ts","sourceRoot":"","sources":["../src/agent.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAaH,OAAO,KAAK,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAI9D,MAAM,WAAW,kBAAkB;IAClC,UAAU,EAAE,MAAM,CAAC;CACnB;AAuMD,wBAAsB,kBAAkB,CAAC,MAAM,EAAE,kBAAkB;0BAqC/B,eAAe,WAAW,CAAC,KAAK,EAAE,UAAU,KAAK,OAAO,CAAC,IAAI,CAAC,KAAG,OAAO,CAAC,IAAI,CAAC;2BAsF7E,MAAM,KAAG,OAAO,CAAC,IAAI,CAAC;iCAkBhB,MAAM,KAAG,OAAO,CAAC,MAAM,CAAC;GA4BlE;AAWD,MAAM,MAAM,YAAY,GAAG,IAAI,CAC9B,OAAO,CAAC,UAAU,CAAC,OAAO,kBAAkB,CAAC,CAAC,EAC9C,gBAAgB,GAAG,YAAY,GAAG,kBAAkB,CACpD,CAAC"}
|
package/dist/agent.js
ADDED
|
@@ -0,0 +1,341 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Agent module — text-in / text-out AI processor per iMessage chat.
|
|
3
|
+
*
|
|
4
|
+
* Each chat gets a lazily-created AgentSession with persistent context
|
|
5
|
+
* (context.jsonl per chat directory).
|
|
6
|
+
*
|
|
7
|
+
* Reply delivery: each tool or assistant event enqueues an onReply call
|
|
8
|
+
* through replyChain, so iMessages arrive in order.
|
|
9
|
+
*
|
|
10
|
+
* Model: uses ~/.pi/agent/ defaults (via createAgentSession).
|
|
11
|
+
*/
|
|
12
|
+
import { existsSync, mkdirSync, readFileSync, unlinkSync } from "node:fs";
|
|
13
|
+
import { join } from "node:path";
|
|
14
|
+
import { AuthStorage, DefaultResourceLoader, ModelRegistry, SessionManager, createAgentSession, } from "@mariozechner/pi-coding-agent";
|
|
15
|
+
/** Create and initialize shared resources (auth, model registry, resource loader). */
|
|
16
|
+
async function initSharedResources(workingDir) {
|
|
17
|
+
const authStorage = AuthStorage.create();
|
|
18
|
+
const modelRegistry = new ModelRegistry(authStorage);
|
|
19
|
+
// Resource loader with iMessage-specific system prompt; no extensions/skills needed.
|
|
20
|
+
const resourceLoader = new DefaultResourceLoader({
|
|
21
|
+
systemPrompt: buildSystemPrompt(workingDir),
|
|
22
|
+
noExtensions: true,
|
|
23
|
+
noSkills: true,
|
|
24
|
+
noPromptTemplates: true,
|
|
25
|
+
noThemes: true,
|
|
26
|
+
});
|
|
27
|
+
await resourceLoader.reload();
|
|
28
|
+
return { authStorage, modelRegistry, resourceLoader };
|
|
29
|
+
}
|
|
30
|
+
// ── Helpers ───────────────────────────────────────────────────────────────────
|
|
31
|
+
/**
|
|
32
|
+
* Format a prompt with sender/chat context prefix.
|
|
33
|
+
*
|
|
34
|
+
* Examples:
|
|
35
|
+
* [DM from +1234567890] hey
|
|
36
|
+
* [SMS from +1234567890] hey
|
|
37
|
+
* [Group 'Family' from alice@example.com] hey
|
|
38
|
+
*/
|
|
39
|
+
function formatPromptText(msg) {
|
|
40
|
+
const text = msg.text ?? "";
|
|
41
|
+
let prefix;
|
|
42
|
+
if (msg.messageType === "group") {
|
|
43
|
+
const name = msg.groupName || "unnamed";
|
|
44
|
+
prefix = `[Group '${name}' from ${msg.sender}]`;
|
|
45
|
+
}
|
|
46
|
+
else if (msg.messageType === "sms") {
|
|
47
|
+
prefix = `[SMS from ${msg.sender}]`;
|
|
48
|
+
}
|
|
49
|
+
else {
|
|
50
|
+
prefix = `[DM from ${msg.sender}]`;
|
|
51
|
+
}
|
|
52
|
+
return `${prefix} ${text}`;
|
|
53
|
+
}
|
|
54
|
+
/** Replace characters that are invalid in directory names. */
|
|
55
|
+
function sanitizeChatGuid(chatGuid) {
|
|
56
|
+
return chatGuid.replace(/[^a-zA-Z0-9_\-;+.@]/g, "_");
|
|
57
|
+
}
|
|
58
|
+
/** Read global and chat-specific MEMORY.md files, returning combined content. */
|
|
59
|
+
function getMemory(workingDir, chatDir) {
|
|
60
|
+
const parts = [];
|
|
61
|
+
const globalMemoryPath = join(workingDir, "MEMORY.md");
|
|
62
|
+
if (existsSync(globalMemoryPath)) {
|
|
63
|
+
try {
|
|
64
|
+
const content = readFileSync(globalMemoryPath, "utf-8").trim();
|
|
65
|
+
if (content) {
|
|
66
|
+
parts.push(`### Global Memory\n${content}`);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
catch (error) {
|
|
70
|
+
console.warn(`[agent] failed to read global memory: ${error}`);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
if (chatDir) {
|
|
74
|
+
const chatMemoryPath = join(chatDir, "MEMORY.md");
|
|
75
|
+
if (existsSync(chatMemoryPath)) {
|
|
76
|
+
try {
|
|
77
|
+
const content = readFileSync(chatMemoryPath, "utf-8").trim();
|
|
78
|
+
if (content) {
|
|
79
|
+
parts.push(`### Chat Memory\n${content}`);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
catch (error) {
|
|
83
|
+
console.warn(`[agent] failed to read chat memory: ${error}`);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
return parts.length > 0 ? parts.join("\n\n") : "(no memory yet)";
|
|
88
|
+
}
|
|
89
|
+
function buildSystemPrompt(workingDir, chatDir) {
|
|
90
|
+
const memory = getMemory(workingDir, chatDir);
|
|
91
|
+
return `You are the user's best friend communicating via iMessage. Be concise. No emojis.
|
|
92
|
+
|
|
93
|
+
## Context
|
|
94
|
+
- Plain text only. Do not use Markdown formatting, double asterisks (**like this**), or [markdown](links).
|
|
95
|
+
- Reply in the same language the user is writing in.
|
|
96
|
+
|
|
97
|
+
## Environment
|
|
98
|
+
You are running directly on the host machine.
|
|
99
|
+
- Bash working directory: ${workingDir}
|
|
100
|
+
- Be careful with system modifications;
|
|
101
|
+
|
|
102
|
+
## Workspace Layout
|
|
103
|
+
${workingDir}/
|
|
104
|
+
├── settings.json # Bot configuration (see below)
|
|
105
|
+
├── MEMORY.md # Global memory (all chats)
|
|
106
|
+
├── SYSTEM.md # System configuration log
|
|
107
|
+
├── skills/ # Global CLI tools you create
|
|
108
|
+
└── <chatId>/ # Each iMessage chat gets a directory
|
|
109
|
+
├── MEMORY.md # Chat-specific memory
|
|
110
|
+
├── context.jsonl # LLM context (session persistence)
|
|
111
|
+
├── log.jsonl # Message history
|
|
112
|
+
├── attachments/ # User-shared files
|
|
113
|
+
├── scratch/ # Your working directory
|
|
114
|
+
└── skills/ # Chat-specific tools
|
|
115
|
+
|
|
116
|
+
## Memory
|
|
117
|
+
Write to MEMORY.md files to persist context across conversations.
|
|
118
|
+
- Global (${workingDir}/MEMORY.md): preferences, project info, shared knowledge
|
|
119
|
+
- Chat-specific (<chatDir>/MEMORY.md): user details, ongoing topics, decisions
|
|
120
|
+
Update when you learn something important or when asked to remember something.
|
|
121
|
+
|
|
122
|
+
### Current Memory
|
|
123
|
+
${memory}
|
|
124
|
+
|
|
125
|
+
## System Configuration Log
|
|
126
|
+
Maintain ${workingDir}/SYSTEM.md to log all environment modifications:
|
|
127
|
+
- Installed packages (npm install, pip install, brew install, etc.)
|
|
128
|
+
- Environment variables set
|
|
129
|
+
- Config files modified (~/.gitconfig, cron jobs, etc.)
|
|
130
|
+
- Skill dependencies installed
|
|
131
|
+
|
|
132
|
+
Update this file whenever you modify the environment.
|
|
133
|
+
|
|
134
|
+
## Skills (Custom CLI Tools)
|
|
135
|
+
You can create reusable CLI tools for recurring tasks (email, APIs, data processing, etc.).
|
|
136
|
+
|
|
137
|
+
### Creating Skills
|
|
138
|
+
Store in \`${workingDir}/skills/<name>/\` (global) or \`<chatDir>/skills/<name>/\` (chat-specific).
|
|
139
|
+
Each skill directory needs a \`SKILL.md\` with YAML frontmatter:
|
|
140
|
+
|
|
141
|
+
\`\`\`markdown
|
|
142
|
+
---
|
|
143
|
+
name: skill-name
|
|
144
|
+
description: What this skill does
|
|
145
|
+
---
|
|
146
|
+
Usage instructions and details here.
|
|
147
|
+
\`\`\``;
|
|
148
|
+
}
|
|
149
|
+
/** Extract concatenated text from a Message, ignoring non-text content parts. */
|
|
150
|
+
function extractMessageText(message) {
|
|
151
|
+
if (typeof message.content === "string")
|
|
152
|
+
return message.content;
|
|
153
|
+
const texts = message.content
|
|
154
|
+
.filter((part) => part.type === "text" && "text" in part)
|
|
155
|
+
.map((part) => part.text);
|
|
156
|
+
const joined = texts.join("\n").trim();
|
|
157
|
+
return joined || null;
|
|
158
|
+
}
|
|
159
|
+
/** Extract human-readable text from a tool result (string or content-array). */
|
|
160
|
+
function extractToolResultText(result) {
|
|
161
|
+
if (typeof result === "string")
|
|
162
|
+
return result;
|
|
163
|
+
if (result && typeof result === "object" && "content" in result) {
|
|
164
|
+
const content = result.content;
|
|
165
|
+
if (Array.isArray(content)) {
|
|
166
|
+
const parts = [];
|
|
167
|
+
for (const part of content) {
|
|
168
|
+
if (part && typeof part === "object" && part.type === "text" && "text" in part) {
|
|
169
|
+
parts.push(part.text);
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
const joined = parts.join("\n").trim();
|
|
173
|
+
if (joined)
|
|
174
|
+
return joined;
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
return JSON.stringify(result);
|
|
178
|
+
}
|
|
179
|
+
/** Pick a human-readable label for a tool invocation. */
|
|
180
|
+
function extractToolLabel(toolName, args) {
|
|
181
|
+
if (toolName === "bash" && typeof args.command === "string")
|
|
182
|
+
return args.command;
|
|
183
|
+
if (typeof args.path === "string")
|
|
184
|
+
return `${toolName}: ${args.path}`;
|
|
185
|
+
if (typeof args.label === "string")
|
|
186
|
+
return args.label;
|
|
187
|
+
return toolName;
|
|
188
|
+
}
|
|
189
|
+
// ── Agent Manager ─────────────────────────────────────────────────────────────
|
|
190
|
+
export async function createAgentManager(config) {
|
|
191
|
+
const { workingDir } = config;
|
|
192
|
+
const sessionMap = new Map();
|
|
193
|
+
const { modelRegistry, resourceLoader } = await initSharedResources(workingDir);
|
|
194
|
+
/** Lazily create one AgentSession per chat, persisted to context.jsonl. */
|
|
195
|
+
async function getOrCreateSession(chatGuid) {
|
|
196
|
+
const existing = sessionMap.get(chatGuid);
|
|
197
|
+
if (existing)
|
|
198
|
+
return existing;
|
|
199
|
+
// Per-chat session manager — each chat gets its own context.jsonl.
|
|
200
|
+
const chatDir = join(workingDir, sanitizeChatGuid(chatGuid));
|
|
201
|
+
mkdirSync(chatDir, { recursive: true });
|
|
202
|
+
const sessionManager = SessionManager.open(join(chatDir, "context.jsonl"), chatDir);
|
|
203
|
+
const { session } = await createAgentSession({
|
|
204
|
+
modelRegistry,
|
|
205
|
+
sessionManager,
|
|
206
|
+
resourceLoader,
|
|
207
|
+
});
|
|
208
|
+
const model = session.model;
|
|
209
|
+
const modelLabel = model ? `${model.provider}/${model.id}` : "default";
|
|
210
|
+
console.log(`[agent] session created: ${chatGuid} model=${modelLabel}`);
|
|
211
|
+
const entry = { session, chatGuid };
|
|
212
|
+
sessionMap.set(chatGuid, entry);
|
|
213
|
+
return entry;
|
|
214
|
+
}
|
|
215
|
+
/**
|
|
216
|
+
* Send a user message through the agent and deliver replies via onReply.
|
|
217
|
+
*
|
|
218
|
+
* Events are serialized: each tool_execution_start/end and assistant
|
|
219
|
+
* message_end enqueues an onReply call through replyChain so iMessages
|
|
220
|
+
* arrive in order.
|
|
221
|
+
*/
|
|
222
|
+
async function processMessage(msg, onReply) {
|
|
223
|
+
const entry = await getOrCreateSession(msg.chatGuid);
|
|
224
|
+
// Track pending tool calls for duration logging
|
|
225
|
+
const pendingTools = new Map();
|
|
226
|
+
// Serialize onReply calls — subscribe is sync so we chain promises
|
|
227
|
+
let replyChain = Promise.resolve();
|
|
228
|
+
const unsub = entry.session.subscribe((event) => {
|
|
229
|
+
if (event.type === "message_end" && event.message.role === "assistant") {
|
|
230
|
+
const assistantMsg = event.message;
|
|
231
|
+
const text = extractMessageText(event.message);
|
|
232
|
+
const stopReason = assistantMsg.stopReason;
|
|
233
|
+
const errorMessage = assistantMsg.errorMessage;
|
|
234
|
+
console.log(`[agent] message end: ${entry.chatGuid} role=assistant stopReason=${stopReason}` +
|
|
235
|
+
`${errorMessage ? ` error="${errorMessage}"` : ""}` +
|
|
236
|
+
` text="${(text ?? "(empty)").substring(0, 60)}"`);
|
|
237
|
+
if (text) {
|
|
238
|
+
replyChain = replyChain.then(() => onReply({ kind: "assistant", text }));
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
else if (event.type === "tool_execution_start") {
|
|
242
|
+
const toolArgs = event.args;
|
|
243
|
+
const label = extractToolLabel(event.toolName, toolArgs);
|
|
244
|
+
pendingTools.set(event.toolCallId, {
|
|
245
|
+
toolName: event.toolName,
|
|
246
|
+
args: toolArgs,
|
|
247
|
+
startTime: Date.now(),
|
|
248
|
+
});
|
|
249
|
+
console.log(`[agent] tool start: ${entry.chatGuid} → ${label}`);
|
|
250
|
+
replyChain = replyChain.then(() => onReply({ kind: "tool_start", label }));
|
|
251
|
+
}
|
|
252
|
+
else if (event.type === "tool_execution_end") {
|
|
253
|
+
const resultText = extractToolResultText(event.result);
|
|
254
|
+
const pending = pendingTools.get(event.toolCallId);
|
|
255
|
+
pendingTools.delete(event.toolCallId);
|
|
256
|
+
const durationMs = pending ? Date.now() - pending.startTime : 0;
|
|
257
|
+
const duration = (durationMs / 1000).toFixed(1);
|
|
258
|
+
const symbol = event.isError ? "✗" : "✓";
|
|
259
|
+
console.log(`[agent] tool end: ${entry.chatGuid} ${symbol} ${event.toolName} (${duration}s)` +
|
|
260
|
+
` result="${resultText.substring(0, 60)}"`);
|
|
261
|
+
replyChain = replyChain.then(() => onReply({ kind: "tool_end", toolName: event.toolName, symbol, duration, result: resultText }));
|
|
262
|
+
}
|
|
263
|
+
});
|
|
264
|
+
// Build prompt with sender/chat context prefix
|
|
265
|
+
// Format: "[DM from +1234567890] hey" or "[Group 'Family' from alice@example.com] hey"
|
|
266
|
+
const promptText = formatPromptText(msg);
|
|
267
|
+
// Refresh system prompt with current memory before each prompt
|
|
268
|
+
const chatDir = join(workingDir, sanitizeChatGuid(msg.chatGuid));
|
|
269
|
+
entry.session.agent.setSystemPrompt(buildSystemPrompt(workingDir, chatDir));
|
|
270
|
+
const currentModel = entry.session.model;
|
|
271
|
+
const currentModelLabel = currentModel ? `${currentModel.provider}/${currentModel.id}` : "default";
|
|
272
|
+
console.log(`[agent] prompt start (steer): ${entry.chatGuid} model=${currentModelLabel} "${promptText.substring(0, 60)}"`);
|
|
273
|
+
const promptPromise = msg.images.length > 0
|
|
274
|
+
? entry.session.prompt(promptText, { images: msg.images, streamingBehavior: "steer" })
|
|
275
|
+
: entry.session.prompt(promptText, { streamingBehavior: "steer" });
|
|
276
|
+
const timeoutPromise = new Promise((_, reject) => setTimeout(() => reject(new Error("agent prompt timed out after 120s")), 120_000));
|
|
277
|
+
try {
|
|
278
|
+
await Promise.race([promptPromise, timeoutPromise]);
|
|
279
|
+
await replyChain; // wait for all dispatched replies to finish
|
|
280
|
+
console.log(`[agent] prompt end: ${entry.chatGuid}`);
|
|
281
|
+
}
|
|
282
|
+
finally {
|
|
283
|
+
unsub();
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
/** Start a new session for a chat by deleting context and evicting the in-memory session. */
|
|
287
|
+
async function newSession(chatGuid) {
|
|
288
|
+
sessionMap.delete(chatGuid);
|
|
289
|
+
const chatDir = join(workingDir, sanitizeChatGuid(chatGuid));
|
|
290
|
+
const contextFile = join(chatDir, "context.jsonl");
|
|
291
|
+
if (existsSync(contextFile)) {
|
|
292
|
+
unlinkSync(contextFile);
|
|
293
|
+
}
|
|
294
|
+
console.log(`[agent] new session: ${chatGuid}`);
|
|
295
|
+
}
|
|
296
|
+
/**
|
|
297
|
+
* Get a formatted status string for a chat session.
|
|
298
|
+
* Lazily creates/resumes the session from disk if not already in memory.
|
|
299
|
+
*
|
|
300
|
+
* Format (two lines):
|
|
301
|
+
* 💬 3 msgs - ↑7.2k ↓505 1.1%/128k
|
|
302
|
+
* 🤖 github-copilot/gpt-5-mini • 💭 minimal
|
|
303
|
+
*/
|
|
304
|
+
async function getSessionStatus(chatGuid) {
|
|
305
|
+
const entry = await getOrCreateSession(chatGuid);
|
|
306
|
+
const { session } = entry;
|
|
307
|
+
const stats = session.getSessionStats();
|
|
308
|
+
const contextUsage = session.getContextUsage();
|
|
309
|
+
const model = session.model;
|
|
310
|
+
const thinkingLevel = session.thinkingLevel;
|
|
311
|
+
// Line 1: message count + token counts + context usage
|
|
312
|
+
const line1Parts = [];
|
|
313
|
+
line1Parts.push(`💬 ${stats.userMessages} msgs`);
|
|
314
|
+
line1Parts.push(`↑${formatTokenCount(stats.tokens.input)}`);
|
|
315
|
+
line1Parts.push(`↓${formatTokenCount(stats.tokens.output)}`);
|
|
316
|
+
if (contextUsage) {
|
|
317
|
+
const percent = contextUsage.percent !== null ? `${contextUsage.percent.toFixed(1)}%` : "?%";
|
|
318
|
+
const window = formatTokenCount(contextUsage.contextWindow);
|
|
319
|
+
line1Parts.push(`${percent}/${window}`);
|
|
320
|
+
}
|
|
321
|
+
const line1 = `${line1Parts[0]} - ${line1Parts.slice(1).join(" ")}`;
|
|
322
|
+
// Line 2: provider/model • thinking level
|
|
323
|
+
const modelLabel = model ? `${model.provider}/${model.id}` : "default";
|
|
324
|
+
const line2 = `🤖 ${modelLabel} • 💭 ${thinkingLevel ?? "off"}`;
|
|
325
|
+
return `${line1}\n${line2}`;
|
|
326
|
+
}
|
|
327
|
+
return { processMessage, newSession, getSessionStatus };
|
|
328
|
+
}
|
|
329
|
+
/** Format a token count as a compact string: 0, 1.2k, 5.9k, 12k, 1.8M, etc. */
|
|
330
|
+
function formatTokenCount(tokens) {
|
|
331
|
+
if (tokens === 0)
|
|
332
|
+
return "0";
|
|
333
|
+
if (tokens < 1_000)
|
|
334
|
+
return String(tokens);
|
|
335
|
+
if (tokens < 10_000)
|
|
336
|
+
return `${(tokens / 1_000).toFixed(1)}k`;
|
|
337
|
+
if (tokens < 1_000_000)
|
|
338
|
+
return `${Math.round(tokens / 1_000)}k`;
|
|
339
|
+
return `${(tokens / 1_000_000).toFixed(1)}M`;
|
|
340
|
+
}
|
|
341
|
+
//# sourceMappingURL=agent.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agent.js","sourceRoot":"","sources":["../src/agent.ts"],"names":[],"mappings":"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"}
|
package/dist/cli.d.ts
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* CLI entry point — handles launchd service management and foreground run.
|
|
4
|
+
*
|
|
5
|
+
* Usage:
|
|
6
|
+
* pi-imessage Run in foreground
|
|
7
|
+
* pi-imessage install Install + start launchd service (auto-starts on boot)
|
|
8
|
+
* pi-imessage uninstall Stop + remove launchd service
|
|
9
|
+
* pi-imessage start Start the service
|
|
10
|
+
* pi-imessage stop Stop the service
|
|
11
|
+
* pi-imessage restart Restart the service
|
|
12
|
+
* pi-imessage logs Tail service logs
|
|
13
|
+
*/
|
|
14
|
+
export {};
|
|
15
|
+
//# sourceMappingURL=cli.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AACA;;;;;;;;;;;GAWG"}
|