@holon-run/agentinbox 0.7.0 → 1.0.0-beta.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.
Files changed (33) hide show
  1. package/README.md +36 -7
  2. package/dist/src/adapters.js +55 -0
  3. package/dist/src/backend.js +4 -16
  4. package/dist/src/cli.js +329 -52
  5. package/dist/src/client.js +2 -2
  6. package/dist/src/http.js +479 -55
  7. package/dist/src/runtime_gate.js +49 -41
  8. package/dist/src/service.js +922 -200
  9. package/dist/src/source_hosts.js +75 -0
  10. package/dist/src/source_resolution.js +2 -2
  11. package/dist/src/source_schema.js +2 -2
  12. package/dist/src/sources/feishu.js +66 -28
  13. package/dist/src/sources/github.js +222 -36
  14. package/dist/src/sources/remote.js +50 -3
  15. package/dist/src/sources/remote_modules.js +100 -15
  16. package/dist/src/store.js +875 -110
  17. package/dist/src/terminal.js +33 -7
  18. package/dist/src/util.js +46 -1
  19. package/drizzle/migrations/{0000_initial.sql → 0000_v1_initial.sql} +182 -6
  20. package/drizzle/migrations/0002_host_scoped_lifecycle_retirements.sql +42 -0
  21. package/drizzle/migrations/0003_subscription_tracked_resource_indexes.sql +5 -0
  22. package/drizzle/schema.ts +98 -3
  23. package/package.json +2 -1
  24. package/scripts/release_smoke.sh +123 -0
  25. package/dist/src/sources/remote_profiles.js +0 -13
  26. package/drizzle/migrations/0001_inbox_items_source_occurred_at_idx.sql +0 -3
  27. package/drizzle/migrations/0002_subscription_cleanup_policy.sql +0 -45
  28. package/drizzle/migrations/0003_subscription_lifecycle_retirements.sql +0 -14
  29. package/drizzle/migrations/0004_source_idle_states.sql +0 -10
  30. package/drizzle/migrations/0005_timers.sql +0 -22
  31. package/drizzle/migrations/0006_terminal_runtime_pid.sql +0 -1
  32. package/drizzle/migrations/0007_activation_dispatch_last_notified_fingerprint.sql +0 -2
  33. package/drizzle/migrations/0008_inbox_item_sequence.sql +0 -21
package/README.md CHANGED
@@ -64,6 +64,22 @@ manually or relying on the agent runtime to expose its own notification API.
64
64
  - filtering and source model are still evolving
65
65
  - first-run onboarding is currently skill-first rather than wizard-first
66
66
 
67
+ ## v1.0.0 Beta Upgrade Notes
68
+
69
+ `v1.0.0-beta.0` was the first release on the final v1 storage and API boundary.
70
+
71
+ - pre-v1 local databases are archived and replaced with a fresh v1 database
72
+ - old local state is not imported into the new v1 database
73
+ - canonical public surfaces are now host + stream registration, entry/thread
74
+ inbox reads, and handle-scoped delivery operations
75
+ - pre-v1 compatibility shims such as legacy source-kind registration aliases,
76
+ raw inbox-item read paths, and deprecated remote-module aliases are no longer
77
+ part of the supported surface
78
+
79
+ If you are upgrading from any pre-v1 build, expect `AgentInbox` to archive the
80
+ existing local database under `~/.agentinbox/` and start with a fresh v1
81
+ database.
82
+
67
83
  ## Install
68
84
 
69
85
  Requires:
@@ -127,13 +143,21 @@ Register the current terminal session:
127
143
  ```bash
128
144
  agentinbox agent register
129
145
  agentinbox agent register --agent-id agent-alpha
146
+ agentinbox agent register --notify-lease-ms 600000 --min-unacked-items 5
130
147
  agentinbox agent current
131
148
  ```
132
149
 
150
+ `notifyLeaseMs` and `minUnackedItems` are target-facing notification policy:
151
+ they control how often a target may be reminded and how many unacked items must
152
+ accumulate before AgentInbox notifies it. Service-wide activation batching
153
+ (`windowMs`, `maxItems`) and terminal gating heuristics remain daemon-level
154
+ policy, not per-agent knobs.
155
+
133
156
  Create a local source and publish an event:
134
157
 
135
158
  ```bash
136
- agentinbox source add local_event local-demo
159
+ agentinbox host add local_event local-demo
160
+ agentinbox source add <host_id> events local-demo
137
161
  agentinbox subscription add <source_id>
138
162
  agentinbox subscription add <source_id> --agent-id <agent_id>
139
163
  agentinbox source schema <source_id>
@@ -144,10 +168,14 @@ cat filter.json | agentinbox subscription add <source_id> --filter-stdin
144
168
  agentinbox source event <source_id> --native-id demo-1 --event local.demo
145
169
  agentinbox inbox read
146
170
  agentinbox inbox read --agent-id <agent_id>
147
- agentinbox inbox ack --agent-id <agent_id> --through <last_item_id>
171
+ agentinbox inbox ack --agent-id <agent_id> --through <last_entry_id>
148
172
  ```
149
173
 
150
- When acking a reviewed batch, prefer `--through <last_item_id>` over `--all`.
174
+ The HTTP `POST /subscriptions` endpoint always returns
175
+ `{ "subscriptions": [...] }`, even when only one subscription is created. That
176
+ keeps shortcut expansion consistent for external callers.
177
+
178
+ When acking a reviewed batch, prefer `--through <last_entry_id>` over `--all`.
151
179
  That preserves the boundary of the items you actually inspected. Use
152
180
  `ack --all` only when you have intentionally verified that every current
153
181
  unacked item should be cleared.
@@ -257,10 +285,11 @@ Generate new SQLite migrations after schema changes:
257
285
  npm run db:migrations:generate
258
286
  ```
259
287
 
260
- `AgentInbox` now upgrades SQLite state with versioned SQL migrations in
261
- `drizzle/migrations`. On upgrade with pending migrations, the daemon creates a
262
- local backup next to the DB file (for example,
263
- `~/.agentinbox/agentinbox.sqlite.backup-<timestamp>`).
288
+ `AgentInbox` now initializes SQLite state from a single v1 baseline migration in
289
+ `drizzle/migrations`. If startup detects a pre-v1 local database, it archives
290
+ that database next to the DB path (for example,
291
+ `~/.agentinbox/agentinbox.sqlite.pre-v1.<timestamp>.bak`) and starts with a
292
+ fresh v1 database; pre-v1 local data is not imported.
264
293
 
265
294
  ## License
266
295
 
@@ -146,10 +146,65 @@ class AdapterRegistry {
146
146
  }
147
147
  return this.remoteSource.deriveInlinePreview(source, item);
148
148
  }
149
+ async deriveNotificationGrouping(source, item) {
150
+ if (source.sourceType === "local_event") {
151
+ return null;
152
+ }
153
+ return this.remoteSource.deriveNotificationGrouping(source, item);
154
+ }
155
+ async summarizeDigestThread(source, items, grouping) {
156
+ if (source.sourceType === "local_event") {
157
+ return null;
158
+ }
159
+ return this.remoteSource.summarizeDigestThread(source, items, grouping);
160
+ }
161
+ async listDeliveryOperations(source, handle) {
162
+ const module = await this.resolveDeliveryModule(source, handle);
163
+ if (!module?.listDeliveryOperations) {
164
+ return [];
165
+ }
166
+ return module.listDeliveryOperations({ handle, source });
167
+ }
168
+ async invokeDeliveryOperation(source, handle, operation, input, attempt) {
169
+ const module = await this.resolveDeliveryModule(source, handle);
170
+ if (!module?.invokeDeliveryOperation) {
171
+ throw new Error(`delivery operations are not supported for provider ${handle.provider}`);
172
+ }
173
+ return module.invokeDeliveryOperation({ handle, operation, input, attempt, source });
174
+ }
149
175
  status() {
150
176
  return {
151
177
  remote: this.remoteSource.status?.() ?? {},
152
178
  };
153
179
  }
180
+ async resolveDeliveryModule(source, handle) {
181
+ if (source) {
182
+ if (source.sourceType === "local_event") {
183
+ return null;
184
+ }
185
+ return this.remoteModuleRegistry.resolve(source, this.homeDir);
186
+ }
187
+ if (handle.provider === "github") {
188
+ return this.remoteModuleRegistry.resolve(syntheticBuiltinSource("github_repo"), this.homeDir);
189
+ }
190
+ if (handle.provider === "feishu") {
191
+ return this.remoteModuleRegistry.resolve(syntheticBuiltinSource("feishu_bot"), this.homeDir);
192
+ }
193
+ return null;
194
+ }
154
195
  }
155
196
  exports.AdapterRegistry = AdapterRegistry;
197
+ function syntheticBuiltinSource(sourceType) {
198
+ return {
199
+ sourceId: `builtin:${sourceType}`,
200
+ hostId: `builtin-host:${sourceType}`,
201
+ streamKind: sourceType === "github_repo" ? "repo_events" : "message_events",
202
+ streamKey: sourceType,
203
+ sourceType,
204
+ sourceKey: sourceType,
205
+ status: "active",
206
+ createdAt: "",
207
+ updatedAt: "",
208
+ config: {},
209
+ };
210
+ }
@@ -1,9 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.SqliteEventBusBackend = void 0;
4
- exports.streamIdForSource = streamIdForSource;
5
- exports.consumerIdForSubscription = consumerIdForSubscription;
6
- exports.defaultInboxIdForAgent = defaultInboxIdForAgent;
7
4
  exports.streamKeyForSource = streamKeyForSource;
8
5
  exports.toAppendResult = toAppendResult;
9
6
  const util_1 = require("./util");
@@ -18,7 +15,7 @@ class SqliteEventBusBackend {
18
15
  return existing;
19
16
  }
20
17
  const stream = {
21
- streamId: streamIdForSource(input.sourceId),
18
+ streamId: (0, util_1.generateCanonicalId)("str"),
22
19
  sourceId: input.sourceId,
23
20
  streamKey: input.streamKey,
24
21
  backend: input.backend,
@@ -46,7 +43,7 @@ class SqliteEventBusBackend {
46
43
  }
47
44
  const nextOffset = this.resolveInitialOffset(input.streamId, input.startPolicy, input.startOffset ?? null, input.startTime ?? null);
48
45
  const consumer = {
49
- consumerId: consumerIdForSubscription(input.subscriptionId),
46
+ consumerId: (0, util_1.generateCanonicalId)("con"),
50
47
  streamId: input.streamId,
51
48
  subscriptionId: input.subscriptionId,
52
49
  consumerKey: input.consumerKey,
@@ -154,17 +151,8 @@ class SqliteEventBusBackend {
154
151
  }
155
152
  }
156
153
  exports.SqliteEventBusBackend = SqliteEventBusBackend;
157
- function streamIdForSource(sourceId) {
158
- return `stream_${sourceId}`;
159
- }
160
- function consumerIdForSubscription(subscriptionId) {
161
- return `consumer_${subscriptionId}`;
162
- }
163
- function defaultInboxIdForAgent(agentId) {
164
- return `inbox_${agentId}`;
165
- }
166
- function streamKeyForSource(sourceType, sourceKey) {
167
- return `${sourceType}:${sourceKey}`;
154
+ function streamKeyForSource(sourceId) {
155
+ return `source:${sourceId}`;
168
156
  }
169
157
  function toAppendResult(result) {
170
158
  return {