@elizaos/autonomous 2.0.0-alpha.65 → 2.0.0-alpha.66
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/package.json
CHANGED
package/src/runtime/eliza.ts
CHANGED
|
@@ -4166,12 +4166,36 @@ export async function startEliza(
|
|
|
4166
4166
|
// (ActionFilterService, EmbeddingGenerationService) race ahead and use
|
|
4167
4167
|
// the cloud plugin's TEXT_EMBEDDING handler — which hits a paid API —
|
|
4168
4168
|
// because local-embedding's heavier init hasn't completed yet.
|
|
4169
|
+
// Check whether the embedding model file is already downloaded.
|
|
4170
|
+
// When missing, we defer local-embedding registration to after
|
|
4171
|
+
// runtime.initialize() so the multi-GB download does not block
|
|
4172
|
+
// startup (runtime.initialize → ensureEmbeddingDimension would hang
|
|
4173
|
+
// waiting for the model).
|
|
4174
|
+
let deferLocalEmbedding = false;
|
|
4169
4175
|
if (localEmbeddingPlugin) {
|
|
4170
4176
|
configureLocalEmbeddingPlugin(localEmbeddingPlugin.plugin, config);
|
|
4171
|
-
|
|
4172
|
-
|
|
4173
|
-
|
|
4174
|
-
|
|
4177
|
+
|
|
4178
|
+
const embeddingModelDir =
|
|
4179
|
+
process.env.MODELS_DIR ??
|
|
4180
|
+
path.join(resolveStateDir(), "models");
|
|
4181
|
+
const embeddingModelFile =
|
|
4182
|
+
process.env.LOCAL_EMBEDDING_MODEL ?? "nomic-embed-text-v1.5.Q5_K_M.gguf";
|
|
4183
|
+
const modelPath = path.join(embeddingModelDir, embeddingModelFile);
|
|
4184
|
+
|
|
4185
|
+
try {
|
|
4186
|
+
await fs.access(modelPath);
|
|
4187
|
+
// Model exists — register now so ensureEmbeddingDimension works
|
|
4188
|
+
await runtime.registerPlugin(localEmbeddingPlugin.plugin);
|
|
4189
|
+
logger.info(
|
|
4190
|
+
"[eliza] plugin-local-embedding pre-registered (TEXT_EMBEDDING ready)",
|
|
4191
|
+
);
|
|
4192
|
+
} catch {
|
|
4193
|
+
deferLocalEmbedding = true;
|
|
4194
|
+
logger.info(
|
|
4195
|
+
`[eliza] Embedding model not yet downloaded (${embeddingModelFile}). ` +
|
|
4196
|
+
"Deferring local-embedding to avoid blocking startup.",
|
|
4197
|
+
);
|
|
4198
|
+
}
|
|
4175
4199
|
} else {
|
|
4176
4200
|
logger.warn(
|
|
4177
4201
|
"[eliza] @elizaos/plugin-local-embedding not found — embeddings " +
|
|
@@ -4277,6 +4301,15 @@ export async function startEliza(
|
|
|
4277
4301
|
}
|
|
4278
4302
|
};
|
|
4279
4303
|
|
|
4304
|
+
// Keep the event loop alive during the entire startup sequence.
|
|
4305
|
+
// PGLite and the local-embedding model download may `unref()` their
|
|
4306
|
+
// internal handles, causing Node to exit before the initialize() promise
|
|
4307
|
+
// settles when there is nothing else keeping the loop alive (e.g.
|
|
4308
|
+
// server-only mode with stdin set to "ignore"). This guard stays active
|
|
4309
|
+
// until a permanent handle (API server or the serverOnly keepAlive
|
|
4310
|
+
// interval) takes over.
|
|
4311
|
+
const startupKeepAlive = setInterval(() => {}, 1 << 30);
|
|
4312
|
+
|
|
4280
4313
|
const initializeRuntimeServices = async (): Promise<void> => {
|
|
4281
4314
|
// 8. Initialize the runtime (registers remaining plugins, starts services)
|
|
4282
4315
|
await runtime.initialize();
|
|
@@ -4343,6 +4376,24 @@ export async function startEliza(
|
|
|
4343
4376
|
|
|
4344
4377
|
installActionAliases(runtime);
|
|
4345
4378
|
|
|
4379
|
+
// Deferred local-embedding registration — register the plugin now that
|
|
4380
|
+
// runtime.initialize() has completed. The model will be downloaded on
|
|
4381
|
+
// first embedding request rather than blocking startup.
|
|
4382
|
+
if (deferLocalEmbedding && localEmbeddingPlugin) {
|
|
4383
|
+
void (async () => {
|
|
4384
|
+
try {
|
|
4385
|
+
await runtime.registerPlugin(localEmbeddingPlugin.plugin);
|
|
4386
|
+
logger.info(
|
|
4387
|
+
"[eliza] plugin-local-embedding registered (deferred — model will download on first use)",
|
|
4388
|
+
);
|
|
4389
|
+
} catch (err) {
|
|
4390
|
+
logger.warn(
|
|
4391
|
+
`[eliza] Deferred local-embedding registration failed: ${formatError(err)}`,
|
|
4392
|
+
);
|
|
4393
|
+
}
|
|
4394
|
+
})();
|
|
4395
|
+
}
|
|
4396
|
+
|
|
4346
4397
|
// 9. Graceful shutdown handler
|
|
4347
4398
|
//
|
|
4348
4399
|
// In headless mode the caller (dev-server / Electron) owns the process
|
|
@@ -4406,6 +4457,10 @@ export async function startEliza(
|
|
|
4406
4457
|
|
|
4407
4458
|
// ── Headless mode — return runtime for API server wiring ──────────────
|
|
4408
4459
|
if (opts?.headless) {
|
|
4460
|
+
// In headless mode the caller owns the process lifecycle, so the
|
|
4461
|
+
// startupKeepAlive is no longer needed — the caller's own event-loop
|
|
4462
|
+
// handles (bun --watch, Electron, etc.) keep the process alive.
|
|
4463
|
+
clearInterval(startupKeepAlive);
|
|
4409
4464
|
void loadHooksSystem();
|
|
4410
4465
|
logger.info(
|
|
4411
4466
|
"[eliza] Runtime initialised in headless mode (autonomy enabled)",
|
|
@@ -4613,7 +4668,9 @@ export async function startEliza(
|
|
|
4613
4668
|
logger.info("[eliza] Running in server-only mode (no interactive chat)");
|
|
4614
4669
|
console.log("[eliza] Server running. Press Ctrl+C to stop.");
|
|
4615
4670
|
|
|
4616
|
-
//
|
|
4671
|
+
// The startupKeepAlive already keeps the process alive. Replace it
|
|
4672
|
+
// with a permanent interval so the cleanup handler can reference it.
|
|
4673
|
+
clearInterval(startupKeepAlive);
|
|
4617
4674
|
const keepAlive = setInterval(() => {}, 1 << 30); // ~12 days
|
|
4618
4675
|
|
|
4619
4676
|
// Cleanup on exit
|
|
@@ -4634,6 +4691,9 @@ export async function startEliza(
|
|
|
4634
4691
|
}
|
|
4635
4692
|
|
|
4636
4693
|
// ── Interactive chat loop ────────────────────────────────────────────────
|
|
4694
|
+
// The readline interface and API server keep the event loop alive from
|
|
4695
|
+
// here on, so the startup guard is no longer needed.
|
|
4696
|
+
clearInterval(startupKeepAlive);
|
|
4637
4697
|
const agentName = character.name ?? "Eliza";
|
|
4638
4698
|
const userId = crypto.randomUUID() as UUID;
|
|
4639
4699
|
// Use `let` so the fallback path can reassign to fresh IDs.
|
|
@@ -4843,6 +4903,7 @@ export async function startInCloudMode(
|
|
|
4843
4903
|
if (opts?.headless || opts?.serverOnly) {
|
|
4844
4904
|
// In headless/server mode, start the API server with the cloud proxy.
|
|
4845
4905
|
// The proxy exposes the same interface the API server needs.
|
|
4906
|
+
clearInterval(startupKeepAlive);
|
|
4846
4907
|
logger.info(
|
|
4847
4908
|
`[eliza] Cloud agent connected (headless). Agent: ${proxy.agentName}`,
|
|
4848
4909
|
);
|
|
@@ -4852,6 +4913,7 @@ export async function startInCloudMode(
|
|
|
4852
4913
|
}
|
|
4853
4914
|
|
|
4854
4915
|
// Interactive CLI mode — simple chat loop against the cloud agent
|
|
4916
|
+
clearInterval(startupKeepAlive);
|
|
4855
4917
|
console.log(
|
|
4856
4918
|
`\n☁️ Connected to cloud agent "${proxy.agentName}" (${agentId})\n`,
|
|
4857
4919
|
);
|