pi-fabric 0.84.2 → 0.84.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/dist/actors/log-store.d.ts +22 -0
- package/dist/actors/log-store.d.ts.map +1 -0
- package/dist/actors/manager.d.ts.map +1 -1
- package/dist/actors/mesh-monitor.d.ts +22 -0
- package/dist/actors/mesh-monitor.d.ts.map +1 -0
- package/dist/actors/registry-store.d.ts +15 -0
- package/dist/actors/registry-store.d.ts.map +1 -0
- package/dist/chunks/{chunk-2NI5YMKK.js → chunk-257ES5IL.js} +432 -371
- package/dist/chunks/{chunk-2NI5YMKK.js.map → chunk-257ES5IL.js.map} +4 -4
- package/dist/chunks/chunk-AB5JTS5M.js +397 -0
- package/dist/chunks/chunk-AB5JTS5M.js.map +7 -0
- package/dist/chunks/{chunk-66WTXNRP.js → chunk-AIN5KTE6.js} +1034 -1015
- package/dist/chunks/chunk-AIN5KTE6.js.map +7 -0
- package/dist/chunks/chunk-I2LDU6BS.js +817 -0
- package/dist/chunks/chunk-I2LDU6BS.js.map +7 -0
- package/dist/chunks/{chunk-D6BNJP5M.js → chunk-J4XMXVU2.js} +171 -165
- package/dist/chunks/chunk-J4XMXVU2.js.map +7 -0
- package/dist/chunks/{chunk-X7NUHPPE.js → chunk-K7U4B6ZQ.js} +2 -2
- package/dist/chunks/{chunk-XLGMWNCB.js → chunk-L6R3Y7XI.js} +912 -1714
- package/dist/chunks/chunk-L6R3Y7XI.js.map +7 -0
- package/dist/chunks/{chunk-QCHHE3GO.js → chunk-MPNEVZIH.js} +5 -3
- package/dist/chunks/{chunk-QCHHE3GO.js.map → chunk-MPNEVZIH.js.map} +1 -1
- package/dist/chunks/{chunk-KKM7TKIM.js → chunk-T3GPMH5E.js} +158 -229
- package/dist/chunks/chunk-T3GPMH5E.js.map +7 -0
- package/dist/chunks/chunk-VE5LH2Z7.js +74 -0
- package/dist/chunks/chunk-VE5LH2Z7.js.map +7 -0
- package/dist/components/effect-policy.d.ts +21 -0
- package/dist/components/effect-policy.d.ts.map +1 -0
- package/dist/components/supervisor.d.ts.map +1 -1
- package/dist/core/action-arguments.d.ts +10 -0
- package/dist/core/action-arguments.d.ts.map +1 -0
- package/dist/core/action-registry.d.ts.map +1 -1
- package/dist/core/action-registry.js +1 -1
- package/dist/core/action-result.d.ts +13 -0
- package/dist/core/action-result.d.ts.map +1 -0
- package/dist/fabric-runtime-state.d.ts +1 -1
- package/dist/fabric-runtime-state.d.ts.map +1 -1
- package/dist/fabric-runtime-state.js +6253 -6175
- package/dist/fabric-runtime-state.js.map +4 -4
- package/dist/index.js +27 -409
- package/dist/index.js.map +4 -4
- package/dist/memory/expand-service.d.ts +4 -0
- package/dist/memory/expand-service.d.ts.map +1 -0
- package/dist/memory/recall-service.d.ts +5 -0
- package/dist/memory/recall-service.d.ts.map +1 -0
- package/dist/memory/request-cache.d.ts +49 -0
- package/dist/memory/request-cache.d.ts.map +1 -0
- package/dist/memory/request-context.d.ts +54 -0
- package/dist/memory/request-context.d.ts.map +1 -0
- package/dist/memory/request-limits.d.ts +8 -0
- package/dist/memory/request-limits.d.ts.map +1 -0
- package/dist/memory/sessions-service.d.ts +3 -0
- package/dist/memory/sessions-service.d.ts.map +1 -0
- package/dist/memory/source-observation.d.ts +22 -0
- package/dist/memory/source-observation.d.ts.map +1 -0
- package/dist/providers/agents-message-router.d.ts +29 -0
- package/dist/providers/agents-message-router.d.ts.map +1 -0
- package/dist/providers/agents-progress.d.ts +18 -0
- package/dist/providers/agents-progress.d.ts.map +1 -0
- package/dist/providers/agents-provider.d.ts +2 -10
- package/dist/providers/agents-provider.d.ts.map +1 -1
- package/dist/providers/memory-provider.d.ts +3 -22
- package/dist/providers/memory-provider.d.ts.map +1 -1
- package/dist/providers/memory-provider.js +1 -1
- package/dist/residency/host.js +2 -2
- package/dist/residency/pi-entry.js +2 -2
- package/dist/runtime-state-builtins.d.ts +20 -0
- package/dist/runtime-state-builtins.d.ts.map +1 -0
- package/dist/runtime-state-speculation.d.ts +15 -0
- package/dist/runtime-state-speculation.d.ts.map +1 -0
- package/dist/ui/dashboard-graph-controller.d.ts +52 -0
- package/dist/ui/dashboard-graph-controller.d.ts.map +1 -0
- package/dist/ui/dashboard-modal-controller.d.ts +36 -0
- package/dist/ui/dashboard-modal-controller.d.ts.map +1 -0
- package/dist/ui/dashboard.d.ts +3 -35
- package/dist/ui/dashboard.d.ts.map +1 -1
- package/dist/ui/dashboard.js +367 -340
- package/dist/ui/dashboard.js.map +4 -4
- package/dist/ui/settings-component.d.ts +26 -0
- package/dist/ui/settings-component.d.ts.map +1 -0
- package/dist/ui/settings-rpc.d.ts +15 -0
- package/dist/ui/settings-rpc.d.ts.map +1 -0
- package/dist/ui/settings-section-context.d.ts +18 -0
- package/dist/ui/settings-section-context.d.ts.map +1 -0
- package/dist/ui/settings-sections-agents.d.ts +5 -0
- package/dist/ui/settings-sections-agents.d.ts.map +1 -0
- package/dist/ui/settings-sections-execution.d.ts +8 -0
- package/dist/ui/settings-sections-execution.d.ts.map +1 -0
- package/dist/ui/settings-sections-lifecycle.d.ts +6 -0
- package/dist/ui/settings-sections-lifecycle.d.ts.map +1 -0
- package/dist/ui/settings-sections-presentation.d.ts +6 -0
- package/dist/ui/settings-sections-presentation.d.ts.map +1 -0
- package/dist/ui/settings-sections.d.ts +12 -0
- package/dist/ui/settings-sections.d.ts.map +1 -0
- package/dist/ui/settings-submenus.d.ts +74 -0
- package/dist/ui/settings-submenus.d.ts.map +1 -0
- package/dist/ui/settings-values.d.ts +61 -0
- package/dist/ui/settings-values.d.ts.map +1 -0
- package/dist/ui/settings.d.ts +12 -48
- package/dist/ui/settings.d.ts.map +1 -1
- package/dist/ui/settings.js +986 -903
- package/dist/ui/settings.js.map +4 -4
- package/package.json +4 -5
- package/dist/chunks/chunk-66WTXNRP.js.map +0 -7
- package/dist/chunks/chunk-D6BNJP5M.js.map +0 -7
- package/dist/chunks/chunk-KKM7TKIM.js.map +0 -7
- package/dist/chunks/chunk-XB3RJVT4.js +0 -17
- package/dist/chunks/chunk-XB3RJVT4.js.map +0 -7
- package/dist/chunks/chunk-XLGMWNCB.js.map +0 -7
- /package/dist/chunks/{chunk-X7NUHPPE.js.map → chunk-K7U4B6ZQ.js.map} +0 -0
|
@@ -2885,13 +2885,253 @@ var actorDeliveryNotice = (delivery, triggerTurn) => {
|
|
|
2885
2885
|
};
|
|
2886
2886
|
|
|
2887
2887
|
// src/actors/directory.ts
|
|
2888
|
-
import
|
|
2888
|
+
import fs15 from "node:fs";
|
|
2889
|
+
|
|
2890
|
+
// src/actors/manager.ts
|
|
2891
|
+
import { randomUUID as randomUUID7 } from "node:crypto";
|
|
2892
|
+
import fs14 from "node:fs";
|
|
2893
|
+
|
|
2894
|
+
// src/actors/mesh-monitor.ts
|
|
2895
|
+
import fs10 from "node:fs";
|
|
2896
|
+
import path12 from "node:path";
|
|
2897
|
+
var MESH_WATCH_RECONCILE_MS = 2e3;
|
|
2898
|
+
var ActorMeshMonitor = class {
|
|
2899
|
+
constructor(mesh, config, callbacks) {
|
|
2900
|
+
this.mesh = mesh;
|
|
2901
|
+
this.config = config;
|
|
2902
|
+
this.callbacks = callbacks;
|
|
2903
|
+
this.#offset = this.#readCursor() ?? mesh.latestOffset();
|
|
2904
|
+
}
|
|
2905
|
+
#timer;
|
|
2906
|
+
#watcher;
|
|
2907
|
+
#offset;
|
|
2908
|
+
#scheduled = false;
|
|
2909
|
+
#polling = false;
|
|
2910
|
+
#closed = false;
|
|
2911
|
+
#started = false;
|
|
2912
|
+
start() {
|
|
2913
|
+
if (this.#started || this.#closed || !this.config.enabled) return;
|
|
2914
|
+
this.#started = true;
|
|
2915
|
+
if (process.platform === "win32") {
|
|
2916
|
+
this.#startTimer(this.config.actorPollMs);
|
|
2917
|
+
this.schedule();
|
|
2918
|
+
return;
|
|
2919
|
+
}
|
|
2920
|
+
try {
|
|
2921
|
+
const watcher = fs10.watch(this.mesh.root, { persistent: false }, (_event, filename) => {
|
|
2922
|
+
if (filename !== null && path12.basename(filename.toString()) !== "events.jsonl") return;
|
|
2923
|
+
this.schedule();
|
|
2924
|
+
});
|
|
2925
|
+
this.#watcher = watcher;
|
|
2926
|
+
watcher.on("error", () => this.#fallback(watcher));
|
|
2927
|
+
this.#startTimer(Math.max(MESH_WATCH_RECONCILE_MS, this.config.actorPollMs));
|
|
2928
|
+
} catch {
|
|
2929
|
+
this.#startTimer(this.config.actorPollMs);
|
|
2930
|
+
}
|
|
2931
|
+
this.schedule();
|
|
2932
|
+
}
|
|
2933
|
+
close() {
|
|
2934
|
+
this.#closed = true;
|
|
2935
|
+
if (this.#timer) clearInterval(this.#timer);
|
|
2936
|
+
this.#timer = void 0;
|
|
2937
|
+
this.#watcher?.close();
|
|
2938
|
+
this.#watcher = void 0;
|
|
2939
|
+
}
|
|
2940
|
+
schedule() {
|
|
2941
|
+
if (this.#scheduled || this.#closed || !this.config.enabled) return;
|
|
2942
|
+
this.#scheduled = true;
|
|
2943
|
+
queueMicrotask(() => {
|
|
2944
|
+
this.#scheduled = false;
|
|
2945
|
+
if (this.#closed) return;
|
|
2946
|
+
void this.#poll().catch(() => void 0);
|
|
2947
|
+
});
|
|
2948
|
+
}
|
|
2949
|
+
#fallback(watcher) {
|
|
2950
|
+
if (this.#closed || this.#watcher !== watcher) return;
|
|
2951
|
+
watcher.close();
|
|
2952
|
+
this.#watcher = void 0;
|
|
2953
|
+
this.#startTimer(this.config.actorPollMs);
|
|
2954
|
+
this.schedule();
|
|
2955
|
+
}
|
|
2956
|
+
#startTimer(delay5) {
|
|
2957
|
+
if (this.#timer) clearInterval(this.#timer);
|
|
2958
|
+
this.#timer = setInterval(() => this.schedule(), delay5);
|
|
2959
|
+
this.#timer.unref();
|
|
2960
|
+
}
|
|
2961
|
+
async #poll() {
|
|
2962
|
+
if (this.#polling || this.#closed || !this.config.enabled) return;
|
|
2963
|
+
if (!this.callbacks.beforePoll()) return;
|
|
2964
|
+
this.#polling = true;
|
|
2965
|
+
try {
|
|
2966
|
+
const tail = this.mesh.tail(this.#offset, this.config.maxReadEvents);
|
|
2967
|
+
this.#offset = tail.nextOffset;
|
|
2968
|
+
for (const event of tail.events) this.callbacks.onEvent(event);
|
|
2969
|
+
this.#writeCursor();
|
|
2970
|
+
} finally {
|
|
2971
|
+
this.#polling = false;
|
|
2972
|
+
}
|
|
2973
|
+
}
|
|
2974
|
+
#readCursor() {
|
|
2975
|
+
if (!this.callbacks.cursorPath) return void 0;
|
|
2976
|
+
try {
|
|
2977
|
+
const value = JSON.parse(fs10.readFileSync(this.callbacks.cursorPath, "utf8"));
|
|
2978
|
+
return value.format === 1 && typeof value.cursor === "number" && value.cursor >= 0 ? value.cursor : void 0;
|
|
2979
|
+
} catch {
|
|
2980
|
+
return void 0;
|
|
2981
|
+
}
|
|
2982
|
+
}
|
|
2983
|
+
#writeCursor() {
|
|
2984
|
+
if (!this.callbacks.cursorPath) return;
|
|
2985
|
+
try {
|
|
2986
|
+
writeJsonAtomic(this.callbacks.cursorPath, { format: 1, cursor: this.#offset }, { space: 2 });
|
|
2987
|
+
} catch {
|
|
2988
|
+
}
|
|
2989
|
+
}
|
|
2990
|
+
};
|
|
2889
2991
|
|
|
2890
2992
|
// src/actors/manager.ts
|
|
2891
|
-
import { randomUUID as randomUUID6 } from "node:crypto";
|
|
2892
|
-
import fs11 from "node:fs";
|
|
2893
2993
|
import os4 from "node:os";
|
|
2994
|
+
import path16 from "node:path";
|
|
2995
|
+
|
|
2996
|
+
// src/actors/log-store.ts
|
|
2997
|
+
import fs11 from "node:fs";
|
|
2894
2998
|
import path13 from "node:path";
|
|
2999
|
+
var ACTOR_MESSAGE_HISTORY_LIMIT = 100;
|
|
3000
|
+
var ACTOR_MESSAGE_ENVELOPE_BYTES = 4096;
|
|
3001
|
+
var ACTOR_TRUNCATION_SUFFIX = "\n[actor message truncated]";
|
|
3002
|
+
var serializedBytes = (value) => Buffer.byteLength(JSON.stringify(value), "utf8");
|
|
3003
|
+
var truncateUtf8 = (value, maxBytes, suffix = "") => {
|
|
3004
|
+
if (Buffer.byteLength(value, "utf8") <= maxBytes) return value;
|
|
3005
|
+
const boundedSuffix = Buffer.byteLength(suffix, "utf8") <= maxBytes ? suffix : truncateUtf8(suffix, maxBytes);
|
|
3006
|
+
const available = Math.max(0, maxBytes - Buffer.byteLength(boundedSuffix, "utf8"));
|
|
3007
|
+
let low = 0;
|
|
3008
|
+
let high = value.length;
|
|
3009
|
+
while (low < high) {
|
|
3010
|
+
const middle = Math.ceil((low + high) / 2);
|
|
3011
|
+
if (Buffer.byteLength(value.slice(0, middle), "utf8") <= available) low = middle;
|
|
3012
|
+
else high = middle - 1;
|
|
3013
|
+
}
|
|
3014
|
+
return `${value.slice(0, low)}${boundedSuffix}`;
|
|
3015
|
+
};
|
|
3016
|
+
var boundedActorText = (value, maxBytes) => {
|
|
3017
|
+
if (serializedBytes({ text: value }) <= maxBytes) return value;
|
|
3018
|
+
const suffix = serializedBytes({ text: ACTOR_TRUNCATION_SUFFIX }) <= maxBytes ? ACTOR_TRUNCATION_SUFFIX : "";
|
|
3019
|
+
let low = 0;
|
|
3020
|
+
let high = value.length;
|
|
3021
|
+
while (low < high) {
|
|
3022
|
+
const middle = Math.ceil((low + high) / 2);
|
|
3023
|
+
if (serializedBytes({ text: `${value.slice(0, middle)}${suffix}` }) <= maxBytes) {
|
|
3024
|
+
low = middle;
|
|
3025
|
+
} else {
|
|
3026
|
+
high = middle - 1;
|
|
3027
|
+
}
|
|
3028
|
+
}
|
|
3029
|
+
return `${value.slice(0, low)}${suffix}`;
|
|
3030
|
+
};
|
|
3031
|
+
var boundedActorData = (data, maxBytes) => {
|
|
3032
|
+
let serialized;
|
|
3033
|
+
try {
|
|
3034
|
+
const encoded = JSON.stringify(data);
|
|
3035
|
+
serialized = typeof encoded === "string" ? encoded : String(data);
|
|
3036
|
+
if (serializedBytes({ data }) <= maxBytes) return data;
|
|
3037
|
+
} catch {
|
|
3038
|
+
serialized = String(data);
|
|
3039
|
+
}
|
|
3040
|
+
const originalBytes = Buffer.byteLength(serialized, "utf8");
|
|
3041
|
+
let preview = truncateUtf8(serialized, Math.max(0, maxBytes - 256));
|
|
3042
|
+
let bounded = { fabricTruncated: true, originalBytes, preview };
|
|
3043
|
+
while (preview && serializedBytes({ data: bounded }) > maxBytes) {
|
|
3044
|
+
preview = truncateUtf8(preview, Math.floor(Buffer.byteLength(preview, "utf8") / 2));
|
|
3045
|
+
bounded = { fabricTruncated: true, originalBytes, preview };
|
|
3046
|
+
}
|
|
3047
|
+
return serializedBytes({ data: bounded }) <= maxBytes ? bounded : { fabricTruncated: true, originalBytes };
|
|
3048
|
+
};
|
|
3049
|
+
var ActorLogStore = class {
|
|
3050
|
+
constructor(mesh, config, retention) {
|
|
3051
|
+
this.mesh = mesh;
|
|
3052
|
+
this.config = config;
|
|
3053
|
+
this.retention = retention;
|
|
3054
|
+
}
|
|
3055
|
+
async retainRun(actor, runId, runDirectory) {
|
|
3056
|
+
if (!runDirectory || !fs11.existsSync(runDirectory)) return;
|
|
3057
|
+
const dest = path13.join(path13.dirname(actor.sessionFile), "runs", runId);
|
|
3058
|
+
fs11.mkdirSync(dest, { recursive: true, mode: 448 });
|
|
3059
|
+
for (const file of ["events.jsonl", "status.json", "task.txt"]) {
|
|
3060
|
+
const src = path13.join(runDirectory, file);
|
|
3061
|
+
if (fs11.existsSync(src)) fs11.copyFileSync(src, path13.join(dest, file));
|
|
3062
|
+
}
|
|
3063
|
+
const nested = path13.join(runDirectory, "nested");
|
|
3064
|
+
if (fs11.existsSync(nested)) {
|
|
3065
|
+
try {
|
|
3066
|
+
fs11.cpSync(nested, path13.join(dest, "nested"), { recursive: true });
|
|
3067
|
+
} catch {
|
|
3068
|
+
}
|
|
3069
|
+
}
|
|
3070
|
+
this.pruneRuns(actor);
|
|
3071
|
+
}
|
|
3072
|
+
pruneRuns(actor, now = Date.now()) {
|
|
3073
|
+
pruneActorRunArchives({
|
|
3074
|
+
runsDirectory: path13.join(path13.dirname(actor.sessionFile), "runs"),
|
|
3075
|
+
...actor.lastRunId ? { latestRunId: actor.lastRunId } : {},
|
|
3076
|
+
retentionMs: this.retention.actorRunArchiveMs,
|
|
3077
|
+
now
|
|
3078
|
+
});
|
|
3079
|
+
}
|
|
3080
|
+
retainedRunIds(actor) {
|
|
3081
|
+
const runsDir = path13.join(path13.dirname(actor.sessionFile), "runs");
|
|
3082
|
+
try {
|
|
3083
|
+
return fs11.readdirSync(runsDir).sort();
|
|
3084
|
+
} catch {
|
|
3085
|
+
return [];
|
|
3086
|
+
}
|
|
3087
|
+
}
|
|
3088
|
+
recordMessage(messages, message) {
|
|
3089
|
+
let bounded = structuredClone(message);
|
|
3090
|
+
const maxPayloadBytes = Math.max(1, this.mesh.maxEventBytes - ACTOR_MESSAGE_ENVELOPE_BYTES);
|
|
3091
|
+
const fixed = structuredClone(bounded);
|
|
3092
|
+
delete fixed.text;
|
|
3093
|
+
delete fixed.data;
|
|
3094
|
+
const contentBytes = Math.max(1, maxPayloadBytes - serializedBytes(fixed) - 128);
|
|
3095
|
+
const hasText = Boolean(bounded.text);
|
|
3096
|
+
const hasData = bounded.data !== void 0;
|
|
3097
|
+
const textBytes = hasText && hasData ? Math.floor(contentBytes / 2) : contentBytes;
|
|
3098
|
+
const dataBytes = hasText && hasData ? contentBytes - textBytes : contentBytes;
|
|
3099
|
+
if (bounded.text) {
|
|
3100
|
+
const contextBounded = bounded.text.length > this.config.eventContextChars ? `${bounded.text.slice(0, this.config.eventContextChars)}${ACTOR_TRUNCATION_SUFFIX}` : bounded.text;
|
|
3101
|
+
bounded.text = boundedActorText(contextBounded, textBytes);
|
|
3102
|
+
}
|
|
3103
|
+
if (bounded.data !== void 0) {
|
|
3104
|
+
bounded.data = boundedActorData(bounded.data, dataBytes);
|
|
3105
|
+
}
|
|
3106
|
+
if (serializedBytes(bounded) > maxPayloadBytes) {
|
|
3107
|
+
delete bounded.data;
|
|
3108
|
+
if (bounded.text) {
|
|
3109
|
+
bounded.text = boundedActorText(bounded.text, contentBytes);
|
|
3110
|
+
}
|
|
3111
|
+
}
|
|
3112
|
+
if (serializedBytes(bounded) > maxPayloadBytes) {
|
|
3113
|
+
bounded = {
|
|
3114
|
+
id: bounded.id,
|
|
3115
|
+
actorId: bounded.actorId,
|
|
3116
|
+
actorName: bounded.actorName,
|
|
3117
|
+
direction: bounded.direction,
|
|
3118
|
+
source: boundedActorText(bounded.source, 1024),
|
|
3119
|
+
createdAt: bounded.createdAt,
|
|
3120
|
+
...bounded.action ? { action: bounded.action } : {},
|
|
3121
|
+
...bounded.runId ? { runId: bounded.runId } : {},
|
|
3122
|
+
error: "Actor message content exceeded the mesh event limit"
|
|
3123
|
+
};
|
|
3124
|
+
}
|
|
3125
|
+
for (const key of Object.keys(message)) {
|
|
3126
|
+
delete message[key];
|
|
3127
|
+
}
|
|
3128
|
+
Object.assign(message, bounded);
|
|
3129
|
+
messages.push(bounded);
|
|
3130
|
+
if (messages.length > ACTOR_MESSAGE_HISTORY_LIMIT) {
|
|
3131
|
+
messages.splice(0, messages.length - ACTOR_MESSAGE_HISTORY_LIMIT);
|
|
3132
|
+
}
|
|
3133
|
+
}
|
|
3134
|
+
};
|
|
2895
3135
|
|
|
2896
3136
|
// src/actors/predicate.ts
|
|
2897
3137
|
var PREDICATE_VERSION = 1;
|
|
@@ -2962,8 +3202,8 @@ var evaluateActorValidWhile = async (source, facts) => {
|
|
|
2962
3202
|
|
|
2963
3203
|
// src/actors/binding-store.ts
|
|
2964
3204
|
import { createHash, randomUUID as randomUUID5 } from "node:crypto";
|
|
2965
|
-
import
|
|
2966
|
-
import
|
|
3205
|
+
import fs12 from "node:fs";
|
|
3206
|
+
import path14 from "node:path";
|
|
2967
3207
|
var BINDING_LOCK_TIMEOUT_MS = 5e3;
|
|
2968
3208
|
var BINDING_STALE_LOCK_MS = 3e4;
|
|
2969
3209
|
var bindingFileName = (sessionId) => `${createHash("sha256").update(sessionId).digest("hex")}.json`;
|
|
@@ -2973,7 +3213,7 @@ var delay3 = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
|
2973
3213
|
var ActorBindingStore = class {
|
|
2974
3214
|
constructor(sessionId, root) {
|
|
2975
3215
|
this.sessionId = sessionId;
|
|
2976
|
-
this.filePath = root ?
|
|
3216
|
+
this.filePath = root ? path14.join(root, "bindings", bindingFileName(sessionId)) : void 0;
|
|
2977
3217
|
this.#sync(true);
|
|
2978
3218
|
}
|
|
2979
3219
|
#bindings = /* @__PURE__ */ new Map();
|
|
@@ -3039,7 +3279,7 @@ var ActorBindingStore = class {
|
|
|
3039
3279
|
if (!this.filePath) return bindings;
|
|
3040
3280
|
let parsed;
|
|
3041
3281
|
try {
|
|
3042
|
-
parsed = JSON.parse(
|
|
3282
|
+
parsed = JSON.parse(fs12.readFileSync(this.filePath, "utf8"));
|
|
3043
3283
|
} catch {
|
|
3044
3284
|
return bindings;
|
|
3045
3285
|
}
|
|
@@ -3080,7 +3320,7 @@ var ActorBindingStore = class {
|
|
|
3080
3320
|
#currentFingerprint() {
|
|
3081
3321
|
if (!this.filePath) return void 0;
|
|
3082
3322
|
try {
|
|
3083
|
-
const stat =
|
|
3323
|
+
const stat = fs12.statSync(this.filePath);
|
|
3084
3324
|
return `${stat.dev}:${stat.ino}:${stat.size}:${stat.mtimeMs}`;
|
|
3085
3325
|
} catch {
|
|
3086
3326
|
return void 0;
|
|
@@ -3089,7 +3329,7 @@ var ActorBindingStore = class {
|
|
|
3089
3329
|
async #withLock(operation) {
|
|
3090
3330
|
if (!this.filePath) return operation();
|
|
3091
3331
|
const lockPath = `${this.filePath}.lock`;
|
|
3092
|
-
const ownerPath2 =
|
|
3332
|
+
const ownerPath2 = path14.join(lockPath, "owner");
|
|
3093
3333
|
const deadline = Date.now() + BINDING_LOCK_TIMEOUT_MS;
|
|
3094
3334
|
const token = randomUUID5();
|
|
3095
3335
|
const processAlive3 = (pid) => {
|
|
@@ -3101,11 +3341,11 @@ var ActorBindingStore = class {
|
|
|
3101
3341
|
return false;
|
|
3102
3342
|
}
|
|
3103
3343
|
};
|
|
3104
|
-
|
|
3344
|
+
fs12.mkdirSync(path14.dirname(this.filePath), { recursive: true, mode: 448 });
|
|
3105
3345
|
while (true) {
|
|
3106
3346
|
try {
|
|
3107
|
-
|
|
3108
|
-
|
|
3347
|
+
fs12.mkdirSync(lockPath, { mode: 448 });
|
|
3348
|
+
fs12.writeFileSync(ownerPath2, `${token}
|
|
3109
3349
|
${process.pid}
|
|
3110
3350
|
${Date.now()}
|
|
3111
3351
|
`, {
|
|
@@ -3116,13 +3356,13 @@ ${Date.now()}
|
|
|
3116
3356
|
} catch (error) {
|
|
3117
3357
|
if (errorCode2(error) !== "EEXIST") throw error;
|
|
3118
3358
|
try {
|
|
3119
|
-
const firstOwner =
|
|
3359
|
+
const firstOwner = fs12.readFileSync(ownerPath2, "utf8");
|
|
3120
3360
|
const [, pidText, createdText] = firstOwner.trim().split("\n");
|
|
3121
3361
|
const stale = Date.now() - Number(createdText) > BINDING_STALE_LOCK_MS;
|
|
3122
3362
|
if (stale && !processAlive3(Number(pidText))) {
|
|
3123
|
-
const secondOwner =
|
|
3363
|
+
const secondOwner = fs12.readFileSync(ownerPath2, "utf8");
|
|
3124
3364
|
if (secondOwner === firstOwner) {
|
|
3125
|
-
|
|
3365
|
+
fs12.rmSync(lockPath, { recursive: true, force: true });
|
|
3126
3366
|
continue;
|
|
3127
3367
|
}
|
|
3128
3368
|
}
|
|
@@ -3138,10 +3378,10 @@ ${Date.now()}
|
|
|
3138
3378
|
return operation();
|
|
3139
3379
|
} finally {
|
|
3140
3380
|
try {
|
|
3141
|
-
const owner =
|
|
3381
|
+
const owner = fs12.readFileSync(ownerPath2, "utf8");
|
|
3142
3382
|
if (owner.startsWith(`${token}
|
|
3143
3383
|
`)) {
|
|
3144
|
-
|
|
3384
|
+
fs12.rmSync(lockPath, { recursive: true, force: true });
|
|
3145
3385
|
}
|
|
3146
3386
|
} catch {
|
|
3147
3387
|
}
|
|
@@ -3149,6 +3389,110 @@ ${Date.now()}
|
|
|
3149
3389
|
}
|
|
3150
3390
|
};
|
|
3151
3391
|
|
|
3392
|
+
// src/actors/registry-store.ts
|
|
3393
|
+
import { randomUUID as randomUUID6 } from "node:crypto";
|
|
3394
|
+
import fs13 from "node:fs";
|
|
3395
|
+
import path15 from "node:path";
|
|
3396
|
+
var ACTOR_REGISTRY_LOCK_TIMEOUT_MS = 5e3;
|
|
3397
|
+
var ACTOR_REGISTRY_STALE_LOCK_MS = 3e4;
|
|
3398
|
+
var delay4 = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
3399
|
+
var errorCode3 = (error) => error instanceof Error && "code" in error ? String(error.code) : void 0;
|
|
3400
|
+
var ActorRegistryStore = class {
|
|
3401
|
+
#registryPath;
|
|
3402
|
+
#actorRoot;
|
|
3403
|
+
constructor(actorRoot) {
|
|
3404
|
+
this.#actorRoot = actorRoot;
|
|
3405
|
+
this.#registryPath = path15.join(actorRoot, "actors.json");
|
|
3406
|
+
}
|
|
3407
|
+
records() {
|
|
3408
|
+
try {
|
|
3409
|
+
const parsed = JSON.parse(fs13.readFileSync(this.#registryPath, "utf8"));
|
|
3410
|
+
if (!Array.isArray(parsed.actors)) return [];
|
|
3411
|
+
return parsed.actors.flatMap(
|
|
3412
|
+
(record) => typeof record === "object" && record !== null && !Array.isArray(record) && typeof record.id === "string" ? [record] : []
|
|
3413
|
+
);
|
|
3414
|
+
} catch {
|
|
3415
|
+
return [];
|
|
3416
|
+
}
|
|
3417
|
+
}
|
|
3418
|
+
/** The callback must be synchronous: release precedes promise assimilation. */
|
|
3419
|
+
async withLock(operation) {
|
|
3420
|
+
const lockPath = `${this.#registryPath}.lock`;
|
|
3421
|
+
const ownerPath2 = path15.join(lockPath, "owner");
|
|
3422
|
+
const deadline = Date.now() + ACTOR_REGISTRY_LOCK_TIMEOUT_MS;
|
|
3423
|
+
const token = randomUUID6();
|
|
3424
|
+
const processAlive3 = (pid) => {
|
|
3425
|
+
if (!Number.isSafeInteger(pid) || pid <= 0) return false;
|
|
3426
|
+
try {
|
|
3427
|
+
process.kill(pid, 0);
|
|
3428
|
+
return true;
|
|
3429
|
+
} catch {
|
|
3430
|
+
return false;
|
|
3431
|
+
}
|
|
3432
|
+
};
|
|
3433
|
+
fs13.mkdirSync(this.#actorRoot, { recursive: true, mode: 448 });
|
|
3434
|
+
while (true) {
|
|
3435
|
+
try {
|
|
3436
|
+
fs13.mkdirSync(lockPath, { mode: 448 });
|
|
3437
|
+
fs13.writeFileSync(ownerPath2, `${token}
|
|
3438
|
+
${process.pid}
|
|
3439
|
+
${Date.now()}
|
|
3440
|
+
`, {
|
|
3441
|
+
encoding: "utf8",
|
|
3442
|
+
mode: 384
|
|
3443
|
+
});
|
|
3444
|
+
break;
|
|
3445
|
+
} catch (error) {
|
|
3446
|
+
if (errorCode3(error) !== "EEXIST") throw error;
|
|
3447
|
+
try {
|
|
3448
|
+
const firstOwner = fs13.readFileSync(ownerPath2, "utf8");
|
|
3449
|
+
const [, pidText, createdText] = firstOwner.trim().split("\n");
|
|
3450
|
+
const stale = Date.now() - Number(createdText) > ACTOR_REGISTRY_STALE_LOCK_MS;
|
|
3451
|
+
if (stale && !processAlive3(Number(pidText))) {
|
|
3452
|
+
const secondOwner = fs13.readFileSync(ownerPath2, "utf8");
|
|
3453
|
+
if (secondOwner === firstOwner) {
|
|
3454
|
+
fs13.rmSync(lockPath, { recursive: true, force: true });
|
|
3455
|
+
continue;
|
|
3456
|
+
}
|
|
3457
|
+
}
|
|
3458
|
+
} catch {
|
|
3459
|
+
}
|
|
3460
|
+
if (Date.now() >= deadline) {
|
|
3461
|
+
throw new Error("Timed out waiting for the Fabric actor registry lock");
|
|
3462
|
+
}
|
|
3463
|
+
await delay4(10);
|
|
3464
|
+
}
|
|
3465
|
+
}
|
|
3466
|
+
try {
|
|
3467
|
+
return operation();
|
|
3468
|
+
} finally {
|
|
3469
|
+
try {
|
|
3470
|
+
const owner = fs13.readFileSync(ownerPath2, "utf8");
|
|
3471
|
+
if (owner.startsWith(`${token}
|
|
3472
|
+
`)) {
|
|
3473
|
+
fs13.rmSync(lockPath, { recursive: true, force: true });
|
|
3474
|
+
}
|
|
3475
|
+
} catch {
|
|
3476
|
+
}
|
|
3477
|
+
}
|
|
3478
|
+
}
|
|
3479
|
+
fingerprint() {
|
|
3480
|
+
try {
|
|
3481
|
+
const stat = fs13.statSync(this.#registryPath);
|
|
3482
|
+
return `${stat.dev}:${stat.ino}:${stat.size}:${stat.mtimeMs}`;
|
|
3483
|
+
} catch {
|
|
3484
|
+
return void 0;
|
|
3485
|
+
}
|
|
3486
|
+
}
|
|
3487
|
+
read() {
|
|
3488
|
+
return JSON.parse(fs13.readFileSync(this.#registryPath, "utf8"));
|
|
3489
|
+
}
|
|
3490
|
+
/** Call within withLock for read-modify-write operations. */
|
|
3491
|
+
write(actors) {
|
|
3492
|
+
writeJsonAtomic(this.#registryPath, { format: 1, actors }, { space: 2 });
|
|
3493
|
+
}
|
|
3494
|
+
};
|
|
3495
|
+
|
|
3152
3496
|
// src/actors/manager.ts
|
|
3153
3497
|
var ACTOR_NAME_PATTERN = /^[a-zA-Z0-9][a-zA-Z0-9 _.-]{0,59}$/;
|
|
3154
3498
|
var TOPIC_PATTERN2 = /^[a-zA-Z0-9][a-zA-Z0-9._:/-]{0,127}$/;
|
|
@@ -3160,62 +3504,9 @@ var MAIN_REVISION_EVENTS = /* @__PURE__ */ new Set([
|
|
|
3160
3504
|
"tool_error",
|
|
3161
3505
|
"session_compact"
|
|
3162
3506
|
]);
|
|
3163
|
-
var MESSAGE_HISTORY_LIMIT = 100;
|
|
3164
|
-
var MESH_WATCH_RECONCILE_MS = 2e3;
|
|
3165
|
-
var ACTOR_REGISTRY_LOCK_TIMEOUT_MS = 5e3;
|
|
3166
3507
|
var ORPHAN_ADOPTION_RETRY_MS = 3e4;
|
|
3167
|
-
var ACTOR_REGISTRY_STALE_LOCK_MS = 3e4;
|
|
3168
3508
|
var RETENTION_SWEEP_INTERVAL_MS2 = 15 * 60 * 1e3;
|
|
3169
3509
|
var RESIDENT_HOST_EVENT_TOPIC = "fabric.actor.host-event";
|
|
3170
|
-
var ACTOR_MESSAGE_ENVELOPE_BYTES = 4096;
|
|
3171
|
-
var ACTOR_TRUNCATION_SUFFIX = "\n[actor message truncated]";
|
|
3172
|
-
var serializedBytes = (value) => Buffer.byteLength(JSON.stringify(value), "utf8");
|
|
3173
|
-
var truncateUtf8 = (value, maxBytes, suffix = "") => {
|
|
3174
|
-
if (Buffer.byteLength(value, "utf8") <= maxBytes) return value;
|
|
3175
|
-
const boundedSuffix = Buffer.byteLength(suffix, "utf8") <= maxBytes ? suffix : truncateUtf8(suffix, maxBytes);
|
|
3176
|
-
const available = Math.max(0, maxBytes - Buffer.byteLength(boundedSuffix, "utf8"));
|
|
3177
|
-
let low = 0;
|
|
3178
|
-
let high = value.length;
|
|
3179
|
-
while (low < high) {
|
|
3180
|
-
const middle = Math.ceil((low + high) / 2);
|
|
3181
|
-
if (Buffer.byteLength(value.slice(0, middle), "utf8") <= available) low = middle;
|
|
3182
|
-
else high = middle - 1;
|
|
3183
|
-
}
|
|
3184
|
-
return `${value.slice(0, low)}${boundedSuffix}`;
|
|
3185
|
-
};
|
|
3186
|
-
var boundedActorText = (value, maxBytes) => {
|
|
3187
|
-
if (serializedBytes({ text: value }) <= maxBytes) return value;
|
|
3188
|
-
const suffix = serializedBytes({ text: ACTOR_TRUNCATION_SUFFIX }) <= maxBytes ? ACTOR_TRUNCATION_SUFFIX : "";
|
|
3189
|
-
let low = 0;
|
|
3190
|
-
let high = value.length;
|
|
3191
|
-
while (low < high) {
|
|
3192
|
-
const middle = Math.ceil((low + high) / 2);
|
|
3193
|
-
if (serializedBytes({ text: `${value.slice(0, middle)}${suffix}` }) <= maxBytes) {
|
|
3194
|
-
low = middle;
|
|
3195
|
-
} else {
|
|
3196
|
-
high = middle - 1;
|
|
3197
|
-
}
|
|
3198
|
-
}
|
|
3199
|
-
return `${value.slice(0, low)}${suffix}`;
|
|
3200
|
-
};
|
|
3201
|
-
var boundedActorData = (data, maxBytes) => {
|
|
3202
|
-
let serialized;
|
|
3203
|
-
try {
|
|
3204
|
-
const encoded = JSON.stringify(data);
|
|
3205
|
-
serialized = typeof encoded === "string" ? encoded : String(data);
|
|
3206
|
-
if (serializedBytes({ data }) <= maxBytes) return data;
|
|
3207
|
-
} catch {
|
|
3208
|
-
serialized = String(data);
|
|
3209
|
-
}
|
|
3210
|
-
const originalBytes = Buffer.byteLength(serialized, "utf8");
|
|
3211
|
-
let preview = truncateUtf8(serialized, Math.max(0, maxBytes - 256));
|
|
3212
|
-
let bounded = { fabricTruncated: true, originalBytes, preview };
|
|
3213
|
-
while (preview && serializedBytes({ data: bounded }) > maxBytes) {
|
|
3214
|
-
preview = truncateUtf8(preview, Math.floor(Buffer.byteLength(preview, "utf8") / 2));
|
|
3215
|
-
bounded = { fabricTruncated: true, originalBytes, preview };
|
|
3216
|
-
}
|
|
3217
|
-
return serializedBytes({ data: bounded }) <= maxBytes ? bounded : { fabricTruncated: true, originalBytes };
|
|
3218
|
-
};
|
|
3219
3510
|
var normalizeCapabilityRequirements = (requirements = []) => {
|
|
3220
3511
|
const normalized = /* @__PURE__ */ new Map();
|
|
3221
3512
|
for (const requirement of requirements) {
|
|
@@ -3230,14 +3521,9 @@ var normalizeCapabilityRequirements = (requirements = []) => {
|
|
|
3230
3521
|
if (normalized.size > 128) throw new Error("Actors may require at most 128 Fabric capabilities");
|
|
3231
3522
|
return [...normalized].sort(([left], [right]) => left.localeCompare(right)).map(([ref, optional]) => ({ ref, ...optional ? { optional: true } : {} }));
|
|
3232
3523
|
};
|
|
3233
|
-
var delay4 = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
3234
|
-
var errorCode3 = (error) => error instanceof Error && "code" in error ? String(error.code) : void 0;
|
|
3235
|
-
var atomicWrite2 = (filePath, value) => {
|
|
3236
|
-
writeJsonAtomic(filePath, value, { space: 2 });
|
|
3237
|
-
};
|
|
3238
3524
|
var readRunRecord = (filePath) => {
|
|
3239
3525
|
try {
|
|
3240
|
-
const parsed = JSON.parse(
|
|
3526
|
+
const parsed = JSON.parse(fs14.readFileSync(filePath, "utf8"));
|
|
3241
3527
|
if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) return void 0;
|
|
3242
3528
|
return parsed;
|
|
3243
3529
|
} catch {
|
|
@@ -3287,7 +3573,7 @@ var ActorManager = class {
|
|
|
3287
3573
|
this.meshConfig = meshConfig;
|
|
3288
3574
|
this.agents = agents;
|
|
3289
3575
|
this.onDeliver = onDeliver;
|
|
3290
|
-
this.#actorRoot = options.actorRoot ??
|
|
3576
|
+
this.#actorRoot = options.actorRoot ?? fs14.mkdtempSync(path16.join(os4.tmpdir(), "pi-fabric-actors-"));
|
|
3291
3577
|
this.#actorScope = options.actorScope ?? meshConfig.actorScope;
|
|
3292
3578
|
this.#persistent = options.persistent ?? false;
|
|
3293
3579
|
this.#mainAgent = options.mainAgent;
|
|
@@ -3297,30 +3583,44 @@ var ActorManager = class {
|
|
|
3297
3583
|
this.#adoptionGraceMs = options.adoptionGraceMs ?? ORPHAN_ADOPTION_RETRY_MS;
|
|
3298
3584
|
this.#claimResidency = options.claimResidency;
|
|
3299
3585
|
this.#rootId = options.rootId ?? identity.id;
|
|
3300
|
-
this.#meshCursorPath = options.meshCursorPath;
|
|
3301
3586
|
this.#relayParticipantSteering = options.relayParticipantSteering ?? true;
|
|
3302
|
-
this.#
|
|
3587
|
+
this.#logs = new ActorLogStore(
|
|
3588
|
+
mesh,
|
|
3589
|
+
meshConfig,
|
|
3590
|
+
options.retention ?? DEFAULT_FABRIC_CONFIG.retention
|
|
3591
|
+
);
|
|
3592
|
+
this.#registry = new ActorRegistryStore(this.#actorRoot);
|
|
3303
3593
|
this.#bindings = new ActorBindingStore(
|
|
3304
3594
|
sessionId,
|
|
3305
3595
|
this.#persistent && meshConfig.enabled ? this.#actorRoot : void 0
|
|
3306
3596
|
);
|
|
3307
3597
|
if (this.#persistent && meshConfig.enabled) this.#loadActors();
|
|
3308
|
-
this.#registryFingerprint = this.#
|
|
3598
|
+
this.#registryFingerprint = this.#registry.fingerprint();
|
|
3309
3599
|
for (const actor of this.#actors.values()) {
|
|
3310
3600
|
this.#ownership.set(actor.id, this.#ownershipDecision(actor.id));
|
|
3311
3601
|
}
|
|
3312
|
-
this.#retention = options.retention ?? DEFAULT_FABRIC_CONFIG.retention;
|
|
3313
3602
|
this.#acquireCapabilityView = options.acquireCapabilityView;
|
|
3314
3603
|
this.#sweepRetainedRuns();
|
|
3315
3604
|
this.#retentionTimer = setInterval(() => this.#sweepRetainedRuns(), RETENTION_SWEEP_INTERVAL_MS2);
|
|
3316
3605
|
this.#retentionTimer.unref();
|
|
3317
|
-
this.#
|
|
3318
|
-
|
|
3606
|
+
this.#meshMonitor = new ActorMeshMonitor(mesh, meshConfig, {
|
|
3607
|
+
cursorPath: options.meshCursorPath,
|
|
3608
|
+
beforePoll: () => {
|
|
3609
|
+
this.#syncActorsFromRegistry();
|
|
3610
|
+
this.#refreshOwnership();
|
|
3611
|
+
return !this.#halted;
|
|
3612
|
+
},
|
|
3613
|
+
onEvent: (event) => {
|
|
3614
|
+
if (event.topic === "fabric.steer") this.#relaySteer(event);
|
|
3615
|
+
else if (!event.topic.startsWith("fabric.control.")) this.#dispatchMeshEvent(event);
|
|
3616
|
+
}
|
|
3617
|
+
});
|
|
3618
|
+
this.#meshMonitor.start();
|
|
3319
3619
|
}
|
|
3320
3620
|
#actors = /* @__PURE__ */ new Map();
|
|
3321
3621
|
#actorRoot;
|
|
3322
3622
|
#actorScope;
|
|
3323
|
-
#
|
|
3623
|
+
#registry;
|
|
3324
3624
|
#persistent;
|
|
3325
3625
|
#bindings;
|
|
3326
3626
|
#mainAgent;
|
|
@@ -3329,9 +3629,9 @@ var ActorManager = class {
|
|
|
3329
3629
|
#lineageAlive;
|
|
3330
3630
|
#claimResidency;
|
|
3331
3631
|
#rootId;
|
|
3332
|
-
#
|
|
3632
|
+
#meshMonitor;
|
|
3333
3633
|
#relayParticipantSteering;
|
|
3334
|
-
#
|
|
3634
|
+
#logs;
|
|
3335
3635
|
#acquireCapabilityView;
|
|
3336
3636
|
#locallyCreated = /* @__PURE__ */ new Set();
|
|
3337
3637
|
#ceded = /* @__PURE__ */ new Set();
|
|
@@ -3344,12 +3644,7 @@ var ActorManager = class {
|
|
|
3344
3644
|
#adoptionPending = /* @__PURE__ */ new Set();
|
|
3345
3645
|
#adoptionGraceMs;
|
|
3346
3646
|
#listeners = /* @__PURE__ */ new Set();
|
|
3347
|
-
#pollTimer;
|
|
3348
3647
|
#retentionTimer;
|
|
3349
|
-
#meshWatcher;
|
|
3350
|
-
#meshOffset;
|
|
3351
|
-
#meshPollScheduled = false;
|
|
3352
|
-
#polling = false;
|
|
3353
3648
|
#closing = false;
|
|
3354
3649
|
// Stop-the-world gate armed by haltAll() (ESC): while true, host-event and
|
|
3355
3650
|
// mesh dispatch are frozen so interrupted actors are not re-armed by the
|
|
@@ -3423,9 +3718,9 @@ var ActorManager = class {
|
|
|
3423
3718
|
if (requirements.length > 0 && !this.#acquireCapabilityView) {
|
|
3424
3719
|
throw new Error("This Fabric host cannot commit actor capability requirements");
|
|
3425
3720
|
}
|
|
3426
|
-
const id =
|
|
3427
|
-
const actorDirectory =
|
|
3428
|
-
|
|
3721
|
+
const id = randomUUID7().replaceAll("-", "");
|
|
3722
|
+
const actorDirectory = path16.join(this.#actorRoot, id);
|
|
3723
|
+
fs14.mkdirSync(actorDirectory, { recursive: true, mode: 448 });
|
|
3429
3724
|
const actor = {
|
|
3430
3725
|
id,
|
|
3431
3726
|
name,
|
|
@@ -3449,7 +3744,7 @@ var ActorManager = class {
|
|
|
3449
3744
|
requirements,
|
|
3450
3745
|
...request.validWhile ? { validWhile: structuredClone(request.validWhile) } : {},
|
|
3451
3746
|
latestActivationSequence: 0,
|
|
3452
|
-
sessionFile:
|
|
3747
|
+
sessionFile: path16.join(actorDirectory, "session.jsonl"),
|
|
3453
3748
|
queue: [],
|
|
3454
3749
|
draining: false,
|
|
3455
3750
|
messages: [],
|
|
@@ -3733,7 +4028,7 @@ var ActorManager = class {
|
|
|
3733
4028
|
messages(id, limit = 50) {
|
|
3734
4029
|
this.#syncActorsFromRegistry();
|
|
3735
4030
|
const actor = this.#requireActor(id);
|
|
3736
|
-
const bounded = Math.max(1, Math.min(Math.floor(limit),
|
|
4031
|
+
const bounded = Math.max(1, Math.min(Math.floor(limit), ACTOR_MESSAGE_HISTORY_LIMIT));
|
|
3737
4032
|
return actor.messages.slice(-bounded).map((message) => structuredClone(message));
|
|
3738
4033
|
}
|
|
3739
4034
|
/**
|
|
@@ -3782,17 +4077,17 @@ var ActorManager = class {
|
|
|
3782
4077
|
const type = opts.type ?? "session";
|
|
3783
4078
|
const lines = Math.max(1, Math.min(opts.lines ?? 200, 5e3));
|
|
3784
4079
|
const sessionFile = actor.sessionFile;
|
|
3785
|
-
const logDir =
|
|
4080
|
+
const logDir = path16.join(path16.dirname(sessionFile), "runs");
|
|
3786
4081
|
const sessionPage = type === "run" ? { lines: [], hasMore: false } : readJsonlPage(sessionFile, lines, opts.before);
|
|
3787
4082
|
const session = sessionPage.lines;
|
|
3788
4083
|
let run;
|
|
3789
4084
|
if (type !== "session") {
|
|
3790
4085
|
const targetRunId = opts.runId ?? actor.lastRunId;
|
|
3791
4086
|
if (targetRunId) {
|
|
3792
|
-
const runPath =
|
|
3793
|
-
if (
|
|
3794
|
-
const statusRecord = readRunRecord(
|
|
3795
|
-
const eventsFile =
|
|
4087
|
+
const runPath = path16.join(logDir, targetRunId);
|
|
4088
|
+
if (fs14.existsSync(runPath)) {
|
|
4089
|
+
const statusRecord = readRunRecord(path16.join(runPath, "status.json"));
|
|
4090
|
+
const eventsFile = path16.join(runPath, "events.jsonl");
|
|
3796
4091
|
const page = readJsonlPage(eventsFile, lines, opts.before);
|
|
3797
4092
|
run = {
|
|
3798
4093
|
runId: targetRunId,
|
|
@@ -3814,7 +4109,7 @@ var ActorManager = class {
|
|
|
3814
4109
|
sessionHasMore: sessionPage.hasMore,
|
|
3815
4110
|
...sessionPage.before !== void 0 ? { sessionBefore: sessionPage.before } : {},
|
|
3816
4111
|
...run ? { run } : {},
|
|
3817
|
-
retainedRuns: this.#retainedRunIds(actor)
|
|
4112
|
+
retainedRuns: this.#logs.retainedRunIds(actor)
|
|
3818
4113
|
};
|
|
3819
4114
|
}
|
|
3820
4115
|
noteMainActivity(idle = false) {
|
|
@@ -3905,22 +4200,6 @@ var ActorManager = class {
|
|
|
3905
4200
|
ownershipChecked: true
|
|
3906
4201
|
});
|
|
3907
4202
|
}
|
|
3908
|
-
#readMeshCursor() {
|
|
3909
|
-
if (!this.#meshCursorPath) return void 0;
|
|
3910
|
-
try {
|
|
3911
|
-
const value = JSON.parse(fs11.readFileSync(this.#meshCursorPath, "utf8"));
|
|
3912
|
-
return value.format === 1 && typeof value.cursor === "number" && value.cursor >= 0 ? value.cursor : void 0;
|
|
3913
|
-
} catch {
|
|
3914
|
-
return void 0;
|
|
3915
|
-
}
|
|
3916
|
-
}
|
|
3917
|
-
#writeMeshCursor() {
|
|
3918
|
-
if (!this.#meshCursorPath) return;
|
|
3919
|
-
try {
|
|
3920
|
-
atomicWrite2(this.#meshCursorPath, { format: 1, cursor: this.#meshOffset });
|
|
3921
|
-
} catch {
|
|
3922
|
-
}
|
|
3923
|
-
}
|
|
3924
4203
|
#beginHostEvent(event, idle) {
|
|
3925
4204
|
if (this.#closing || !this.meshConfig.enabled) return false;
|
|
3926
4205
|
if (!MAIN_REVISION_EVENTS.has(event) && ![...this.#actors.values()].some((actor) => this.#observesHostEvent(actor, event))) return false;
|
|
@@ -3928,7 +4207,7 @@ var ActorManager = class {
|
|
|
3928
4207
|
this.#refreshOwnership();
|
|
3929
4208
|
if (event === "input" && this.#halted) {
|
|
3930
4209
|
this.#halted = false;
|
|
3931
|
-
this.#
|
|
4210
|
+
this.#meshMonitor.schedule();
|
|
3932
4211
|
}
|
|
3933
4212
|
if (this.#halted) return false;
|
|
3934
4213
|
if (MAIN_REVISION_EVENTS.has(event)) this.#mainRevision++;
|
|
@@ -4009,7 +4288,7 @@ var ActorManager = class {
|
|
|
4009
4288
|
await this.#bindings.delete(actor.id);
|
|
4010
4289
|
this.#actors.delete(actor.id);
|
|
4011
4290
|
this.#emitChange();
|
|
4012
|
-
|
|
4291
|
+
fs14.rmSync(path16.dirname(actor.sessionFile), { recursive: true, force: true });
|
|
4013
4292
|
await this.#saveActors(/* @__PURE__ */ new Set([actor.id]));
|
|
4014
4293
|
await this.mesh.delete({ key: this.#presenceKey(actor.id) }).catch(() => ({ deleted: false }));
|
|
4015
4294
|
if (retainedRunId) await this.agents.cleanup(retainedRunId).catch(() => ({ cleaned: false }));
|
|
@@ -4018,12 +4297,9 @@ var ActorManager = class {
|
|
|
4018
4297
|
async close() {
|
|
4019
4298
|
if (this.#closing) return;
|
|
4020
4299
|
this.#closing = true;
|
|
4021
|
-
|
|
4022
|
-
this.#pollTimer = void 0;
|
|
4300
|
+
this.#meshMonitor.close();
|
|
4023
4301
|
if (this.#retentionTimer) clearInterval(this.#retentionTimer);
|
|
4024
4302
|
this.#retentionTimer = void 0;
|
|
4025
|
-
this.#meshWatcher?.close();
|
|
4026
|
-
this.#meshWatcher = void 0;
|
|
4027
4303
|
this.#listeners.clear();
|
|
4028
4304
|
if (this.#persistent) {
|
|
4029
4305
|
this.#refreshOwnership();
|
|
@@ -4052,7 +4328,7 @@ var ActorManager = class {
|
|
|
4052
4328
|
await Promise.allSettled(
|
|
4053
4329
|
[...this.#actors.values()].map((actor) => actor.drain ?? Promise.resolve())
|
|
4054
4330
|
);
|
|
4055
|
-
|
|
4331
|
+
fs14.rmSync(this.#actorRoot, { recursive: true, force: true });
|
|
4056
4332
|
}
|
|
4057
4333
|
#enqueue(actor, source, payload, options = {}) {
|
|
4058
4334
|
const canManage = options.ownershipChecked ? this.#canManageCached(actor.id) : this.#canManage(actor.id);
|
|
@@ -4092,7 +4368,7 @@ var ActorManager = class {
|
|
|
4092
4368
|
`Fabric actor queue limit reached for ${actor.name} (${this.meshConfig.actorQueueLimit})`
|
|
4093
4369
|
);
|
|
4094
4370
|
}
|
|
4095
|
-
const itemId =
|
|
4371
|
+
const itemId = randomUUID7();
|
|
4096
4372
|
const item = {
|
|
4097
4373
|
id: itemId,
|
|
4098
4374
|
source,
|
|
@@ -4205,7 +4481,7 @@ var ActorManager = class {
|
|
|
4205
4481
|
if (actor.responseMode === "directive") {
|
|
4206
4482
|
const reason = result.error || `Actor run ${result.status}`;
|
|
4207
4483
|
const silent = {
|
|
4208
|
-
id:
|
|
4484
|
+
id: randomUUID7(),
|
|
4209
4485
|
actorId: actor.id,
|
|
4210
4486
|
actorName: actor.name,
|
|
4211
4487
|
direction: "out",
|
|
@@ -4270,7 +4546,7 @@ var ActorManager = class {
|
|
|
4270
4546
|
}
|
|
4271
4547
|
actor.lastError = message;
|
|
4272
4548
|
const failed = {
|
|
4273
|
-
id:
|
|
4549
|
+
id: randomUUID7(),
|
|
4274
4550
|
actorId: actor.id,
|
|
4275
4551
|
actorName: actor.name,
|
|
4276
4552
|
direction: "out",
|
|
@@ -4352,7 +4628,7 @@ var ActorManager = class {
|
|
|
4352
4628
|
if (actor.responseMode === "directive") {
|
|
4353
4629
|
const directive = asDirective(result);
|
|
4354
4630
|
return {
|
|
4355
|
-
id:
|
|
4631
|
+
id: randomUUID7(),
|
|
4356
4632
|
actorId: actor.id,
|
|
4357
4633
|
actorName: actor.name,
|
|
4358
4634
|
direction: "out",
|
|
@@ -4366,7 +4642,7 @@ var ActorManager = class {
|
|
|
4366
4642
|
};
|
|
4367
4643
|
}
|
|
4368
4644
|
return {
|
|
4369
|
-
id:
|
|
4645
|
+
id: randomUUID7(),
|
|
4370
4646
|
actorId: actor.id,
|
|
4371
4647
|
actorName: actor.name,
|
|
4372
4648
|
direction: "out",
|
|
@@ -4421,7 +4697,7 @@ var ActorManager = class {
|
|
|
4421
4697
|
}
|
|
4422
4698
|
#recordStale(actor, item, reason = "validWhile returned false", runId, usage) {
|
|
4423
4699
|
const message = {
|
|
4424
|
-
id:
|
|
4700
|
+
id: randomUUID7(),
|
|
4425
4701
|
actorId: actor.id,
|
|
4426
4702
|
actorName: actor.name,
|
|
4427
4703
|
direction: "out",
|
|
@@ -4436,65 +4712,6 @@ var ActorManager = class {
|
|
|
4436
4712
|
this.#recordMessage(actor, message);
|
|
4437
4713
|
item.reject?.(new Error(`Fabric actor activation invalidated: ${reason}`));
|
|
4438
4714
|
}
|
|
4439
|
-
#startMeshMonitor() {
|
|
4440
|
-
if (!this.meshConfig.enabled || this.#closing) return;
|
|
4441
|
-
if (process.platform === "win32") {
|
|
4442
|
-
this.#startPollTimer(this.meshConfig.actorPollMs);
|
|
4443
|
-
this.#scheduleMeshPoll();
|
|
4444
|
-
return;
|
|
4445
|
-
}
|
|
4446
|
-
try {
|
|
4447
|
-
const watcher = fs11.watch(this.mesh.root, { persistent: false }, (_event, filename) => {
|
|
4448
|
-
if (filename !== null && path13.basename(filename.toString()) !== "events.jsonl") return;
|
|
4449
|
-
this.#scheduleMeshPoll();
|
|
4450
|
-
});
|
|
4451
|
-
this.#meshWatcher = watcher;
|
|
4452
|
-
watcher.on("error", () => this.#fallBackToMeshPolling(watcher));
|
|
4453
|
-
this.#startPollTimer(Math.max(MESH_WATCH_RECONCILE_MS, this.meshConfig.actorPollMs));
|
|
4454
|
-
} catch {
|
|
4455
|
-
this.#startPollTimer(this.meshConfig.actorPollMs);
|
|
4456
|
-
}
|
|
4457
|
-
this.#scheduleMeshPoll();
|
|
4458
|
-
}
|
|
4459
|
-
#fallBackToMeshPolling(watcher) {
|
|
4460
|
-
if (this.#closing || this.#meshWatcher !== watcher) return;
|
|
4461
|
-
watcher.close();
|
|
4462
|
-
this.#meshWatcher = void 0;
|
|
4463
|
-
this.#startPollTimer(this.meshConfig.actorPollMs);
|
|
4464
|
-
this.#scheduleMeshPoll();
|
|
4465
|
-
}
|
|
4466
|
-
#startPollTimer(delay5) {
|
|
4467
|
-
if (this.#pollTimer) clearInterval(this.#pollTimer);
|
|
4468
|
-
this.#pollTimer = setInterval(() => this.#scheduleMeshPoll(), delay5);
|
|
4469
|
-
this.#pollTimer.unref();
|
|
4470
|
-
}
|
|
4471
|
-
#scheduleMeshPoll() {
|
|
4472
|
-
if (this.#meshPollScheduled || this.#closing || !this.meshConfig.enabled) return;
|
|
4473
|
-
this.#meshPollScheduled = true;
|
|
4474
|
-
queueMicrotask(() => {
|
|
4475
|
-
this.#meshPollScheduled = false;
|
|
4476
|
-
if (this.#closing) return;
|
|
4477
|
-
void this.#pollMesh().catch(() => void 0);
|
|
4478
|
-
});
|
|
4479
|
-
}
|
|
4480
|
-
async #pollMesh() {
|
|
4481
|
-
if (this.#polling || this.#closing || !this.meshConfig.enabled) return;
|
|
4482
|
-
this.#syncActorsFromRegistry();
|
|
4483
|
-
this.#refreshOwnership();
|
|
4484
|
-
if (this.#halted) return;
|
|
4485
|
-
this.#polling = true;
|
|
4486
|
-
try {
|
|
4487
|
-
const tail = this.mesh.tail(this.#meshOffset, this.meshConfig.maxReadEvents);
|
|
4488
|
-
this.#meshOffset = tail.nextOffset;
|
|
4489
|
-
for (const event of tail.events) {
|
|
4490
|
-
if (event.topic === "fabric.steer") this.#relaySteer(event);
|
|
4491
|
-
else if (!event.topic.startsWith("fabric.control.")) this.#dispatchMeshEvent(event);
|
|
4492
|
-
}
|
|
4493
|
-
this.#writeMeshCursor();
|
|
4494
|
-
} finally {
|
|
4495
|
-
this.#polling = false;
|
|
4496
|
-
}
|
|
4497
|
-
}
|
|
4498
4715
|
/**
|
|
4499
4716
|
* Receive legacy fabric.steer events from older Fabric writers. This path is
|
|
4500
4717
|
* intentionally best-effort; current writers use acknowledged owner-addressed
|
|
@@ -4555,91 +4772,17 @@ var ActorManager = class {
|
|
|
4555
4772
|
}
|
|
4556
4773
|
}
|
|
4557
4774
|
async #retainRunLog(actor, runId) {
|
|
4558
|
-
|
|
4559
|
-
if (!runDirectory || !fs11.existsSync(runDirectory)) return;
|
|
4560
|
-
const dest = path13.join(path13.dirname(actor.sessionFile), "runs", runId);
|
|
4561
|
-
fs11.mkdirSync(dest, { recursive: true, mode: 448 });
|
|
4562
|
-
for (const file of ["events.jsonl", "status.json", "task.txt"]) {
|
|
4563
|
-
const src = path13.join(runDirectory, file);
|
|
4564
|
-
if (fs11.existsSync(src)) fs11.copyFileSync(src, path13.join(dest, file));
|
|
4565
|
-
}
|
|
4566
|
-
const nested = path13.join(runDirectory, "nested");
|
|
4567
|
-
if (fs11.existsSync(nested)) {
|
|
4568
|
-
try {
|
|
4569
|
-
fs11.cpSync(nested, path13.join(dest, "nested"), { recursive: true });
|
|
4570
|
-
} catch {
|
|
4571
|
-
}
|
|
4572
|
-
}
|
|
4573
|
-
this.#pruneRetainedRuns(actor);
|
|
4574
|
-
}
|
|
4575
|
-
#pruneRetainedRuns(actor, now = Date.now()) {
|
|
4576
|
-
pruneActorRunArchives({
|
|
4577
|
-
runsDirectory: path13.join(path13.dirname(actor.sessionFile), "runs"),
|
|
4578
|
-
...actor.lastRunId ? { latestRunId: actor.lastRunId } : {},
|
|
4579
|
-
retentionMs: this.#retention.actorRunArchiveMs,
|
|
4580
|
-
now
|
|
4581
|
-
});
|
|
4775
|
+
await this.#logs.retainRun(actor, runId, this.agents.runDirectory(runId));
|
|
4582
4776
|
}
|
|
4583
4777
|
#sweepRetainedRuns(now = Date.now()) {
|
|
4584
4778
|
if (this.#closing) return;
|
|
4585
4779
|
this.#refreshOwnership();
|
|
4586
4780
|
for (const actor of this.#actors.values()) {
|
|
4587
|
-
if (this.#canManage(actor.id)) this.#
|
|
4588
|
-
}
|
|
4589
|
-
}
|
|
4590
|
-
#retainedRunIds(actor) {
|
|
4591
|
-
const runsDir = path13.join(path13.dirname(actor.sessionFile), "runs");
|
|
4592
|
-
try {
|
|
4593
|
-
return fs11.readdirSync(runsDir).sort();
|
|
4594
|
-
} catch {
|
|
4595
|
-
return [];
|
|
4781
|
+
if (this.#canManage(actor.id)) this.#logs.pruneRuns(actor, now);
|
|
4596
4782
|
}
|
|
4597
4783
|
}
|
|
4598
4784
|
#recordMessage(actor, message) {
|
|
4599
|
-
|
|
4600
|
-
const maxPayloadBytes = Math.max(1, this.mesh.maxEventBytes - ACTOR_MESSAGE_ENVELOPE_BYTES);
|
|
4601
|
-
const fixed = structuredClone(bounded);
|
|
4602
|
-
delete fixed.text;
|
|
4603
|
-
delete fixed.data;
|
|
4604
|
-
const contentBytes = Math.max(1, maxPayloadBytes - serializedBytes(fixed) - 128);
|
|
4605
|
-
const hasText = Boolean(bounded.text);
|
|
4606
|
-
const hasData = bounded.data !== void 0;
|
|
4607
|
-
const textBytes = hasText && hasData ? Math.floor(contentBytes / 2) : contentBytes;
|
|
4608
|
-
const dataBytes = hasText && hasData ? contentBytes - textBytes : contentBytes;
|
|
4609
|
-
if (bounded.text) {
|
|
4610
|
-
const contextBounded = bounded.text.length > this.meshConfig.eventContextChars ? `${bounded.text.slice(0, this.meshConfig.eventContextChars)}${ACTOR_TRUNCATION_SUFFIX}` : bounded.text;
|
|
4611
|
-
bounded.text = boundedActorText(contextBounded, textBytes);
|
|
4612
|
-
}
|
|
4613
|
-
if (bounded.data !== void 0) {
|
|
4614
|
-
bounded.data = boundedActorData(bounded.data, dataBytes);
|
|
4615
|
-
}
|
|
4616
|
-
if (serializedBytes(bounded) > maxPayloadBytes) {
|
|
4617
|
-
delete bounded.data;
|
|
4618
|
-
if (bounded.text) {
|
|
4619
|
-
bounded.text = boundedActorText(bounded.text, contentBytes);
|
|
4620
|
-
}
|
|
4621
|
-
}
|
|
4622
|
-
if (serializedBytes(bounded) > maxPayloadBytes) {
|
|
4623
|
-
bounded = {
|
|
4624
|
-
id: bounded.id,
|
|
4625
|
-
actorId: bounded.actorId,
|
|
4626
|
-
actorName: bounded.actorName,
|
|
4627
|
-
direction: bounded.direction,
|
|
4628
|
-
source: boundedActorText(bounded.source, 1024),
|
|
4629
|
-
createdAt: bounded.createdAt,
|
|
4630
|
-
...bounded.action ? { action: bounded.action } : {},
|
|
4631
|
-
...bounded.runId ? { runId: bounded.runId } : {},
|
|
4632
|
-
error: "Actor message content exceeded the mesh event limit"
|
|
4633
|
-
};
|
|
4634
|
-
}
|
|
4635
|
-
for (const key of Object.keys(message)) {
|
|
4636
|
-
delete message[key];
|
|
4637
|
-
}
|
|
4638
|
-
Object.assign(message, bounded);
|
|
4639
|
-
actor.messages.push(bounded);
|
|
4640
|
-
if (actor.messages.length > MESSAGE_HISTORY_LIMIT) {
|
|
4641
|
-
actor.messages.splice(0, actor.messages.length - MESSAGE_HISTORY_LIMIT);
|
|
4642
|
-
}
|
|
4785
|
+
this.#logs.recordMessage(actor.messages, message);
|
|
4643
4786
|
}
|
|
4644
4787
|
async #publishPresence(actor) {
|
|
4645
4788
|
if (!this.#canManage(actor.id)) return;
|
|
@@ -4704,88 +4847,17 @@ var ActorManager = class {
|
|
|
4704
4847
|
...actor.lastRunId ? { lastRunId: actor.lastRunId } : {}
|
|
4705
4848
|
};
|
|
4706
4849
|
}
|
|
4707
|
-
#registryRecords() {
|
|
4708
|
-
try {
|
|
4709
|
-
const parsed = JSON.parse(fs11.readFileSync(this.#registryPath, "utf8"));
|
|
4710
|
-
if (!Array.isArray(parsed.actors)) return [];
|
|
4711
|
-
return parsed.actors.flatMap(
|
|
4712
|
-
(record) => typeof record === "object" && record !== null && !Array.isArray(record) && typeof record.id === "string" ? [record] : []
|
|
4713
|
-
);
|
|
4714
|
-
} catch {
|
|
4715
|
-
return [];
|
|
4716
|
-
}
|
|
4717
|
-
}
|
|
4718
|
-
async #withRegistryLock(operation) {
|
|
4719
|
-
const lockPath = `${this.#registryPath}.lock`;
|
|
4720
|
-
const ownerPath2 = path13.join(lockPath, "owner");
|
|
4721
|
-
const deadline = Date.now() + ACTOR_REGISTRY_LOCK_TIMEOUT_MS;
|
|
4722
|
-
const token = randomUUID6();
|
|
4723
|
-
const processAlive3 = (pid) => {
|
|
4724
|
-
if (!Number.isSafeInteger(pid) || pid <= 0) return false;
|
|
4725
|
-
try {
|
|
4726
|
-
process.kill(pid, 0);
|
|
4727
|
-
return true;
|
|
4728
|
-
} catch {
|
|
4729
|
-
return false;
|
|
4730
|
-
}
|
|
4731
|
-
};
|
|
4732
|
-
fs11.mkdirSync(this.#actorRoot, { recursive: true, mode: 448 });
|
|
4733
|
-
while (true) {
|
|
4734
|
-
try {
|
|
4735
|
-
fs11.mkdirSync(lockPath, { mode: 448 });
|
|
4736
|
-
fs11.writeFileSync(ownerPath2, `${token}
|
|
4737
|
-
${process.pid}
|
|
4738
|
-
${Date.now()}
|
|
4739
|
-
`, {
|
|
4740
|
-
encoding: "utf8",
|
|
4741
|
-
mode: 384
|
|
4742
|
-
});
|
|
4743
|
-
break;
|
|
4744
|
-
} catch (error) {
|
|
4745
|
-
if (errorCode3(error) !== "EEXIST") throw error;
|
|
4746
|
-
try {
|
|
4747
|
-
const firstOwner = fs11.readFileSync(ownerPath2, "utf8");
|
|
4748
|
-
const [, pidText, createdText] = firstOwner.trim().split("\n");
|
|
4749
|
-
const stale = Date.now() - Number(createdText) > ACTOR_REGISTRY_STALE_LOCK_MS;
|
|
4750
|
-
if (stale && !processAlive3(Number(pidText))) {
|
|
4751
|
-
const secondOwner = fs11.readFileSync(ownerPath2, "utf8");
|
|
4752
|
-
if (secondOwner === firstOwner) {
|
|
4753
|
-
fs11.rmSync(lockPath, { recursive: true, force: true });
|
|
4754
|
-
continue;
|
|
4755
|
-
}
|
|
4756
|
-
}
|
|
4757
|
-
} catch {
|
|
4758
|
-
}
|
|
4759
|
-
if (Date.now() >= deadline) {
|
|
4760
|
-
throw new Error("Timed out waiting for the Fabric actor registry lock");
|
|
4761
|
-
}
|
|
4762
|
-
await delay4(10);
|
|
4763
|
-
}
|
|
4764
|
-
}
|
|
4765
|
-
try {
|
|
4766
|
-
return operation();
|
|
4767
|
-
} finally {
|
|
4768
|
-
try {
|
|
4769
|
-
const owner = fs11.readFileSync(ownerPath2, "utf8");
|
|
4770
|
-
if (owner.startsWith(`${token}
|
|
4771
|
-
`)) {
|
|
4772
|
-
fs11.rmSync(lockPath, { recursive: true, force: true });
|
|
4773
|
-
}
|
|
4774
|
-
} catch {
|
|
4775
|
-
}
|
|
4776
|
-
}
|
|
4777
|
-
}
|
|
4778
4850
|
async #saveActors(removedIds = /* @__PURE__ */ new Set()) {
|
|
4779
4851
|
if (!this.#persistent || !this.meshConfig.enabled) return;
|
|
4780
|
-
await this.#
|
|
4852
|
+
await this.#registry.withLock(() => {
|
|
4781
4853
|
const owned = [...this.#actors.values()].filter(
|
|
4782
4854
|
(actor) => this.#ownershipDecision(actor.id)
|
|
4783
4855
|
);
|
|
4784
4856
|
const replaced = /* @__PURE__ */ new Set([...removedIds, ...owned.map((actor) => actor.id)]);
|
|
4785
|
-
const preserved = this.#
|
|
4857
|
+
const preserved = this.#registry.records().filter((record) => !replaced.has(record.id));
|
|
4786
4858
|
const actors = [...preserved, ...owned.map((actor) => this.#serializedActor(actor))];
|
|
4787
|
-
|
|
4788
|
-
this.#registryFingerprint = this.#
|
|
4859
|
+
this.#registry.write(actors);
|
|
4860
|
+
this.#registryFingerprint = this.#registry.fingerprint();
|
|
4789
4861
|
for (const id of removedIds) this.#persistedRoots.delete(id);
|
|
4790
4862
|
for (const actor of owned) this.#persistedRoots.set(actor.id, actor.rootId);
|
|
4791
4863
|
for (const record of preserved) {
|
|
@@ -4795,17 +4867,9 @@ ${Date.now()}
|
|
|
4795
4867
|
this.#registryFingerprint = void 0;
|
|
4796
4868
|
this.#syncActorsFromRegistry();
|
|
4797
4869
|
}
|
|
4798
|
-
#currentRegistryFingerprint() {
|
|
4799
|
-
try {
|
|
4800
|
-
const stat = fs11.statSync(this.#registryPath);
|
|
4801
|
-
return `${stat.dev}:${stat.ino}:${stat.size}:${stat.mtimeMs}`;
|
|
4802
|
-
} catch {
|
|
4803
|
-
return void 0;
|
|
4804
|
-
}
|
|
4805
|
-
}
|
|
4806
4870
|
#syncActorsFromRegistry() {
|
|
4807
4871
|
if (!this.#persistent || this.#closing || this.#reloadingOwnership) return;
|
|
4808
|
-
const fingerprint = this.#
|
|
4872
|
+
const fingerprint = this.#registry.fingerprint();
|
|
4809
4873
|
if (!fingerprint || fingerprint === this.#registryFingerprint) return;
|
|
4810
4874
|
this.#registryFingerprint = fingerprint;
|
|
4811
4875
|
const ownsAny = [...this.#actors.keys()].some((id) => this.#ownershipDecision(id));
|
|
@@ -4842,7 +4906,7 @@ ${Date.now()}
|
|
|
4842
4906
|
let added = 0;
|
|
4843
4907
|
let parsed;
|
|
4844
4908
|
try {
|
|
4845
|
-
parsed =
|
|
4909
|
+
parsed = this.#registry.read();
|
|
4846
4910
|
} catch (error) {
|
|
4847
4911
|
if (error instanceof Error && "code" in error && error.code === "ENOENT") return;
|
|
4848
4912
|
return;
|
|
@@ -4903,7 +4967,7 @@ ${Date.now()}
|
|
|
4903
4967
|
...typeof record.capabilityDigest === "string" ? { capabilityDigest: record.capabilityDigest } : {},
|
|
4904
4968
|
...record.validWhile?.version === 1 && typeof record.validWhile.source === "string" ? { validWhile: record.validWhile } : {},
|
|
4905
4969
|
latestActivationSequence: 0,
|
|
4906
|
-
sessionFile:
|
|
4970
|
+
sessionFile: path16.join(this.#actorRoot, record.id, "session.jsonl"),
|
|
4907
4971
|
queue: [],
|
|
4908
4972
|
draining: false,
|
|
4909
4973
|
messages: [],
|
|
@@ -4912,7 +4976,7 @@ ${Date.now()}
|
|
|
4912
4976
|
...typeof record.lastRunId === "string" ? { lastRunId: record.lastRunId } : {}
|
|
4913
4977
|
};
|
|
4914
4978
|
if (Array.isArray(record.messages)) {
|
|
4915
|
-
for (const candidate of record.messages.slice(-
|
|
4979
|
+
for (const candidate of record.messages.slice(-ACTOR_MESSAGE_HISTORY_LIMIT)) {
|
|
4916
4980
|
if (typeof candidate === "object" && candidate !== null && !Array.isArray(candidate) && typeof candidate.id === "string" && typeof candidate.source === "string" && typeof candidate.createdAt === "number") {
|
|
4917
4981
|
this.#recordMessage(actor, candidate);
|
|
4918
4982
|
}
|
|
@@ -4995,7 +5059,7 @@ ${Date.now()}
|
|
|
4995
5059
|
...actor.lastRunId ? { lastRunId: actor.lastRunId } : {},
|
|
4996
5060
|
...actor.lastError ? { lastError: actor.lastError } : {},
|
|
4997
5061
|
sessionFile: actor.sessionFile,
|
|
4998
|
-
logDir:
|
|
5062
|
+
logDir: path16.join(path16.dirname(actor.sessionFile), "runs")
|
|
4999
5063
|
};
|
|
5000
5064
|
}
|
|
5001
5065
|
validateDirectMessage(message, data) {
|
|
@@ -5042,8 +5106,8 @@ ${Date.now()}
|
|
|
5042
5106
|
this.#adoptionPending.add(actor.id);
|
|
5043
5107
|
try {
|
|
5044
5108
|
const expectedRootId = actor.rootId;
|
|
5045
|
-
const adopted = await this.#
|
|
5046
|
-
const records = this.#
|
|
5109
|
+
const adopted = await this.#registry.withLock(() => {
|
|
5110
|
+
const records = this.#registry.records();
|
|
5047
5111
|
const current = records.find((record) => record.id === actor.id);
|
|
5048
5112
|
if (!current || current.rootId !== expectedRootId) return false;
|
|
5049
5113
|
if (this.#canManageActor?.(actor.id) !== void 0) return false;
|
|
@@ -5058,17 +5122,14 @@ ${Date.now()}
|
|
|
5058
5122
|
actor.adoptedAt = Date.now();
|
|
5059
5123
|
actor.updatedAt = Date.now();
|
|
5060
5124
|
const preserved = records.filter((record) => record.id !== actor.id);
|
|
5061
|
-
|
|
5062
|
-
|
|
5063
|
-
actors: [...preserved, this.#serializedActor(actor)]
|
|
5064
|
-
});
|
|
5065
|
-
this.#registryFingerprint = this.#currentRegistryFingerprint();
|
|
5125
|
+
this.#registry.write([...preserved, this.#serializedActor(actor)]);
|
|
5126
|
+
this.#registryFingerprint = this.#registry.fingerprint();
|
|
5066
5127
|
return true;
|
|
5067
5128
|
});
|
|
5068
5129
|
if (adopted) {
|
|
5069
5130
|
this.#persistedRoots.set(actor.id, this.#rootId);
|
|
5070
5131
|
} else {
|
|
5071
|
-
const current = this.#
|
|
5132
|
+
const current = this.#registry.records().find((record) => record.id === actor.id);
|
|
5072
5133
|
if (!current) {
|
|
5073
5134
|
this.#persistedRoots.delete(actor.id);
|
|
5074
5135
|
} else if (typeof current.rootId === "string" && current.rootId !== this.#rootId) {
|
|
@@ -5166,10 +5227,10 @@ var ActorDirectory = class extends ActorManager {
|
|
|
5166
5227
|
delete options.actorRoot;
|
|
5167
5228
|
delete options.meshCursorPath;
|
|
5168
5229
|
const cursorPaths = meshCursorPath ? { project: `${meshCursorPath}.project`, session: `${meshCursorPath}.session` } : void 0;
|
|
5169
|
-
if (meshCursorPath &&
|
|
5230
|
+
if (meshCursorPath && fs15.existsSync(meshCursorPath)) {
|
|
5170
5231
|
for (const cursorPath of Object.values(cursorPaths)) {
|
|
5171
5232
|
try {
|
|
5172
|
-
if (!
|
|
5233
|
+
if (!fs15.existsSync(cursorPath)) fs15.copyFileSync(meshCursorPath, cursorPath);
|
|
5173
5234
|
} catch {
|
|
5174
5235
|
}
|
|
5175
5236
|
}
|
|
@@ -5325,7 +5386,7 @@ var ActorDirectory = class extends ActorManager {
|
|
|
5325
5386
|
};
|
|
5326
5387
|
|
|
5327
5388
|
// src/lifecycle/broker.ts
|
|
5328
|
-
import { randomUUID as
|
|
5389
|
+
import { randomUUID as randomUUID8 } from "node:crypto";
|
|
5329
5390
|
var subscriptionKey = (id) => FABRIC_LIFECYCLE_SUBSCRIPTION_PREFIX + id;
|
|
5330
5391
|
var LifecycleBroker = class {
|
|
5331
5392
|
constructor(mesh, identity, participants, options, deliver) {
|
|
@@ -5404,7 +5465,7 @@ var LifecycleBroker = class {
|
|
|
5404
5465
|
const now = Date.now();
|
|
5405
5466
|
const subscription = {
|
|
5406
5467
|
format: 1,
|
|
5407
|
-
id:
|
|
5468
|
+
id: randomUUID8().replaceAll("-", ""),
|
|
5408
5469
|
from,
|
|
5409
5470
|
events,
|
|
5410
5471
|
to,
|
|
@@ -5569,7 +5630,7 @@ var LifecycleBroker = class {
|
|
|
5569
5630
|
};
|
|
5570
5631
|
|
|
5571
5632
|
// src/topology/control-plane.ts
|
|
5572
|
-
import { createHash as createHash2, randomUUID as
|
|
5633
|
+
import { createHash as createHash2, randomUUID as randomUUID9 } from "node:crypto";
|
|
5573
5634
|
var CONTROL_TOPIC = "fabric.control.command";
|
|
5574
5635
|
var ACK_TOPIC = "fabric.control.ack";
|
|
5575
5636
|
var CONTROL_SEEN_PREFIX = "topology/control-seen/";
|
|
@@ -5664,7 +5725,7 @@ var FabricControlPlane = class {
|
|
|
5664
5725
|
this.#pollMs * 4,
|
|
5665
5726
|
Math.min(MAX_CONTROL_TIMEOUT_MS, Math.floor(options.timeoutMs ?? this.#ackTimeoutMs))
|
|
5666
5727
|
);
|
|
5667
|
-
const commandId =
|
|
5728
|
+
const commandId = randomUUID9();
|
|
5668
5729
|
const requestedAt = Date.now();
|
|
5669
5730
|
let pendingRequest;
|
|
5670
5731
|
const acceptance = new Promise((resolve, reject) => {
|
|
@@ -5756,7 +5817,7 @@ var FabricControlPlane = class {
|
|
|
5756
5817
|
to: pending.ownerHostId,
|
|
5757
5818
|
data: {
|
|
5758
5819
|
version: 1,
|
|
5759
|
-
commandId:
|
|
5820
|
+
commandId: randomUUID9(),
|
|
5760
5821
|
targetId: pending.targetId,
|
|
5761
5822
|
operation: "cancel",
|
|
5762
5823
|
cancelCommandId: commandId,
|
|
@@ -6626,4 +6687,4 @@ export {
|
|
|
6626
6687
|
agentParticipantRecords,
|
|
6627
6688
|
actorParticipantRecord
|
|
6628
6689
|
};
|
|
6629
|
-
//# sourceMappingURL=chunk-
|
|
6690
|
+
//# sourceMappingURL=chunk-257ES5IL.js.map
|