@holon-run/agentinbox 1.0.0-beta.3 → 1.0.0-beta.4
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 +1 -1
- package/dist/src/adapters.js +49 -1
- package/dist/src/cli.js +91 -0
- package/dist/src/http.js +53 -3
- package/dist/src/service.js +301 -16
- package/dist/src/source_resolution.js +10 -0
- package/dist/src/source_schema.js +2 -0
- package/dist/src/sources/github.js +218 -6
- package/dist/src/sources/github_ci.js +48 -23
- package/dist/src/sources/remote.js +183 -1
- package/dist/src/sources/remote_modules.js +22 -3
- package/dist/src/store.js +8 -4
- package/dist/src/terminal.js +4 -3
- package/drizzle/migrations/0001_activation_entry_boundary.sql +11 -0
- package/drizzle/schema.ts +2 -0
- package/package.json +2 -2
package/README.md
CHANGED
package/dist/src/adapters.js
CHANGED
|
@@ -44,7 +44,9 @@ class AdapterRegistry {
|
|
|
44
44
|
remoteModuleRegistry;
|
|
45
45
|
constructor(store, appendSourceEvent, options) {
|
|
46
46
|
this.homeDir = options?.homeDir ?? (0, paths_1.resolveAgentInboxHome)(process.env);
|
|
47
|
-
this.remoteModuleRegistry = options?.remoteModuleRegistry ?? new remote_modules_1.RemoteSourceModuleRegistry(
|
|
47
|
+
this.remoteModuleRegistry = options?.remoteModuleRegistry ?? new remote_modules_1.RemoteSourceModuleRegistry({
|
|
48
|
+
githubCallClient: options?.githubCallClient,
|
|
49
|
+
});
|
|
48
50
|
this.remoteSource = new remote_1.RemoteSourceRuntime(store, appendSourceEvent, {
|
|
49
51
|
homeDir: this.homeDir,
|
|
50
52
|
client: options?.remoteSourceClient,
|
|
@@ -140,6 +142,31 @@ class AdapterRegistry {
|
|
|
140
142
|
}
|
|
141
143
|
return this.remoteSource.expandSubscriptionShortcut(source, input);
|
|
142
144
|
}
|
|
145
|
+
async listFollowTemplates(source) {
|
|
146
|
+
if (source.sourceType === "local_event") {
|
|
147
|
+
return [];
|
|
148
|
+
}
|
|
149
|
+
return this.remoteSource.listFollowTemplates(source);
|
|
150
|
+
}
|
|
151
|
+
async expandFollowTemplate(source, input) {
|
|
152
|
+
if (source.sourceType === "local_event") {
|
|
153
|
+
return null;
|
|
154
|
+
}
|
|
155
|
+
return this.remoteSource.expandFollowTemplate(source, input);
|
|
156
|
+
}
|
|
157
|
+
followPreviewRefsForProviderOrKind(providerOrKind, config) {
|
|
158
|
+
const trimmed = providerOrKind.trim();
|
|
159
|
+
if (trimmed.length === 0) {
|
|
160
|
+
throw new Error("follow requires a providerOrKind");
|
|
161
|
+
}
|
|
162
|
+
if (isExplicitFollowPreviewRef(trimmed)) {
|
|
163
|
+
return [trimmed];
|
|
164
|
+
}
|
|
165
|
+
const candidates = hasRemoteSourceModulePath(config)
|
|
166
|
+
? ["remote_source", ...(0, remote_modules_1.builtinRemoteSourceTypes)()]
|
|
167
|
+
: (0, remote_modules_1.builtinRemoteSourceTypes)();
|
|
168
|
+
return Array.from(new Set(candidates));
|
|
169
|
+
}
|
|
143
170
|
async deriveInlinePreview(source, item) {
|
|
144
171
|
if (source.sourceType === "local_event") {
|
|
145
172
|
return null;
|
|
@@ -152,6 +179,15 @@ class AdapterRegistry {
|
|
|
152
179
|
}
|
|
153
180
|
return this.remoteSource.deriveNotificationGrouping(source, item);
|
|
154
181
|
}
|
|
182
|
+
async getSourceRuntime(source) {
|
|
183
|
+
if (source.sourceType === "local_event") {
|
|
184
|
+
return null;
|
|
185
|
+
}
|
|
186
|
+
return this.remoteSource.getSourceRuntime(source);
|
|
187
|
+
}
|
|
188
|
+
async listSourceRuntimes(sources) {
|
|
189
|
+
return this.remoteSource.listSourceRuntimes(sources);
|
|
190
|
+
}
|
|
155
191
|
async summarizeDigestThread(source, items, grouping) {
|
|
156
192
|
if (source.sourceType === "local_event") {
|
|
157
193
|
return null;
|
|
@@ -194,6 +230,18 @@ class AdapterRegistry {
|
|
|
194
230
|
}
|
|
195
231
|
}
|
|
196
232
|
exports.AdapterRegistry = AdapterRegistry;
|
|
233
|
+
function isExplicitFollowPreviewRef(value) {
|
|
234
|
+
return (value === "local_event" ||
|
|
235
|
+
value === "remote_source" ||
|
|
236
|
+
value === "github_repo" ||
|
|
237
|
+
value === "github_repo_ci" ||
|
|
238
|
+
value === "feishu_bot" ||
|
|
239
|
+
value.startsWith("remote:"));
|
|
240
|
+
}
|
|
241
|
+
function hasRemoteSourceModulePath(config) {
|
|
242
|
+
const modulePath = config?.modulePath;
|
|
243
|
+
return typeof modulePath === "string" && modulePath.trim().length > 0;
|
|
244
|
+
}
|
|
197
245
|
function syntheticBuiltinSource(sourceType) {
|
|
198
246
|
return {
|
|
199
247
|
sourceId: `builtin:${sourceType}`,
|
package/dist/src/cli.js
CHANGED
|
@@ -182,6 +182,47 @@ async function main() {
|
|
|
182
182
|
await printRemote(client, `/streams/${encodeURIComponent(streamRef)}/schema`, undefined, "GET");
|
|
183
183
|
return;
|
|
184
184
|
}
|
|
185
|
+
if (command === "follow") {
|
|
186
|
+
const args = normalized.slice(1);
|
|
187
|
+
const positionals = positionalArgs(args, [
|
|
188
|
+
"--agent-id",
|
|
189
|
+
"--args-json",
|
|
190
|
+
"--arg",
|
|
191
|
+
"--config-json",
|
|
192
|
+
"--config-ref",
|
|
193
|
+
"--start-policy",
|
|
194
|
+
"--start-offset",
|
|
195
|
+
"--start-time",
|
|
196
|
+
]);
|
|
197
|
+
const [providerOrKind, template] = positionals;
|
|
198
|
+
if (!providerOrKind || !template || positionals[2]) {
|
|
199
|
+
throw new Error("usage: agentinbox follow <providerOrKind> <template> [--agent-id ID] [--args-json JSON | --arg KEY=VALUE ...] [--config-json JSON] [--config-ref REF] [--start-policy POLICY] [--start-offset N] [--start-time ISO8601]");
|
|
200
|
+
}
|
|
201
|
+
const argsJson = takeFlagValue(normalized, "--args-json");
|
|
202
|
+
const hasArgFlags = hasFlag(normalized, "--arg");
|
|
203
|
+
if (argsJson != null && hasArgFlags) {
|
|
204
|
+
throw new Error("follow accepts either --args-json or repeated --arg flags, but not both");
|
|
205
|
+
}
|
|
206
|
+
const selection = await selectAgentForCommand(client, {
|
|
207
|
+
explicitAgentId: takeFlagValue(normalized, "--agent-id"),
|
|
208
|
+
autoRegister: true,
|
|
209
|
+
});
|
|
210
|
+
const response = await requestRemote(client, "/follow", {
|
|
211
|
+
agentId: selection.agentId,
|
|
212
|
+
providerOrKind,
|
|
213
|
+
template,
|
|
214
|
+
templateArgs: argsJson != null
|
|
215
|
+
? (0, util_1.parseJsonArg)(argsJson, "--args-json")
|
|
216
|
+
: readFollowTemplateArgs(normalized),
|
|
217
|
+
configRef: takeFlagValue(normalized, "--config-ref") ?? undefined,
|
|
218
|
+
config: (0, util_1.parseJsonArg)(takeFlagValue(normalized, "--config-json")),
|
|
219
|
+
startPolicy: takeFlagValue(normalized, "--start-policy") ?? undefined,
|
|
220
|
+
startOffset: parseOptionalNumber(takeFlagValue(normalized, "--start-offset")),
|
|
221
|
+
startTime: takeFlagValue(normalized, "--start-time") ?? undefined,
|
|
222
|
+
});
|
|
223
|
+
console.log((0, util_1.jsonResponse)(withCommandMetadata(response.data, selection)));
|
|
224
|
+
return;
|
|
225
|
+
}
|
|
185
226
|
if (command === "stream" && normalized[1] === "poll") {
|
|
186
227
|
const streamId = normalized[2];
|
|
187
228
|
if (!streamId) {
|
|
@@ -1065,6 +1106,50 @@ function readSubscriptionFilter(args) {
|
|
|
1065
1106
|
}
|
|
1066
1107
|
return {};
|
|
1067
1108
|
}
|
|
1109
|
+
function readFollowTemplateArgs(args) {
|
|
1110
|
+
const parsed = {};
|
|
1111
|
+
for (let index = 0; index < args.length; index += 1) {
|
|
1112
|
+
if (args[index] !== "--arg") {
|
|
1113
|
+
continue;
|
|
1114
|
+
}
|
|
1115
|
+
const raw = args[index + 1];
|
|
1116
|
+
if (!raw || raw.startsWith("--")) {
|
|
1117
|
+
throw new Error("flag --arg requires KEY=VALUE");
|
|
1118
|
+
}
|
|
1119
|
+
const separator = raw.indexOf("=");
|
|
1120
|
+
if (separator <= 0) {
|
|
1121
|
+
throw new Error("flag --arg requires KEY=VALUE");
|
|
1122
|
+
}
|
|
1123
|
+
const key = raw.slice(0, separator).trim();
|
|
1124
|
+
const rawValue = raw.slice(separator + 1);
|
|
1125
|
+
if (key.length === 0) {
|
|
1126
|
+
throw new Error("flag --arg requires a non-empty key");
|
|
1127
|
+
}
|
|
1128
|
+
parsed[key] = parseFollowTemplateArgValue(rawValue);
|
|
1129
|
+
index += 1;
|
|
1130
|
+
}
|
|
1131
|
+
return parsed;
|
|
1132
|
+
}
|
|
1133
|
+
function parseFollowTemplateArgValue(raw) {
|
|
1134
|
+
if (raw === "true") {
|
|
1135
|
+
return true;
|
|
1136
|
+
}
|
|
1137
|
+
if (raw === "false") {
|
|
1138
|
+
return false;
|
|
1139
|
+
}
|
|
1140
|
+
if (/^-?\d+(?:\.\d+)?$/.test(raw)) {
|
|
1141
|
+
return Number(raw);
|
|
1142
|
+
}
|
|
1143
|
+
if ((raw.startsWith("[") && raw.endsWith("]")) || (raw.startsWith("{") && raw.endsWith("}")) || raw === "null") {
|
|
1144
|
+
try {
|
|
1145
|
+
return JSON.parse(raw);
|
|
1146
|
+
}
|
|
1147
|
+
catch {
|
|
1148
|
+
return raw;
|
|
1149
|
+
}
|
|
1150
|
+
}
|
|
1151
|
+
return raw;
|
|
1152
|
+
}
|
|
1068
1153
|
function withCommandMetadata(data, selection) {
|
|
1069
1154
|
return {
|
|
1070
1155
|
...data,
|
|
@@ -1142,6 +1227,7 @@ Usage:
|
|
|
1142
1227
|
Commands:
|
|
1143
1228
|
serve
|
|
1144
1229
|
daemon
|
|
1230
|
+
follow
|
|
1145
1231
|
source
|
|
1146
1232
|
agent
|
|
1147
1233
|
timer
|
|
@@ -1187,6 +1273,11 @@ Usage:
|
|
|
1187
1273
|
agentinbox stream schema preview <sourceKind|sourceType> [--config-json JSON] [--config-ref REF]
|
|
1188
1274
|
agentinbox stream poll <streamId>
|
|
1189
1275
|
agentinbox stream event <streamId> --native-id ID --event EVENT [--occurred-at ISO8601] [--metadata-json JSON] [--payload-json JSON]
|
|
1276
|
+
`,
|
|
1277
|
+
follow: `agentinbox follow
|
|
1278
|
+
|
|
1279
|
+
Usage:
|
|
1280
|
+
agentinbox follow <providerOrKind> <template> [--agent-id ID] [--args-json JSON | --arg KEY=VALUE ...] [--config-json JSON] [--config-ref REF] [--start-policy POLICY] [--start-offset N] [--start-time ISO8601]
|
|
1190
1281
|
`,
|
|
1191
1282
|
source: `agentinbox source
|
|
1192
1283
|
|
package/dist/src/http.js
CHANGED
|
@@ -29,6 +29,10 @@ const errorResponseSchema = {
|
|
|
29
29
|
error: { type: "string" },
|
|
30
30
|
},
|
|
31
31
|
};
|
|
32
|
+
const subscriptionStartPolicySchema = {
|
|
33
|
+
type: "string",
|
|
34
|
+
enum: ["latest", "earliest", "at_offset", "at_time"],
|
|
35
|
+
};
|
|
32
36
|
const subscriptionCollectionSchema = {
|
|
33
37
|
type: "object",
|
|
34
38
|
required: ["subscriptions"],
|
|
@@ -286,7 +290,7 @@ function buildFastifyServer(service) {
|
|
|
286
290
|
},
|
|
287
291
|
},
|
|
288
292
|
},
|
|
289
|
-
}, async () => ({ sources: service.
|
|
293
|
+
}, async () => ({ sources: await service.listSourceViews() }));
|
|
290
294
|
app.post("/sources", {
|
|
291
295
|
schema: {
|
|
292
296
|
tags: ["sources"],
|
|
@@ -464,6 +468,48 @@ function buildFastifyServer(service) {
|
|
|
464
468
|
},
|
|
465
469
|
},
|
|
466
470
|
}, async (request) => service.previewSourceSchema(request.body));
|
|
471
|
+
app.post("/follow", {
|
|
472
|
+
schema: {
|
|
473
|
+
tags: ["subscriptions"],
|
|
474
|
+
body: {
|
|
475
|
+
type: "object",
|
|
476
|
+
additionalProperties: false,
|
|
477
|
+
required: ["agentId", "providerOrKind", "template"],
|
|
478
|
+
properties: {
|
|
479
|
+
agentId: { type: "string", minLength: 1 },
|
|
480
|
+
providerOrKind: { type: "string", minLength: 1 },
|
|
481
|
+
template: { type: "string", minLength: 1 },
|
|
482
|
+
templateArgs: jsonObjectSchema,
|
|
483
|
+
configRef: { anyOf: [{ type: "string" }, { type: "null" }] },
|
|
484
|
+
config: jsonObjectSchema,
|
|
485
|
+
startPolicy: subscriptionStartPolicySchema,
|
|
486
|
+
startOffset: { type: "integer" },
|
|
487
|
+
startTime: { type: "string" },
|
|
488
|
+
},
|
|
489
|
+
},
|
|
490
|
+
response: {
|
|
491
|
+
200: jsonObjectSchema,
|
|
492
|
+
400: errorResponseSchema,
|
|
493
|
+
},
|
|
494
|
+
},
|
|
495
|
+
}, async (request) => {
|
|
496
|
+
const body = request.body;
|
|
497
|
+
return service.follow({
|
|
498
|
+
agentId: String(body.agentId),
|
|
499
|
+
providerOrKind: String(body.providerOrKind),
|
|
500
|
+
template: String(body.template),
|
|
501
|
+
templateArgs: body.templateArgs && typeof body.templateArgs === "object"
|
|
502
|
+
? body.templateArgs
|
|
503
|
+
: undefined,
|
|
504
|
+
configRef: optionalString(body.configRef) ?? null,
|
|
505
|
+
config: body.config && typeof body.config === "object"
|
|
506
|
+
? body.config
|
|
507
|
+
: undefined,
|
|
508
|
+
startPolicy: optionalString(body.startPolicy),
|
|
509
|
+
startOffset: typeof body.startOffset === "number" ? body.startOffset : undefined,
|
|
510
|
+
startTime: optionalString(body.startTime) ?? undefined,
|
|
511
|
+
});
|
|
512
|
+
});
|
|
467
513
|
app.post("/streams/:streamId/poll", {
|
|
468
514
|
schema: {
|
|
469
515
|
tags: ["sources"],
|
|
@@ -1083,7 +1129,7 @@ function buildFastifyServer(service) {
|
|
|
1083
1129
|
filter: jsonObjectSchema,
|
|
1084
1130
|
trackedResourceRef: { type: "string" },
|
|
1085
1131
|
cleanupPolicy: jsonObjectSchema,
|
|
1086
|
-
startPolicy:
|
|
1132
|
+
startPolicy: subscriptionStartPolicySchema,
|
|
1087
1133
|
startOffset: { type: "integer" },
|
|
1088
1134
|
startTime: { type: "string" },
|
|
1089
1135
|
},
|
|
@@ -1204,7 +1250,7 @@ function buildFastifyServer(service) {
|
|
|
1204
1250
|
additionalProperties: false,
|
|
1205
1251
|
required: ["startPolicy"],
|
|
1206
1252
|
properties: {
|
|
1207
|
-
startPolicy:
|
|
1253
|
+
startPolicy: subscriptionStartPolicySchema,
|
|
1208
1254
|
startOffset: { type: "integer" },
|
|
1209
1255
|
startTime: { type: "string" },
|
|
1210
1256
|
},
|
|
@@ -1690,6 +1736,10 @@ function isBadRequestError(message) {
|
|
|
1690
1736
|
message.startsWith("cleanupPolicy ") ||
|
|
1691
1737
|
message.startsWith("trackedResourceRef ") ||
|
|
1692
1738
|
message.startsWith("preview failed: ") ||
|
|
1739
|
+
message.startsWith("follow preview failed: ") ||
|
|
1740
|
+
message.startsWith("follow template ") ||
|
|
1741
|
+
message.startsWith("unknown follow template ") ||
|
|
1742
|
+
message.startsWith("follow requires a providerOrKind") ||
|
|
1693
1743
|
message.startsWith("unknown source kind or type for preview") ||
|
|
1694
1744
|
message.startsWith("preview source kind ") ||
|
|
1695
1745
|
message.startsWith("subscription add shortcut") ||
|