@nettee/beacon 0.3.6 → 0.4.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 +16 -1
- package/dist/cli-app.d.ts +31 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +11 -8
- package/dist/daemon/config/channels.d.ts +11 -0
- package/dist/daemon/config/event-credentials.d.ts +6 -0
- package/dist/daemon/config/global.d.ts +40 -0
- package/dist/daemon/config/profile.d.ts +38 -0
- package/dist/daemon/config/registry.d.ts +3 -0
- package/dist/daemon/config/runtime-environment.d.ts +2 -0
- package/dist/daemon/config/secrets.d.ts +5 -0
- package/dist/daemon/config/yaml.d.ts +1 -0
- package/dist/daemon/dashboard/export.d.ts +11 -0
- package/dist/daemon/dashboard/profiles.d.ts +5 -0
- package/dist/daemon/dashboard/records.d.ts +25 -0
- package/dist/daemon/dashboard/server.d.ts +15 -0
- package/dist/daemon/dashboard/session-prompt.d.ts +4 -0
- package/dist/daemon/dashboard/static.d.ts +2 -0
- package/dist/daemon/doctor.d.ts +1 -0
- package/dist/daemon/domain/types.d.ts +137 -0
- package/dist/daemon/events/cloudevent.d.ts +25 -0
- package/dist/daemon/events/pipeline.d.ts +35 -0
- package/dist/daemon/events/server.d.ts +15 -0
- package/dist/daemon/events/store.d.ts +58 -0
- package/dist/daemon/feishu/doctor.d.ts +2 -0
- package/dist/daemon/feishu/final-outcome-card.d.ts +20 -0
- package/dist/daemon/feishu/gateway.d.ts +46 -0
- package/dist/daemon/feishu/intake.d.ts +37 -0
- package/dist/daemon/feishu/mentions.d.ts +37 -0
- package/dist/daemon/feishu/message-gateway.d.ts +4 -0
- package/dist/daemon/feishu/message-pipeline.d.ts +13 -0
- package/dist/daemon/feishu/reply-experiment.d.ts +3 -0
- package/dist/daemon/feishu/trigger-input.d.ts +36 -0
- package/dist/daemon/index.d.ts +6 -0
- package/dist/daemon/index.js +5 -0
- package/dist/daemon/manual-trigger.d.ts +2 -0
- package/dist/{manual-trigger.js → daemon/manual-trigger.js} +2 -1
- package/dist/daemon/message/gateway.d.ts +9 -0
- package/dist/daemon/outcome/content.d.ts +68 -0
- package/dist/daemon/outcome/doctor.d.ts +2 -0
- package/dist/{outcome → daemon/outcome}/doctor.js +2 -3
- package/dist/daemon/outcome/instructions.d.ts +3 -0
- package/dist/daemon/outcome/server.d.ts +20 -0
- package/dist/daemon/outcome/submit.d.ts +5 -0
- package/dist/daemon/run/create-pi-orchestrator.d.ts +17 -0
- package/dist/{run → daemon/run}/create-pi-orchestrator.js +1 -2
- package/dist/daemon/run/orchestrator.d.ts +61 -0
- package/dist/daemon/run/profile-runner.d.ts +9 -0
- package/dist/daemon/run/queue.d.ts +20 -0
- package/dist/daemon/runtime/pi-doctor.d.ts +1 -0
- package/dist/daemon/runtime/pi-outcome-extension.d.ts +43 -0
- package/dist/daemon/runtime/pi-rpc.d.ts +56 -0
- package/dist/{runtime → daemon/runtime}/pi-rpc.js +92 -25
- package/dist/daemon/runtime/system-prompt.d.ts +10 -0
- package/dist/daemon/runtime-options.d.ts +4 -0
- package/dist/daemon/runtime-options.js +1 -0
- package/dist/daemon/schedule/cron.d.ts +2 -0
- package/dist/daemon/schedule/cursor-store.d.ts +18 -0
- package/dist/daemon/schedule/loop.d.ts +17 -0
- package/dist/daemon/schedule/reconciler.d.ts +16 -0
- package/dist/daemon/schedule-trigger.d.ts +18 -0
- package/dist/{schedule-trigger.js → daemon/schedule-trigger.js} +2 -1
- package/dist/daemon/service.d.ts +4 -0
- package/dist/{service.js → daemon/service.js} +3 -1
- package/dist/daemon/state/trigger-store.d.ts +30 -0
- package/dist/version.d.ts +1 -0
- package/package.json +13 -25
- /package/dist/{config → daemon/config}/channels.js +0 -0
- /package/dist/{config → daemon/config}/event-credentials.js +0 -0
- /package/dist/{config → daemon/config}/global.js +0 -0
- /package/dist/{config → daemon/config}/profile.js +0 -0
- /package/dist/{config → daemon/config}/registry.js +0 -0
- /package/dist/{config → daemon/config}/runtime-environment.js +0 -0
- /package/dist/{config → daemon/config}/secrets.js +0 -0
- /package/dist/{config → daemon/config}/yaml.js +0 -0
- /package/dist/{dashboard → daemon/dashboard}/export.js +0 -0
- /package/dist/{dashboard → daemon/dashboard}/profiles.js +0 -0
- /package/dist/{dashboard → daemon/dashboard}/records.js +0 -0
- /package/dist/{dashboard → daemon/dashboard}/server.js +0 -0
- /package/dist/{dashboard → daemon/dashboard}/session-prompt.js +0 -0
- /package/dist/{dashboard → daemon/dashboard}/static.js +0 -0
- /package/dist/{doctor.js → daemon/doctor.js} +0 -0
- /package/dist/{domain → daemon/domain}/types.js +0 -0
- /package/dist/{events → daemon/events}/cloudevent.js +0 -0
- /package/dist/{events → daemon/events}/pipeline.js +0 -0
- /package/dist/{events → daemon/events}/server.js +0 -0
- /package/dist/{events → daemon/events}/store.js +0 -0
- /package/dist/{feishu → daemon/feishu}/doctor.js +0 -0
- /package/dist/{feishu → daemon/feishu}/final-outcome-card.js +0 -0
- /package/dist/{feishu → daemon/feishu}/gateway.js +0 -0
- /package/dist/{feishu → daemon/feishu}/intake.js +0 -0
- /package/dist/{feishu → daemon/feishu}/mentions.js +0 -0
- /package/dist/{feishu → daemon/feishu}/message-gateway.js +0 -0
- /package/dist/{feishu → daemon/feishu}/message-pipeline.js +0 -0
- /package/dist/{feishu → daemon/feishu}/reply-experiment.js +0 -0
- /package/dist/{feishu → daemon/feishu}/trigger-input.js +0 -0
- /package/dist/{message → daemon/message}/gateway.js +0 -0
- /package/dist/{outcome → daemon/outcome}/content.js +0 -0
- /package/dist/{outcome → daemon/outcome}/instructions.js +0 -0
- /package/dist/{outcome → daemon/outcome}/server.js +0 -0
- /package/dist/{outcome → daemon/outcome}/submit.js +0 -0
- /package/dist/{run → daemon/run}/orchestrator.js +0 -0
- /package/dist/{run → daemon/run}/profile-runner.js +0 -0
- /package/dist/{run → daemon/run}/queue.js +0 -0
- /package/dist/{runtime → daemon/runtime}/pi-doctor.js +0 -0
- /package/dist/{runtime → daemon/runtime}/pi-outcome-extension.js +0 -0
- /package/dist/{runtime → daemon/runtime}/system-prompt.js +0 -0
- /package/dist/{schedule → daemon/schedule}/cron.js +0 -0
- /package/dist/{schedule → daemon/schedule}/cursor-store.js +0 -0
- /package/dist/{schedule → daemon/schedule}/loop.js +0 -0
- /package/dist/{schedule → daemon/schedule}/reconciler.js +0 -0
- /package/dist/{state → daemon/state}/trigger-store.js +0 -0
- /package/dist/{dashboard/ui → web}/assets/index-BP5xd2Iv.js +0 -0
- /package/dist/{dashboard/ui → web}/assets/index-D3C6sw_J.css +0 -0
- /package/dist/{dashboard/ui → web}/index.html +0 -0
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { spawn } from "node:child_process";
|
|
2
2
|
import { chmod, mkdir } from "node:fs/promises";
|
|
3
3
|
import { isAbsolute } from "node:path";
|
|
4
|
-
import { createInterface } from "node:readline";
|
|
5
4
|
import { fileURLToPath } from "node:url";
|
|
6
5
|
import { assertRuntimeEnvironmentKey } from "../config/runtime-environment.js";
|
|
7
6
|
export class PiRuntimeError extends Error {
|
|
@@ -83,7 +82,9 @@ function buildArguments(request) {
|
|
|
83
82
|
if (request.systemPrompt)
|
|
84
83
|
args.push("--system-prompt", request.systemPrompt);
|
|
85
84
|
if (request.outcome) {
|
|
86
|
-
args.push("--extension", fileURLToPath(new URL(
|
|
85
|
+
args.push("--extension", fileURLToPath(new URL(import.meta.url.endsWith(".ts")
|
|
86
|
+
? "../../dist/runtime/pi-outcome-extension.js"
|
|
87
|
+
: "./pi-outcome-extension.js", import.meta.url)));
|
|
87
88
|
}
|
|
88
89
|
return args;
|
|
89
90
|
}
|
|
@@ -153,6 +154,81 @@ async function stopProcess(child, terminateGraceMs) {
|
|
|
153
154
|
});
|
|
154
155
|
});
|
|
155
156
|
}
|
|
157
|
+
/**
|
|
158
|
+
* Read NDJSON frames from Pi stdout with a hard per-frame byte cap.
|
|
159
|
+
*
|
|
160
|
+
* Oversized frames (for example tool events carrying multi-MB stdout) are
|
|
161
|
+
* discarded through the next newline instead of failing the whole Run. Beacon
|
|
162
|
+
* only needs prompt responses, `message_end`, and `agent_settled`; intermediate
|
|
163
|
+
* tool frames are ignored anyway, and Pi already truncates tool output for the
|
|
164
|
+
* model. The cap still bounds parse/buffer memory — we never raise it here.
|
|
165
|
+
*/
|
|
166
|
+
export function createCappedNdjsonReader(maxFrameBytes, onFrame) {
|
|
167
|
+
if (!Number.isSafeInteger(maxFrameBytes) || maxFrameBytes <= 0) {
|
|
168
|
+
throw new Error("Pi RPC frame limit must be a positive integer");
|
|
169
|
+
}
|
|
170
|
+
const chunks = [];
|
|
171
|
+
let bufferedBytes = 0;
|
|
172
|
+
let discarding = false;
|
|
173
|
+
let closed = false;
|
|
174
|
+
let skippedOversizedFrames = 0;
|
|
175
|
+
const resetBuffer = () => {
|
|
176
|
+
chunks.length = 0;
|
|
177
|
+
bufferedBytes = 0;
|
|
178
|
+
};
|
|
179
|
+
const emitFrame = () => {
|
|
180
|
+
const line = Buffer.concat(chunks, bufferedBytes).toString("utf8");
|
|
181
|
+
resetBuffer();
|
|
182
|
+
onFrame(line);
|
|
183
|
+
};
|
|
184
|
+
const push = (chunk) => {
|
|
185
|
+
if (closed || chunk.length === 0)
|
|
186
|
+
return;
|
|
187
|
+
let offset = 0;
|
|
188
|
+
while (offset < chunk.length) {
|
|
189
|
+
if (discarding) {
|
|
190
|
+
const nl = chunk.indexOf(10, offset);
|
|
191
|
+
if (nl === -1)
|
|
192
|
+
return;
|
|
193
|
+
discarding = false;
|
|
194
|
+
offset = nl + 1;
|
|
195
|
+
continue;
|
|
196
|
+
}
|
|
197
|
+
const nl = chunk.indexOf(10, offset);
|
|
198
|
+
const end = nl === -1 ? chunk.length : nl;
|
|
199
|
+
const pieceLen = end - offset;
|
|
200
|
+
if (bufferedBytes + pieceLen > maxFrameBytes) {
|
|
201
|
+
skippedOversizedFrames += 1;
|
|
202
|
+
resetBuffer();
|
|
203
|
+
if (nl === -1) {
|
|
204
|
+
discarding = true;
|
|
205
|
+
return;
|
|
206
|
+
}
|
|
207
|
+
offset = nl + 1;
|
|
208
|
+
continue;
|
|
209
|
+
}
|
|
210
|
+
if (pieceLen > 0) {
|
|
211
|
+
chunks.push(chunk.subarray(offset, end));
|
|
212
|
+
bufferedBytes += pieceLen;
|
|
213
|
+
}
|
|
214
|
+
if (nl === -1)
|
|
215
|
+
return;
|
|
216
|
+
emitFrame();
|
|
217
|
+
offset = nl + 1;
|
|
218
|
+
}
|
|
219
|
+
};
|
|
220
|
+
return {
|
|
221
|
+
push,
|
|
222
|
+
close: () => {
|
|
223
|
+
closed = true;
|
|
224
|
+
resetBuffer();
|
|
225
|
+
discarding = false;
|
|
226
|
+
},
|
|
227
|
+
get skippedOversizedFrames() {
|
|
228
|
+
return skippedOversizedFrames;
|
|
229
|
+
},
|
|
230
|
+
};
|
|
231
|
+
}
|
|
156
232
|
export async function runPiAgent(request, options = {}) {
|
|
157
233
|
if (!request.prompt.trim())
|
|
158
234
|
throw new Error("Pi Run prompt must not be empty");
|
|
@@ -197,11 +273,11 @@ export async function runPiAgent(request, options = {}) {
|
|
|
197
273
|
env: buildPiEnvironment(request.outcome, options.environment, options.runtimeEnvironment),
|
|
198
274
|
stdio: ["pipe", "pipe", "pipe"],
|
|
199
275
|
});
|
|
200
|
-
const lines = createInterface({ input: child.stdout, crlfDelay: Infinity });
|
|
201
276
|
let stderr = "";
|
|
202
277
|
let finalMessage;
|
|
203
278
|
let promptAccepted = false;
|
|
204
279
|
let finished = false;
|
|
280
|
+
let frames;
|
|
205
281
|
child.stderr.setEncoding("utf8");
|
|
206
282
|
child.stderr.on("data", (chunk) => {
|
|
207
283
|
stderr = (stderr + chunk).slice(-64 * 1024);
|
|
@@ -216,27 +292,7 @@ export async function runPiAgent(request, options = {}) {
|
|
|
216
292
|
reject(error);
|
|
217
293
|
};
|
|
218
294
|
const timer = setTimeout(() => fail(new PiRuntimeError("runtime_timeout", `Pi Run timed out after ${timeoutMs}ms${stderr.trim() ? `: ${stderr.trim()}` : ""}`)), timeoutMs);
|
|
219
|
-
|
|
220
|
-
child.stdout.on("data", (chunk) => {
|
|
221
|
-
for (const byte of chunk) {
|
|
222
|
-
if (byte === 10)
|
|
223
|
-
frameBytes = 0;
|
|
224
|
-
else
|
|
225
|
-
frameBytes += 1;
|
|
226
|
-
if (frameBytes > maxFrameBytes) {
|
|
227
|
-
fail(new PiRuntimeError("runtime_protocol_error", `Pi RPC frame exceeds ${maxFrameBytes} bytes`));
|
|
228
|
-
return;
|
|
229
|
-
}
|
|
230
|
-
}
|
|
231
|
-
});
|
|
232
|
-
child.once("error", (error) => fail(new PiRuntimeError("runtime_spawn_failed", `Failed to start Pi: ${error.message}`, {
|
|
233
|
-
cause: error,
|
|
234
|
-
})));
|
|
235
|
-
child.once("exit", (code, signal) => {
|
|
236
|
-
if (!finished)
|
|
237
|
-
fail(describeExit(code, signal, stderr));
|
|
238
|
-
});
|
|
239
|
-
lines.on("line", (line) => {
|
|
295
|
+
const handleFrame = (line) => {
|
|
240
296
|
if (finished)
|
|
241
297
|
return;
|
|
242
298
|
let value;
|
|
@@ -293,13 +349,24 @@ export async function runPiAgent(request, options = {}) {
|
|
|
293
349
|
catch (error) {
|
|
294
350
|
fail(error instanceof Error ? error : new Error(String(error)));
|
|
295
351
|
}
|
|
352
|
+
};
|
|
353
|
+
frames = createCappedNdjsonReader(maxFrameBytes, handleFrame);
|
|
354
|
+
child.stdout.on("data", (chunk) => {
|
|
355
|
+
frames?.push(chunk);
|
|
356
|
+
});
|
|
357
|
+
child.once("error", (error) => fail(new PiRuntimeError("runtime_spawn_failed", `Failed to start Pi: ${error.message}`, {
|
|
358
|
+
cause: error,
|
|
359
|
+
})));
|
|
360
|
+
child.once("exit", (code, signal) => {
|
|
361
|
+
if (!finished)
|
|
362
|
+
fail(describeExit(code, signal, stderr));
|
|
296
363
|
});
|
|
297
364
|
child.stdin.on("error", (error) => fail(new PiRuntimeError("runtime_protocol_error", `Failed to write Pi RPC command: ${error.message}`, { cause: error })));
|
|
298
365
|
child.stdin.write(`${JSON.stringify({ id: "run-prompt", type: "prompt", message: request.prompt })}\n`);
|
|
299
366
|
});
|
|
300
367
|
}
|
|
301
368
|
finally {
|
|
302
|
-
|
|
369
|
+
frames?.close();
|
|
303
370
|
await stopProcess(child, terminateGraceMs);
|
|
304
371
|
}
|
|
305
372
|
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { Profile } from "../config/profile.js";
|
|
2
|
+
import type { DeliveryTarget, TriggerInput } from "../domain/types.js";
|
|
3
|
+
export type AgentSystemPromptTrigger = {
|
|
4
|
+
kind: TriggerInput["kind"];
|
|
5
|
+
scheduleId?: string | undefined;
|
|
6
|
+
notify: boolean;
|
|
7
|
+
};
|
|
8
|
+
export declare function agentSystemPromptTrigger(input: TriggerInput | undefined, notifyTarget: DeliveryTarget | undefined): AgentSystemPromptTrigger;
|
|
9
|
+
export declare function profilePromptDigest(profile: Pick<Profile, "persona" | "task">): string;
|
|
10
|
+
export declare function buildAgentSystemPrompt(profile: Pick<Profile, "persona" | "task" | "workspace">, trigger: AgentSystemPromptTrigger): string;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
declare const cursorSchema: z.ZodObject<{
|
|
3
|
+
version: z.ZodLiteral<1>;
|
|
4
|
+
scheduleId: z.ZodString;
|
|
5
|
+
through: z.ZodString;
|
|
6
|
+
}, z.core.$strict>;
|
|
7
|
+
export type ScheduleCursor = z.infer<typeof cursorSchema>;
|
|
8
|
+
export declare class ScheduleCursorStore {
|
|
9
|
+
private readonly root;
|
|
10
|
+
constructor(profileDirectory: string);
|
|
11
|
+
private path;
|
|
12
|
+
private prepare;
|
|
13
|
+
read(scheduleId: string): Promise<ScheduleCursor | undefined>;
|
|
14
|
+
private write;
|
|
15
|
+
initialize(scheduleId: string, through: Date): Promise<ScheduleCursor>;
|
|
16
|
+
advance(scheduleId: string, through: Date): Promise<ScheduleCursor>;
|
|
17
|
+
}
|
|
18
|
+
export {};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { Profile } from "../config/profile.js";
|
|
2
|
+
type Reconciler = {
|
|
3
|
+
reconcile(now: Date): Promise<void>;
|
|
4
|
+
};
|
|
5
|
+
export declare class ScheduleLoop {
|
|
6
|
+
private readonly profile;
|
|
7
|
+
private readonly reconciler;
|
|
8
|
+
private readonly onFatal;
|
|
9
|
+
private timer;
|
|
10
|
+
private stopped;
|
|
11
|
+
private active;
|
|
12
|
+
constructor(profile: Profile, reconciler: Reconciler, onFatal: (error: Error) => void);
|
|
13
|
+
start(after?: Date): void;
|
|
14
|
+
stop(): void;
|
|
15
|
+
drain(): Promise<void>;
|
|
16
|
+
}
|
|
17
|
+
export {};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { type Profile } from "../config/profile.js";
|
|
2
|
+
import type { TriggerInput } from "../domain/types.js";
|
|
3
|
+
import type { TriggerStore } from "../state/trigger-store.js";
|
|
4
|
+
import type { ScheduleCursorStore } from "./cursor-store.js";
|
|
5
|
+
export type ScheduleReconcilerOptions = {
|
|
6
|
+
profile: Profile;
|
|
7
|
+
triggers: TriggerStore;
|
|
8
|
+
cursors: ScheduleCursorStore;
|
|
9
|
+
maxOccurrences: number;
|
|
10
|
+
process(triggerKey: string, normalize: () => Promise<TriggerInput>): Promise<void>;
|
|
11
|
+
};
|
|
12
|
+
export declare class ScheduleReconciler {
|
|
13
|
+
private readonly options;
|
|
14
|
+
constructor(options: ScheduleReconcilerOptions);
|
|
15
|
+
reconcile(now: Date): Promise<void>;
|
|
16
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { type Profile } from "./config/profile.js";
|
|
2
|
+
import type { TriggerRecord } from "./domain/types.js";
|
|
3
|
+
import type { RuntimeOptions } from "./runtime-options.js";
|
|
4
|
+
import { TriggerStore } from "./state/trigger-store.js";
|
|
5
|
+
export declare function triggerScheduleOnce(options: {
|
|
6
|
+
profile: Profile;
|
|
7
|
+
scheduleId: string;
|
|
8
|
+
store: TriggerStore;
|
|
9
|
+
process(triggerKey: string, normalize: () => Promise<{
|
|
10
|
+
kind: "schedule";
|
|
11
|
+
scheduleId: string;
|
|
12
|
+
scheduledFor: string;
|
|
13
|
+
text: string;
|
|
14
|
+
}>): Promise<void>;
|
|
15
|
+
now?: (() => Date) | undefined;
|
|
16
|
+
id?: (() => string) | undefined;
|
|
17
|
+
}): Promise<TriggerRecord>;
|
|
18
|
+
export declare function runScheduleTrigger(configPath: string, profileId: string, scheduleId: string, options: RuntimeOptions): Promise<void>;
|
|
@@ -55,7 +55,7 @@ export async function triggerScheduleOnce(options) {
|
|
|
55
55
|
}
|
|
56
56
|
return record;
|
|
57
57
|
}
|
|
58
|
-
export async function runScheduleTrigger(configPath, profileId, scheduleId) {
|
|
58
|
+
export async function runScheduleTrigger(configPath, profileId, scheduleId, options) {
|
|
59
59
|
const global = await loadGlobalConfig(configPath);
|
|
60
60
|
const runtimeEnvironment = await loadRuntimeEnvironment(global.runtimeEnvironmentPath);
|
|
61
61
|
const channels = await loadChannelRegistry(global.channelsPath);
|
|
@@ -69,6 +69,7 @@ export async function runScheduleTrigger(configPath, profileId, scheduleId) {
|
|
|
69
69
|
try {
|
|
70
70
|
const store = new TriggerStore(profile.directory, profile.id);
|
|
71
71
|
const orchestrator = createPiRunOrchestrator({
|
|
72
|
+
beaconCliPath: options.beaconCliPath,
|
|
72
73
|
config: global,
|
|
73
74
|
runtimeEnvironment,
|
|
74
75
|
profile,
|
|
@@ -35,7 +35,7 @@ function shutdownController() {
|
|
|
35
35
|
},
|
|
36
36
|
};
|
|
37
37
|
}
|
|
38
|
-
export async function runBeacon(configPath) {
|
|
38
|
+
export async function runBeacon(configPath, options) {
|
|
39
39
|
const global = await loadGlobalConfig(configPath);
|
|
40
40
|
const runtimeEnvironment = await loadRuntimeEnvironment(global.runtimeEnvironmentPath);
|
|
41
41
|
const channels = await loadChannelRegistry(global.channelsPath);
|
|
@@ -50,6 +50,7 @@ export async function runBeacon(configPath) {
|
|
|
50
50
|
try {
|
|
51
51
|
if (global.dashboard.enabled) {
|
|
52
52
|
dashboard = await startDashboard({
|
|
53
|
+
uiDirectory: options.uiDirectory,
|
|
53
54
|
listen: global.dashboard.listen,
|
|
54
55
|
port: global.dashboard.port,
|
|
55
56
|
profilesDirectory: global.profilesDirectory,
|
|
@@ -81,6 +82,7 @@ export async function runBeacon(configPath) {
|
|
|
81
82
|
const gateway = createFeishuGateway(profileCredentials);
|
|
82
83
|
const store = new TriggerStore(profile.directory, profile.id);
|
|
83
84
|
const orchestrator = createPiRunOrchestrator({
|
|
85
|
+
beaconCliPath: options.beaconCliPath,
|
|
84
86
|
config: global,
|
|
85
87
|
runtimeEnvironment,
|
|
86
88
|
profile,
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { type DeliveryTarget, type TriggerInput, type TriggerRecord } from "../domain/types.js";
|
|
2
|
+
export type TriggerClaim = {
|
|
3
|
+
input?: TriggerInput | undefined;
|
|
4
|
+
sourceKey: string[];
|
|
5
|
+
target: DeliveryTarget;
|
|
6
|
+
notifyTarget?: DeliveryTarget | undefined;
|
|
7
|
+
ingress?: Record<string, unknown> | undefined;
|
|
8
|
+
acceptedAt?: Date | undefined;
|
|
9
|
+
};
|
|
10
|
+
export declare class TriggerStore {
|
|
11
|
+
private readonly profileId;
|
|
12
|
+
readonly root: string;
|
|
13
|
+
constructor(profileDirectory: string, profileId: string);
|
|
14
|
+
recordPath(triggerKey: string): string;
|
|
15
|
+
private prepare;
|
|
16
|
+
private read;
|
|
17
|
+
private syncDirectory;
|
|
18
|
+
private write;
|
|
19
|
+
claim(request: TriggerClaim): Promise<{
|
|
20
|
+
created: boolean;
|
|
21
|
+
record: TriggerRecord;
|
|
22
|
+
}>;
|
|
23
|
+
update(triggerKey: string, transform: (record: TriggerRecord) => TriggerRecord): Promise<TriggerRecord>;
|
|
24
|
+
list(): Promise<TriggerRecord[]>;
|
|
25
|
+
/**
|
|
26
|
+
* Locate the Trigger whose reply or notify Delivery produced this Feishu
|
|
27
|
+
* outbound `message_id`. Newest accepted Trigger wins on collision.
|
|
28
|
+
*/
|
|
29
|
+
findByDeliveredMessageId(messageId: string): Promise<TriggerRecord | undefined>;
|
|
30
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const packageVersion: string;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nettee/beacon",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.1",
|
|
4
4
|
"description": "A single-host bridge from messaging and schedules to isolated agent runs",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"repository": {
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
},
|
|
24
24
|
"files": [
|
|
25
25
|
"dist/",
|
|
26
|
-
"deploy/
|
|
26
|
+
"deploy/",
|
|
27
27
|
"examples/",
|
|
28
28
|
"README.md",
|
|
29
29
|
"LICENSE"
|
|
@@ -31,19 +31,6 @@
|
|
|
31
31
|
"publishConfig": {
|
|
32
32
|
"access": "public"
|
|
33
33
|
},
|
|
34
|
-
"scripts": {
|
|
35
|
-
"build": "tsc -p tsconfig.json && vite build --config dashboard-ui/vite.config.ts",
|
|
36
|
-
"bump-version": "node scripts/bump-version.mjs",
|
|
37
|
-
"check": "biome check .",
|
|
38
|
-
"dev": "tsx src/cli.ts",
|
|
39
|
-
"e2e:message": "tsc -p tsconfig.e2e.json --noEmit && pnpm build && tsx --test e2e/message/*.e2e.test.ts",
|
|
40
|
-
"prebuild": "node scripts/clean-dist.mjs",
|
|
41
|
-
"prepack": "pnpm build",
|
|
42
|
-
"test": "tsx --test src/*.test.ts src/**/*.test.ts scripts/*.test.mjs",
|
|
43
|
-
"test:package": "node scripts/test-package.mjs",
|
|
44
|
-
"typecheck": "tsc -p tsconfig.json --noEmit && tsc -p dashboard-ui/tsconfig.json --noEmit"
|
|
45
|
-
},
|
|
46
|
-
"packageManager": "pnpm@10.33.2",
|
|
47
34
|
"engines": {
|
|
48
35
|
"node": ">=22"
|
|
49
36
|
},
|
|
@@ -53,18 +40,19 @@
|
|
|
53
40
|
"yaml": "^2.9.1",
|
|
54
41
|
"zod": "^4.1.8"
|
|
55
42
|
},
|
|
43
|
+
"scripts": {
|
|
44
|
+
"build": "tsc -p tsconfig.json && node ../../scripts/assemble-cli.mjs",
|
|
45
|
+
"typecheck": "tsc -p tsconfig.json --noEmit",
|
|
46
|
+
"test": "tsx --test src/*.test.ts",
|
|
47
|
+
"dev": "pnpm --dir ../.. build && node dist/cli.js",
|
|
48
|
+
"prepack": "pnpm --dir ../.. build",
|
|
49
|
+
"prebuild": "node ../../scripts/clean-dist.mjs"
|
|
50
|
+
},
|
|
56
51
|
"devDependencies": {
|
|
57
|
-
"@
|
|
58
|
-
"@
|
|
52
|
+
"@nettee/beacon-daemon": "workspace:*",
|
|
53
|
+
"@nettee/beacon-web": "workspace:*",
|
|
59
54
|
"@types/node": "^24.3.0",
|
|
60
|
-
"@types/react": "^19.3.0",
|
|
61
|
-
"@types/react-dom": "^19.3.0",
|
|
62
|
-
"@vitejs/plugin-react": "^6.1.1",
|
|
63
|
-
"react": "^19.3.0",
|
|
64
|
-
"react-dom": "^19.3.0",
|
|
65
|
-
"tailwindcss": "^4.3.3",
|
|
66
55
|
"tsx": "^4.20.5",
|
|
67
|
-
"typescript": "^5.9.2"
|
|
68
|
-
"vite": "^8.3.0"
|
|
56
|
+
"typescript": "^5.9.2"
|
|
69
57
|
}
|
|
70
58
|
}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|