oomi-ai 0.9.0 → 0.9.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 +1 -1
- package/bin/oomi-ai.js +3 -0
- package/lib/hermesAcp.js +12 -1
- package/lib/localAgent.js +19 -1
- package/package.json +1 -1
- package/skills/oomi/SKILL.md +1 -1
package/README.md
CHANGED
|
@@ -109,7 +109,7 @@ oomi connect --runtime hermes --name hermes --app-url https://www.oomi.ai
|
|
|
109
109
|
oomi connect --runtime command --name my-agent --command '["/absolute/path/to/adapter"]' --app-url https://www.oomi.ai
|
|
110
110
|
```
|
|
111
111
|
|
|
112
|
-
Use the user's app URL when provided. Hermes supports `--profile <profile>` and `--resume <exact-session-id>`. Without `--resume`, Oomi starts a persistent conversation with the same configured agent. Do not use `latest` or claim that an existing chat session was transferred unless its exact ID was selected. With oomi-ai 0.8.2+, an already-open Hermes conversation uses its existing local gateway owner and exact profile/session. Oomi attaches as another client; it never closes desktop, clears history, deletes a session lock, or substitutes a new chat. When no live owner exists, an Oomi-owned conversation (no `--resume`) runs on a warm `hermes acp` process with oomi-ai 0.9.0+: replies stream as they are written and stop when the person interrupts. Hermes permission requests are denied, as `chat --quiet` denies dangerous commands; ordinary file edits run as they do in quiet mode. A conversation moving from the CLI starts a new Hermes session that receives the recent Oomi history. `--resume` conversations, Hermes without ACP, and `--hermes-transport cli` use `chat --quiet --query-file -` and resume the exact returned `session_id` on subsequent turns.
|
|
112
|
+
Use the user's app URL when provided. Hermes supports `--profile <profile>` and `--resume <exact-session-id>`. Without `--resume`, Oomi starts a persistent conversation with the same configured agent. Do not use `latest` or claim that an existing chat session was transferred unless its exact ID was selected. With oomi-ai 0.8.2+, an already-open Hermes conversation uses its existing local gateway owner and exact profile/session. Oomi attaches as another client; it never closes desktop, clears history, deletes a session lock, or substitutes a new chat. When no live owner exists, an Oomi-owned conversation (no `--resume`) runs on a warm `hermes acp` process with oomi-ai 0.9.0+: replies stream as they are written and stop when the person interrupts. From 0.9.1 the bridge starts Hermes and reopens recent conversations ahead of time (at bridge start and when a call opens), so the first message doesn't wait for Hermes to start. Hermes permission requests are denied, as `chat --quiet` denies dangerous commands; ordinary file edits run as they do in quiet mode. A conversation moving from the CLI starts a new Hermes session that receives the recent Oomi history. `--resume` conversations, Hermes without ACP, and `--hermes-transport cli` use `chat --quiet --query-file -` and resume the exact returned `session_id` on subsequent turns.
|
|
113
113
|
|
|
114
114
|
Shared desktop conversations require Hermes's loopback WebSocket gateway, active-session discovery, and durable prompt/reply row IDs. Busy conversations ask you to retry after the current task. If a simultaneous desktop send queues your message without a reply receipt, or the connection drops after sending, check the same Hermes chat before resending. Oomi cannot safely repeat an uncertain action. Human approvals stay in the existing Hermes desktop UI. Shared photo submission is not yet supported; use Hermes desktop for that photo. Older or terminal-only owners without a shared gateway receive an actionable error, never a competing process. The shared owner keeps its existing environment, so use the explicit Oomi `--connection NAME` for account commands.
|
|
115
115
|
|
package/bin/oomi-ai.js
CHANGED
|
@@ -2539,6 +2539,7 @@ async function startOpenclawBridge(flags) {
|
|
|
2539
2539
|
const localRuntime = bridgeState.localAgent
|
|
2540
2540
|
? new LocalAgentRuntime({ ...bridgeState.localAgent, connection: bridgeConnectionName }, path.dirname(resolveBridgeStatePath()), (health) => updateBridgeStatus(health))
|
|
2541
2541
|
: null;
|
|
2542
|
+
localRuntime?.warm();
|
|
2542
2543
|
const gateway = localRuntime ? { gatewayUrl: 'local-agent:', configPath: resolveBridgeStatePath() } : readOpenclawGatewayConfig();
|
|
2543
2544
|
if (!localRuntime && !gateway.token && !gateway.password) {
|
|
2544
2545
|
throw new Error(`Gateway auth token/password not found in ${gateway.configPath}.`);
|
|
@@ -3600,6 +3601,8 @@ async function startOpenclawBridge(flags) {
|
|
|
3600
3601
|
const sessionId = String(payload.sessionId || '').trim();
|
|
3601
3602
|
if (!sessionId) return;
|
|
3602
3603
|
bridgeDebugLog(`[bridge] client.open ${sessionId}`);
|
|
3604
|
+
// A call is starting: make sure the agent is awake before the caller's first words.
|
|
3605
|
+
if (classifyBridgeSessionScope(sessionId) === 'voice') localRuntime?.warm();
|
|
3603
3606
|
getOrCreateGatewaySession(sessionId);
|
|
3604
3607
|
return;
|
|
3605
3608
|
}
|
package/lib/hermesAcp.js
CHANGED
|
@@ -196,7 +196,7 @@ class HermesAcpClient {
|
|
|
196
196
|
* The ACP session for a conversation in this process: the one it already has, a stored one
|
|
197
197
|
* reloaded from Hermes's history, or a new one. `created` says whether history was lost.
|
|
198
198
|
*/
|
|
199
|
-
async openSession(sessionId) {
|
|
199
|
+
async openSession(sessionId, { create = true } = {}) {
|
|
200
200
|
const cwd = this.config.cwd;
|
|
201
201
|
if (sessionId && this.loaded.has(sessionId)) return { sessionId, created: false };
|
|
202
202
|
if (sessionId) {
|
|
@@ -213,6 +213,7 @@ class HermesAcpClient {
|
|
|
213
213
|
if (err.code === 'hermes_acp_exited') throw err;
|
|
214
214
|
} finally { this.replayed.delete(sessionId); }
|
|
215
215
|
}
|
|
216
|
+
if (!create) return null;
|
|
216
217
|
const created = await this.request('session/new', { cwd, mcpServers: [] });
|
|
217
218
|
if (typeof created?.sessionId !== 'string' || !created.sessionId) throw unavailable();
|
|
218
219
|
await this.prepare(created.sessionId);
|
|
@@ -342,6 +343,16 @@ function promptBlocks(request, seed) {
|
|
|
342
343
|
return blocks;
|
|
343
344
|
}
|
|
344
345
|
|
|
346
|
+
/**
|
|
347
|
+
* Starts Hermes ahead of the first message and reopens recent conversations, so a call's first
|
|
348
|
+
* turn doesn't wait for Hermes to start (about 3.5 s on the maintainer's Mac).
|
|
349
|
+
*/
|
|
350
|
+
export async function warmHermesAcp(config, sessionIds = []) {
|
|
351
|
+
const client = hermesAcpClient(config);
|
|
352
|
+
await client.start();
|
|
353
|
+
for (const sessionId of sessionIds) await client.openSession(sessionId, { create: false }).catch(() => null);
|
|
354
|
+
}
|
|
355
|
+
|
|
345
356
|
/** One Hermes turn over ACP. Returns the reply and the ACP session that holds the conversation. */
|
|
346
357
|
export async function runHermesAcpTurn(config, request, { signal, timeoutMs = 180000, onText } = {}) {
|
|
347
358
|
const client = hermesAcpClient(config);
|
package/lib/localAgent.js
CHANGED
|
@@ -5,7 +5,7 @@ import { spawn } from 'node:child_process';
|
|
|
5
5
|
import { EventEmitter } from 'node:events';
|
|
6
6
|
import { createHash, randomUUID } from 'node:crypto';
|
|
7
7
|
import { runSharedHermesTurn, hermesRefusal } from './hermesGateway.js';
|
|
8
|
-
import { runHermesAcpTurn, hermesAcpAvailable, resetHermesAcp } from './hermesAcp.js';
|
|
8
|
+
import { runHermesAcpTurn, hermesAcpAvailable, resetHermesAcp, warmHermesAcp } from './hermesAcp.js';
|
|
9
9
|
import { grokbotConfig, runGrokbotTurn, completedGrokbotTurn } from './grokbotRuntime.js';
|
|
10
10
|
|
|
11
11
|
const IMAGE_EXTENSIONS = { 'image/jpeg': '.jpg', 'image/png': '.png', 'image/webp': '.webp', 'image/gif': '.gif' };
|
|
@@ -275,6 +275,24 @@ export class LocalAgentRuntime {
|
|
|
275
275
|
}
|
|
276
276
|
socket() { return new LocalAgentSocket(this); }
|
|
277
277
|
close() { if (this.config.runtime === 'hermes') resetHermesAcp(this.config); }
|
|
278
|
+
/** Gets Hermes ready before a message arrives: at bridge start and when a call opens. */
|
|
279
|
+
warm() {
|
|
280
|
+
if (this.config.runtime !== 'hermes' || !usesHermesAcp(this.config)) return Promise.resolve();
|
|
281
|
+
return warmHermesAcp(this.config, this.recentAcpSessions(2)).catch(() => {});
|
|
282
|
+
}
|
|
283
|
+
recentAcpSessions(limit) {
|
|
284
|
+
const directory = path.join(this.directory, 'conversations');
|
|
285
|
+
let files;
|
|
286
|
+
try { files = fs.readdirSync(directory).filter((name) => name.endsWith('.json')); } catch { return []; }
|
|
287
|
+
return files
|
|
288
|
+
.map((name) => { const file = path.join(directory, name); try { return { file, modified: fs.statSync(file).mtimeMs }; } catch { return null; } })
|
|
289
|
+
.filter(Boolean)
|
|
290
|
+
.sort((a, b) => b.modified - a.modified)
|
|
291
|
+
.map(({ file }) => readJson(file, {}))
|
|
292
|
+
.filter((state) => state.runtimeTransport === 'acp' && state.runtimeSessionId)
|
|
293
|
+
.slice(0, limit)
|
|
294
|
+
.map((state) => state.runtimeSessionId);
|
|
295
|
+
}
|
|
278
296
|
}
|
|
279
297
|
|
|
280
298
|
class LocalAgentSocket extends EventEmitter {
|
package/package.json
CHANGED
package/skills/oomi/SKILL.md
CHANGED
|
@@ -188,7 +188,7 @@ oomi connect --runtime hermes --name hermes --app-url https://www.oomi.ai
|
|
|
188
188
|
oomi connect --runtime command --name my-agent --command '["/absolute/path/to/adapter"]' --app-url https://www.oomi.ai
|
|
189
189
|
```
|
|
190
190
|
|
|
191
|
-
Use the user's app URL when provided. Hermes supports `--profile <profile>` and `--resume <exact-session-id>`. Without `--resume`, Oomi starts a persistent conversation with the same configured agent. Do not use `latest` or claim that an existing chat session was transferred unless its exact ID was selected. With oomi-ai 0.8.2+, an already-open Hermes conversation uses its existing local gateway owner and exact profile/session. Oomi attaches as another client; it never closes desktop, clears history, deletes a session lock, or substitutes a new chat. When no live owner exists, an Oomi-owned conversation (no `--resume`) runs on a warm `hermes acp` process with oomi-ai 0.9.0+: replies stream as they are written and stop when the person interrupts. Hermes permission requests are denied, as `chat --quiet` denies dangerous commands; ordinary file edits run as they do in quiet mode. A conversation moving from the CLI starts a new Hermes session that receives the recent Oomi history. `--resume` conversations, Hermes without ACP, and `--hermes-transport cli` use `chat --quiet --query-file -` and resume the exact returned `session_id` on subsequent turns.
|
|
191
|
+
Use the user's app URL when provided. Hermes supports `--profile <profile>` and `--resume <exact-session-id>`. Without `--resume`, Oomi starts a persistent conversation with the same configured agent. Do not use `latest` or claim that an existing chat session was transferred unless its exact ID was selected. With oomi-ai 0.8.2+, an already-open Hermes conversation uses its existing local gateway owner and exact profile/session. Oomi attaches as another client; it never closes desktop, clears history, deletes a session lock, or substitutes a new chat. When no live owner exists, an Oomi-owned conversation (no `--resume`) runs on a warm `hermes acp` process with oomi-ai 0.9.0+: replies stream as they are written and stop when the person interrupts. From 0.9.1 the bridge starts Hermes and reopens recent conversations ahead of time (at bridge start and when a call opens), so the first message doesn't wait for Hermes to start. Hermes permission requests are denied, as `chat --quiet` denies dangerous commands; ordinary file edits run as they do in quiet mode. A conversation moving from the CLI starts a new Hermes session that receives the recent Oomi history. `--resume` conversations, Hermes without ACP, and `--hermes-transport cli` use `chat --quiet --query-file -` and resume the exact returned `session_id` on subsequent turns.
|
|
192
192
|
|
|
193
193
|
Shared desktop conversations require Hermes's loopback WebSocket gateway, active-session discovery, and durable prompt/reply row IDs. Busy conversations ask you to retry after the current task. If a simultaneous desktop send queues your message without a reply receipt, or the connection drops after sending, check the same Hermes chat before resending. Oomi cannot safely repeat an uncertain action. Human approvals stay in the existing Hermes desktop UI. Shared photo submission is not yet supported; use Hermes desktop for that photo. Older or terminal-only owners without a shared gateway receive an actionable error, never a competing process. The shared owner keeps its existing environment, so use the explicit Oomi `--connection NAME` for account commands.
|
|
194
194
|
|