negotium 0.2.10 → 0.2.12
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/agent-helpers.js +335 -92
- package/dist/agent-helpers.js.map +8 -6
- package/dist/background-bash.js +2 -2
- package/dist/background-bash.js.map +2 -2
- package/dist/browser-runtime.js +2 -2
- package/dist/browser-runtime.js.map +2 -2
- package/dist/{chunk-dcfmsrnb.js → chunk-8asy22vc.js} +2 -2
- package/dist/{chunk-dcfmsrnb.js.map → chunk-8asy22vc.js.map} +2 -2
- package/dist/hosted-agent.js +3 -3
- package/dist/hosted-agent.js.map +3 -3
- package/dist/main.js +3 -3
- package/dist/main.js.map +3 -3
- package/dist/mcp-factories.js +3 -3
- package/dist/mcp-factories.js.map +3 -3
- package/dist/prompts.js +2 -2
- package/dist/prompts.js.map +2 -2
- package/dist/query-runtime.js +2 -2
- package/dist/query-runtime.js.map +2 -2
- package/dist/registry.js +3 -3
- package/dist/registry.js.map +2 -2
- package/dist/rollout.js +1 -1
- package/dist/runtime/src/agents/public-helpers.ts +4 -0
- package/dist/runtime/src/platform/config.ts +1 -1
- package/dist/runtime/src/version.ts +1 -1
- package/dist/runtime-helpers.js +2 -2
- package/dist/runtime-helpers.js.map +2 -2
- package/dist/types/packages/core/src/agents/mcp-tools/inline-assets.d.ts +24 -0
- package/dist/types/packages/core/src/agents/mcp-tools/publish-html.d.ts +18 -0
- package/dist/types/packages/core/src/agents/public-helpers.d.ts +1 -0
- package/dist/types/packages/core/src/platform/config.d.ts +1 -1
- package/dist/types/packages/core/src/version.d.ts +1 -1
- package/dist/vault.js +2 -2
- package/dist/vault.js.map +2 -2
- package/install-browser-rs.mjs +3 -3
- package/package.json +1 -1
package/dist/agent-helpers.js
CHANGED
|
@@ -331,7 +331,7 @@ function resolveDefaultModel(agent, registryDefaultModel) {
|
|
|
331
331
|
function codexAuthFilePath() {
|
|
332
332
|
return process.env.NEGOTIUM_CODEX_AUTH_FILE || join(process.env.CODEX_HOME || join(homedir(), ".codex"), "auth.json");
|
|
333
333
|
}
|
|
334
|
-
var HOME, PROJECT_ROOT, STATE_DIR_ENV, STATE_DIR, WORKSPACE_DIR, TOPIC_WORKSPACE_DIR, SHARED_WIKI_DIR, CRON_WORKSPACE_DIR, BROWSER_DIR, BROWSER_PROFILES_DIR, BINARIES_DIR, SECRETS_DIR, DM_WORKSPACE_DIR, SESSION_WORKSPACE_DIR, CLAUDE_EXECUTABLE_ENV, CLAUDE_EXECUTABLE, DEFAULT_OUTPUT_LANGUAGE = "English", BROWSER_RS_VERSION = "v0.1.
|
|
334
|
+
var HOME, PROJECT_ROOT, STATE_DIR_ENV, STATE_DIR, WORKSPACE_DIR, TOPIC_WORKSPACE_DIR, SHARED_WIKI_DIR, CRON_WORKSPACE_DIR, BROWSER_DIR, BROWSER_PROFILES_DIR, BINARIES_DIR, SECRETS_DIR, DM_WORKSPACE_DIR, SESSION_WORKSPACE_DIR, CLAUDE_EXECUTABLE_ENV, CLAUDE_EXECUTABLE, DEFAULT_OUTPUT_LANGUAGE = "English", BROWSER_RS_VERSION = "v0.1.19", BROWSER_RS_MIN_SECURE_VERSION = "0.1.15", SNIPPETS_API_URL, BROWSER_RS_BIN, PLAYWRIGHT_MCP_BIN, TSX_BIN, TSX_LOADER, TSCONFIG_PATH, SESSION_COMM_SERVER, TASK_SERVER, BROWSER_MCP_SSE_PROXY_SERVER, CANONICAL_MCP_PROXY_SERVER, WIKI_SERVER, TOKEN_STATS_SERVER, COMPACTION_LOG_SERVER, SYSTEM_HEALTH_SERVER, AGENT_HEALTH_SERVER, BACKGROUND_BASH_SERVER, VAULT_SERVER, BG_BASH_BASE_PORT, BG_BASH_MAX_PORT, RUNTIME_MCP_SECRET, NODE_CONTROL_TOKEN, VAULT_MASTER_KEY, NEGOTIUM_PORT, hostname, DATA_DIR, LOG_DIR, UPLOADS_DIR, VAULT_DIR, SESSIONS_DB, DEBUG_FILE, USERS_LOG_DIR, RUN_DIR, PROGRESS_DIR, DM_CMD_DIR, DM_RESP_DIR, SESSION_INBOX_DIR, SESSION_ASKS_DIR, PLAYWRIGHT_BASE_PORT, PLAYWRIGHT_MAX_PORT, PLAYWRIGHT_PORTS_DIR, ACTIVE_QUERY_STALE_MS, AGENTS_PROMPTS_DIR, RESOURCES_DIR, FILE_TAG_REGEX, MODEL_SONNET = "claude-sonnet-5", MODEL_OPUS = "claude-opus-5", MODEL_FABLE = "claude-fable-5", FALLBACK_AGENT, SESSION_AGENT, GATEWAY_AGENT, FALLBACK_MODEL, SESSION_MODEL, GATEWAY_MODEL, FFMPEG_BIN, FFPROBE_BIN, PYTHON_BIN, FASTER_WHISPER_WRAPPER, WHISPER_MODEL, TESSERACT_BIN, PDFTOTEXT_BIN, _envMaxTellDepth, MAX_TELL_DEPTH;
|
|
335
335
|
var init_config = __esm(() => {
|
|
336
336
|
init_config_helpers();
|
|
337
337
|
init_logger();
|
|
@@ -2148,7 +2148,7 @@ var init_claude_registry = __esm(() => {
|
|
|
2148
2148
|
});
|
|
2149
2149
|
|
|
2150
2150
|
// ../../packages/core/src/version.ts
|
|
2151
|
-
var NEGOTIUM_VERSION = "0.2.
|
|
2151
|
+
var NEGOTIUM_VERSION = "0.2.12";
|
|
2152
2152
|
|
|
2153
2153
|
// ../../packages/core/src/agents/codex-native-multi-agent.ts
|
|
2154
2154
|
import { spawn as spawn2 } from "child_process";
|
|
@@ -10228,7 +10228,7 @@ var init_manager_utils = () => {};
|
|
|
10228
10228
|
import { execFileSync as execFileSync6 } from "child_process";
|
|
10229
10229
|
import { readdirSync as readdirSync3, unlinkSync as unlinkSync10 } from "fs";
|
|
10230
10230
|
import { createServer } from "net";
|
|
10231
|
-
import { resolve as
|
|
10231
|
+
import { resolve as resolve12, sep } from "path";
|
|
10232
10232
|
function isPortInUse(port) {
|
|
10233
10233
|
return new Promise((resolveProbe) => {
|
|
10234
10234
|
const server = createServer();
|
|
@@ -10261,8 +10261,8 @@ async function reserveAvailableLoopbackPort(minPort, maxPort, reservedPorts, pro
|
|
|
10261
10261
|
return null;
|
|
10262
10262
|
}
|
|
10263
10263
|
function killBrowserProcsForUserDataDir(userDataDir) {
|
|
10264
|
-
const target =
|
|
10265
|
-
const profileRoot =
|
|
10264
|
+
const target = resolve12(userDataDir);
|
|
10265
|
+
const profileRoot = resolve12(BROWSER_PROFILES_DIR);
|
|
10266
10266
|
if (target !== profileRoot && !target.startsWith(`${profileRoot}${sep}`))
|
|
10267
10267
|
return;
|
|
10268
10268
|
let pids;
|
|
@@ -10283,7 +10283,7 @@ function killBrowserProcsForUserDataDir(userDataDir) {
|
|
|
10283
10283
|
stdio: "pipe"
|
|
10284
10284
|
}).toString().trim();
|
|
10285
10285
|
const argDir = extractUserDataDirArg(cmdline);
|
|
10286
|
-
if (!argDir ||
|
|
10286
|
+
if (!argDir || resolve12(argDir) !== target)
|
|
10287
10287
|
continue;
|
|
10288
10288
|
killProcessTreeChildren(pidNum);
|
|
10289
10289
|
process.kill(pidNum, "SIGKILL");
|
|
@@ -10294,13 +10294,13 @@ function killBrowserProcsForUserDataDir(userDataDir) {
|
|
|
10294
10294
|
}
|
|
10295
10295
|
}
|
|
10296
10296
|
function selectOrphanBrowserPids(procs, liveUserDataDirs, profileRoot, selfPid) {
|
|
10297
|
-
const root =
|
|
10298
|
-
const live = new Set([...liveUserDataDirs].map((d) =>
|
|
10297
|
+
const root = resolve12(profileRoot);
|
|
10298
|
+
const live = new Set([...liveUserDataDirs].map((d) => resolve12(d)));
|
|
10299
10299
|
const out = [];
|
|
10300
10300
|
for (const { pid, userDataDir } of procs) {
|
|
10301
10301
|
if (pid === selfPid || !userDataDir)
|
|
10302
10302
|
continue;
|
|
10303
|
-
const dir =
|
|
10303
|
+
const dir = resolve12(userDataDir);
|
|
10304
10304
|
if (dir !== root && !dir.startsWith(`${root}${sep}`))
|
|
10305
10305
|
continue;
|
|
10306
10306
|
if (live.has(dir))
|
|
@@ -10316,7 +10316,7 @@ function reapOrphanBrowsers(liveUserDataDirs) {
|
|
|
10316
10316
|
const daemonLease = getRuntimeProcessLease("node-daemon", Date.now(), Number.POSITIVE_INFINITY);
|
|
10317
10317
|
if (!isBrowserJanitorOwner(daemonLease?.pid ?? null, process.pid))
|
|
10318
10318
|
return;
|
|
10319
|
-
const profileRoot =
|
|
10319
|
+
const profileRoot = resolve12(BROWSER_PROFILES_DIR);
|
|
10320
10320
|
let pids;
|
|
10321
10321
|
try {
|
|
10322
10322
|
pids = execFileSync6("pgrep", ["-f", "--", profileRoot], { stdio: "pipe" }).toString().trim();
|
|
@@ -10355,7 +10355,7 @@ function cleanSingletonFiles(userDataDir) {
|
|
|
10355
10355
|
for (const f of files) {
|
|
10356
10356
|
if (f.startsWith("Singleton")) {
|
|
10357
10357
|
try {
|
|
10358
|
-
unlinkSync10(
|
|
10358
|
+
unlinkSync10(resolve12(userDataDir, f));
|
|
10359
10359
|
logger.info({ file: f, userDataDir }, "Removed stale Singleton file");
|
|
10360
10360
|
} catch (e) {
|
|
10361
10361
|
logger.warn({ err: e, file: f }, "Failed to remove stale Chrome Singleton file");
|
|
@@ -10395,9 +10395,9 @@ var init_browser_processes = __esm(async () => {
|
|
|
10395
10395
|
|
|
10396
10396
|
// ../../packages/core/src/platform/playwright/headed-launch.ts
|
|
10397
10397
|
import { accessSync as accessSync2, constants as constants2 } from "fs";
|
|
10398
|
-
import { delimiter, isAbsolute as
|
|
10398
|
+
import { delimiter, isAbsolute as isAbsolute4, resolve as resolve13 } from "path";
|
|
10399
10399
|
function findExecutableOnPath(command, environment = process.env) {
|
|
10400
|
-
const candidates =
|
|
10400
|
+
const candidates = isAbsolute4(command) ? [command] : (environment.PATH ?? "").split(delimiter).filter(Boolean).map((directory) => resolve13(directory, command));
|
|
10401
10401
|
for (const candidate of candidates) {
|
|
10402
10402
|
try {
|
|
10403
10403
|
accessSync2(candidate, constants2.X_OK);
|
|
@@ -10785,21 +10785,21 @@ import { execFileSync as execFileSync7, spawn as spawn5 } from "child_process";
|
|
|
10785
10785
|
import { createHash as createHash3, randomBytes as randomBytes6, timingSafeEqual as timingSafeEqual3 } from "crypto";
|
|
10786
10786
|
import {
|
|
10787
10787
|
cpSync,
|
|
10788
|
-
existsSync as
|
|
10788
|
+
existsSync as existsSync17,
|
|
10789
10789
|
mkdirSync as mkdirSync11,
|
|
10790
|
-
readFileSync as
|
|
10790
|
+
readFileSync as readFileSync15,
|
|
10791
10791
|
rmSync as rmSync3,
|
|
10792
10792
|
unlinkSync as unlinkSync11,
|
|
10793
10793
|
writeFileSync as writeFileSync9
|
|
10794
10794
|
} from "fs";
|
|
10795
|
-
import { dirname as dirname11, join as join19, resolve as
|
|
10795
|
+
import { dirname as dirname11, join as join19, resolve as resolve14 } from "path";
|
|
10796
10796
|
function removeDefaultProfileDataDir(userDataDir) {
|
|
10797
|
-
const root =
|
|
10798
|
-
const target =
|
|
10797
|
+
const root = resolve14(BROWSER_PROFILES_DIR);
|
|
10798
|
+
const target = resolve14(userDataDir);
|
|
10799
10799
|
if (dirname11(target) !== root) {
|
|
10800
10800
|
throw new Error(`Refusing to delete browser profile outside managed root: ${target}`);
|
|
10801
10801
|
}
|
|
10802
|
-
const existed =
|
|
10802
|
+
const existed = existsSync17(target);
|
|
10803
10803
|
rmSync3(target, { recursive: true, force: true });
|
|
10804
10804
|
return existed;
|
|
10805
10805
|
}
|
|
@@ -11013,7 +11013,7 @@ function releasePort(port) {
|
|
|
11013
11013
|
usedPorts.delete(port);
|
|
11014
11014
|
}
|
|
11015
11015
|
function defaultProfileDir(_ownerId, profile) {
|
|
11016
|
-
return
|
|
11016
|
+
return resolve14(BROWSER_PROFILES_DIR, profile);
|
|
11017
11017
|
}
|
|
11018
11018
|
function resolveUserDataDir(instanceKey) {
|
|
11019
11019
|
return managerHost.resolveInstanceDataDir(instanceKey);
|
|
@@ -11374,11 +11374,11 @@ async function cloneProfileForChild(opts) {
|
|
|
11374
11374
|
killInstance(dstKey);
|
|
11375
11375
|
await delay(500);
|
|
11376
11376
|
}
|
|
11377
|
-
if (!
|
|
11377
|
+
if (!existsSync17(srcDir)) {
|
|
11378
11378
|
return { copied: false, srcDir, dstDir, reason: "src-missing" };
|
|
11379
11379
|
}
|
|
11380
11380
|
try {
|
|
11381
|
-
if (
|
|
11381
|
+
if (existsSync17(dstDir)) {
|
|
11382
11382
|
rmSync3(dstDir, { recursive: true, force: true });
|
|
11383
11383
|
}
|
|
11384
11384
|
mkdirSync11(dirname11(dstDir), { recursive: true });
|
|
@@ -11399,7 +11399,7 @@ async function cloneProfileForChild(opts) {
|
|
|
11399
11399
|
cleanSingletonFiles(dstDir);
|
|
11400
11400
|
for (const f of ["DevToolsActivePort", "LOCK"]) {
|
|
11401
11401
|
try {
|
|
11402
|
-
unlinkSync11(
|
|
11402
|
+
unlinkSync11(resolve14(dstDir, f));
|
|
11403
11403
|
} catch {}
|
|
11404
11404
|
}
|
|
11405
11405
|
logger.info({ srcKey, dstKey, srcDir, dstDir }, "Cloned Playwright profile for child topic");
|
|
@@ -13035,8 +13035,8 @@ import {
|
|
|
13035
13035
|
mkdirSync as mkdirSync15,
|
|
13036
13036
|
openSync as openSync2,
|
|
13037
13037
|
readdirSync as readdirSync4,
|
|
13038
|
-
readFileSync as
|
|
13039
|
-
statSync as
|
|
13038
|
+
readFileSync as readFileSync16,
|
|
13039
|
+
statSync as statSync8,
|
|
13040
13040
|
unlinkSync as unlinkSync16,
|
|
13041
13041
|
writeFileSync as writeFileSync13
|
|
13042
13042
|
} from "fs";
|
|
@@ -13084,11 +13084,11 @@ function parsePendingAskFilename(fileName) {
|
|
|
13084
13084
|
}
|
|
13085
13085
|
function readPendingAskFile(path, fallback) {
|
|
13086
13086
|
try {
|
|
13087
|
-
const raw =
|
|
13087
|
+
const raw = readFileSync16(path, "utf8").trim();
|
|
13088
13088
|
if (!raw)
|
|
13089
13089
|
return null;
|
|
13090
13090
|
if (!raw.startsWith("{")) {
|
|
13091
|
-
const ts = new Date(
|
|
13091
|
+
const ts = new Date(statSync8(path).mtimeMs).toISOString();
|
|
13092
13092
|
return {
|
|
13093
13093
|
userId: fallback.userId,
|
|
13094
13094
|
from: fallback.from,
|
|
@@ -13128,7 +13128,7 @@ function isStale(record, path) {
|
|
|
13128
13128
|
if (Number.isFinite(ts))
|
|
13129
13129
|
return Date.now() - ts > PENDING_ASK_TTL_MS;
|
|
13130
13130
|
try {
|
|
13131
|
-
return Date.now() -
|
|
13131
|
+
return Date.now() - statSync8(path).mtimeMs > PENDING_ASK_TTL_MS;
|
|
13132
13132
|
} catch {
|
|
13133
13133
|
return false;
|
|
13134
13134
|
}
|
|
@@ -14215,12 +14215,12 @@ var init_errors = __esm(() => {
|
|
|
14215
14215
|
|
|
14216
14216
|
// ../../packages/core/src/runtime/event-heartbeat.ts
|
|
14217
14217
|
function nextOrHeartbeat(pending, intervalMs) {
|
|
14218
|
-
return new Promise((
|
|
14219
|
-
const timer = setTimeout(() =>
|
|
14218
|
+
return new Promise((resolve15, reject) => {
|
|
14219
|
+
const timer = setTimeout(() => resolve15({ kind: "heartbeat" }), intervalMs);
|
|
14220
14220
|
timer.unref?.();
|
|
14221
14221
|
pending.then((result) => {
|
|
14222
14222
|
clearTimeout(timer);
|
|
14223
|
-
|
|
14223
|
+
resolve15({ kind: "event", result });
|
|
14224
14224
|
}, (error) => {
|
|
14225
14225
|
clearTimeout(timer);
|
|
14226
14226
|
reject(error);
|
|
@@ -14477,7 +14477,7 @@ var init_visual_html = __esm(() => {
|
|
|
14477
14477
|
|
|
14478
14478
|
// ../../packages/core/src/runtime/visuals.ts
|
|
14479
14479
|
import { realpathSync as realpathSync4 } from "fs";
|
|
14480
|
-
import { isAbsolute as
|
|
14480
|
+
import { isAbsolute as isAbsolute5, resolve as resolve15 } from "path";
|
|
14481
14481
|
function activeVisualHtmlForPrompt(html) {
|
|
14482
14482
|
if (html.length <= ACTIVE_VISUAL_PROMPT_MAX_CHARS) {
|
|
14483
14483
|
return { html, omittedChars: 0 };
|
|
@@ -14528,8 +14528,8 @@ function topicAllowsVisualFileId(topicId, fileId) {
|
|
|
14528
14528
|
return topicHasAttachmentFileId(topicId, fileId) || topicHasVisualFileId(topicId, fileId);
|
|
14529
14529
|
}
|
|
14530
14530
|
function isPathInside(baseDir, filePath) {
|
|
14531
|
-
const base =
|
|
14532
|
-
const normalized =
|
|
14531
|
+
const base = resolve15(baseDir);
|
|
14532
|
+
const normalized = resolve15(filePath);
|
|
14533
14533
|
try {
|
|
14534
14534
|
const realBase = realpathSync4(base);
|
|
14535
14535
|
const real = realpathSync4(normalized);
|
|
@@ -14591,7 +14591,7 @@ function resolveVisualMediaInput(topicId, input) {
|
|
|
14591
14591
|
}
|
|
14592
14592
|
const rawPath = input.file_path.trim();
|
|
14593
14593
|
const cwd = workspaceCwdFor(topicId);
|
|
14594
|
-
const candidate =
|
|
14594
|
+
const candidate = isAbsolute5(rawPath) ? rawPath : resolve15(cwd, rawPath);
|
|
14595
14595
|
if (!isPathInside(cwd, candidate)) {
|
|
14596
14596
|
return { error: "file_path must be inside the topic workspace" };
|
|
14597
14597
|
}
|
|
@@ -14665,8 +14665,8 @@ var init_token_stats = __esm(async () => {
|
|
|
14665
14665
|
|
|
14666
14666
|
// ../../packages/core/src/runtime/turn-event-stream.ts
|
|
14667
14667
|
import { randomUUID as randomUUID15 } from "crypto";
|
|
14668
|
-
import { realpathSync as realpathSync5, statSync as
|
|
14669
|
-
import { isAbsolute as
|
|
14668
|
+
import { realpathSync as realpathSync5, statSync as statSync9 } from "fs";
|
|
14669
|
+
import { isAbsolute as isAbsolute6, resolve as resolve16 } from "path";
|
|
14670
14670
|
function sessionEventMatchesCurrentExecution(topicId, queryId, agent, model) {
|
|
14671
14671
|
if (getRoomQuery(topicId)?.queryId !== queryId)
|
|
14672
14672
|
return false;
|
|
@@ -14981,7 +14981,7 @@ async function runTurnEventStream(topicId, topicTitle, queryId, events, control,
|
|
|
14981
14981
|
case "file":
|
|
14982
14982
|
if (!silent && peerBridge) {
|
|
14983
14983
|
const cwd = workspaceCwdFor(topicId);
|
|
14984
|
-
const path =
|
|
14984
|
+
const path = isAbsolute6(event.path) ? event.path : resolve16(cwd, event.path);
|
|
14985
14985
|
if (!isPathInside(cwd, path)) {
|
|
14986
14986
|
logger.warn({ topicId, path }, "peer output file is outside the topic workspace");
|
|
14987
14987
|
break;
|
|
@@ -14989,7 +14989,7 @@ async function runTurnEventStream(topicId, topicTitle, queryId, events, control,
|
|
|
14989
14989
|
let safePath;
|
|
14990
14990
|
try {
|
|
14991
14991
|
safePath = realpathSync5(path);
|
|
14992
|
-
if (!
|
|
14992
|
+
if (!statSync9(safePath).isFile()) {
|
|
14993
14993
|
logger.warn({ topicId, path }, "peer output path is not a regular file");
|
|
14994
14994
|
break;
|
|
14995
14995
|
}
|
|
@@ -15265,7 +15265,7 @@ var init_turn_session = __esm(async () => {
|
|
|
15265
15265
|
});
|
|
15266
15266
|
|
|
15267
15267
|
// ../../packages/core/src/storage/app-settings.ts
|
|
15268
|
-
import { existsSync as
|
|
15268
|
+
import { existsSync as existsSync18, mkdirSync as mkdirSync18, readFileSync as readFileSync17, writeFileSync as writeFileSync15 } from "fs";
|
|
15269
15269
|
import { dirname as dirname14, join as join27 } from "path";
|
|
15270
15270
|
function settingsFile() {
|
|
15271
15271
|
return join27(resolveStorageDataDir(), "otium-settings.json");
|
|
@@ -15277,8 +15277,8 @@ function ensureSettingsLoaded() {
|
|
|
15277
15277
|
loadedSettingsFile = path;
|
|
15278
15278
|
aiName = DEFAULT_AI_NAME;
|
|
15279
15279
|
try {
|
|
15280
|
-
if (
|
|
15281
|
-
const data = JSON.parse(
|
|
15280
|
+
if (existsSync18(path)) {
|
|
15281
|
+
const data = JSON.parse(readFileSync17(path, "utf8"));
|
|
15282
15282
|
if (typeof data.aiName === "string" && data.aiName.trim()) {
|
|
15283
15283
|
aiName = data.aiName.trim();
|
|
15284
15284
|
}
|
|
@@ -15370,7 +15370,7 @@ __export(exports_turn_runner, {
|
|
|
15370
15370
|
AGENT_DISPLAY_NAME: () => AGENT_DISPLAY_NAME
|
|
15371
15371
|
});
|
|
15372
15372
|
import { randomUUID as randomUUID16 } from "crypto";
|
|
15373
|
-
import { existsSync as
|
|
15373
|
+
import { existsSync as existsSync19, mkdirSync as mkdirSync19, readdirSync as readdirSync5, statSync as statSync10 } from "fs";
|
|
15374
15374
|
import { join as join28 } from "path";
|
|
15375
15375
|
function withDefaultPlaywright(configuredMcp, isManager) {
|
|
15376
15376
|
if (isManager)
|
|
@@ -15415,7 +15415,7 @@ function appendAskReplyMessage(topicId, text2, agentType) {
|
|
|
15415
15415
|
}
|
|
15416
15416
|
function resolveWikiMirrorPath(directory, preferredFilename, matchesLegacyId, matchesTitle, preferExact = true) {
|
|
15417
15417
|
const preferred = join28(directory, preferredFilename);
|
|
15418
|
-
if (preferExact &&
|
|
15418
|
+
if (preferExact && existsSync19(preferred))
|
|
15419
15419
|
return preferred;
|
|
15420
15420
|
let newestLegacyId = null;
|
|
15421
15421
|
let newestTitle = null;
|
|
@@ -15426,7 +15426,7 @@ function resolveWikiMirrorPath(directory, preferredFilename, matchesLegacyId, ma
|
|
|
15426
15426
|
if (!titleMatch && !legacyIdMatch)
|
|
15427
15427
|
continue;
|
|
15428
15428
|
const path = join28(directory, filename);
|
|
15429
|
-
const mtimeMs =
|
|
15429
|
+
const mtimeMs = statSync10(path).mtimeMs;
|
|
15430
15430
|
if (titleMatch) {
|
|
15431
15431
|
if (!newestTitle || mtimeMs > newestTitle.mtimeMs) {
|
|
15432
15432
|
newestTitle = { path, mtimeMs };
|
|
@@ -15440,9 +15440,9 @@ function resolveWikiMirrorPath(directory, preferredFilename, matchesLegacyId, ma
|
|
|
15440
15440
|
}
|
|
15441
15441
|
function resolveWikiMemoryMirror(wikiDir, topicId, topicTitle) {
|
|
15442
15442
|
const briefFile = resolveWikiMirrorPath(join28(wikiDir, "topic"), `${wikiBriefStorageKey(topicTitle, topicId)}.md`, (filename) => isTopicBriefFile(filename, topicId), (filename) => isTopicBriefFile(filename, topicId, topicTitle));
|
|
15443
|
-
const hasBriefFile =
|
|
15443
|
+
const hasBriefFile = existsSync19(briefFile) && statSync10(briefFile).isFile();
|
|
15444
15444
|
const latestSummaryCandidate = resolveWikiMirrorPath(join28(wikiDir, "summaries"), `__missing__-${wikiSummaryFilename("0000-00-00", topicTitle, topicId)}`, (filename) => isTopicSummaryFile(filename, topicId), (filename) => isTopicSummaryFile(filename, topicId, topicTitle), false);
|
|
15445
|
-
const latestSummaryFile =
|
|
15445
|
+
const latestSummaryFile = existsSync19(latestSummaryCandidate) && statSync10(latestSummaryCandidate).isFile() ? latestSummaryCandidate : null;
|
|
15446
15446
|
return { briefFile, hasBriefFile, latestSummaryFile };
|
|
15447
15447
|
}
|
|
15448
15448
|
async function streamAgentEvents(topicId, topicTitle, queryId, events, control, agentType, model, effort, userId, retryableSessionExpired = true, onSessionId, execution) {
|
|
@@ -16636,7 +16636,7 @@ var init_turn_runner = __esm(async () => {
|
|
|
16636
16636
|
});
|
|
16637
16637
|
|
|
16638
16638
|
// ../../packages/core/src/agents/mcp-tools/spawn-subagent.ts
|
|
16639
|
-
import { z as
|
|
16639
|
+
import { z as z4 } from "zod";
|
|
16640
16640
|
function createSubagentLifecycle(host) {
|
|
16641
16641
|
const runtimeOwnerId = host.runtime.ownerId;
|
|
16642
16642
|
const limits = Object.freeze({
|
|
@@ -17171,7 +17171,7 @@ ${card.task}${reportInstruction}`;
|
|
|
17171
17171
|
name: "start_subagent",
|
|
17172
17172
|
description: "Start a prepared descendant subagent task.",
|
|
17173
17173
|
schema: {
|
|
17174
|
-
topic_id:
|
|
17174
|
+
topic_id: z4.string().describe("Prepared subagent room id.")
|
|
17175
17175
|
},
|
|
17176
17176
|
async handler(input) {
|
|
17177
17177
|
const result = ownedSubagentTree(ctx);
|
|
@@ -17191,7 +17191,7 @@ ${card.task}${reportInstruction}`;
|
|
|
17191
17191
|
name: "delete_subagent",
|
|
17192
17192
|
description: "Permanently delete one descendant subagent room managed by the current room. " + "This removes its conversation, workspace, runtime state, and topic. Keep it when follow-up work is likely.",
|
|
17193
17193
|
schema: {
|
|
17194
|
-
topic_id:
|
|
17194
|
+
topic_id: z4.string().describe("Exact subagent room id returned by list_subagents; names are not accepted.")
|
|
17195
17195
|
},
|
|
17196
17196
|
async handler(input) {
|
|
17197
17197
|
const result = ownedSubagentTree(ctx);
|
|
@@ -17215,8 +17215,8 @@ ${card.task}${reportInstruction}`;
|
|
|
17215
17215
|
name: "grant_subagent_tell",
|
|
17216
17216
|
description: "Allow one descendant subagent to tell_session another topic in this managed subagent tree. " + "Direct-parent reporting is always allowed and does not need a grant.",
|
|
17217
17217
|
schema: {
|
|
17218
|
-
subagent_topic_id:
|
|
17219
|
-
target_topic_id:
|
|
17218
|
+
subagent_topic_id: z4.string().describe("Source descendant subagent topic id."),
|
|
17219
|
+
target_topic_id: z4.string().describe("Target topic id: this manager room or another descendant in its tree.")
|
|
17220
17220
|
},
|
|
17221
17221
|
async handler(input) {
|
|
17222
17222
|
const result = ownedSubagentTree(ctx);
|
|
@@ -17242,8 +17242,8 @@ ${card.task}${reportInstruction}`;
|
|
|
17242
17242
|
name: "revoke_subagent_tell",
|
|
17243
17243
|
description: "Remove an extra tell_session connection previously granted to a descendant subagent.",
|
|
17244
17244
|
schema: {
|
|
17245
|
-
subagent_topic_id:
|
|
17246
|
-
target_topic_id:
|
|
17245
|
+
subagent_topic_id: z4.string().describe("Source descendant subagent topic id."),
|
|
17246
|
+
target_topic_id: z4.string().describe("Granted target topic id.")
|
|
17247
17247
|
},
|
|
17248
17248
|
async handler(input) {
|
|
17249
17249
|
const result = ownedSubagentTree(ctx);
|
|
@@ -17269,12 +17269,12 @@ ${card.task}${reportInstruction}`;
|
|
|
17269
17269
|
name: "spawn_subagent",
|
|
17270
17270
|
description: "Delegate a self-contained task to a subagent that works in its own new agent room. " + "Returns immediately; the subagent runs in the background and reports according to report_mode. " + "The fresh room has no parent conversation history; it receives the task plus the selected or inherited topic memory. " + "Use for parallelizable or long-running side work. Do not use provider built-in Task/Agent subagents.",
|
|
17271
17271
|
schema: {
|
|
17272
|
-
task:
|
|
17273
|
-
name:
|
|
17274
|
-
agent:
|
|
17275
|
-
model:
|
|
17276
|
-
memory_topic:
|
|
17277
|
-
report_mode:
|
|
17272
|
+
task: z4.string().describe("Self-contained task brief. The worker has topic memory but no parent conversation history, so include all task-specific context."),
|
|
17273
|
+
name: z4.string().optional().describe("Short name for the subagent room. Auto-generated when omitted."),
|
|
17274
|
+
agent: z4.enum(["claude", "codex", "maestro"]).optional().describe("Agent backend override. Defaults to this room's agent."),
|
|
17275
|
+
model: z4.string().optional().describe(`Best-fit model override from the system prompt catalog. Omit agent+model to inherit ${ctx.agent}/${ctx.model ?? "default"}; overriding agent without model uses that agent's default.`),
|
|
17276
|
+
memory_topic: z4.string().optional().describe("Optional knowledge source: an accessible topic id/title or topic/*.md brief. Defaults to the parent room's effective topic brief."),
|
|
17277
|
+
report_mode: z4.enum(["auto", "tell", "status-only"]).optional().describe("Completion reporting: auto injects the final result, tell requires tell_session, status-only updates only the lifecycle card.")
|
|
17278
17278
|
},
|
|
17279
17279
|
async handler(input) {
|
|
17280
17280
|
return createSubagent(ctx, input, true);
|
|
@@ -17286,12 +17286,12 @@ ${card.task}${reportInstruction}`;
|
|
|
17286
17286
|
name: "create_subagent",
|
|
17287
17287
|
description: "Create a prepared subagent room and task definition without starting its AI turn. " + "Use start_subagent when the team is ready to run it.",
|
|
17288
17288
|
schema: {
|
|
17289
|
-
task:
|
|
17290
|
-
name:
|
|
17291
|
-
agent:
|
|
17292
|
-
model:
|
|
17293
|
-
memory_topic:
|
|
17294
|
-
report_mode:
|
|
17289
|
+
task: z4.string().describe("Self-contained task brief for the subagent."),
|
|
17290
|
+
name: z4.string().optional().describe("Short room name. Auto-generated when omitted."),
|
|
17291
|
+
agent: z4.enum(["claude", "codex", "maestro"]).optional(),
|
|
17292
|
+
model: z4.string().optional(),
|
|
17293
|
+
memory_topic: z4.string().optional().describe("Optional accessible topic id/title or topic/*.md brief to use as this worker's knowledge source. Defaults to the parent."),
|
|
17294
|
+
report_mode: z4.enum(["auto", "tell", "status-only"]).optional()
|
|
17295
17295
|
},
|
|
17296
17296
|
async handler(input) {
|
|
17297
17297
|
return createSubagent(ctx, input, false);
|
|
@@ -17479,10 +17479,252 @@ await __promiseAll([
|
|
|
17479
17479
|
init_ask_user()
|
|
17480
17480
|
]);
|
|
17481
17481
|
|
|
17482
|
-
// ../../packages/core/src/agents/mcp-tools/
|
|
17482
|
+
// ../../packages/core/src/agents/mcp-tools/publish-html.ts
|
|
17483
17483
|
init_common();
|
|
17484
17484
|
import { z as z2 } from "zod";
|
|
17485
17485
|
|
|
17486
|
+
// ../../packages/core/src/agents/mcp-tools/inline-assets.ts
|
|
17487
|
+
import { existsSync as existsSync16, readFileSync as readFileSync14, statSync as statSync7 } from "fs";
|
|
17488
|
+
import { extname, isAbsolute as isAbsolute3, resolve as resolve11 } from "path";
|
|
17489
|
+
var MIME_BY_EXT = {
|
|
17490
|
+
".apng": "image/apng",
|
|
17491
|
+
".avif": "image/avif",
|
|
17492
|
+
".bmp": "image/bmp",
|
|
17493
|
+
".css": "text/css",
|
|
17494
|
+
".gif": "image/gif",
|
|
17495
|
+
".ico": "image/x-icon",
|
|
17496
|
+
".jpeg": "image/jpeg",
|
|
17497
|
+
".jpg": "image/jpeg",
|
|
17498
|
+
".mp3": "audio/mpeg",
|
|
17499
|
+
".mp4": "video/mp4",
|
|
17500
|
+
".otf": "font/otf",
|
|
17501
|
+
".png": "image/png",
|
|
17502
|
+
".svg": "image/svg+xml",
|
|
17503
|
+
".ttf": "font/ttf",
|
|
17504
|
+
".wav": "audio/wav",
|
|
17505
|
+
".webm": "video/webm",
|
|
17506
|
+
".webp": "image/webp",
|
|
17507
|
+
".woff": "font/woff",
|
|
17508
|
+
".woff2": "font/woff2"
|
|
17509
|
+
};
|
|
17510
|
+
function isNonLocal(ref) {
|
|
17511
|
+
return /^(?:[a-z][a-z0-9+.-]*:|\/\/|#)/i.test(ref.trim());
|
|
17512
|
+
}
|
|
17513
|
+
function stripSuffix(ref) {
|
|
17514
|
+
return ref.replace(/[?#].*$/, "");
|
|
17515
|
+
}
|
|
17516
|
+
function inlineLocalAssets(html, options) {
|
|
17517
|
+
const { baseDir, maxAssetBytes, maxTotalBytes } = options;
|
|
17518
|
+
const inlined = [];
|
|
17519
|
+
const unresolved = [];
|
|
17520
|
+
const skipped = [];
|
|
17521
|
+
const cache = new Map;
|
|
17522
|
+
let budget = maxTotalBytes - Buffer.byteLength(html, "utf-8");
|
|
17523
|
+
function toDataUri(rawRef) {
|
|
17524
|
+
const ref = rawRef.trim();
|
|
17525
|
+
if (!ref || isNonLocal(ref))
|
|
17526
|
+
return null;
|
|
17527
|
+
const cached = cache.get(ref);
|
|
17528
|
+
if (cached !== undefined)
|
|
17529
|
+
return cached;
|
|
17530
|
+
const relPath = stripSuffix(ref);
|
|
17531
|
+
if (!relPath)
|
|
17532
|
+
return null;
|
|
17533
|
+
const abs = isAbsolute3(relPath) ? relPath : resolve11(baseDir, relPath);
|
|
17534
|
+
let bytes;
|
|
17535
|
+
try {
|
|
17536
|
+
if (!existsSync16(abs) || !statSync7(abs).isFile()) {
|
|
17537
|
+
unresolved.push(ref);
|
|
17538
|
+
cache.set(ref, null);
|
|
17539
|
+
return null;
|
|
17540
|
+
}
|
|
17541
|
+
bytes = statSync7(abs).size;
|
|
17542
|
+
} catch {
|
|
17543
|
+
unresolved.push(ref);
|
|
17544
|
+
cache.set(ref, null);
|
|
17545
|
+
return null;
|
|
17546
|
+
}
|
|
17547
|
+
if (bytes > maxAssetBytes) {
|
|
17548
|
+
skipped.push({ ref, bytes, reason: "asset-too-large" });
|
|
17549
|
+
cache.set(ref, null);
|
|
17550
|
+
return null;
|
|
17551
|
+
}
|
|
17552
|
+
const encodedCost = Math.ceil(bytes / 3) * 4;
|
|
17553
|
+
if (encodedCost > budget) {
|
|
17554
|
+
skipped.push({ ref, bytes, reason: "document-too-large" });
|
|
17555
|
+
cache.set(ref, null);
|
|
17556
|
+
return null;
|
|
17557
|
+
}
|
|
17558
|
+
let uri;
|
|
17559
|
+
try {
|
|
17560
|
+
const mime = MIME_BY_EXT[extname(abs).toLowerCase()] ?? "application/octet-stream";
|
|
17561
|
+
uri = `data:${mime};base64,${readFileSync14(abs).toString("base64")}`;
|
|
17562
|
+
} catch {
|
|
17563
|
+
unresolved.push(ref);
|
|
17564
|
+
cache.set(ref, null);
|
|
17565
|
+
return null;
|
|
17566
|
+
}
|
|
17567
|
+
budget -= uri.length;
|
|
17568
|
+
inlined.push({ ref, bytes });
|
|
17569
|
+
cache.set(ref, uri);
|
|
17570
|
+
return uri;
|
|
17571
|
+
}
|
|
17572
|
+
function rewriteSrcset(value) {
|
|
17573
|
+
return value.split(",").map((candidate) => {
|
|
17574
|
+
const trimmed = candidate.trim();
|
|
17575
|
+
if (!trimmed)
|
|
17576
|
+
return candidate;
|
|
17577
|
+
const [url, ...descriptor] = trimmed.split(/\s+/);
|
|
17578
|
+
const uri = url ? toDataUri(url) : null;
|
|
17579
|
+
if (!uri)
|
|
17580
|
+
return candidate;
|
|
17581
|
+
return [uri, ...descriptor].join(" ");
|
|
17582
|
+
}).join(", ");
|
|
17583
|
+
}
|
|
17584
|
+
let out = html;
|
|
17585
|
+
out = out.replace(/(\b(?:src|poster)\s*=\s*)(["'])([^"']*)\2/gi, (match, prefix, quote, ref) => {
|
|
17586
|
+
const uri = toDataUri(ref);
|
|
17587
|
+
return uri ? `${prefix}${quote}${uri}${quote}` : match;
|
|
17588
|
+
});
|
|
17589
|
+
out = out.replace(/(\bsrcset\s*=\s*)(["'])([^"']*)\2/gi, (match, prefix, quote, value) => {
|
|
17590
|
+
const rewritten = rewriteSrcset(value);
|
|
17591
|
+
return rewritten === value ? match : `${prefix}${quote}${rewritten}${quote}`;
|
|
17592
|
+
});
|
|
17593
|
+
out = out.replace(/<link\b[^>]*>/gi, (tag) => tag.replace(/(\bhref\s*=\s*)(["'])([^"']*)\2/i, (match, prefix, quote, ref) => {
|
|
17594
|
+
const uri = toDataUri(ref);
|
|
17595
|
+
return uri ? `${prefix}${quote}${uri}${quote}` : match;
|
|
17596
|
+
}));
|
|
17597
|
+
out = out.replace(/url\(\s*(["']?)([^"')]+)\1\s*\)/gi, (match, quote, ref) => {
|
|
17598
|
+
const uri = toDataUri(ref);
|
|
17599
|
+
return uri ? `url(${quote}${uri}${quote})` : match;
|
|
17600
|
+
});
|
|
17601
|
+
return { html: out, inlined, unresolved, skipped };
|
|
17602
|
+
}
|
|
17603
|
+
|
|
17604
|
+
// ../../packages/core/src/agents/mcp-tools/publish-html.ts
|
|
17605
|
+
init_config();
|
|
17606
|
+
var REQUEST_TIMEOUT_MS = 30000;
|
|
17607
|
+
var MAX_PUBLISHED_BYTES = 10 * 1024 * 1024;
|
|
17608
|
+
var MAX_PUBLISHED_ASSET_BYTES = 5 * 1024 * 1024;
|
|
17609
|
+
function formatPublishBytes(bytes) {
|
|
17610
|
+
if (bytes < 1024)
|
|
17611
|
+
return `${bytes}B`;
|
|
17612
|
+
if (bytes < 1024 * 1024)
|
|
17613
|
+
return `${(bytes / 1024).toFixed(0)}KB`;
|
|
17614
|
+
return `${(bytes / 1024 / 1024).toFixed(1)}MB`;
|
|
17615
|
+
}
|
|
17616
|
+
function parseSnippetId(input) {
|
|
17617
|
+
const trimmed = input.trim();
|
|
17618
|
+
const fromUrl = trimmed.match(/\/snippets\/([A-Za-z0-9-]+)/)?.[1];
|
|
17619
|
+
const id = fromUrl ?? trimmed;
|
|
17620
|
+
return /^[A-Za-z0-9-]+$/.test(id) ? id : null;
|
|
17621
|
+
}
|
|
17622
|
+
async function snippetRequest(baseUrl, path, init = {}) {
|
|
17623
|
+
try {
|
|
17624
|
+
const response = await fetch(`${baseUrl}${path}`, {
|
|
17625
|
+
...init,
|
|
17626
|
+
signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS)
|
|
17627
|
+
});
|
|
17628
|
+
const body = await response.json().catch(() => null);
|
|
17629
|
+
if (body)
|
|
17630
|
+
return body;
|
|
17631
|
+
return { ok: false, error: `snippet service returned ${response.status}` };
|
|
17632
|
+
} catch (error) {
|
|
17633
|
+
const message = error instanceof Error ? error.message : "snippet service unreachable";
|
|
17634
|
+
return { ok: false, error: message };
|
|
17635
|
+
}
|
|
17636
|
+
}
|
|
17637
|
+
function createPublishHtmlToolDefinitions(ctx, options = {}) {
|
|
17638
|
+
const apiUrl = (options.apiUrl ?? SNIPPETS_API_URL)?.replace(/\/+$/, "");
|
|
17639
|
+
if (!apiUrl)
|
|
17640
|
+
return [];
|
|
17641
|
+
const getCtx = typeof ctx === "function" ? ctx : () => ctx;
|
|
17642
|
+
return [
|
|
17643
|
+
{
|
|
17644
|
+
name: "publish_html",
|
|
17645
|
+
description: [
|
|
17646
|
+
"Publish an HTML document and return a public, shareable https link that",
|
|
17647
|
+
"stays live for 72 hours. Use this when the user should be able to open,",
|
|
17648
|
+
"keep, or send the result \u2014 a report, dashboard, or styled table \u2014 rather",
|
|
17649
|
+
"than only glance at it in the side panel.",
|
|
17650
|
+
"Pass a complete standalone document and inline the CSS and JS.",
|
|
17651
|
+
"For charts and diagrams prefer inline <svg>: it stays sharp at any zoom",
|
|
17652
|
+
"and is far smaller than an image file.",
|
|
17653
|
+
"Images may be remote URLs, data: URIs, or paths to local files you",
|
|
17654
|
+
"created \u2014 local files are embedded automatically, so the page keeps",
|
|
17655
|
+
"working after your workspace is gone."
|
|
17656
|
+
].join(" "),
|
|
17657
|
+
schema: {
|
|
17658
|
+
html: z2.string().describe("Complete standalone HTML document to publish. Inline the CSS and JS."),
|
|
17659
|
+
base_dir: z2.string().optional().describe("Directory that relative image paths resolve against. Defaults to the working directory.")
|
|
17660
|
+
},
|
|
17661
|
+
async handler(input) {
|
|
17662
|
+
const html = input?.html ?? "";
|
|
17663
|
+
if (!html.trim())
|
|
17664
|
+
return errorResult("html is empty \u2014 provide an HTML document.");
|
|
17665
|
+
const baseDir = input.base_dir?.trim() || getCtx().cwd || process.cwd();
|
|
17666
|
+
const report = inlineLocalAssets(html, {
|
|
17667
|
+
baseDir,
|
|
17668
|
+
maxAssetBytes: MAX_PUBLISHED_ASSET_BYTES,
|
|
17669
|
+
maxTotalBytes: MAX_PUBLISHED_BYTES
|
|
17670
|
+
});
|
|
17671
|
+
const bytes = Buffer.byteLength(report.html, "utf-8");
|
|
17672
|
+
if (bytes > MAX_PUBLISHED_BYTES) {
|
|
17673
|
+
return errorResult(`Document is ${formatPublishBytes(bytes)} after embedding images, over the ${formatPublishBytes(MAX_PUBLISHED_BYTES)} limit. Use fewer or smaller images, or switch charts to inline <svg>.`);
|
|
17674
|
+
}
|
|
17675
|
+
const result = await snippetRequest(apiUrl, "/snippets", {
|
|
17676
|
+
method: "POST",
|
|
17677
|
+
headers: { "content-type": "text/html; charset=utf-8" },
|
|
17678
|
+
body: report.html
|
|
17679
|
+
});
|
|
17680
|
+
if (!result.ok || !result.url) {
|
|
17681
|
+
return errorResult(result.error ?? "Failed to publish.");
|
|
17682
|
+
}
|
|
17683
|
+
const notes = [];
|
|
17684
|
+
if (report.inlined.length > 0) {
|
|
17685
|
+
const total = report.inlined.reduce((sum, a) => sum + a.bytes, 0);
|
|
17686
|
+
notes.push(`Embedded ${report.inlined.length} local file(s), ${formatPublishBytes(total)}.`);
|
|
17687
|
+
}
|
|
17688
|
+
if (report.unresolved.length > 0) {
|
|
17689
|
+
notes.push(`WARNING \u2014 these look like local files but were not found, so they will render broken: ${report.unresolved.join(", ")}. Check the paths (relative to ${baseDir}) and republish.`);
|
|
17690
|
+
}
|
|
17691
|
+
for (const s of report.skipped) {
|
|
17692
|
+
notes.push(s.reason === "asset-too-large" ? `WARNING \u2014 ${s.ref} is ${formatPublishBytes(s.bytes)}, over the ${formatPublishBytes(MAX_PUBLISHED_ASSET_BYTES)} per-file limit, and was left as a broken link.` : `WARNING \u2014 ${s.ref} was left out because the document hit the ${formatPublishBytes(MAX_PUBLISHED_BYTES)} limit.`);
|
|
17693
|
+
}
|
|
17694
|
+
const payload = {
|
|
17695
|
+
url: result.url,
|
|
17696
|
+
snippetId: result.snippetId,
|
|
17697
|
+
expiresAt: result.expiresAt,
|
|
17698
|
+
sizeBytes: bytes,
|
|
17699
|
+
...report.inlined.length > 0 ? { embeddedFiles: report.inlined.length } : {}
|
|
17700
|
+
};
|
|
17701
|
+
return textResult([JSON.stringify(payload, null, 2), ...notes].join(`
|
|
17702
|
+
|
|
17703
|
+
`));
|
|
17704
|
+
}
|
|
17705
|
+
},
|
|
17706
|
+
{
|
|
17707
|
+
name: "unpublish_html",
|
|
17708
|
+
description: "Delete a previously published HTML document before its 72-hour expiry. Accepts the URL returned by publish_html, or its id.",
|
|
17709
|
+
schema: {
|
|
17710
|
+
snippet: z2.string().describe("URL returned by publish_html, or the bare id.")
|
|
17711
|
+
},
|
|
17712
|
+
async handler(input) {
|
|
17713
|
+
const id = parseSnippetId(input?.snippet ?? "");
|
|
17714
|
+
if (!id)
|
|
17715
|
+
return errorResult("Could not read a published document id from that value.");
|
|
17716
|
+
const result = await snippetRequest(apiUrl, `/snippets/${id}`, { method: "DELETE" });
|
|
17717
|
+
if (!result.ok)
|
|
17718
|
+
return errorResult(result.error ?? "Failed to delete.");
|
|
17719
|
+
return textResult(`Published document ${id} deleted.`);
|
|
17720
|
+
}
|
|
17721
|
+
}
|
|
17722
|
+
];
|
|
17723
|
+
}
|
|
17724
|
+
// ../../packages/core/src/agents/mcp-tools/self-config.ts
|
|
17725
|
+
init_common();
|
|
17726
|
+
import { z as z3 } from "zod";
|
|
17727
|
+
|
|
17486
17728
|
// ../../packages/core/src/agents/api-topic-agent-switch.ts
|
|
17487
17729
|
init_model_catalog();
|
|
17488
17730
|
init_logger();
|
|
@@ -18028,7 +18270,7 @@ function createSelfConfigToolDefinitionsForCore(core, ctx) {
|
|
|
18028
18270
|
{
|
|
18029
18271
|
name: "set_model",
|
|
18030
18272
|
description: toolDescription(core, "set_model", "Set the model for THIS topic; it persists and applies from the NEXT turn. Use a model from the system prompt's same-agent catalog. Cross-agent changes require an explicit user-requested set_agent first. Fails if the user locked this setting. NEVER use 'fable' unless explicitly requested."),
|
|
18031
|
-
schema: { model:
|
|
18273
|
+
schema: { model: z3.string().describe("Model id valid for the topic's current agent.") },
|
|
18032
18274
|
async handler({ model }) {
|
|
18033
18275
|
return mcpResult(core.setModel(getCtx(), model));
|
|
18034
18276
|
}
|
|
@@ -18044,7 +18286,7 @@ function createSelfConfigToolDefinitionsForCore(core, ctx) {
|
|
|
18044
18286
|
{
|
|
18045
18287
|
name: "set_agent",
|
|
18046
18288
|
description: toolDescription(core, "set_agent", "Switch the agent backend for THIS topic between 'claude', 'codex', and 'maestro'. Clears the topic's model/effort override so the new agent starts at its defaults. Fails if the user locked this setting. Use only when the user explicitly asks to switch the runtime itself."),
|
|
18047
|
-
schema: { agent:
|
|
18289
|
+
schema: { agent: z3.enum(AGENT_VALUES) },
|
|
18048
18290
|
async handler({ agent }) {
|
|
18049
18291
|
return mcpResult(core.setAgent(getCtx(), agent));
|
|
18050
18292
|
}
|
|
@@ -18061,7 +18303,7 @@ function createSelfConfigToolDefinitionsForCore(core, ctx) {
|
|
|
18061
18303
|
name: "set_effort",
|
|
18062
18304
|
description: toolDescription(core, "set_effort", "Set the reasoning effort for THIS topic. Claude: low/medium/high/xhigh/max. Codex: low/medium/high/xhigh. Maestro: low/medium/high/xhigh/max. Higher effort costs more and is slower. Fails if the user locked this setting."),
|
|
18063
18305
|
schema: {
|
|
18064
|
-
effort:
|
|
18306
|
+
effort: z3.enum(EFFORT_VALUES).describe("Reasoning effort level valid for the topic's current agent.")
|
|
18065
18307
|
},
|
|
18066
18308
|
async handler({ effort }) {
|
|
18067
18309
|
return mcpResult(core.setEffort(getCtx(), effort));
|
|
@@ -18081,8 +18323,8 @@ function createSelfConfigToolDefinitionsForCore(core, ctx) {
|
|
|
18081
18323
|
name: "schedule_self",
|
|
18082
18324
|
description: toolDescription(core, "schedule_self", "Create the one pending durable delayed continuation allowed for THIS topic without blocking the current turn. Use it to check a long-running operation or resume work later. The future message must be self-contained. If one already exists, use get_self_schedule then update_self_schedule or cancel_self_schedule. For recurring or longer-lived schedules, use cron-manager instead."),
|
|
18083
18325
|
schema: {
|
|
18084
|
-
delay_seconds:
|
|
18085
|
-
message:
|
|
18326
|
+
delay_seconds: z3.number().int().min(1).max(core.product.scheduleMaxDelaySeconds).describe(`Seconds before this topic resumes, from 1 through ${core.product.scheduleMaxDelaySeconds}${core.product.scheduleMaxDelaySeconds === 86400 ? " (24 hours)" : ""}.`),
|
|
18327
|
+
message: z3.string().min(1).max(core.product.scheduleMaxMessageLength).describe("Self-contained instruction delivered to your future turn.")
|
|
18086
18328
|
},
|
|
18087
18329
|
async handler({ delay_seconds, message }) {
|
|
18088
18330
|
return mcpResult(core.scheduleContinue(getCtx(), delay_seconds, message));
|
|
@@ -18100,9 +18342,9 @@ function createSelfConfigToolDefinitionsForCore(core, ctx) {
|
|
|
18100
18342
|
name: "update_self_schedule",
|
|
18101
18343
|
description: toolDescription(core, "update_self_schedule", "Edit THIS topic's pending self-schedule. Provide its schedule_id from schedule_self/get_self_schedule and change delay_seconds, message, or both. delay_seconds is measured from this update. A schedule that already started cannot be edited."),
|
|
18102
18344
|
schema: {
|
|
18103
|
-
schedule_id:
|
|
18104
|
-
delay_seconds:
|
|
18105
|
-
message:
|
|
18345
|
+
schedule_id: z3.string().min(1).describe("Exact ID of the pending self-schedule."),
|
|
18346
|
+
delay_seconds: z3.number().int().min(1).max(core.product.scheduleMaxDelaySeconds).optional().describe(`New delay from now, from 1 through ${core.product.scheduleMaxDelaySeconds} seconds.`),
|
|
18347
|
+
message: z3.string().min(1).max(core.product.scheduleMaxMessageLength).optional().describe("Replacement self-contained future instruction.")
|
|
18106
18348
|
},
|
|
18107
18349
|
async handler({
|
|
18108
18350
|
schedule_id,
|
|
@@ -18119,7 +18361,7 @@ function createSelfConfigToolDefinitionsForCore(core, ctx) {
|
|
|
18119
18361
|
name: "cancel_self_schedule",
|
|
18120
18362
|
description: toolDescription(core, "cancel_self_schedule", "Cancel THIS topic's pending self-schedule by its exact schedule_id. A schedule that already started cannot be cancelled with this tool."),
|
|
18121
18363
|
schema: {
|
|
18122
|
-
schedule_id:
|
|
18364
|
+
schedule_id: z3.string().min(1).describe("Exact ID of the pending self-schedule.")
|
|
18123
18365
|
},
|
|
18124
18366
|
async handler({ schedule_id }) {
|
|
18125
18367
|
return mcpResult(core.cancelSchedule(getCtx(), schedule_id));
|
|
@@ -18131,7 +18373,7 @@ function createSelfConfigToolDefinitionsForCore(core, ctx) {
|
|
|
18131
18373
|
name: "spawn_topic",
|
|
18132
18374
|
description: toolDescription(core, "spawn_topic", `Create a new forum topic that inherits all settings from THIS topic but starts with a fresh session. Limited to ${core.product.derivedTopicLimit} calls per conversation turn.`),
|
|
18133
18375
|
schema: {
|
|
18134
|
-
name:
|
|
18376
|
+
name: z3.string().optional().describe("New topic name. Auto-generated if omitted.")
|
|
18135
18377
|
},
|
|
18136
18378
|
async handler({ name }) {
|
|
18137
18379
|
if (derivedCount >= core.product.derivedTopicLimit) {
|
|
@@ -18148,7 +18390,7 @@ function createSelfConfigToolDefinitionsForCore(core, ctx) {
|
|
|
18148
18390
|
name: "fork_topic",
|
|
18149
18391
|
description: toolDescription(core, "fork_topic", `Fork THIS topic by creating a new topic that inherits both settings AND conversation history. Limited to ${core.product.derivedTopicLimit} calls per conversation turn.`),
|
|
18150
18392
|
schema: {
|
|
18151
|
-
name:
|
|
18393
|
+
name: z3.string().optional().describe("New topic name. Auto-generated if omitted.")
|
|
18152
18394
|
},
|
|
18153
18395
|
async handler({ name }) {
|
|
18154
18396
|
if (derivedCount >= core.product.derivedTopicLimit) {
|
|
@@ -18170,14 +18412,14 @@ await init_spawn_subagent();
|
|
|
18170
18412
|
|
|
18171
18413
|
// ../../packages/core/src/agents/mcp-tools/visuals.ts
|
|
18172
18414
|
init_common();
|
|
18173
|
-
import { z as
|
|
18415
|
+
import { z as z5 } from "zod";
|
|
18174
18416
|
var VISUALS_MCP_KEY = "visuals";
|
|
18175
18417
|
var showHtmlTool = {
|
|
18176
18418
|
name: "show_html",
|
|
18177
18419
|
description: "Display charts, tables, or interactive HTML to the user in a sandboxed WebView side panel. Pass a complete, self-contained HTML string with inline CSS/JS. Local DOM interactions are supported. Links (<a href> to http/https URLs) are safe to include: a click opens the URL in the user's system browser. Network requests, external scripts, form posts, popups, and parent-window access are blocked.",
|
|
18178
18420
|
schema: {
|
|
18179
|
-
html:
|
|
18180
|
-
title:
|
|
18421
|
+
html: z5.string().describe("Complete, self-contained HTML document or fragment to render."),
|
|
18422
|
+
title: z5.string().optional().describe("Optional title shown above the rendered card.")
|
|
18181
18423
|
},
|
|
18182
18424
|
async handler() {
|
|
18183
18425
|
return textResult("HTML card displayed to the user.");
|
|
@@ -18187,9 +18429,9 @@ var showMermaidTool = {
|
|
|
18187
18429
|
name: "show_mermaid",
|
|
18188
18430
|
description: "Render a Mermaid diagram in the user's visual side panel. Pass Mermaid DSL only, not markdown fences. Use this for flowcharts, sequence diagrams, class diagrams, state diagrams, ER diagrams, timelines, and architecture diagrams.",
|
|
18189
18431
|
schema: {
|
|
18190
|
-
code:
|
|
18191
|
-
title:
|
|
18192
|
-
theme:
|
|
18432
|
+
code: z5.string().describe("Mermaid diagram source without markdown code fences."),
|
|
18433
|
+
title: z5.string().optional().describe("Optional title shown above the rendered card."),
|
|
18434
|
+
theme: z5.enum(["default", "neutral", "dark", "forest"]).optional().describe("Optional Mermaid theme. Defaults to neutral.")
|
|
18193
18435
|
},
|
|
18194
18436
|
async handler() {
|
|
18195
18437
|
return textResult("Mermaid diagram displayed to the user.");
|
|
@@ -18199,10 +18441,10 @@ var showImageTool = {
|
|
|
18199
18441
|
name: "show_image",
|
|
18200
18442
|
description: "Display an image in the user's visual side panel. Provide either file_path for an image in the topic workspace, or file_id for an uploaded file already attached in this topic.",
|
|
18201
18443
|
schema: {
|
|
18202
|
-
file_path:
|
|
18203
|
-
file_id:
|
|
18204
|
-
title:
|
|
18205
|
-
alt:
|
|
18444
|
+
file_path: z5.string().optional().describe("Absolute or workspace-relative path to an image file."),
|
|
18445
|
+
file_id: z5.string().optional().describe("Full Otium uploaded file UUID for an image attached in this topic."),
|
|
18446
|
+
title: z5.string().optional().describe("Optional title shown above the rendered card."),
|
|
18447
|
+
alt: z5.string().optional().describe("Optional alt text for the image.")
|
|
18206
18448
|
},
|
|
18207
18449
|
async handler(input) {
|
|
18208
18450
|
if (!input?.file_path && !input?.file_id) {
|
|
@@ -18215,9 +18457,9 @@ var showVideoTool = {
|
|
|
18215
18457
|
name: "show_video",
|
|
18216
18458
|
description: "Display a playable video in the user's visual side panel. Provide either file_path for a video in the topic workspace, or file_id for an uploaded file already attached in this topic.",
|
|
18217
18459
|
schema: {
|
|
18218
|
-
file_path:
|
|
18219
|
-
file_id:
|
|
18220
|
-
title:
|
|
18460
|
+
file_path: z5.string().optional().describe("Absolute or workspace-relative path to a video file."),
|
|
18461
|
+
file_id: z5.string().optional().describe("Full Otium uploaded file UUID for a video attached in this topic."),
|
|
18462
|
+
title: z5.string().optional().describe("Optional title shown above the rendered card.")
|
|
18221
18463
|
},
|
|
18222
18464
|
async handler(input) {
|
|
18223
18465
|
if (!input?.file_path && !input?.file_id) {
|
|
@@ -18291,6 +18533,7 @@ export {
|
|
|
18291
18533
|
createSelfConfigToolDefinitionsForCore,
|
|
18292
18534
|
createSelfConfigRuntime,
|
|
18293
18535
|
createSelfConfigCore,
|
|
18536
|
+
createPublishHtmlToolDefinitions,
|
|
18294
18537
|
createCodexTreeManager,
|
|
18295
18538
|
createAskUserRuntime,
|
|
18296
18539
|
createArchiverRuntime,
|
|
@@ -18310,4 +18553,4 @@ export {
|
|
|
18310
18553
|
DEFAULT_SELF_CONFIG_PRODUCT
|
|
18311
18554
|
};
|
|
18312
18555
|
|
|
18313
|
-
//# debugId=
|
|
18556
|
+
//# debugId=A750A8503E5A9A9064756E2164756E21
|