@boringos/core 0.1.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.
Files changed (66) hide show
  1. package/LICENSE +21 -0
  2. package/dist/admin-routes.d.ts +12 -0
  3. package/dist/admin-routes.d.ts.map +1 -0
  4. package/dist/admin-routes.js +836 -0
  5. package/dist/admin-routes.js.map +1 -0
  6. package/dist/auth-routes.d.ts +9 -0
  7. package/dist/auth-routes.d.ts.map +1 -0
  8. package/dist/auth-routes.js +112 -0
  9. package/dist/auth-routes.js.map +1 -0
  10. package/dist/auth.d.ts +32 -0
  11. package/dist/auth.d.ts.map +1 -0
  12. package/dist/auth.js +102 -0
  13. package/dist/auth.js.map +1 -0
  14. package/dist/boringos.d.ts +52 -0
  15. package/dist/boringos.d.ts.map +1 -0
  16. package/dist/boringos.js +301 -0
  17. package/dist/boringos.js.map +1 -0
  18. package/dist/connector-routes.d.ts +5 -0
  19. package/dist/connector-routes.d.ts.map +1 -0
  20. package/dist/connector-routes.js +77 -0
  21. package/dist/connector-routes.js.map +1 -0
  22. package/dist/device-auth-routes.d.ts +12 -0
  23. package/dist/device-auth-routes.d.ts.map +1 -0
  24. package/dist/device-auth-routes.js +68 -0
  25. package/dist/device-auth-routes.js.map +1 -0
  26. package/dist/index.d.ts +17 -0
  27. package/dist/index.d.ts.map +1 -0
  28. package/dist/index.js +8 -0
  29. package/dist/index.js.map +1 -0
  30. package/dist/notifications.d.ts +30 -0
  31. package/dist/notifications.d.ts.map +1 -0
  32. package/dist/notifications.js +61 -0
  33. package/dist/notifications.js.map +1 -0
  34. package/dist/plugin-routes.d.ts +12 -0
  35. package/dist/plugin-routes.d.ts.map +1 -0
  36. package/dist/plugin-routes.js +70 -0
  37. package/dist/plugin-routes.js.map +1 -0
  38. package/dist/plugin-system.d.ts +57 -0
  39. package/dist/plugin-system.d.ts.map +1 -0
  40. package/dist/plugin-system.js +62 -0
  41. package/dist/plugin-system.js.map +1 -0
  42. package/dist/plugins/github.d.ts +18 -0
  43. package/dist/plugins/github.d.ts.map +1 -0
  44. package/dist/plugins/github.js +97 -0
  45. package/dist/plugins/github.js.map +1 -0
  46. package/dist/realtime.d.ts +15 -0
  47. package/dist/realtime.d.ts.map +1 -0
  48. package/dist/realtime.js +38 -0
  49. package/dist/realtime.js.map +1 -0
  50. package/dist/routes.d.ts +12 -0
  51. package/dist/routes.d.ts.map +1 -0
  52. package/dist/routes.js +151 -0
  53. package/dist/routes.js.map +1 -0
  54. package/dist/scheduler.d.ts +13 -0
  55. package/dist/scheduler.d.ts.map +1 -0
  56. package/dist/scheduler.js +77 -0
  57. package/dist/scheduler.js.map +1 -0
  58. package/dist/sse-routes.d.ts +4 -0
  59. package/dist/sse-routes.d.ts.map +1 -0
  60. package/dist/sse-routes.js +37 -0
  61. package/dist/sse-routes.js.map +1 -0
  62. package/dist/types.d.ts +81 -0
  63. package/dist/types.d.ts.map +1 -0
  64. package/dist/types.js +2 -0
  65. package/dist/types.js.map +1 -0
  66. package/package.json +53 -0
@@ -0,0 +1,12 @@
1
+ import { Hono } from "hono";
2
+ import type { Db } from "@boringos/db";
3
+ import type { PluginRegistry } from "./plugin-system.js";
4
+ /**
5
+ * Plugin webhook routes — receives inbound webhooks at /webhooks/plugins/:name/:event
6
+ */
7
+ export declare function createPluginWebhookRoutes(db: Db, registry: PluginRegistry): Hono;
8
+ /**
9
+ * Plugin admin routes — manage plugins, view job history
10
+ */
11
+ export declare function createPluginAdminRoutes(db: Db, registry: PluginRegistry): Hono;
12
+ //# sourceMappingURL=plugin-routes.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plugin-routes.d.ts","sourceRoot":"","sources":["../src/plugin-routes.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAE5B,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,cAAc,CAAC;AAEvC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAIzD;;GAEG;AACH,wBAAgB,yBAAyB,CAAC,EAAE,EAAE,EAAE,EAAE,QAAQ,EAAE,cAAc,GAAG,IAAI,CA0BhF;AAED;;GAEG;AACH,wBAAgB,uBAAuB,CAAC,EAAE,EAAE,EAAE,EAAE,QAAQ,EAAE,cAAc,GAAG,IAAI,CA8C9E"}
@@ -0,0 +1,70 @@
1
+ import { Hono } from "hono";
2
+ import { eq, and, desc } from "drizzle-orm";
3
+ import { plugins as pluginsTable, pluginJobRuns } from "@boringos/db";
4
+ import { runPluginJob } from "./plugin-system.js";
5
+ /**
6
+ * Plugin webhook routes — receives inbound webhooks at /webhooks/plugins/:name/:event
7
+ */
8
+ export function createPluginWebhookRoutes(db, registry) {
9
+ const app = new Hono();
10
+ app.post("/:pluginName/:event", async (c) => {
11
+ const pluginName = c.req.param("pluginName");
12
+ const event = c.req.param("event");
13
+ const webhook = registry.getWebhookHandler(pluginName, event);
14
+ if (!webhook)
15
+ return c.json({ error: `No handler for ${pluginName}/${event}` }, 404);
16
+ const headers = {};
17
+ c.req.raw.headers.forEach((v, k) => { headers[k] = v; });
18
+ const body = await c.req.json().catch(() => ({}));
19
+ const tenantId = c.req.query("tenantId") ?? c.req.header("X-Tenant-Id") ?? "";
20
+ // Get plugin config from DB
21
+ const pluginRows = await db.select().from(pluginsTable).where(and(eq(pluginsTable.tenantId, tenantId), eq(pluginsTable.name, pluginName))).limit(1);
22
+ const config = pluginRows[0]?.config ?? {};
23
+ const response = await webhook.handler({ method: "POST", headers, body, tenantId, config });
24
+ return c.json(response.body ?? { ok: true }, response.status);
25
+ });
26
+ return app;
27
+ }
28
+ /**
29
+ * Plugin admin routes — manage plugins, view job history
30
+ */
31
+ export function createPluginAdminRoutes(db, registry) {
32
+ const app = new Hono();
33
+ // List available plugins
34
+ app.get("/", (c) => {
35
+ const list = registry.list().map((p) => ({
36
+ name: p.name,
37
+ version: p.version,
38
+ description: p.description,
39
+ jobs: p.jobs?.map((j) => ({ name: j.name, schedule: j.schedule })) ?? [],
40
+ webhooks: p.webhooks?.map((w) => ({ event: w.event })) ?? [],
41
+ }));
42
+ return c.json({ plugins: list });
43
+ });
44
+ // Get plugin job history
45
+ app.get("/:name/jobs", async (c) => {
46
+ const tenantId = c.req.header("X-Tenant-Id") ?? "";
47
+ const rows = await db.select().from(pluginJobRuns)
48
+ .where(and(eq(pluginJobRuns.tenantId, tenantId), eq(pluginJobRuns.pluginName, c.req.param("name"))))
49
+ .orderBy(desc(pluginJobRuns.startedAt))
50
+ .limit(50);
51
+ return c.json({ jobs: rows });
52
+ });
53
+ // Trigger a plugin job manually
54
+ app.post("/:name/jobs/:jobName/trigger", async (c) => {
55
+ const tenantId = c.req.header("X-Tenant-Id") ?? "";
56
+ const plugin = registry.get(c.req.param("name"));
57
+ if (!plugin)
58
+ return c.json({ error: "Plugin not found" }, 404);
59
+ const job = plugin.jobs?.find((j) => j.name === c.req.param("jobName"));
60
+ if (!job)
61
+ return c.json({ error: "Job not found" }, 404);
62
+ const pluginRows = await db.select().from(pluginsTable).where(and(eq(pluginsTable.tenantId, tenantId), eq(pluginsTable.name, plugin.name))).limit(1);
63
+ const config = pluginRows[0]?.config ?? {};
64
+ // Run async
65
+ runPluginJob(db, plugin, job, tenantId, config).catch(() => { });
66
+ return c.json({ triggered: true });
67
+ });
68
+ return app;
69
+ }
70
+ //# sourceMappingURL=plugin-routes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plugin-routes.js","sourceRoot":"","sources":["../src/plugin-routes.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,57 @@
1
+ import type { Db } from "@boringos/db";
2
+ import type { AppContext } from "./types.js";
3
+ export interface PluginJob {
4
+ name: string;
5
+ schedule?: string;
6
+ handler: (ctx: PluginJobContext) => Promise<void>;
7
+ }
8
+ export interface PluginWebhook {
9
+ event: string;
10
+ handler: (req: PluginWebhookRequest) => Promise<PluginWebhookResponse>;
11
+ }
12
+ export interface PluginDefinition {
13
+ name: string;
14
+ version: string;
15
+ description?: string;
16
+ configSchema?: Record<string, {
17
+ type: string;
18
+ description: string;
19
+ required?: boolean;
20
+ }>;
21
+ jobs?: PluginJob[];
22
+ webhooks?: PluginWebhook[];
23
+ setup?(ctx: AppContext): Promise<void>;
24
+ }
25
+ export interface PluginJobContext {
26
+ pluginName: string;
27
+ tenantId: string;
28
+ config: Record<string, unknown>;
29
+ db: Db;
30
+ state: PluginStateStore;
31
+ }
32
+ export interface PluginWebhookRequest {
33
+ method: string;
34
+ headers: Record<string, string>;
35
+ body: unknown;
36
+ tenantId: string;
37
+ config: Record<string, unknown>;
38
+ }
39
+ export interface PluginWebhookResponse {
40
+ status: number;
41
+ body?: unknown;
42
+ }
43
+ export interface PluginStateStore {
44
+ get(key: string): Promise<unknown | null>;
45
+ set(key: string, value: unknown): Promise<void>;
46
+ delete(key: string): Promise<void>;
47
+ }
48
+ export declare function createPluginStateStore(db: Db, tenantId: string, pluginName: string): PluginStateStore;
49
+ export interface PluginRegistry {
50
+ register(plugin: PluginDefinition): void;
51
+ get(name: string): PluginDefinition | undefined;
52
+ list(): PluginDefinition[];
53
+ getWebhookHandler(pluginName: string, event: string): PluginWebhook | undefined;
54
+ }
55
+ export declare function createPluginRegistry(): PluginRegistry;
56
+ export declare function runPluginJob(db: Db, plugin: PluginDefinition, job: PluginJob, tenantId: string, config: Record<string, unknown>): Promise<void>;
57
+ //# sourceMappingURL=plugin-system.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plugin-system.d.ts","sourceRoot":"","sources":["../src/plugin-system.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,62 @@
1
+ import { eq, and } from "drizzle-orm";
2
+ import { pluginState, pluginJobRuns } from "@boringos/db";
3
+ import { generateId } from "@boringos/shared";
4
+ export function createPluginStateStore(db, tenantId, pluginName) {
5
+ return {
6
+ async get(key) {
7
+ const rows = await db.select().from(pluginState).where(and(eq(pluginState.tenantId, tenantId), eq(pluginState.pluginName, pluginName), eq(pluginState.key, key))).limit(1);
8
+ return rows[0]?.value ?? null;
9
+ },
10
+ async set(key, value) {
11
+ const existing = await db.select().from(pluginState).where(and(eq(pluginState.tenantId, tenantId), eq(pluginState.pluginName, pluginName), eq(pluginState.key, key))).limit(1);
12
+ if (existing[0]) {
13
+ await db.update(pluginState).set({ value: value, updatedAt: new Date() }).where(eq(pluginState.id, existing[0].id));
14
+ }
15
+ else {
16
+ await db.insert(pluginState).values({ id: generateId(), tenantId, pluginName, key, value: value });
17
+ }
18
+ },
19
+ async delete(key) {
20
+ await db.delete(pluginState).where(and(eq(pluginState.tenantId, tenantId), eq(pluginState.pluginName, pluginName), eq(pluginState.key, key)));
21
+ },
22
+ };
23
+ }
24
+ export function createPluginRegistry() {
25
+ const plugins = new Map();
26
+ return {
27
+ register(plugin) {
28
+ plugins.set(plugin.name, plugin);
29
+ },
30
+ get(name) {
31
+ return plugins.get(name);
32
+ },
33
+ list() {
34
+ return Array.from(plugins.values());
35
+ },
36
+ getWebhookHandler(pluginName, event) {
37
+ const plugin = plugins.get(pluginName);
38
+ return plugin?.webhooks?.find((w) => w.event === event);
39
+ },
40
+ };
41
+ }
42
+ // ── Plugin job runner ────────────────────────────────────────────────────────
43
+ export async function runPluginJob(db, plugin, job, tenantId, config) {
44
+ const runId = generateId();
45
+ await db.insert(pluginJobRuns).values({
46
+ id: runId,
47
+ tenantId,
48
+ pluginName: plugin.name,
49
+ jobName: job.name,
50
+ status: "running",
51
+ });
52
+ try {
53
+ const state = createPluginStateStore(db, tenantId, plugin.name);
54
+ await job.handler({ pluginName: plugin.name, tenantId, config, db, state });
55
+ await db.update(pluginJobRuns).set({ status: "completed", finishedAt: new Date() }).where(eq(pluginJobRuns.id, runId));
56
+ }
57
+ catch (err) {
58
+ const error = err instanceof Error ? err.message : String(err);
59
+ await db.update(pluginJobRuns).set({ status: "failed", error, finishedAt: new Date() }).where(eq(pluginJobRuns.id, runId));
60
+ }
61
+ }
62
+ //# sourceMappingURL=plugin-system.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plugin-system.js","sourceRoot":"","sources":["../src/plugin-system.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,18 @@
1
+ import type { PluginDefinition } from "../plugin-system.js";
2
+ /**
3
+ * Built-in GitHub plugin.
4
+ *
5
+ * Jobs:
6
+ * - sync-repos: syncs issues and PRs from configured repos into tasks
7
+ *
8
+ * Webhooks:
9
+ * - issue-created: creates a task when a GitHub issue is opened
10
+ * - pr-opened: creates a task when a PR is opened
11
+ *
12
+ * Config:
13
+ * - token: GitHub personal access token
14
+ * - org: GitHub organization name
15
+ * - repos: array of repo names to sync
16
+ */
17
+ export declare const githubPlugin: PluginDefinition;
18
+ //# sourceMappingURL=github.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"github.d.ts","sourceRoot":"","sources":["../../src/plugins/github.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAE5D;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,YAAY,EAAE,gBAqF1B,CAAC"}
@@ -0,0 +1,97 @@
1
+ /**
2
+ * Built-in GitHub plugin.
3
+ *
4
+ * Jobs:
5
+ * - sync-repos: syncs issues and PRs from configured repos into tasks
6
+ *
7
+ * Webhooks:
8
+ * - issue-created: creates a task when a GitHub issue is opened
9
+ * - pr-opened: creates a task when a PR is opened
10
+ *
11
+ * Config:
12
+ * - token: GitHub personal access token
13
+ * - org: GitHub organization name
14
+ * - repos: array of repo names to sync
15
+ */
16
+ export const githubPlugin = {
17
+ name: "github",
18
+ version: "1.0.0",
19
+ description: "Sync GitHub issues and PRs into BoringOS tasks.",
20
+ configSchema: {
21
+ token: { type: "string", description: "GitHub personal access token", required: true },
22
+ org: { type: "string", description: "GitHub organization name", required: true },
23
+ repos: { type: "array", description: "Repository names to sync" },
24
+ },
25
+ jobs: [
26
+ {
27
+ name: "sync-repos",
28
+ schedule: "*/15 * * * *",
29
+ async handler(ctx) {
30
+ const { token, org, repos } = ctx.config;
31
+ if (!token || !org)
32
+ return;
33
+ const repoList = repos ?? [];
34
+ const lastSync = await ctx.state.get("lastSyncAt");
35
+ for (const repo of repoList) {
36
+ try {
37
+ const since = lastSync ? `&since=${lastSync}` : "";
38
+ const res = await fetch(`https://api.github.com/repos/${org}/${repo}/issues?state=open${since}`, {
39
+ headers: { Authorization: `token ${token}`, Accept: "application/vnd.github.v3+json" },
40
+ });
41
+ if (res.ok) {
42
+ const issues = await res.json();
43
+ // Store count for state tracking
44
+ await ctx.state.set(`${repo}-issueCount`, issues.length);
45
+ }
46
+ }
47
+ catch {
48
+ // Individual repo failure doesn't stop the sync
49
+ }
50
+ }
51
+ await ctx.state.set("lastSyncAt", new Date().toISOString());
52
+ },
53
+ },
54
+ ],
55
+ webhooks: [
56
+ {
57
+ event: "issue-created",
58
+ async handler(req) {
59
+ const body = req.body;
60
+ const action = body.action;
61
+ if (action !== "opened")
62
+ return { status: 200, body: { ignored: true } };
63
+ const issue = body.issue;
64
+ return {
65
+ status: 200,
66
+ body: {
67
+ action: "task_created",
68
+ source: "github",
69
+ title: issue.title,
70
+ number: issue.number,
71
+ },
72
+ };
73
+ },
74
+ },
75
+ {
76
+ event: "pr-opened",
77
+ async handler(req) {
78
+ const body = req.body;
79
+ const action = body.action;
80
+ if (action !== "opened")
81
+ return { status: 200, body: { ignored: true } };
82
+ const pr = body.pull_request;
83
+ return {
84
+ status: 200,
85
+ body: {
86
+ action: "task_created",
87
+ source: "github",
88
+ title: `PR: ${pr.title}`,
89
+ number: pr.number,
90
+ url: pr.html_url,
91
+ },
92
+ };
93
+ },
94
+ },
95
+ ],
96
+ };
97
+ //# sourceMappingURL=github.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"github.js","sourceRoot":"","sources":["../../src/plugins/github.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,15 @@
1
+ export interface RealtimeEvent {
2
+ type: string;
3
+ tenantId: string;
4
+ data: Record<string, unknown>;
5
+ timestamp: string;
6
+ }
7
+ export declare const EVENT_TYPES: readonly ["run:started", "run:completed", "run:failed", "run:log_line", "run:stderr_line", "task:created", "task:updated", "task:comment_added", "agent:created", "agent:updated", "agent:woken", "approval:created", "approval:decided", "workflow:started", "workflow:completed"];
8
+ export type EventType = (typeof EVENT_TYPES)[number];
9
+ export interface RealtimeBus {
10
+ publish(event: RealtimeEvent): void;
11
+ subscribe(tenantId: string, listener: (event: RealtimeEvent) => void): () => void;
12
+ subscribeAll(listener: (event: RealtimeEvent) => void): () => void;
13
+ }
14
+ export declare function createRealtimeBus(): RealtimeBus;
15
+ //# sourceMappingURL=realtime.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"realtime.d.ts","sourceRoot":"","sources":["../src/realtime.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC9B,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,eAAO,MAAM,WAAW,qRAgBd,CAAC;AAEX,MAAM,MAAM,SAAS,GAAG,CAAC,OAAO,WAAW,CAAC,CAAC,MAAM,CAAC,CAAC;AAIrD,MAAM,WAAW,WAAW;IAC1B,OAAO,CAAC,KAAK,EAAE,aAAa,GAAG,IAAI,CAAC;IACpC,SAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,KAAK,EAAE,aAAa,KAAK,IAAI,GAAG,MAAM,IAAI,CAAC;IAClF,YAAY,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,aAAa,KAAK,IAAI,GAAG,MAAM,IAAI,CAAC;CACpE;AAED,wBAAgB,iBAAiB,IAAI,WAAW,CAqB/C"}
@@ -0,0 +1,38 @@
1
+ import { EventEmitter } from "node:events";
2
+ export const EVENT_TYPES = [
3
+ "run:started",
4
+ "run:completed",
5
+ "run:failed",
6
+ "run:log_line",
7
+ "run:stderr_line",
8
+ "task:created",
9
+ "task:updated",
10
+ "task:comment_added",
11
+ "agent:created",
12
+ "agent:updated",
13
+ "agent:woken",
14
+ "approval:created",
15
+ "approval:decided",
16
+ "workflow:started",
17
+ "workflow:completed",
18
+ ];
19
+ export function createRealtimeBus() {
20
+ const emitter = new EventEmitter();
21
+ emitter.setMaxListeners(1000); // many concurrent SSE connections
22
+ return {
23
+ publish(event) {
24
+ emitter.emit(`tenant:${event.tenantId}`, event);
25
+ emitter.emit("*", event);
26
+ },
27
+ subscribe(tenantId, listener) {
28
+ const channel = `tenant:${tenantId}`;
29
+ emitter.on(channel, listener);
30
+ return () => emitter.off(channel, listener);
31
+ },
32
+ subscribeAll(listener) {
33
+ emitter.on("*", listener);
34
+ return () => emitter.off("*", listener);
35
+ },
36
+ };
37
+ }
38
+ //# sourceMappingURL=realtime.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"realtime.js","sourceRoot":"","sources":["../src/realtime.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAW3C,MAAM,CAAC,MAAM,WAAW,GAAG;IACzB,aAAa;IACb,eAAe;IACf,YAAY;IACZ,cAAc;IACd,iBAAiB;IACjB,cAAc;IACd,cAAc;IACd,oBAAoB;IACpB,eAAe;IACf,eAAe;IACf,aAAa;IACb,kBAAkB;IAClB,kBAAkB;IAClB,kBAAkB;IAClB,oBAAoB;CACZ,CAAC;AAYX,MAAM,UAAU,iBAAiB;IAC/B,MAAM,OAAO,GAAG,IAAI,YAAY,EAAE,CAAC;IACnC,OAAO,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC,CAAC,kCAAkC;IAEjE,OAAO;QACL,OAAO,CAAC,KAAoB;YAC1B,OAAO,CAAC,IAAI,CAAC,UAAU,KAAK,CAAC,QAAQ,EAAE,EAAE,KAAK,CAAC,CAAC;YAChD,OAAO,CAAC,IAAI,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;QAC3B,CAAC;QAED,SAAS,CAAC,QAAgB,EAAE,QAAwC;YAClE,MAAM,OAAO,GAAG,UAAU,QAAQ,EAAE,CAAC;YACrC,OAAO,CAAC,EAAE,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;YAC9B,OAAO,GAAG,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;QAC9C,CAAC;QAED,YAAY,CAAC,QAAwC;YACnD,OAAO,CAAC,EAAE,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC;YAC1B,OAAO,GAAG,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC;QAC1C,CAAC;KACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,12 @@
1
+ import { Hono } from "hono";
2
+ import type { Db } from "@boringos/db";
3
+ import type { AgentEngine } from "@boringos/agent";
4
+ import type { CallbackTokenClaims } from "@boringos/agent";
5
+ type AuthEnv = {
6
+ Variables: {
7
+ claims: CallbackTokenClaims;
8
+ };
9
+ };
10
+ export declare function createCallbackRoutes(db: Db, _engine: AgentEngine, jwtSecret: string): Hono<AuthEnv>;
11
+ export {};
12
+ //# sourceMappingURL=routes.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"routes.d.ts","sourceRoot":"","sources":["../src/routes.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAE5B,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,cAAc,CAAC;AAQvC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAEnD,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AAG3D,KAAK,OAAO,GAAG;IACb,SAAS,EAAE;QACT,MAAM,EAAE,mBAAmB,CAAC;KAC7B,CAAC;CACH,CAAC;AAEF,wBAAgB,oBAAoB,CAAC,EAAE,EAAE,EAAE,EAAE,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,CA6JnG"}
package/dist/routes.js ADDED
@@ -0,0 +1,151 @@
1
+ import { Hono } from "hono";
2
+ import { eq } from "drizzle-orm";
3
+ import { tasks, taskComments, taskWorkProducts, costEvents, agents, } from "@boringos/db";
4
+ import { verifyCallbackToken } from "@boringos/agent";
5
+ import { generateId } from "@boringos/shared";
6
+ export function createCallbackRoutes(db, _engine, jwtSecret) {
7
+ const app = new Hono();
8
+ // JWT auth middleware — all callback routes require a valid token
9
+ app.use("/*", async (c, next) => {
10
+ const authHeader = c.req.header("Authorization");
11
+ if (!authHeader?.startsWith("Bearer ")) {
12
+ return c.json({ error: "Missing Authorization header" }, 401);
13
+ }
14
+ const token = authHeader.slice(7);
15
+ const claims = verifyCallbackToken(token, jwtSecret);
16
+ if (!claims) {
17
+ return c.json({ error: "Invalid or expired token" }, 401);
18
+ }
19
+ c.set("claims", claims);
20
+ await next();
21
+ });
22
+ // GET /agents — list agents for tenant
23
+ app.get("/agents", async (c) => {
24
+ const claims = c.get("claims");
25
+ const rows = await db.select().from(agents).where(eq(agents.tenantId, claims.tenant_id));
26
+ return c.json({ agents: rows });
27
+ });
28
+ // GET /tasks — list tasks for tenant
29
+ app.get("/tasks", async (c) => {
30
+ const claims = c.get("claims");
31
+ const rows = await db.select().from(tasks).where(eq(tasks.tenantId, claims.tenant_id));
32
+ return c.json({ tasks: rows });
33
+ });
34
+ // GET /runs — list runs for tenant
35
+ app.get("/runs", async (c) => {
36
+ const claims = c.get("claims");
37
+ const { agentRuns } = await import("@boringos/db");
38
+ const rows = await db.select().from(agentRuns).where(eq(agentRuns.tenantId, claims.tenant_id));
39
+ return c.json({ runs: rows });
40
+ });
41
+ // GET /tasks/:taskId — read task + comments
42
+ app.get("/tasks/:taskId", async (c) => {
43
+ const taskId = c.req.param("taskId");
44
+ const taskRows = await db.select().from(tasks).where(eq(tasks.id, taskId)).limit(1);
45
+ const task = taskRows[0];
46
+ if (!task)
47
+ return c.json({ error: "Task not found" }, 404);
48
+ const comments = await db.select().from(taskComments).where(eq(taskComments.taskId, taskId));
49
+ return c.json({ task, comments });
50
+ });
51
+ // PATCH /tasks/:taskId — update task
52
+ app.patch("/tasks/:taskId", async (c) => {
53
+ const taskId = c.req.param("taskId");
54
+ const body = await c.req.json();
55
+ const updates = { updatedAt: new Date() };
56
+ if (body.status)
57
+ updates.status = body.status;
58
+ if (body.title)
59
+ updates.title = body.title;
60
+ if (body.description !== undefined)
61
+ updates.description = body.description;
62
+ await db.update(tasks).set(updates).where(eq(tasks.id, taskId));
63
+ return c.json({ ok: true });
64
+ });
65
+ // POST /tasks — create task
66
+ app.post("/tasks", async (c) => {
67
+ const claims = c.get("claims");
68
+ const body = await c.req.json();
69
+ const id = generateId();
70
+ await db.insert(tasks).values({
71
+ id,
72
+ tenantId: claims.tenant_id,
73
+ title: body.title,
74
+ description: body.description,
75
+ status: body.status ?? "todo",
76
+ priority: body.priority ?? "medium",
77
+ parentId: body.parentId,
78
+ assigneeAgentId: body.assigneeAgentId,
79
+ createdByAgentId: claims.agent_id,
80
+ originKind: body.originKind ?? "agent_created",
81
+ });
82
+ return c.json({ id }, 201);
83
+ });
84
+ // POST /tasks/:taskId/comments — post comment
85
+ app.post("/tasks/:taskId/comments", async (c) => {
86
+ const claims = c.get("claims");
87
+ const taskId = c.req.param("taskId");
88
+ const body = await c.req.json();
89
+ const id = generateId();
90
+ await db.insert(taskComments).values({
91
+ id,
92
+ taskId,
93
+ tenantId: claims.tenant_id,
94
+ body: body.body,
95
+ authorAgentId: claims.agent_id,
96
+ });
97
+ return c.json({ id }, 201);
98
+ });
99
+ // POST /tasks/:taskId/work-products — record deliverable
100
+ app.post("/tasks/:taskId/work-products", async (c) => {
101
+ const claims = c.get("claims");
102
+ const taskId = c.req.param("taskId");
103
+ const body = await c.req.json();
104
+ const id = generateId();
105
+ await db.insert(taskWorkProducts).values({
106
+ id,
107
+ taskId,
108
+ tenantId: claims.tenant_id,
109
+ kind: body.kind,
110
+ title: body.title,
111
+ url: body.url,
112
+ metadata: body.metadata,
113
+ createdByAgentId: claims.agent_id,
114
+ });
115
+ return c.json({ id }, 201);
116
+ });
117
+ // POST /runs/:runId/cost — report token usage
118
+ app.post("/runs/:runId/cost", async (c) => {
119
+ const claims = c.get("claims");
120
+ const runId = c.req.param("runId");
121
+ const body = await c.req.json();
122
+ const id = generateId();
123
+ await db.insert(costEvents).values({
124
+ id,
125
+ tenantId: claims.tenant_id,
126
+ agentId: claims.agent_id,
127
+ runId,
128
+ inputTokens: body.inputTokens ?? 0,
129
+ outputTokens: body.outputTokens ?? 0,
130
+ model: body.model,
131
+ costUsd: body.costUsd?.toString(),
132
+ });
133
+ return c.json({ ok: true });
134
+ });
135
+ // POST /agents — create agent
136
+ app.post("/agents", async (c) => {
137
+ const claims = c.get("claims");
138
+ const body = await c.req.json();
139
+ const id = generateId();
140
+ await db.insert(agents).values({
141
+ id,
142
+ tenantId: claims.tenant_id,
143
+ name: body.name,
144
+ role: body.role ?? "general",
145
+ instructions: body.instructions,
146
+ });
147
+ return c.json({ id }, 201);
148
+ });
149
+ return app;
150
+ }
151
+ //# sourceMappingURL=routes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"routes.js","sourceRoot":"","sources":["../src/routes.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ import type { Db } from "@boringos/db";
2
+ import type { AgentEngine } from "@boringos/agent";
3
+ export interface RoutineScheduler {
4
+ start(): void;
5
+ stop(): void;
6
+ }
7
+ /**
8
+ * Simple interval-based routine scheduler.
9
+ * Checks every 60 seconds for routines whose cron expression matches the current minute.
10
+ * No external cron library — uses basic time matching.
11
+ */
12
+ export declare function createRoutineScheduler(db: Db, engine: AgentEngine): RoutineScheduler;
13
+ //# sourceMappingURL=scheduler.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scheduler.d.ts","sourceRoot":"","sources":["../src/scheduler.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,cAAc,CAAC;AAEvC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAEnD,MAAM,WAAW,gBAAgB;IAC/B,KAAK,IAAI,IAAI,CAAC;IACd,IAAI,IAAI,IAAI,CAAC;CACd;AAED;;;;GAIG;AACH,wBAAgB,sBAAsB,CAAC,EAAE,EAAE,EAAE,EAAE,MAAM,EAAE,WAAW,GAAG,gBAAgB,CA6CpF"}