negotium 0.1.19 → 0.1.21
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 +146 -23
- package/dist/agent-helpers.js.map +14 -12
- package/dist/cron.js +137 -52
- package/dist/cron.js.map +20 -19
- package/dist/hosted-agent.js +29 -17
- package/dist/hosted-agent.js.map +7 -7
- package/dist/main.js +145 -55
- package/dist/main.js.map +20 -19
- package/dist/mcp-factories.js +23 -22
- package/dist/mcp-factories.js.map +3 -3
- package/dist/prompts.js +98 -9
- package/dist/prompts.js.map +6 -5
- package/dist/runtime/scripts/browser-passkey-policy.mjs +36 -0
- package/dist/runtime/scripts/browser-vault-transform.mjs +33 -0
- package/dist/runtime/scripts/mcp-patchright-http.mjs +22 -4
- package/dist/runtime/src/agents/archiver.ts +0 -14
- package/dist/runtime/src/agents/claude-provider.ts +11 -7
- package/dist/runtime/src/agents/execution-host.ts +10 -1
- package/dist/runtime/src/agents/idle-archiver.ts +21 -0
- package/dist/runtime/src/agents/maestro-provider.ts +9 -14
- package/dist/runtime/src/agents/mcp-tools/self-config.ts +1 -1
- package/dist/runtime/src/agents/mcp-tools/spawn-subagent.ts +6 -1
- package/dist/runtime/src/agents/memory-archive-policy.ts +34 -0
- package/dist/runtime/src/agents/model-catalog.ts +84 -18
- package/dist/runtime/src/mcp/factories/vault.ts +36 -34
- package/dist/runtime/src/mcp/vault-server.ts +1 -0
- package/dist/runtime/src/platform/mcp-config.ts +4 -8
- package/dist/runtime/src/platform/playwright/manager.ts +5 -2
- package/dist/runtime/src/prompts/builders.ts +36 -7
- package/dist/runtime/src/runtime/turn-runner.ts +2 -0
- package/dist/runtime/src/storage/topic-archive.ts +5 -2
- package/dist/runtime/src/topics/lifecycle.ts +2 -1
- package/dist/runtime/src/topics/session.ts +2 -0
- package/dist/runtime/src/version.ts +1 -1
- package/dist/storage.js +23 -3
- package/dist/storage.js.map +5 -4
- package/dist/types/packages/core/src/agents/claude-provider.d.ts +1 -0
- package/dist/types/packages/core/src/agents/execution-host.d.ts +2 -0
- package/dist/types/packages/core/src/agents/idle-archiver.d.ts +2 -0
- package/dist/types/packages/core/src/agents/memory-archive-policy.d.ts +14 -0
- package/dist/types/packages/core/src/agents/model-catalog.d.ts +77 -0
- package/dist/types/packages/core/src/mcp/factories/vault.d.ts +1 -0
- package/dist/types/packages/core/src/prompts/builders.d.ts +5 -1
- package/dist/types/packages/core/src/storage/topic-archive.d.ts +1 -0
- package/dist/types/packages/core/src/version.d.ts +1 -1
- package/package.json +2 -2
package/dist/main.js
CHANGED
|
@@ -2091,6 +2091,19 @@ function vaultDel(userId, key) {
|
|
|
2091
2091
|
function vaultList(userId) {
|
|
2092
2092
|
return activeVaultDatabase().prepare("SELECT key, description FROM vault WHERE user_id = ? ORDER BY key").all(userId);
|
|
2093
2093
|
}
|
|
2094
|
+
function vaultSubstituteDetailed(userId, text) {
|
|
2095
|
+
const entries = new Map(vaultListWithValues(userId).map((entry) => [entry.key, entry.value]));
|
|
2096
|
+
const usedKeys = new Set;
|
|
2097
|
+
const substituted = text.replace(/\{\{([^}]+)\}\}/g, (match, rawKey) => {
|
|
2098
|
+
const key = normalizeVaultKey(rawKey);
|
|
2099
|
+
const value = entries.get(key);
|
|
2100
|
+
if (value === undefined)
|
|
2101
|
+
return match;
|
|
2102
|
+
usedKeys.add(key);
|
|
2103
|
+
return value;
|
|
2104
|
+
});
|
|
2105
|
+
return { text: substituted, usedKeys: [...usedKeys] };
|
|
2106
|
+
}
|
|
2094
2107
|
function valueReferencesVaultKey(userId, value) {
|
|
2095
2108
|
const keys = new Set(vaultList(userId).map((entry) => entry.key));
|
|
2096
2109
|
const visit = (candidate) => {
|
|
@@ -2182,7 +2195,7 @@ function createVaultToolPolicy(host) {
|
|
|
2182
2195
|
}
|
|
2183
2196
|
return { isVaultBrokerTool, referencesRuntimeSecretStorage, shouldRedirectVaultTool };
|
|
2184
2197
|
}
|
|
2185
|
-
var SENSITIVE_RUNTIME_NAMES,
|
|
2198
|
+
var SENSITIVE_RUNTIME_NAMES, defaultVaultToolPolicy, isVaultBrokerTool, referencesRuntimeSecretStorage, shouldRedirectVaultTool;
|
|
2186
2199
|
var init_vault_tool_policy = __esm(async () => {
|
|
2187
2200
|
init_sensitive_path();
|
|
2188
2201
|
await init_vault();
|
|
@@ -3061,9 +3074,7 @@ var init_mcp_config = __esm(() => {
|
|
|
3061
3074
|
vault: {
|
|
3062
3075
|
...commonRuntimeMcpPolicy("vault"),
|
|
3063
3076
|
build({ userId, agent }) {
|
|
3064
|
-
const args = [`--user-id=${userId}
|
|
3065
|
-
if (agent === "codex")
|
|
3066
|
-
args.push("--http-only=true");
|
|
3077
|
+
const args = [`--user-id=${userId}`, "--list-only=true"];
|
|
3067
3078
|
return buildStdioMcpServer(agent, VAULT_SERVER, args);
|
|
3068
3079
|
}
|
|
3069
3080
|
}
|
|
@@ -3094,12 +3105,12 @@ function hostedMcpServers(opts) {
|
|
|
3094
3105
|
function redactHostedSecrets(userId, value) {
|
|
3095
3106
|
return activeHost().redactVaultSecrets(userId, value);
|
|
3096
3107
|
}
|
|
3108
|
+
function substituteHostedSecrets(userId, value) {
|
|
3109
|
+
return activeHost().substituteVaultSecrets(userId, value);
|
|
3110
|
+
}
|
|
3097
3111
|
function referencesHostedSecretStorage(value) {
|
|
3098
3112
|
return activeHost().referencesRuntimeSecretStorage(value);
|
|
3099
3113
|
}
|
|
3100
|
-
function shouldRedirectHostedVaultTool(userId, toolName, input) {
|
|
3101
|
-
return activeHost().shouldRedirectVaultTool(userId, toolName, input);
|
|
3102
|
-
}
|
|
3103
3114
|
function hostedClaudeCodeExecutablePath() {
|
|
3104
3115
|
return activeHost().claudeCodeExecutablePath();
|
|
3105
3116
|
}
|
|
@@ -3115,6 +3126,7 @@ var init_execution_host = __esm(async () => {
|
|
|
3115
3126
|
defaultHost = {
|
|
3116
3127
|
getMcpServersForQuery,
|
|
3117
3128
|
redactVaultSecrets,
|
|
3129
|
+
substituteVaultSecrets: (userId, value) => vaultSubstituteDetailed(userId, value).text,
|
|
3118
3130
|
referencesRuntimeSecretStorage,
|
|
3119
3131
|
shouldRedirectVaultTool,
|
|
3120
3132
|
claudeCodeExecutablePath: () => CLAUDE_EXECUTABLE,
|
|
@@ -3223,6 +3235,9 @@ var DEFAULT_CONTEXT_WARNING_RATIO = 0.8;
|
|
|
3223
3235
|
import { spawn as spawn2 } from "child_process";
|
|
3224
3236
|
import { existsSync as existsSync8, readFileSync as readFileSync6 } from "fs";
|
|
3225
3237
|
import { query } from "@anthropic-ai/claude-agent-sdk";
|
|
3238
|
+
function substituteClaudeToolInput(userId, input) {
|
|
3239
|
+
return deepMapStrings(input, (value) => substituteHostedSecrets(userId, value));
|
|
3240
|
+
}
|
|
3226
3241
|
function buildClaudeDisallowedTools(extra = undefined) {
|
|
3227
3242
|
return [
|
|
3228
3243
|
...new Set([
|
|
@@ -3453,14 +3468,14 @@ async function* claudeProvider(opts) {
|
|
|
3453
3468
|
};
|
|
3454
3469
|
}
|
|
3455
3470
|
const userId = opts.userId ?? "";
|
|
3456
|
-
|
|
3471
|
+
const withVault = substituteClaudeToolInput(userId, tool_input);
|
|
3472
|
+
if (JSON.stringify(withVault) === JSON.stringify(tool_input)) {
|
|
3457
3473
|
return { continue: true };
|
|
3458
3474
|
}
|
|
3459
3475
|
return {
|
|
3460
3476
|
hookSpecificOutput: {
|
|
3461
3477
|
hookEventName: "PreToolUse",
|
|
3462
|
-
|
|
3463
|
-
permissionDecisionReason: VAULT_BROKER_REDIRECT_ERROR
|
|
3478
|
+
updatedInput: withVault
|
|
3464
3479
|
}
|
|
3465
3480
|
};
|
|
3466
3481
|
}
|
|
@@ -3670,7 +3685,6 @@ var CLAUDE_DEFAULT_DISALLOWED_TOOLS, CLAUDE_NATIVE_AGENT_TOOLS, CLAUDE_IMAGE_MAX
|
|
|
3670
3685
|
var init_claude_provider = __esm(async () => {
|
|
3671
3686
|
init_claude_registry();
|
|
3672
3687
|
await init_execution_host();
|
|
3673
|
-
await init_vault_tool_policy();
|
|
3674
3688
|
init_file_events();
|
|
3675
3689
|
init_logger();
|
|
3676
3690
|
CLAUDE_DEFAULT_DISALLOWED_TOOLS = [
|
|
@@ -3693,7 +3707,7 @@ var init_claude_provider = __esm(async () => {
|
|
|
3693
3707
|
});
|
|
3694
3708
|
|
|
3695
3709
|
// ../../packages/core/src/version.ts
|
|
3696
|
-
var NEGOTIUM_VERSION = "0.1.
|
|
3710
|
+
var NEGOTIUM_VERSION = "0.1.21";
|
|
3697
3711
|
|
|
3698
3712
|
// ../../packages/core/src/agents/codex-native-multi-agent.ts
|
|
3699
3713
|
import { spawn as spawn3 } from "child_process";
|
|
@@ -4331,14 +4345,12 @@ function buildMaestroDisallowedTools(callerDisallowedTools = []) {
|
|
|
4331
4345
|
function buildVaultHook(userId) {
|
|
4332
4346
|
return {
|
|
4333
4347
|
name: "vault-guard",
|
|
4334
|
-
pre({
|
|
4348
|
+
pre({ input }) {
|
|
4335
4349
|
if (referencesHostedSecretStorage(input)) {
|
|
4336
4350
|
return { decision: "block", error: "Runtime secret storage access is not permitted" };
|
|
4337
4351
|
}
|
|
4338
|
-
|
|
4339
|
-
|
|
4340
|
-
}
|
|
4341
|
-
return { decision: "allow" };
|
|
4352
|
+
const substituted = deepMapStrings(input, (value) => substituteHostedSecrets(userId, value));
|
|
4353
|
+
return JSON.stringify(substituted) === JSON.stringify(input) ? { decision: "allow" } : { decision: "modify", input: substituted };
|
|
4342
4354
|
},
|
|
4343
4355
|
post({ output }) {
|
|
4344
4356
|
const redacted = redactHostedSecrets(userId, output);
|
|
@@ -4394,7 +4406,6 @@ var MAESTRO_DEFAULT_MAX_TOKENS = 32768, PROVIDER_ASK_USER_TOOL = "AskUserQuestio
|
|
|
4394
4406
|
var init_maestro_provider = __esm(async () => {
|
|
4395
4407
|
init_maestro_bootstrap_env();
|
|
4396
4408
|
await init_execution_host();
|
|
4397
|
-
await init_vault_tool_policy();
|
|
4398
4409
|
MAESTRO_NATIVE_TASK_TOOLS = [
|
|
4399
4410
|
"TaskCreate",
|
|
4400
4411
|
"TaskUpdate",
|
|
@@ -6068,11 +6079,18 @@ __export(exports_model_catalog, {
|
|
|
6068
6079
|
selectableModel: () => selectableModel,
|
|
6069
6080
|
resolveModelForAgent: () => resolveModelForAgent,
|
|
6070
6081
|
modelOwner: () => modelOwner,
|
|
6082
|
+
formatSelectableModel: () => formatSelectableModel,
|
|
6071
6083
|
SELECTABLE_MODELS: () => SELECTABLE_MODELS,
|
|
6072
6084
|
MODEL_OWNER: () => MODEL_OWNER,
|
|
6085
|
+
MODEL_COST_ROUTING_SUMMARY: () => MODEL_COST_ROUTING_SUMMARY,
|
|
6086
|
+
MODEL_COST_RESEARCHED_AT: () => MODEL_COST_RESEARCHED_AT,
|
|
6073
6087
|
FALLBACK_ORDER: () => FALLBACK_ORDER,
|
|
6074
6088
|
AGENT_DISPLAY_NAME: () => AGENT_DISPLAY_NAME
|
|
6075
6089
|
});
|
|
6090
|
+
function formatSelectableModel(candidate) {
|
|
6091
|
+
const tier = `${candidate.intelligenceTier[0].toUpperCase()}${candidate.intelligenceTier.slice(1)}`;
|
|
6092
|
+
return `${candidate.agent} / \`${candidate.model}\` [${tier}-level]: ${candidate.routingSummary}`;
|
|
6093
|
+
}
|
|
6076
6094
|
function selectableModel(value) {
|
|
6077
6095
|
const normalized = value.trim().toLowerCase();
|
|
6078
6096
|
return SELECTABLE_MODELS.find((candidate) => candidate.model === normalized);
|
|
@@ -6095,7 +6113,7 @@ function resolveModelForAgent(agent, requested, registry) {
|
|
|
6095
6113
|
return defaultModel;
|
|
6096
6114
|
return registry.validateModel(requested) ? requested : defaultModel;
|
|
6097
6115
|
}
|
|
6098
|
-
var MODEL_OWNER, SELECTABLE_MODELS, FALLBACK_ORDER, AGENT_DISPLAY_NAME;
|
|
6116
|
+
var MODEL_OWNER, MODEL_COST_RESEARCHED_AT = "2026-07-19", MODEL_COST_ROUTING_SUMMARY = "Cost basis (2026-07-19): Codex Pro 20x and Claude Max 20x are each $200/month; DeepSeek Pro is pay-per-token. Relative marginal token cost: DeepSeek Pro << Codex < Claude.", CODEX_PRO_20X_COST = "ChatGPT Pro 20x subscription: $200/month", CODEX_COMMUNITY_WEEKLY = "Community plan-level observation: roughly 2\u20134B raw/cached tokens per week; fresh-input equivalent is much lower and unstable (low confidence)", CLAUDE_MAX_20X_COST = "Claude Max 20x subscription: $200/month", CLAUDE_COMMUNITY_SESSION = "Community observations vary from roughly 220\u2013250K locally displayed tokens per 5-hour session to billions of cache-heavy raw tokens per week; calibrated reports value a full weekly allowance around $680\u2013$1,900 at API rates. Recent heavy-model reports reach the weekly cap after about 4\u20135 full sessions (low confidence; not a token cap)", SELECTABLE_MODELS, FALLBACK_ORDER, AGENT_DISPLAY_NAME;
|
|
6099
6117
|
var init_model_catalog = __esm(() => {
|
|
6100
6118
|
init_config();
|
|
6101
6119
|
MODEL_OWNER = {
|
|
@@ -6115,47 +6133,72 @@ var init_model_catalog = __esm(() => {
|
|
|
6115
6133
|
{
|
|
6116
6134
|
model: "gpt-5.6-sol",
|
|
6117
6135
|
agent: "codex",
|
|
6118
|
-
description: "
|
|
6136
|
+
description: "Highest-capability Codex route for the hardest agentic coding work.",
|
|
6137
|
+
intelligenceTier: "fable",
|
|
6138
|
+
routingSummary: "hardest coding work; 5x Codex quota cost",
|
|
6139
|
+
accessCost: CODEX_PRO_20X_COST,
|
|
6140
|
+
marginalTokenCost: "Codex credits: $5/M uncached input, $0.50/M cached input, $30/M output",
|
|
6141
|
+
estimatedUsage: `Official Pro 20x range: 300\u20131,800 local messages per 5 hours; quota weight 5x Luna. ${CODEX_COMMUNITY_WEEKLY}`
|
|
6119
6142
|
},
|
|
6120
6143
|
{
|
|
6121
6144
|
model: "gpt-5.6-terra",
|
|
6122
6145
|
agent: "codex",
|
|
6123
|
-
description: "
|
|
6146
|
+
description: "High-capability Codex route for complex coding and reasoning.",
|
|
6147
|
+
intelligenceTier: "opus",
|
|
6148
|
+
routingSummary: "complex coding and reasoning; 2.5x Codex quota cost",
|
|
6149
|
+
accessCost: CODEX_PRO_20X_COST,
|
|
6150
|
+
marginalTokenCost: "Codex credits: $2.50/M uncached input, $0.25/M cached input, $15/M output",
|
|
6151
|
+
estimatedUsage: `Official Pro 20x range: 400\u20132,200 local messages per 5 hours; quota weight 2.5x Luna. ${CODEX_COMMUNITY_WEEKLY}`
|
|
6124
6152
|
},
|
|
6125
6153
|
{
|
|
6126
6154
|
model: "gpt-5.6-luna",
|
|
6127
6155
|
agent: "codex",
|
|
6128
|
-
description: "
|
|
6129
|
-
|
|
6130
|
-
|
|
6131
|
-
|
|
6132
|
-
|
|
6133
|
-
|
|
6156
|
+
description: "Default Codex route with strong everyday coding intelligence.",
|
|
6157
|
+
intelligenceTier: "sonnet",
|
|
6158
|
+
routingSummary: "everyday coding default; lowest Codex quota cost (1x)",
|
|
6159
|
+
accessCost: CODEX_PRO_20X_COST,
|
|
6160
|
+
marginalTokenCost: "Codex credits: $1/M uncached input, $0.10/M cached input, $6/M output",
|
|
6161
|
+
estimatedUsage: `Official Pro 20x range: 1,000\u20135,600 local messages per 5 hours; lowest Codex quota weight (1x). ${CODEX_COMMUNITY_WEEKLY}`
|
|
6134
6162
|
},
|
|
6135
6163
|
{
|
|
6136
6164
|
model: "fable",
|
|
6137
6165
|
agent: "claude",
|
|
6138
|
-
description: "
|
|
6166
|
+
description: "Highest-capability Claude route for the hardest and longest-running tasks.",
|
|
6167
|
+
intelligenceTier: "fable",
|
|
6168
|
+
routingSummary: "hardest long-running work; highest Claude cost; explicit request only",
|
|
6169
|
+
accessCost: CLAUDE_MAX_20X_COST,
|
|
6170
|
+
marginalTokenCost: "Claude API/extra usage: $10/M input, $12.50/M cache write, $1/M cache read, $50/M output",
|
|
6171
|
+
estimatedUsage: `${CLAUDE_COMMUNITY_SESSION}; Fable drains weighted quota fastest, so use only on explicit user request. No stable per-model token cap is published.`
|
|
6139
6172
|
},
|
|
6140
6173
|
{
|
|
6141
6174
|
model: "opus",
|
|
6142
6175
|
agent: "claude",
|
|
6143
|
-
description: "
|
|
6176
|
+
description: "High-capability Claude route for complex reasoning and tool-heavy work.",
|
|
6177
|
+
intelligenceTier: "opus",
|
|
6178
|
+
routingSummary: "complex reasoning and tool-heavy work; about 2.5x Sonnet marginal cost",
|
|
6179
|
+
accessCost: CLAUDE_MAX_20X_COST,
|
|
6180
|
+
marginalTokenCost: "Claude API/extra usage: $5/M input, $6.25/M cache write, $0.50/M cache read, $25/M output",
|
|
6181
|
+
estimatedUsage: `${CLAUDE_COMMUNITY_SESSION}; Opus uses the shared all-model weekly pool more quickly than Sonnet. No stable per-model token cap is published.`
|
|
6144
6182
|
},
|
|
6145
6183
|
{
|
|
6146
6184
|
model: "sonnet",
|
|
6147
6185
|
agent: "claude",
|
|
6148
|
-
description: "
|
|
6186
|
+
description: "Default Claude route for capable, efficient everyday work.",
|
|
6187
|
+
intelligenceTier: "sonnet",
|
|
6188
|
+
routingSummary: "capable everyday default; lowest Claude model cost",
|
|
6189
|
+
accessCost: CLAUDE_MAX_20X_COST,
|
|
6190
|
+
marginalTokenCost: "Claude API/extra usage introductory rate: $2/M input, $2.50/M cache write, $0.20/M cache read, $10/M output through 2026-08-31; then $3/M input and $15/M output",
|
|
6191
|
+
estimatedUsage: `${CLAUDE_COMMUNITY_SESSION}; Sonnet also has a separate weekly allowance and normally provides the highest Claude throughput. No stable weekly token cap is published.`
|
|
6149
6192
|
},
|
|
6150
6193
|
{
|
|
6151
6194
|
model: "deepseek-pro",
|
|
6152
6195
|
agent: "maestro",
|
|
6153
|
-
description: "Sonnet-level
|
|
6154
|
-
|
|
6155
|
-
|
|
6156
|
-
|
|
6157
|
-
|
|
6158
|
-
|
|
6196
|
+
description: "API-priced Sonnet-level route for cost-efficient everyday work.",
|
|
6197
|
+
intelligenceTier: "sonnet",
|
|
6198
|
+
routingSummary: "cost-efficient everyday work; pay-per-token and cheapest route",
|
|
6199
|
+
accessCost: "DeepSeek V4 Pro pay-as-you-go API; no monthly subscription required",
|
|
6200
|
+
marginalTokenCost: "DeepSeek API: $0.435/M uncached input, $0.003625/M cached input, $0.87/M output",
|
|
6201
|
+
estimatedUsage: "No subscription token cap; pay per token. Official account concurrency limit is 500 requests."
|
|
6159
6202
|
}
|
|
6160
6203
|
];
|
|
6161
6204
|
FALLBACK_ORDER = {
|
|
@@ -7109,6 +7152,7 @@ async function spawnPlaywright(instanceKey, userId, reservedPort, browserBin = P
|
|
|
7109
7152
|
String(port),
|
|
7110
7153
|
"--host",
|
|
7111
7154
|
"127.0.0.1",
|
|
7155
|
+
"--headed",
|
|
7112
7156
|
"--user-data-dir",
|
|
7113
7157
|
userDataDir
|
|
7114
7158
|
];
|
|
@@ -7117,6 +7161,7 @@ async function spawnPlaywright(instanceKey, userId, reservedPort, browserBin = P
|
|
|
7117
7161
|
const childEnv = {
|
|
7118
7162
|
...process.env,
|
|
7119
7163
|
NEGOTIUM_BROWSER_CAPABILITY: capability,
|
|
7164
|
+
NEGOTIUM_BROWSER_VAULT_USER_ID: userId,
|
|
7120
7165
|
...proxy ? {
|
|
7121
7166
|
NEGOTIUM_BROWSER_PROXY_SERVER: proxy.server,
|
|
7122
7167
|
...proxy.username ? { NEGOTIUM_BROWSER_PROXY_USERNAME: proxy.username } : {},
|
|
@@ -8434,7 +8479,7 @@ function createSelfConfigToolDefinitions(ctx) {
|
|
|
8434
8479
|
return [
|
|
8435
8480
|
{
|
|
8436
8481
|
name: "set_model",
|
|
8437
|
-
description: "Set the model for THIS topic
|
|
8482
|
+
description: "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.",
|
|
8438
8483
|
schema: { model: z2.string().describe("Model id valid for the topic's current agent.") },
|
|
8439
8484
|
async handler({ model }) {
|
|
8440
8485
|
return mcpResult(setSelfConfigModel(getCtx(), model));
|
|
@@ -8831,7 +8876,7 @@ function loadAgentPrompt(filename) {
|
|
|
8831
8876
|
prompt: match[2].trim()
|
|
8832
8877
|
};
|
|
8833
8878
|
}
|
|
8834
|
-
function buildRuntimeToolSection(agentKind, canSpawnSubagents = false, visualTools = false, fileDeliveryTools = false) {
|
|
8879
|
+
function buildRuntimeToolSection(agentKind, canSpawnSubagents = false, visualTools = false, fileDeliveryTools = false, currentModel, currentEffort) {
|
|
8835
8880
|
const runtimeNamespace = "mcp__runtime";
|
|
8836
8881
|
const taskNamespace = "mcp__task";
|
|
8837
8882
|
const visualToolLine = agentKind === "codex" ? `To display charts, tables, or interactive HTML results to the user, call the \`show_html\` function in the \`${runtimeNamespace}\` namespace with { html: "<complete HTML string>", title?: "optional title" }.` : `To display charts, tables, or interactive HTML results to the user, call the MCP tool "${runtimeNamespace}__show_html" with { html: "<complete HTML string>", title?: "optional title" }.`;
|
|
@@ -8889,20 +8934,26 @@ function buildRuntimeToolSection(agentKind, canSpawnSubagents = false, visualToo
|
|
|
8889
8934
|
"Do not use session communication to make another topic perform destructive changes without the user's clear intent.",
|
|
8890
8935
|
...spawnSubagentSection
|
|
8891
8936
|
];
|
|
8937
|
+
const modelCatalog = SELECTABLE_MODELS.map((candidate) => `- ${formatSelectableModel(candidate)}`);
|
|
8892
8938
|
const topicConfig = [
|
|
8893
8939
|
"",
|
|
8894
8940
|
"## Topic Configuration (model / agent / effort)",
|
|
8941
|
+
`Current execution: agent=\`${agentKind}\`, model=\`${currentModel ?? "unknown (call get_model)"}\`, effort=\`${currentEffort ?? "provider default/off"}\`.`,
|
|
8895
8942
|
"The user's configured agent/model/effort is intentional. Preserve it by default.",
|
|
8896
8943
|
`When the user explicitly asks to change the model, agent backend, or reasoning effort for THIS topic, call "${runtimeNamespace}__set_model", "${runtimeNamespace}__set_agent", or "${runtimeNamespace}__set_effort". The change applies from your NEXT turn. After calling, briefly confirm and the system will continue with the new setting.`,
|
|
8897
8944
|
"`set_effort` is available but discouraged; use it only when the user explicitly requests an effort change.",
|
|
8898
|
-
"`set_model` may be called autonomously only when the current model is clearly below the task's required capability, such as complex algorithm design, proof-level math, or broad multi-file refactoring.
|
|
8945
|
+
"`set_model` may be called autonomously only when the current model is clearly below the task's required capability, such as complex algorithm design, proof-level math, or broad multi-file refactoring. Choose the best-fit model directly from the same-agent catalog; model selection is not a mandatory one-step ladder. End the turn after changing it. Do not use vague task complexity as a trigger.",
|
|
8899
8946
|
"`set_agent` autonomous calls are forbidden. Only switch agent when the user explicitly asks to switch runtime, e.g. \u201Ccodex\uB85C \uAC00\u201D, \u201Cclaude\uB85C \uBC14\uAFD4\u201D.",
|
|
8900
8947
|
"Never use `fable` unless the user explicitly requests it; it is expensive.",
|
|
8901
8948
|
"",
|
|
8902
|
-
"
|
|
8903
|
-
|
|
8904
|
-
|
|
8905
|
-
"
|
|
8949
|
+
"Model catalog (capability/cost routing guidance):",
|
|
8950
|
+
MODEL_COST_ROUTING_SUMMARY,
|
|
8951
|
+
...modelCatalog,
|
|
8952
|
+
"",
|
|
8953
|
+
"Accepted effort values:",
|
|
8954
|
+
"- claude: `low`, `medium`, `high`, `xhigh`, `max`.",
|
|
8955
|
+
"- codex: `low`, `medium`, `high`, `xhigh`, `max`.",
|
|
8956
|
+
"- maestro: `low`, `medium`, `high`, `xhigh`, `max`.",
|
|
8906
8957
|
"Agent guidance when the user explicitly asks to switch: `codex` for deepest reasoning and complex code/math; `claude` for tool-heavy MCP/file automation; `maestro` for inexpensive fast drafts and lighter experiments."
|
|
8907
8958
|
];
|
|
8908
8959
|
if (agentKind !== "claude") {
|
|
@@ -8925,7 +8976,7 @@ function buildTopicSystemPrompt(opts) {
|
|
|
8925
8976
|
TOPIC_TITLE: opts.topicTitle,
|
|
8926
8977
|
WORKSPACE_CWD: opts.workspaceCwd,
|
|
8927
8978
|
UPLOADS_DIR: uploadsDir
|
|
8928
|
-
}) + buildRuntimeToolSection(opts.agentKind, opts.canSpawnSubagents, opts.visualTools, opts.fileDeliveryTools);
|
|
8979
|
+
}) + buildRuntimeToolSection(opts.agentKind, opts.canSpawnSubagents, opts.visualTools, opts.fileDeliveryTools, opts.currentModel, opts.currentEffort);
|
|
8929
8980
|
if (opts.description?.trim()) {
|
|
8930
8981
|
prompt += `
|
|
8931
8982
|
|
|
@@ -8941,7 +8992,7 @@ function buildChannelSystemPrompt(opts) {
|
|
|
8941
8992
|
TOPIC_TITLE: opts.topicTitle,
|
|
8942
8993
|
WORKSPACE_CWD: opts.workspaceCwd,
|
|
8943
8994
|
UPLOADS_DIR: uploadsDir
|
|
8944
|
-
}) + buildRuntimeToolSection(opts.agentKind, false, opts.visualTools, opts.fileDeliveryTools);
|
|
8995
|
+
}) + buildRuntimeToolSection(opts.agentKind, false, opts.visualTools, opts.fileDeliveryTools, opts.currentModel, opts.currentEffort);
|
|
8945
8996
|
}
|
|
8946
8997
|
function buildManagerSystemPrompt(opts) {
|
|
8947
8998
|
return `${buildTopicSystemPrompt(opts)}
|
|
@@ -8991,6 +9042,7 @@ User-uploaded files for this Channel are copied under "{{UPLOADS_DIR}}" as attac
|
|
|
8991
9042
|
This is the shared "General" hub of the user's workspace.
|
|
8992
9043
|
Act as the workspace manager: orient the user across topics, summarize what is going on, and route focused work to the right room.`, _topicSystemPromptTemplate = null, _channelSystemPromptTemplate = null, _managerSystemPromptTemplate = null, _visualDesignGuide = null;
|
|
8993
9044
|
var init_builders = __esm(() => {
|
|
9045
|
+
init_model_catalog();
|
|
8994
9046
|
init_config();
|
|
8995
9047
|
init_logger();
|
|
8996
9048
|
PROMPTS_DIR = resolve6(PROJECT_ROOT, "src/prompts");
|
|
@@ -9109,10 +9161,6 @@ function getArchiverDef() {
|
|
|
9109
9161
|
}
|
|
9110
9162
|
function runArchiverTurn(params) {
|
|
9111
9163
|
const { userId, topicId, topicTitle, archivePath, messageCount, mode = "deleted-topic" } = params;
|
|
9112
|
-
if (mode !== "active-topic" && messageCount < MIN_ARCHIVE_MESSAGES) {
|
|
9113
|
-
logger.info({ userId, topicTitle, messageCount, min: MIN_ARCHIVE_MESSAGES }, "archiver: skipped \u2014 too few messages to distil");
|
|
9114
|
-
return false;
|
|
9115
|
-
}
|
|
9116
9164
|
let archiverDef;
|
|
9117
9165
|
try {
|
|
9118
9166
|
archiverDef = getArchiverDef();
|
|
@@ -9320,7 +9368,7 @@ ${rolled.join(`
|
|
|
9320
9368
|
logger.warn({ err: err2, topicTitle }, "archiver: failed to post #General notification");
|
|
9321
9369
|
}
|
|
9322
9370
|
}
|
|
9323
|
-
var MAX_BRIEF_ENTRIES = 8,
|
|
9371
|
+
var MAX_BRIEF_ENTRIES = 8, MAX_SESSION_STEPS = 20, activeArchiverSessions, _archiverDef = null;
|
|
9324
9372
|
var init_archiver = __esm(async () => {
|
|
9325
9373
|
await init_agents();
|
|
9326
9374
|
await init_bus();
|
|
@@ -9335,6 +9383,26 @@ var init_archiver = __esm(async () => {
|
|
|
9335
9383
|
activeArchiverSessions = new Map;
|
|
9336
9384
|
});
|
|
9337
9385
|
|
|
9386
|
+
// ../../packages/core/src/agents/memory-archive-policy.ts
|
|
9387
|
+
function countMemoryArchiveExchanges(rows) {
|
|
9388
|
+
let waitingForAssistant = false;
|
|
9389
|
+
let completed = 0;
|
|
9390
|
+
for (const row of rows) {
|
|
9391
|
+
const assistant = row.author_id === "ai" || Boolean(row.agent_type);
|
|
9392
|
+
const conversational = row.kind == null || row.kind === "message";
|
|
9393
|
+
if (!assistant && row.author_id !== "system" && conversational) {
|
|
9394
|
+
waitingForAssistant = true;
|
|
9395
|
+
continue;
|
|
9396
|
+
}
|
|
9397
|
+
if (assistant && conversational && waitingForAssistant) {
|
|
9398
|
+
completed++;
|
|
9399
|
+
waitingForAssistant = false;
|
|
9400
|
+
}
|
|
9401
|
+
}
|
|
9402
|
+
return completed;
|
|
9403
|
+
}
|
|
9404
|
+
var MIN_MEMORY_ARCHIVE_EXCHANGES = 6;
|
|
9405
|
+
|
|
9338
9406
|
// ../../packages/core/src/storage/topic-transcript.ts
|
|
9339
9407
|
function parseJsonField(value) {
|
|
9340
9408
|
if (!value)
|
|
@@ -9422,8 +9490,9 @@ function archiveTopicMessages(topicId, topicTitle, options = {}) {
|
|
|
9422
9490
|
counter++;
|
|
9423
9491
|
}
|
|
9424
9492
|
}
|
|
9425
|
-
|
|
9426
|
-
|
|
9493
|
+
const exchangeCount = countMemoryArchiveExchanges(rows);
|
|
9494
|
+
logger.info({ topicId, topicTitle, archive: path, messageCount: rows.length, exchangeCount, lastRowid }, "archiveTopicMessages: archived topic messages");
|
|
9495
|
+
return { path, messageCount: rows.length, exchangeCount, lastRowid };
|
|
9427
9496
|
}
|
|
9428
9497
|
var init_topic_archive = __esm(async () => {
|
|
9429
9498
|
init_logger();
|
|
@@ -9641,6 +9710,7 @@ function archiveActiveTopicForMemory(topicId, userId, options) {
|
|
|
9641
9710
|
if (!options.allowMentionOnly && topic.aiMode === "mention")
|
|
9642
9711
|
return "mention-only-channel";
|
|
9643
9712
|
let skipped = "empty";
|
|
9713
|
+
let skipMemoryTurn = false;
|
|
9644
9714
|
const claim = claimTopicArchiveJob(topicId, (afterRowid) => {
|
|
9645
9715
|
const pending = getMessagesForTopicAfterRowid(topicId, afterRowid);
|
|
9646
9716
|
const minMessages = options.minMessages;
|
|
@@ -9649,6 +9719,8 @@ function archiveActiveTopicForMemory(topicId, userId, options) {
|
|
|
9649
9719
|
logger.debug({ topicId, topicTitle: topic.title, pending: pending.length, minMessages }, "topic-memory-archiver: skipped below threshold");
|
|
9650
9720
|
return null;
|
|
9651
9721
|
}
|
|
9722
|
+
const exchangeCount = countMemoryArchiveExchanges(pending);
|
|
9723
|
+
skipMemoryTurn = options.minExchanges !== undefined && exchangeCount < options.minExchanges;
|
|
9652
9724
|
const archived = (options.archiveMessages ?? archiveTopicMessages)(topicId, topic.title, {
|
|
9653
9725
|
afterRowid,
|
|
9654
9726
|
reason: options.reason
|
|
@@ -9666,6 +9738,18 @@ function archiveActiveTopicForMemory(topicId, userId, options) {
|
|
|
9666
9738
|
if (claim.kind === "busy")
|
|
9667
9739
|
return "busy";
|
|
9668
9740
|
const { job } = claim;
|
|
9741
|
+
if (skipMemoryTurn) {
|
|
9742
|
+
settleTopicArchiveJob(topicId, job.archivePath, true);
|
|
9743
|
+
logger.info({
|
|
9744
|
+
topicId,
|
|
9745
|
+
topicTitle: topic.title,
|
|
9746
|
+
messageCount: job.messageCount,
|
|
9747
|
+
minExchanges: options.minExchanges,
|
|
9748
|
+
archive: job.archivePath,
|
|
9749
|
+
reason: options.reason
|
|
9750
|
+
}, "topic-memory-archiver: raw snapshot preserved below exchange threshold");
|
|
9751
|
+
return "below-threshold";
|
|
9752
|
+
}
|
|
9669
9753
|
const memoryTopic = getTopicMemoryOrigin(topicId) ?? topic;
|
|
9670
9754
|
const launched = (options.launchArchiver ?? runArchiverTurn)({
|
|
9671
9755
|
userId,
|
|
@@ -11606,6 +11690,7 @@ __export(exports_turn_runner, {
|
|
|
11606
11690
|
isPathInside: () => isPathInside,
|
|
11607
11691
|
isLikelyCurrentChannelTrigger: () => isLikelyCurrentChannelTrigger,
|
|
11608
11692
|
ingestAttachment: () => ingestAttachment,
|
|
11693
|
+
formatSelectableModel: () => formatSelectableModel,
|
|
11609
11694
|
formatChannelTranscriptLine: () => formatChannelTranscriptLine,
|
|
11610
11695
|
escapeRegExp: () => escapeRegExp2,
|
|
11611
11696
|
escapeHtml: () => escapeHtml2,
|
|
@@ -11623,6 +11708,8 @@ __export(exports_turn_runner, {
|
|
|
11623
11708
|
SESSION_EXPIRED_MSG: () => SESSION_EXPIRED_MSG,
|
|
11624
11709
|
SELECTABLE_MODELS: () => SELECTABLE_MODELS,
|
|
11625
11710
|
MODEL_OWNER: () => MODEL_OWNER,
|
|
11711
|
+
MODEL_COST_ROUTING_SUMMARY: () => MODEL_COST_ROUTING_SUMMARY,
|
|
11712
|
+
MODEL_COST_RESEARCHED_AT: () => MODEL_COST_RESEARCHED_AT,
|
|
11626
11713
|
FALLBACK_ORDER: () => FALLBACK_ORDER,
|
|
11627
11714
|
AGENT_DISPLAY_NAME: () => AGENT_DISPLAY_NAME
|
|
11628
11715
|
});
|
|
@@ -12830,6 +12917,8 @@ function startAiTurn(params) {
|
|
|
12830
12917
|
topicTitle: topic.title,
|
|
12831
12918
|
workspaceCwd,
|
|
12832
12919
|
agentKind,
|
|
12920
|
+
currentModel: resolvedModel,
|
|
12921
|
+
currentEffort: resolvedEffort,
|
|
12833
12922
|
description: topic.description,
|
|
12834
12923
|
canSpawnSubagents: peerBridge?.canSpawnSubagents ?? (topicRecord?.kind === "agent" && !topicRecord.isSubagent),
|
|
12835
12924
|
visualTools,
|
|
@@ -13508,7 +13597,7 @@ async function deleteTopicCascadeImpl(topic, userId, options, deletingAncestorId
|
|
|
13508
13597
|
logger.warn({ err: err2, topicId }, "deleteTopicCascade: archive failed but force=true - continuing with hard delete");
|
|
13509
13598
|
}
|
|
13510
13599
|
}
|
|
13511
|
-
if (archived) {
|
|
13600
|
+
if (archived && archived.exchangeCount >= MIN_MEMORY_ARCHIVE_EXCHANGES) {
|
|
13512
13601
|
try {
|
|
13513
13602
|
const memoryTopic = getTopicMemoryOrigin(topicId) ?? topic;
|
|
13514
13603
|
runArchiverTurn({
|
|
@@ -14048,7 +14137,7 @@ function createSpawnSubagentToolDefinition(ctx) {
|
|
|
14048
14137
|
task: z3.string().describe("Self-contained task brief for the subagent. It sees nothing else \u2014 include all context."),
|
|
14049
14138
|
name: z3.string().optional().describe("Short name for the subagent room. Auto-generated when omitted."),
|
|
14050
14139
|
agent: z3.enum(["claude", "codex", "maestro"]).optional().describe("Agent backend override. Defaults to this room's agent."),
|
|
14051
|
-
model: z3.string().optional().describe(
|
|
14140
|
+
model: z3.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.`)
|
|
14052
14141
|
},
|
|
14053
14142
|
async handler(input) {
|
|
14054
14143
|
return spawnSubagent(ctx, input);
|
|
@@ -14556,6 +14645,7 @@ async function restartTopicSession(topicId, userId, reason = "topic-session-rest
|
|
|
14556
14645
|
(options.archiveMemory ?? archiveActiveTopicForMemory)(topicId, userId, {
|
|
14557
14646
|
reason: "reset",
|
|
14558
14647
|
minMessages: 1,
|
|
14648
|
+
minExchanges: MIN_MEMORY_ARCHIVE_EXCHANGES,
|
|
14559
14649
|
allowMentionOnly: true,
|
|
14560
14650
|
skipBusyCheck: true
|
|
14561
14651
|
});
|
|
@@ -32799,4 +32889,4 @@ switch (command) {
|
|
|
32799
32889
|
}
|
|
32800
32890
|
}
|
|
32801
32891
|
|
|
32802
|
-
//# debugId=
|
|
32892
|
+
//# debugId=C8F4C2CD3CFA25F564756E2164756E21
|