@mnemom/mnemom 0.17.0-next.7 → 0.17.0-next.9
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 +26 -0
- package/dist/commands/agent-config.d.ts +12 -0
- package/dist/commands/agent-config.js +22 -2
- package/dist/commands/agent-session.d.ts +26 -10
- package/dist/commands/agent-session.js +59 -23
- package/dist/commands/agent-sessions.d.ts +99 -0
- package/dist/commands/agent-sessions.js +271 -0
- package/dist/commands/agent.d.ts +55 -0
- package/dist/commands/agent.js +123 -13
- package/dist/commands/validate.js +1 -16
- package/dist/index.js +47 -5
- package/dist/lib/agent-ledger.d.ts +91 -0
- package/dist/lib/agent-ledger.js +126 -0
- package/dist/lib/agent.d.ts +43 -1
- package/dist/lib/agent.js +80 -1
- package/dist/lib/api.d.ts +62 -0
- package/dist/lib/api.js +11 -0
- package/dist/lib/auth.js +21 -1
- package/dist/lib/format.d.ts +6 -0
- package/dist/lib/format.js +20 -0
- package/dist/lib/launcher-config.d.ts +3 -1
- package/dist/lib/launcher-config.js +20 -1
- package/dist/lib/oauth.d.ts +26 -4
- package/dist/lib/oauth.js +98 -29
- package/dist/rc-proxy.mjs +14 -4
- package/package.json +7 -3
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
* resolvers in lib/code.ts keep the built-in default as the final fallback);
|
|
16
16
|
* the caller folds the plain-value settings under the CLI flags.
|
|
17
17
|
*/
|
|
18
|
-
import { type LaunchShape } from "./agent.js";
|
|
18
|
+
import { type GoalModeDefault, type LaunchShape } from "./agent.js";
|
|
19
19
|
/** The human-editable settings file. Secret key lives elsewhere (launcher.json). */
|
|
20
20
|
export declare const LAUNCHER_CONFIG_PATH: string;
|
|
21
21
|
/** Where the CLI resolves the Anthropic key from; advisory ordering/restriction. */
|
|
@@ -29,6 +29,8 @@ export interface LauncherConfig {
|
|
|
29
29
|
cli?: string;
|
|
30
30
|
launch?: LaunchShape;
|
|
31
31
|
keySource?: KeySource;
|
|
32
|
+
/** Standing goal-alignment default when neither --goal nor --implicit is given. */
|
|
33
|
+
goalMode?: GoalModeDefault;
|
|
32
34
|
guardrails?: {
|
|
33
35
|
maxTurns?: number;
|
|
34
36
|
budgetUsd?: number;
|
|
@@ -19,12 +19,13 @@ import { existsSync, mkdirSync, readFileSync, renameSync, writeFileSync } from "
|
|
|
19
19
|
import { dirname, join } from "node:path";
|
|
20
20
|
import { parse as parseToml, stringify as stringifyToml, TomlError } from "smol-toml";
|
|
21
21
|
import { MNEMOM_DIR } from "./config.js";
|
|
22
|
-
import { isPositiveInt, isPositiveNumber } from "./agent.js";
|
|
22
|
+
import { isPositiveInt, isPositiveNumber, } from "./agent.js";
|
|
23
23
|
/** The human-editable settings file. Secret key lives elsewhere (launcher.json). */
|
|
24
24
|
export const LAUNCHER_CONFIG_PATH = join(MNEMOM_DIR, "launcher.toml");
|
|
25
25
|
const LAUNCH_SHAPES = ["terminal", "remote-control", "server"];
|
|
26
26
|
const EFFORTS = ["low", "medium", "high", "xhigh", "max"];
|
|
27
27
|
const KEY_SOURCES = ["env", "store", "prompt"];
|
|
28
|
+
const GOAL_MODES = ["implicit", "off"];
|
|
28
29
|
function coerceLaunch(raw) {
|
|
29
30
|
const v = raw.trim();
|
|
30
31
|
if (LAUNCH_SHAPES.includes(v))
|
|
@@ -43,6 +44,12 @@ function coerceKeySource(raw) {
|
|
|
43
44
|
return v;
|
|
44
45
|
throw new Error(`key_source must be one of ${KEY_SOURCES.join(", ")} (got '${raw}').`);
|
|
45
46
|
}
|
|
47
|
+
function coerceGoalMode(raw) {
|
|
48
|
+
const v = raw.trim().toLowerCase();
|
|
49
|
+
if (GOAL_MODES.includes(v))
|
|
50
|
+
return v;
|
|
51
|
+
throw new Error(`goal_mode must be one of ${GOAL_MODES.join(", ")} (got '${raw}'). A sealed contract needs a statement, so it is always a per-launch --goal.`);
|
|
52
|
+
}
|
|
46
53
|
function coerceNonEmpty(name, raw) {
|
|
47
54
|
const v = raw.trim();
|
|
48
55
|
if (!v)
|
|
@@ -112,6 +119,14 @@ export const CONFIG_KEYS = [
|
|
|
112
119
|
c.keySource = coerceKeySource(v);
|
|
113
120
|
},
|
|
114
121
|
},
|
|
122
|
+
{
|
|
123
|
+
key: "goal_mode",
|
|
124
|
+
describe: `Goal alignment when no --goal/--implicit is given (${GOAL_MODES.join("|")}); a sealed contract needs a per-launch --goal`,
|
|
125
|
+
get: (c) => c.goalMode,
|
|
126
|
+
set: (c, v) => {
|
|
127
|
+
c.goalMode = coerceGoalMode(v);
|
|
128
|
+
},
|
|
129
|
+
},
|
|
115
130
|
{
|
|
116
131
|
key: "guardrails.max_turns",
|
|
117
132
|
describe: "Contract guardrail: turn ceiling (positive integer)",
|
|
@@ -176,6 +191,8 @@ export function parseLauncherConfig(text) {
|
|
|
176
191
|
cfg.launch = coerceLaunch(str(raw.launch) ?? "");
|
|
177
192
|
if (raw.key_source !== undefined)
|
|
178
193
|
cfg.keySource = coerceKeySource(str(raw.key_source) ?? "");
|
|
194
|
+
if (raw.goal_mode !== undefined)
|
|
195
|
+
cfg.goalMode = coerceGoalMode(str(raw.goal_mode) ?? "");
|
|
179
196
|
const g = raw.guardrails;
|
|
180
197
|
if (g !== undefined) {
|
|
181
198
|
if (typeof g !== "object" || g === null || Array.isArray(g)) {
|
|
@@ -232,6 +249,8 @@ export function serializeLauncherConfig(cfg) {
|
|
|
232
249
|
doc.launch = cfg.launch;
|
|
233
250
|
if (cfg.keySource !== undefined)
|
|
234
251
|
doc.key_source = cfg.keySource;
|
|
252
|
+
if (cfg.goalMode !== undefined)
|
|
253
|
+
doc.goal_mode = cfg.goalMode;
|
|
235
254
|
const g = cfg.guardrails;
|
|
236
255
|
if (g && (g.maxTurns !== undefined || g.budgetUsd !== undefined || g.stallTurns !== undefined)) {
|
|
237
256
|
const gr = {};
|
package/dist/lib/oauth.d.ts
CHANGED
|
@@ -105,11 +105,33 @@ export declare function loginWithDevice(opts?: {
|
|
|
105
105
|
sleep?: (ms: number) => Promise<void>;
|
|
106
106
|
}): Promise<DeviceResult>;
|
|
107
107
|
/**
|
|
108
|
-
* Exchange a refresh token for a fresh access token.
|
|
109
|
-
*
|
|
110
|
-
*
|
|
108
|
+
* Exchange a refresh token for a fresh access token.
|
|
109
|
+
*
|
|
110
|
+
* Failure classification (R6 / MNE-7394) — a transient failure must never be
|
|
111
|
+
* indistinguishable from a revoked credential:
|
|
112
|
+
* - 2xx → return the fresh tokens (carrying the prior refresh token forward
|
|
113
|
+
* per RFC 6749 §6 when the AS omits a new one).
|
|
114
|
+
* - A 4xx whose OAuth body `error` is `invalid_grant` / `invalid_client` →
|
|
115
|
+
* return `null`, the re-login signal. RFC 6749 §5.2 defines these as the
|
|
116
|
+
* errors that mean the presented grant/client credential is genuinely no
|
|
117
|
+
* longer valid, so a fresh login is the correct remedy. No retry.
|
|
118
|
+
* - Any other 4xx (e.g. `invalid_request`, `429`, an unrecognized/absent body
|
|
119
|
+
* error, a non-JSON body) → throw. Something is wrong, but it does NOT mean
|
|
120
|
+
* the credentials are revoked, so we must not discard the session.
|
|
121
|
+
* - `res.status >= 500` or a fetch/network exception → retry with bounded
|
|
122
|
+
* exponential backoff (~1s/2s/4s, REFRESH_MAX_ATTEMPTS attempts); if the
|
|
123
|
+
* retries are exhausted, throw. Exhausting transient retries must NOT
|
|
124
|
+
* masquerade as "credentials revoked" (fail-closed, MNE-442) — throwing
|
|
125
|
+
* preserves the stored session so a later invocation can succeed once the
|
|
126
|
+
* AS recovers.
|
|
127
|
+
*
|
|
128
|
+
* `null` is therefore narrowed to exactly the two re-login errors; every other
|
|
129
|
+
* outcome is a success, a retry, or a thrown error. `opts.sleep` is injectable
|
|
130
|
+
* so tests drive the backoff without real timers.
|
|
111
131
|
*/
|
|
112
|
-
export declare function refreshTokens(refreshToken: string, clientId: string
|
|
132
|
+
export declare function refreshTokens(refreshToken: string, clientId: string, opts?: {
|
|
133
|
+
sleep?: (ms: number) => Promise<void>;
|
|
134
|
+
}): Promise<OAuthTokens | null>;
|
|
113
135
|
/**
|
|
114
136
|
* Open `url` in the user's default browser WITHOUT a shell. The URL is always
|
|
115
137
|
* passed as a separate argv element (never concatenated into a command string),
|
package/dist/lib/oauth.js
CHANGED
|
@@ -39,6 +39,14 @@ const LOOPBACK_TIMEOUT_MS = 5 * 60 * 1000;
|
|
|
39
39
|
// both interactive login poll loops emit, so a multi-minute browser sign-in
|
|
40
40
|
// doesn't read as a hung CLI (matches the card-write retry tick in try-me).
|
|
41
41
|
const LOGIN_HEARTBEAT_MS = 15 * 1000;
|
|
42
|
+
// Refresh-token retry policy (R6 / MNE-7394). A transient AS 5xx or a dropped
|
|
43
|
+
// network connection during refresh must be retried with bounded exponential
|
|
44
|
+
// backoff rather than collapsed into the re-login signal — a one-second AS
|
|
45
|
+
// hiccup or a flaky Wi-Fi moment must not invalidate a valid, long-lived
|
|
46
|
+
// session. Per-attempt delay is REFRESH_BACKOFF_BASE_MS * 2**attemptIndex →
|
|
47
|
+
// ~1s / 2s / 4s across REFRESH_MAX_ATTEMPTS attempts.
|
|
48
|
+
const REFRESH_MAX_ATTEMPTS = 3;
|
|
49
|
+
const REFRESH_BACKOFF_BASE_MS = 1000;
|
|
42
50
|
let cachedMetadata = null;
|
|
43
51
|
/**
|
|
44
52
|
* Fetch (and process-cache) the AS metadata document. We resolve it relative to
|
|
@@ -359,40 +367,101 @@ async function pollDeviceToken(meta, clientId, authz, sleep, display) {
|
|
|
359
367
|
// Refresh (RFC 6749 §6)
|
|
360
368
|
// ============================================================================
|
|
361
369
|
/**
|
|
362
|
-
* Exchange a refresh token for a fresh access token.
|
|
363
|
-
*
|
|
364
|
-
*
|
|
370
|
+
* Exchange a refresh token for a fresh access token.
|
|
371
|
+
*
|
|
372
|
+
* Failure classification (R6 / MNE-7394) — a transient failure must never be
|
|
373
|
+
* indistinguishable from a revoked credential:
|
|
374
|
+
* - 2xx → return the fresh tokens (carrying the prior refresh token forward
|
|
375
|
+
* per RFC 6749 §6 when the AS omits a new one).
|
|
376
|
+
* - A 4xx whose OAuth body `error` is `invalid_grant` / `invalid_client` →
|
|
377
|
+
* return `null`, the re-login signal. RFC 6749 §5.2 defines these as the
|
|
378
|
+
* errors that mean the presented grant/client credential is genuinely no
|
|
379
|
+
* longer valid, so a fresh login is the correct remedy. No retry.
|
|
380
|
+
* - Any other 4xx (e.g. `invalid_request`, `429`, an unrecognized/absent body
|
|
381
|
+
* error, a non-JSON body) → throw. Something is wrong, but it does NOT mean
|
|
382
|
+
* the credentials are revoked, so we must not discard the session.
|
|
383
|
+
* - `res.status >= 500` or a fetch/network exception → retry with bounded
|
|
384
|
+
* exponential backoff (~1s/2s/4s, REFRESH_MAX_ATTEMPTS attempts); if the
|
|
385
|
+
* retries are exhausted, throw. Exhausting transient retries must NOT
|
|
386
|
+
* masquerade as "credentials revoked" (fail-closed, MNE-442) — throwing
|
|
387
|
+
* preserves the stored session so a later invocation can succeed once the
|
|
388
|
+
* AS recovers.
|
|
389
|
+
*
|
|
390
|
+
* `null` is therefore narrowed to exactly the two re-login errors; every other
|
|
391
|
+
* outcome is a success, a retry, or a thrown error. `opts.sleep` is injectable
|
|
392
|
+
* so tests drive the backoff without real timers.
|
|
365
393
|
*/
|
|
366
|
-
export async function refreshTokens(refreshToken, clientId) {
|
|
394
|
+
export async function refreshTokens(refreshToken, clientId, opts) {
|
|
367
395
|
if (!refreshToken || !clientId)
|
|
368
396
|
return null;
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
397
|
+
const sleep = opts?.sleep ?? defaultSleep;
|
|
398
|
+
// Discovery is not part of the refresh retry budget; a discovery failure
|
|
399
|
+
// propagates as it does today (it is already thrown by discover()).
|
|
400
|
+
const meta = await discover();
|
|
401
|
+
let lastTransient = "";
|
|
402
|
+
for (let attempt = 0; attempt < REFRESH_MAX_ATTEMPTS; attempt++) {
|
|
403
|
+
let res;
|
|
404
|
+
try {
|
|
405
|
+
res = await fetch(meta.token_endpoint, {
|
|
406
|
+
method: "POST",
|
|
407
|
+
headers: {
|
|
408
|
+
"Content-Type": "application/x-www-form-urlencoded",
|
|
409
|
+
Accept: "application/json",
|
|
410
|
+
},
|
|
411
|
+
body: new URLSearchParams({
|
|
412
|
+
grant_type: "refresh_token",
|
|
413
|
+
refresh_token: refreshToken,
|
|
414
|
+
client_id: clientId,
|
|
415
|
+
}),
|
|
416
|
+
});
|
|
417
|
+
}
|
|
418
|
+
catch (err) {
|
|
419
|
+
// Network/fetch exception (DNS failure, connection reset, timeout) — this
|
|
420
|
+
// is unrelated to the validity of the refresh token, so retry it.
|
|
421
|
+
lastTransient = err instanceof Error ? err.message : String(err);
|
|
422
|
+
if (attempt < REFRESH_MAX_ATTEMPTS - 1) {
|
|
423
|
+
await sleep(REFRESH_BACKOFF_BASE_MS * 2 ** attempt);
|
|
424
|
+
continue;
|
|
425
|
+
}
|
|
426
|
+
break;
|
|
427
|
+
}
|
|
428
|
+
if (res.ok) {
|
|
429
|
+
const data = (await res.json());
|
|
430
|
+
const tokens = tokensFromResponse(data);
|
|
431
|
+
// Per RFC 6749 §6, a refresh response MAY omit a new refresh token, in
|
|
432
|
+
// which case the old one remains valid — preserve it so the next refresh
|
|
433
|
+
// works.
|
|
434
|
+
if (!tokens.refreshToken)
|
|
435
|
+
tokens.refreshToken = refreshToken;
|
|
436
|
+
return tokens;
|
|
437
|
+
}
|
|
438
|
+
if (res.status >= 500) {
|
|
439
|
+
// Transient AS outage — retry with backoff, then fall through to the
|
|
440
|
+
// "exhausted" throw once no attempts remain.
|
|
441
|
+
lastTransient = `HTTP ${res.status}`;
|
|
442
|
+
if (attempt < REFRESH_MAX_ATTEMPTS - 1) {
|
|
443
|
+
await sleep(REFRESH_BACKOFF_BASE_MS * 2 ** attempt);
|
|
444
|
+
continue;
|
|
445
|
+
}
|
|
446
|
+
break;
|
|
447
|
+
}
|
|
448
|
+
// 4xx — a definitive client-side rejection, never retried. Only
|
|
449
|
+
// invalid_grant / invalid_client map to the null re-login signal; every
|
|
450
|
+
// other 4xx surfaces as a thrown error rather than a silent null that would
|
|
451
|
+
// wrongly discard a valid session.
|
|
452
|
+
const body = (await res.json().catch(() => ({})));
|
|
453
|
+
if (body.error === "invalid_grant" || body.error === "invalid_client") {
|
|
384
454
|
return null;
|
|
385
|
-
|
|
386
|
-
const
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
tokens.refreshToken = refreshToken;
|
|
391
|
-
return tokens;
|
|
392
|
-
}
|
|
393
|
-
catch {
|
|
394
|
-
return null;
|
|
455
|
+
}
|
|
456
|
+
const detail = body.error
|
|
457
|
+
? body.error + (body.error_description ? ` — ${body.error_description}` : "")
|
|
458
|
+
: `HTTP ${res.status}`;
|
|
459
|
+
throw new Error(`Token refresh failed: ${detail}`);
|
|
395
460
|
}
|
|
461
|
+
// Retries exhausted on a 5xx or a network exception (fail-closed, MNE-442):
|
|
462
|
+
// throw rather than return null so the session is preserved for a later retry.
|
|
463
|
+
throw new Error(`Token refresh failed after ${REFRESH_MAX_ATTEMPTS} attempts ` +
|
|
464
|
+
`(last error: ${lastTransient || "unknown transient failure"}).`);
|
|
396
465
|
}
|
|
397
466
|
// ============================================================================
|
|
398
467
|
// Helpers
|
package/dist/rc-proxy.mjs
CHANGED
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
// * Inside api.anthropic.com, only `POST /v1/messages[?…]` is rewritten to the Mnemom
|
|
20
20
|
// gateway door: the real Anthropic key rides as `x-api-key` (API-key billing), plus
|
|
21
21
|
// `x-mnemom-agent`, `x-mnemom-conversation-id`, and optionally `x-mnemom-api-key`,
|
|
22
|
-
// `x-mnemom-provider`, `x-mnemom-egress-key`, `x-mnemom-contract` — the exact header set
|
|
22
|
+
// `x-mnemom-provider`, `x-mnemom-egress-key`, `x-mnemom-contract` / `x-mnemom-goal-mode` — the exact header set
|
|
23
23
|
// the non-RC launch sends via ANTHROPIC_CUSTOM_HEADERS. The OAuth `authorization` bearer
|
|
24
24
|
// is STRIPPED on that leg (it never leaves the machine) and `oauth-*` tokens are removed
|
|
25
25
|
// from `anthropic-beta`. Everything else under api.anthropic.com (OAuth refresh, the
|
|
@@ -62,6 +62,8 @@
|
|
|
62
62
|
// MNEMOM_AGENT_RC_AGENT x-mnemom-agent value (required)
|
|
63
63
|
// MNEMOM_AGENT_RC_CONVERSATION_ID x-mnemom-conversation-id value (required)
|
|
64
64
|
// MNEMOM_AGENT_RC_CONTRACT_B64 base64 contract for x-mnemom-contract (optional)
|
|
65
|
+
// MNEMOM_AGENT_RC_GOAL_MODE x-mnemom-goal-mode value (optional; `--implicit` — no contract,
|
|
66
|
+
// the gateway infers the goal from the user's messages)
|
|
65
67
|
// MNEMOM_AGENT_RC_PROVIDER x-mnemom-provider directive JSON (optional; router door)
|
|
66
68
|
// MNEMOM_AGENT_RC_THREAD_MODE `reject` (default: answer thread-bearing requests locally,
|
|
67
69
|
// see above) | `strip` (legacy: delete `thread`, forward)
|
|
@@ -98,6 +100,7 @@ const AGENT = env.MNEMOM_AGENT_RC_AGENT || die("MNEMOM_AGENT_RC_AGENT is require
|
|
|
98
100
|
const CONV =
|
|
99
101
|
env.MNEMOM_AGENT_RC_CONVERSATION_ID || die("MNEMOM_AGENT_RC_CONVERSATION_ID is required");
|
|
100
102
|
const CONTRACT_B64 = env.MNEMOM_AGENT_RC_CONTRACT_B64 || "";
|
|
103
|
+
const GOAL_MODE = env.MNEMOM_AGENT_RC_GOAL_MODE || "";
|
|
101
104
|
const PROVIDER = env.MNEMOM_AGENT_RC_PROVIDER || "";
|
|
102
105
|
const THREAD_MODE = env.MNEMOM_AGENT_RC_THREAD_MODE || "reject";
|
|
103
106
|
if (THREAD_MODE !== "reject" && THREAD_MODE !== "strip")
|
|
@@ -107,7 +110,9 @@ const PARENT = Number(env.MNEMOM_AGENT_RC_PARENT_PID || 0);
|
|
|
107
110
|
const PORT = Number(env.MNEMOM_AGENT_RC_PORT || 0);
|
|
108
111
|
|
|
109
112
|
const log = (line) => {
|
|
110
|
-
|
|
113
|
+
// One record per line: gateway header values and error bodies are spliced into log lines, so a
|
|
114
|
+
// CR/LF inside them must not fabricate extra records (log injection).
|
|
115
|
+
const s = `${new Date().toISOString()} ${String(line).replace(/[\r\n]+/g, " ")}\n`;
|
|
111
116
|
if (LOGFILE) {
|
|
112
117
|
try {
|
|
113
118
|
fs.appendFileSync(LOGFILE, s);
|
|
@@ -345,6 +350,7 @@ function handle(req, res, viaPlain) {
|
|
|
345
350
|
if (PROVIDER) headers["x-mnemom-provider"] = PROVIDER;
|
|
346
351
|
if (secrets.openai) headers["x-mnemom-egress-key"] = secrets.openai;
|
|
347
352
|
if (CONTRACT_B64) headers["x-mnemom-contract"] = CONTRACT_B64;
|
|
353
|
+
if (GOAL_MODE) headers["x-mnemom-goal-mode"] = GOAL_MODE;
|
|
348
354
|
if (headers["anthropic-beta"]) {
|
|
349
355
|
// drop the OAuth-only beta tokens
|
|
350
356
|
const b = String(headers["anthropic-beta"])
|
|
@@ -388,8 +394,12 @@ function handle(req, res, viaPlain) {
|
|
|
388
394
|
});
|
|
389
395
|
}
|
|
390
396
|
ur.pipe(res);
|
|
397
|
+
const goalRev = ur.headers["x-mnemom-goal-revision"];
|
|
398
|
+
const steer = ur.headers["x-mnemom-goal-steer"];
|
|
391
399
|
const ident = toGateway
|
|
392
|
-
? ` agent=${ur.headers["x-mnemom-agent"] || "-"} verdict=${ur.headers["x-mnemom-goal-verdict"] || "-"}`
|
|
400
|
+
? ` agent=${ur.headers["x-mnemom-agent"] || "-"} verdict=${ur.headers["x-mnemom-goal-verdict"] || "-"}` +
|
|
401
|
+
(goalRev ? ` goal-rev=${goalRev}` : "") +
|
|
402
|
+
(steer ? ` steer=${steer}` : "")
|
|
393
403
|
: "";
|
|
394
404
|
ur.on("end", () => {
|
|
395
405
|
let bodyNote = "";
|
|
@@ -488,7 +498,7 @@ proxy.on("clientError", (e, sock) => {
|
|
|
488
498
|
proxy.listen(PORT, "127.0.0.1", () => {
|
|
489
499
|
const { port } = proxy.address();
|
|
490
500
|
log(
|
|
491
|
-
`listening 127.0.0.1:${port} agent=${AGENT} conv=${CONV} door=${GATEWAY.href} contract=${CONTRACT_B64 ? "yes" : "no"} provider=${PROVIDER || "-"} thread=${THREAD_MODE}`,
|
|
501
|
+
`listening 127.0.0.1:${port} agent=${AGENT} conv=${CONV} door=${GATEWAY.href} contract=${CONTRACT_B64 ? "yes" : "no"} goal_mode=${GOAL_MODE || "-"} provider=${PROVIDER || "-"} thread=${THREAD_MODE}`,
|
|
492
502
|
);
|
|
493
503
|
process.stdout.write(`READY ${port} ${p("ca.pem")}\n`);
|
|
494
504
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mnemom/mnemom",
|
|
3
|
-
"version": "0.17.0-next.
|
|
3
|
+
"version": "0.17.0-next.9",
|
|
4
4
|
"description": "Transparent AI agent tracing",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -26,10 +26,10 @@
|
|
|
26
26
|
"devDependencies": {
|
|
27
27
|
"@types/js-yaml": "^4.0.9",
|
|
28
28
|
"@types/node": "^20.10.0",
|
|
29
|
-
"@vitest/coverage-v8": "^4.1.
|
|
29
|
+
"@vitest/coverage-v8": "^4.1.11",
|
|
30
30
|
"tsx": "^4.23.1",
|
|
31
31
|
"typescript": "^6.0.3",
|
|
32
|
-
"vitest": "^4.1.
|
|
32
|
+
"vitest": "^4.1.11"
|
|
33
33
|
},
|
|
34
34
|
"files": [
|
|
35
35
|
"dist",
|
|
@@ -65,5 +65,9 @@
|
|
|
65
65
|
},
|
|
66
66
|
"engines": {
|
|
67
67
|
"node": ">=18.0.0"
|
|
68
|
+
},
|
|
69
|
+
"overrides": {
|
|
70
|
+
"@vitest/mocker": "^4.1.11",
|
|
71
|
+
"nanoid": "^3.3.18"
|
|
68
72
|
}
|
|
69
73
|
}
|