@kingcrab/pi-imessage 0.0.41 → 0.0.43

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 CHANGED
@@ -9,6 +9,7 @@ A minimal and self-managing iMessage bot — powered by [pi](https://github.com/
9
9
  - **Self-managing**: Turn the agent into whatever you need. He builds his own tools without pre-built assumptions
10
10
  - **Transparent**: tool calls and reasoning are sent to your iMessage chat, so you can see exactly what it's doing and why
11
11
  - **iMessage Integration**: Responds to DMs, SMS, and group chats; identifies who sent each message; understands quoted/reply-to messages
12
+ - **Persistent Reminders**: Schedule one-time messages without per-reminder cron jobs; reminders survive restarts and retry transient failures
12
13
  - **Web UI**: browse chat history, toggle replies on/off per chat, live updates — disable with WEB_ENABLED=false and let the agent build your own web UI
13
14
 
14
15
  # Get Started
@@ -39,14 +40,33 @@ Available at `http://localhost:7750` (configurable via `WEB_HOST` and `WEB_PORT`
39
40
 
40
41
  P.S. Disable with `WEB_ENABLED=false` and let the agent build your own web UI
41
42
 
43
+ ## Structured Memory
44
+
45
+ Durable memories are stored as namespaced JSONL records under
46
+ `WORKING_DIR/skills/file-memory/namespaces/`. Each record includes a stable ID,
47
+ creation timestamp, factual event date when known, source, kind, subjects,
48
+ importance, confidence, and status. This keeps every memory traceable without
49
+ inventing dates for older facts.
50
+
51
+ The agent uses typed tools to load complete namespaces, search for specific
52
+ records, and append validated memories. Corrections append a new record that
53
+ supersedes the old ID, preserving an auditable history instead of silently
54
+ rewriting it. Legacy global and per-chat `MEMORY.md` files remain read-only
55
+ archives. See [the structured memory flow](docs/structured-memory-sequence.md)
56
+ for migration, retrieval, and write behavior.
57
+
42
58
  ## API
43
59
 
44
60
  The agent is aware of these endpoints via its system prompt and can use them as tools (e.g., scheduling a cron job that calls `/prompt`).
45
61
 
46
62
  | Endpoint | Description | Example |
47
63
  |---|---|---|
48
- | `POST /send` | Send a raw iMessage to a chat (bypasses the agent) | `curl -X POST localhost:7750/send -d '{"chatGuid": "iMessage;-;+11234567890", "text": "hello"}'`<br>→ `{"ok": true}` |
64
+ | `POST /send` | Send text and/or a local file attachment to a chat (bypasses the agent) | `curl -X POST localhost:7750/send -d '{"chatGuid": "iMessage;-;+11234567890", "text": "hello"}'`<br>→ `{"ok": true}` |
49
65
  | `POST /prompt` | Feed a prompt to the agent asynchronously; replies are sent to the chat when ready | `curl -X POST localhost:7750/prompt -d '{"chatGuid": "iMessage;-;+11234567890", "prompt": "say hello"}'`<br>→ `{"ok": true}` |
66
+ | `POST /reminders` | Schedule a persistent one-time reminder; `scheduledAt` requires an explicit timezone | `curl -X POST localhost:7750/reminders -d '{"chatGuid":"iMessage;-;+11234567890","text":"check the oven","scheduledAt":"2026-08-08T21:30:00+08:00"}'` |
67
+ | `GET /reminders` | List reminders; optionally filter with `?status=pending` | `curl 'localhost:7750/reminders?status=pending'` |
68
+ | `DELETE /reminders/:id` | Cancel a pending reminder | `curl -X DELETE localhost:7750/reminders/<id>` |
69
+ | `GET /health/model` | Make a live request to the configured default AI model; returns HTTP 200 when healthy or 503 on failure | `curl localhost:7750/health/model`<br>→ `{"ok":true,"model":"openai/gpt-5","latencyMs":842,"checkedAt":"..."}` |
50
70
 
51
71
  ## Commands
52
72
 
@@ -90,6 +110,8 @@ All fields are optional.
90
110
  | `WEB_HOST` | no | `localhost` | Web UI host |
91
111
  | `WEB_PORT` | no | `7750` | Web UI port |
92
112
  | `WORKING_DIR` | no | `~/.pi/imessage` | Workspace directory |
113
+ | `AGENT_IDLE_TIMEOUT_MS` | no | `120000` | Abort only after this much continuous agent inactivity; model and tool events reset the timer |
114
+ | `AGENT_MAX_PROMPT_DURATION_MS` | no | `1800000` | Absolute ceiling for one prompt, independent of activity |
93
115
 
94
116
  # Development
95
117
 
package/dist/agent.d.ts CHANGED
@@ -10,19 +10,75 @@
10
10
  *
11
11
  * Model: uses ~/.pi/agent/ defaults (via createAgentSession).
12
12
  */
13
+ import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
14
+ import { type AgentSession } from "@earendil-works/pi-coding-agent";
13
15
  import type { AgentReply, IncomingMessage } from "./types.js";
16
+ /**
17
+ * Abort a prompt only after this much continuous inactivity. Any agent event —
18
+ * including streamed model output and tool start/end events — refreshes it.
19
+ */
20
+ export declare const AGENT_IDLE_TIMEOUT_MS: number;
21
+ /** Absolute safety ceiling that activity cannot extend. */
22
+ export declare const AGENT_MAX_PROMPT_DURATION_MS: number;
23
+ export declare const AGENT_COMPACT_TIMEOUT_MS: number;
24
+ export declare const AUTO_COMPACT_CONTEXT_RATIO: number;
25
+ export declare const AUTO_COMPACT_FALLBACK_TOKENS = 100000;
26
+ /**
27
+ * Compact relative to the selected model's context window instead of using a
28
+ * fixed low threshold. AGENT_AUTO_COMPACT_TOKENS remains an explicit override.
29
+ */
30
+ export declare function getAutoCompactTokenThreshold(contextWindow?: number, explicitTokens?: string): number;
31
+ /** Enable OpenAI priority processing without enabling user-discovered extensions. */
32
+ export declare function openAiCodexFastExtension(pi: ExtensionAPI): void;
14
33
  export interface AgentManagerConfig {
15
34
  workingDir: string;
16
35
  }
36
+ /**
37
+ * Stop model work without injecting a synthetic user message into the transcript.
38
+ *
39
+ * AgentSession.steer("stop") is not an abort API: it queues a literal user
40
+ * message. If the current operation fails before consuming that queue (for
41
+ * example, compaction fails), the stale "stop" can be delivered with a later
42
+ * real chat message and misattributed to that sender.
43
+ */
44
+ export declare function clearAndAbortSession(session: Pick<AgentSession, "abort" | "clearQueue">): Promise<void>;
45
+ /**
46
+ * Race an async operation against a wall-clock timeout.
47
+ *
48
+ * If `operation()` settles first, its result (or rejection) is passed through
49
+ * and the timer is cleared. If the timeout fires first, `onTimeout()` is invoked
50
+ * (best-effort — e.g. to abort the underlying request) and the returned promise
51
+ * rejects with a timeout Error. A failure inside `onTimeout()` never masks the
52
+ * timeout rejection.
53
+ *
54
+ * Note: this does not cancel `operation()` itself — cancellation must happen via
55
+ * `onTimeout` (the SDK exposes `AgentSession.abort()`). The timeout rejects
56
+ * immediately without waiting for cancellation, because a stuck abort must not
57
+ * keep the caller blocked.
58
+ */
59
+ export declare function runWithTimeout<T>(operation: () => Promise<T>, onTimeout: () => Promise<void> | void, timeoutMs: number): Promise<T>;
60
+ export type ActivityTimeoutKind = "idle" | "max_duration";
61
+ /**
62
+ * Race an operation against a sliding inactivity timeout and a separate hard
63
+ * duration ceiling. Calling `markActivity()` refreshes only the idle timer.
64
+ */
65
+ export declare function runWithActivityTimeout<T>(operation: (markActivity: () => void) => Promise<T>, onTimeout: (kind: ActivityTimeoutKind) => Promise<void> | void, idleTimeoutMs: number, maxDurationMs: number): Promise<T>;
17
66
  export declare function createAgentManager(config: AgentManagerConfig): Promise<{
18
67
  processMessage: (msg: IncomingMessage, handler: (reply: AgentReply) => Promise<void>, options?: {
19
68
  streamingBehavior?: "steer" | "followUp";
20
69
  }) => Promise<void>;
21
70
  newSession: (chatGuid: string) => Promise<void>;
22
71
  getSessionStatus: (chatGuid: string) => Promise<string>;
72
+ getRuntimeStatus: () => {
73
+ activePrompts: number;
74
+ sessions: number;
75
+ lastAgentActivityAt: string | null;
76
+ };
23
77
  reload: (chatGuid: string) => Promise<void>;
24
78
  stop: (chatGuid: string) => Promise<void>;
25
79
  compact: (chatGuid: string, customInstructions?: string) => Promise<string>;
26
80
  }>;
27
- export type AgentManager = Pick<Awaited<ReturnType<typeof createAgentManager>>, "processMessage" | "newSession" | "getSessionStatus" | "reload" | "stop" | "compact">;
81
+ type CreatedAgentManager = Awaited<ReturnType<typeof createAgentManager>>;
82
+ export type AgentManager = Pick<CreatedAgentManager, "processMessage" | "newSession" | "getSessionStatus" | "reload" | "stop" | "compact"> & Partial<Pick<CreatedAgentManager, "getRuntimeStatus">>;
83
+ export {};
28
84
  //# sourceMappingURL=agent.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"agent.d.ts","sourceRoot":"","sources":["../src/agent.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAgBH,OAAO,KAAK,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAI9D,MAAM,WAAW,kBAAkB;IAClC,UAAU,EAAE,MAAM,CAAC;CACnB;AAyND,wBAAsB,kBAAkB,CAAC,MAAM,EAAE,kBAAkB;0BAgD5D,eAAe,WACX,CAAC,KAAK,EAAE,UAAU,KAAK,OAAO,CAAC,IAAI,CAAC,YACnC;QAAE,iBAAiB,CAAC,EAAE,OAAO,GAAG,UAAU,CAAA;KAAE,KACpD,OAAO,CAAC,IAAI,CAAC;2BA+HoB,MAAM,KAAG,OAAO,CAAC,IAAI,CAAC;iCAkBhB,MAAM,KAAG,OAAO,CAAC,MAAM,CAAC;uBAuClC,MAAM,KAAG,OAAO,CAAC,IAAI,CAAC;qBAzFxB,MAAM,KAAG,OAAO,CAAC,IAAI,CAAC;wBAWnB,MAAM,uBAAuB,MAAM,KAAG,OAAO,CAAC,MAAM,CAAC;GA0GtF;AAWD,MAAM,MAAM,YAAY,GAAG,IAAI,CAC9B,OAAO,CAAC,UAAU,CAAC,OAAO,kBAAkB,CAAC,CAAC,EAC9C,gBAAgB,GAAG,YAAY,GAAG,kBAAkB,GAAG,QAAQ,GAAG,MAAM,GAAG,SAAS,CACpF,CAAC"}
1
+ {"version":3,"file":"agent.d.ts","sourceRoot":"","sources":["../src/agent.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAKH,OAAO,KAAK,EAAoB,YAAY,EAAE,MAAM,iCAAiC,CAAC;AACtF,OAAO,EACN,KAAK,YAAY,EAQjB,MAAM,iCAAiC,CAAC;AAEzC,OAAO,KAAK,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAI9D;;;GAGG;AACH,eAAO,MAAM,qBAAqB,QAAqE,CAAC;AAExG,2DAA2D;AAC3D,eAAO,MAAM,4BAA4B,QAA6E,CAAC;AACvH,eAAO,MAAM,wBAAwB,QAAuE,CAAC;AAC7G,eAAO,MAAM,0BAA0B,QAAmE,CAAC;AAC3G,eAAO,MAAM,4BAA4B,SAAU,CAAC;AAEpD;;;GAGG;AACH,wBAAgB,4BAA4B,CAC3C,aAAa,CAAC,EAAE,MAAM,EACtB,cAAc,SAA8C,GAC1D,MAAM,CAWR;AAID,qFAAqF;AACrF,wBAAgB,wBAAwB,CAAC,EAAE,EAAE,YAAY,GAAG,IAAI,CAU/D;AAED,MAAM,WAAW,kBAAkB;IAClC,UAAU,EAAE,MAAM,CAAC;CACnB;AASD;;;;;;;GAOG;AACH,wBAAsB,oBAAoB,CAAC,OAAO,EAAE,IAAI,CAAC,YAAY,EAAE,OAAO,GAAG,YAAY,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAG7G;AAID;;;;;;;;;;;;;GAaG;AACH,wBAAsB,cAAc,CAAC,CAAC,EACrC,SAAS,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,EAC3B,SAAS,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,EACrC,SAAS,EAAE,MAAM,GACf,OAAO,CAAC,CAAC,CAAC,CAiBZ;AAED,MAAM,MAAM,mBAAmB,GAAG,MAAM,GAAG,cAAc,CAAC;AAE1D;;;GAGG;AACH,wBAAsB,sBAAsB,CAAC,CAAC,EAC7C,SAAS,EAAE,CAAC,YAAY,EAAE,MAAM,IAAI,KAAK,OAAO,CAAC,CAAC,CAAC,EACnD,SAAS,EAAE,CAAC,IAAI,EAAE,mBAAmB,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,EAC9D,aAAa,EAAE,MAAM,EACrB,aAAa,EAAE,MAAM,GACnB,OAAO,CAAC,CAAC,CAAC,CA6CZ;AAuTD,wBAAsB,kBAAkB,CAAC,MAAM,EAAE,kBAAkB;0BAuE5D,eAAe,WACX,CAAC,KAAK,EAAE,UAAU,KAAK,OAAO,CAAC,IAAI,CAAC,YACnC;QAAE,iBAAiB,CAAC,EAAE,OAAO,GAAG,UAAU,CAAA;KAAE,KACpD,OAAO,CAAC,IAAI,CAAC;2BA+LoB,MAAM,KAAG,OAAO,CAAC,IAAI,CAAC;iCAkBhB,MAAM,KAAG,OAAO,CAAC,MAAM,CAAC;;;;;;uBAuClC,MAAM,KAAG,OAAO,CAAC,IAAI,CAAC;qBAzFxB,MAAM,KAAG,OAAO,CAAC,IAAI,CAAC;wBAWnB,MAAM,uBAAuB,MAAM,KAAG,OAAO,CAAC,MAAM,CAAC;GAkHtF;AAWD,KAAK,mBAAmB,GAAG,OAAO,CAAC,UAAU,CAAC,OAAO,kBAAkB,CAAC,CAAC,CAAC;AAC1E,MAAM,MAAM,YAAY,GAAG,IAAI,CAC9B,mBAAmB,EACnB,gBAAgB,GAAG,YAAY,GAAG,kBAAkB,GAAG,QAAQ,GAAG,MAAM,GAAG,SAAS,CACpF,GACA,OAAO,CAAC,IAAI,CAAC,mBAAmB,EAAE,kBAAkB,CAAC,CAAC,CAAC"}