openfox 2.0.0-beta.5 → 2.0.0-beta.6
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/{chat-handler-BM6EBFKS.js → chat-handler-27FY5TEH.js} +14 -27
- package/dist/{chunk-CLGRPDZT.js → chunk-3FFHHYWP.js} +174 -90
- package/dist/{chunk-HGAMIPFO.js → chunk-7FDY3EOH.js} +18 -176
- package/dist/{chunk-V6DYJV5R.js → chunk-7TTEGAO6.js} +12 -10
- package/dist/{chunk-T4HV6GS5.js → chunk-BVHFMAVN.js} +1 -1
- package/dist/{chunk-OBD6D5ZO.js → chunk-CDDMHSZF.js} +4 -4
- package/dist/{chunk-HHAJ3QF6.js → chunk-EMJGF3A7.js} +9 -24
- package/dist/{chunk-DFWGWULB.js → chunk-FRCLNAE2.js} +2935 -3127
- package/dist/{chunk-RF2JGDSS.js → chunk-IGSZUXQP.js} +3 -3
- package/dist/{chunk-UH27FDT7.js → chunk-NPHYEUYE.js} +124 -12
- package/dist/{chunk-NNEHZT3V.js → chunk-QUSUEN5R.js} +3 -3
- package/dist/{chunk-I67T2E5K.js → chunk-R3EK3ODJ.js} +6 -6
- package/dist/{chunk-X36JIWSF.js → chunk-RBJ25FIR.js} +135 -147
- package/dist/{chunk-PSJIT5LZ.js → chunk-RFNEDBVO.js} +4 -4
- package/dist/chunk-RI6GAMNP.js +13 -0
- package/dist/{chunk-XL7SW5B4.js → chunk-XJEOP6XU.js} +5 -4
- package/dist/cli/dev.js +1 -1
- package/dist/cli/index.js +1 -1
- package/dist/compactor-TDNRM3A7.js +9 -0
- package/dist/{config-YU7NYZYG.js → config-VBBMTXJZ.js} +5 -6
- package/dist/{events-T37KTNCX.js → events-PQ3KTI5H.js} +8 -7
- package/dist/{folding-IIKWAGG2.js → folding-CXORTBAU.js} +2 -2
- package/dist/{orchestrator-JTUHXF7C.js → orchestrator-QDCVUBCL.js} +18 -22
- package/dist/package.json +1 -1
- package/dist/{processor-66YBBQ6B.js → processor-K4B7QRO2.js} +8 -9
- package/dist/{protocol-ALBHLBBF.js → protocol-CN24IKQN.js} +3 -5
- package/dist/{protocol-CiYlonA5.d.ts → protocol-De-Pzgry.d.ts} +10 -0
- package/dist/{provider-HTJEB3ON.js → provider-NRWSSO55.js} +9 -10
- package/dist/{serve-EUEQ6ERI.js → serve-J6EM3G6N.js} +25 -26
- package/dist/server/index.d.ts +1 -6
- package/dist/server/index.js +15 -16
- package/dist/{settings-VRAOAPLA.js → settings-6XX56F3F.js} +2 -2
- package/dist/shared/index.d.ts +2 -2
- package/dist/shared/index.js +1 -1
- package/dist/{tools-56LACLKH.js → tools-GCANYSB7.js} +11 -13
- package/dist/web/assets/{index-C5gaXnFj.css → index-aa3jRAZ9.css} +2 -2
- package/dist/web/assets/index-ntDiC8b_.js +299 -0
- package/dist/web/index.html +2 -2
- package/dist/web/sw.js +1 -1
- package/dist/workflow-defaults/default.workflow.json +3 -3
- package/package.json +1 -1
- package/dist/auto-compaction-2ZAYDXGF.js +0 -27
- package/dist/chunk-CGZHLM3K.js +0 -70
- package/dist/chunk-SZKEGZIB.js +0 -140
- package/dist/runtime-config-NPSPMRDA.js +0 -9
- package/dist/vision-fallback-3MIZZ6NQ.js +0 -22
- package/dist/web/assets/index-DQ2Vv-Yl.js +0 -317
- /package/dist/web/{workbox-7fc22fbe.js → workbox-8c29f6e4.js} +0 -0
|
@@ -2,11 +2,11 @@ import {
|
|
|
2
2
|
clearModelCache,
|
|
3
3
|
createLLMClient,
|
|
4
4
|
detectModel
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-EMJGF3A7.js";
|
|
6
6
|
import {
|
|
7
7
|
detectBackend,
|
|
8
8
|
getModelProfile
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-7FDY3EOH.js";
|
|
10
10
|
import {
|
|
11
11
|
logger
|
|
12
12
|
} from "./chunk-K44MW7JJ.js";
|
|
@@ -511,4 +511,4 @@ export {
|
|
|
511
511
|
parseDefaultModelSelection,
|
|
512
512
|
createProviderManager
|
|
513
513
|
};
|
|
514
|
-
//# sourceMappingURL=chunk-
|
|
514
|
+
//# sourceMappingURL=chunk-IGSZUXQP.js.map
|
|
@@ -1,6 +1,3 @@
|
|
|
1
|
-
import {
|
|
2
|
-
getDatabase
|
|
3
|
-
} from "./chunk-FBGWG4N6.js";
|
|
4
1
|
import {
|
|
5
2
|
buildContextMessagesFromEventHistory,
|
|
6
3
|
buildMessagesFromStoredEvents,
|
|
@@ -8,10 +5,10 @@ import {
|
|
|
8
5
|
foldContextState,
|
|
9
6
|
foldSessionState,
|
|
10
7
|
spreadOptionalMessageFields
|
|
11
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-XJEOP6XU.js";
|
|
12
9
|
import {
|
|
13
|
-
|
|
14
|
-
} from "./chunk-
|
|
10
|
+
getDatabase
|
|
11
|
+
} from "./chunk-FBGWG4N6.js";
|
|
15
12
|
import {
|
|
16
13
|
logger
|
|
17
14
|
} from "./chunk-K44MW7JJ.js";
|
|
@@ -104,6 +101,18 @@ var EventStore = class {
|
|
|
104
101
|
CREATE INDEX IF NOT EXISTS idx_events_session_type
|
|
105
102
|
ON events(session_id, event_type)
|
|
106
103
|
`);
|
|
104
|
+
this.db.exec(`
|
|
105
|
+
CREATE TABLE IF NOT EXISTS tombstones (
|
|
106
|
+
session_id TEXT NOT NULL,
|
|
107
|
+
seq INTEGER NOT NULL,
|
|
108
|
+
timestamp INTEGER NOT NULL,
|
|
109
|
+
UNIQUE(session_id, seq)
|
|
110
|
+
)
|
|
111
|
+
`);
|
|
112
|
+
this.db.exec(`
|
|
113
|
+
CREATE INDEX IF NOT EXISTS idx_tombstones_session_seq
|
|
114
|
+
ON tombstones(session_id, seq)
|
|
115
|
+
`);
|
|
107
116
|
}
|
|
108
117
|
// --------------------------------------------------------------------------
|
|
109
118
|
// Append
|
|
@@ -182,10 +191,41 @@ var EventStore = class {
|
|
|
182
191
|
* Get all events for a session, optionally starting from a specific seq
|
|
183
192
|
*/
|
|
184
193
|
getEvents(sessionId, fromSeq) {
|
|
185
|
-
const query = fromSeq !== void 0 ? `SELECT
|
|
194
|
+
const query = fromSeq !== void 0 ? `SELECT e.* FROM events e
|
|
195
|
+
LEFT JOIN tombstones t ON e.session_id = t.session_id AND e.seq = t.seq
|
|
196
|
+
WHERE e.session_id = ? AND e.seq >= ? AND t.seq IS NULL
|
|
197
|
+
ORDER BY e.seq` : `SELECT e.* FROM events e
|
|
198
|
+
LEFT JOIN tombstones t ON e.session_id = t.session_id AND e.seq = t.seq
|
|
199
|
+
WHERE e.session_id = ? AND t.seq IS NULL
|
|
200
|
+
ORDER BY e.seq`;
|
|
186
201
|
const rows = fromSeq !== void 0 ? this.db.prepare(query).all(sessionId, fromSeq) : this.db.prepare(query).all(sessionId);
|
|
187
202
|
return rows.map((row) => this.rowToStoredEvent(row));
|
|
188
203
|
}
|
|
204
|
+
/**
|
|
205
|
+
* Soft-delete (tombstone) events by sequence number.
|
|
206
|
+
* Tombstoned events are hidden from getEvents but remain in the database.
|
|
207
|
+
*
|
|
208
|
+
* @param sessionId - The session ID
|
|
209
|
+
* @param seqs - Array of sequence numbers to tombstone
|
|
210
|
+
* @returns The number of events tombstoned
|
|
211
|
+
*/
|
|
212
|
+
tombstoneEvents(sessionId, seqs) {
|
|
213
|
+
if (seqs.length === 0) return 0;
|
|
214
|
+
const timestamp = Date.now();
|
|
215
|
+
const insert = this.db.prepare(
|
|
216
|
+
`INSERT OR IGNORE INTO tombstones (session_id, seq, timestamp)
|
|
217
|
+
VALUES (?, ?, ?)`
|
|
218
|
+
);
|
|
219
|
+
let count = 0;
|
|
220
|
+
const transaction = this.db.transaction(() => {
|
|
221
|
+
for (const seq of seqs) {
|
|
222
|
+
const result = insert.run(sessionId, seq, timestamp);
|
|
223
|
+
count += result.changes;
|
|
224
|
+
}
|
|
225
|
+
});
|
|
226
|
+
transaction();
|
|
227
|
+
return count;
|
|
228
|
+
}
|
|
189
229
|
/**
|
|
190
230
|
* Get the latest sequence number for a session
|
|
191
231
|
*/
|
|
@@ -791,6 +831,70 @@ function mapSessionSummaryRow(row) {
|
|
|
791
831
|
};
|
|
792
832
|
}
|
|
793
833
|
|
|
834
|
+
// src/server/config.ts
|
|
835
|
+
import { z } from "zod";
|
|
836
|
+
var backendSchema = z.enum(["auto", "vllm", "sglang", "ollama", "llamacpp"]).default("auto");
|
|
837
|
+
var envSchema = z.object({
|
|
838
|
+
// New env var name, with fallback to old name for backward compatibility
|
|
839
|
+
OPENFOX_LLM_URL: z.string().url().optional(),
|
|
840
|
+
OPENFOX_VLLM_URL: z.string().url().optional(),
|
|
841
|
+
OPENFOX_BACKEND: backendSchema,
|
|
842
|
+
OPENFOX_MODEL_NAME: z.string().default("qwen3.5-122b-int4-autoround"),
|
|
843
|
+
OPENFOX_MAX_CONTEXT: z.coerce.number().default(2e5),
|
|
844
|
+
OPENFOX_PORT: z.coerce.number().default(10369),
|
|
845
|
+
OPENFOX_HOST: z.string().optional(),
|
|
846
|
+
OPENFOX_WORKDIR: z.string().optional(),
|
|
847
|
+
OPENFOX_DB_PATH: z.string().default("./openfox.db"),
|
|
848
|
+
OPENFOX_LOG_LEVEL: z.enum(["debug", "info", "warn", "error"]).default("info"),
|
|
849
|
+
OPENFOX_DISABLE_THINKING: z.coerce.boolean().default(false),
|
|
850
|
+
OPENFOX_DEV: z.coerce.boolean().default(false)
|
|
851
|
+
});
|
|
852
|
+
function loadConfig() {
|
|
853
|
+
const env = envSchema.parse(process.env);
|
|
854
|
+
const llmUrl = env.OPENFOX_LLM_URL ?? env.OPENFOX_VLLM_URL ?? "http://localhost:8000/v1";
|
|
855
|
+
const workdir = env.OPENFOX_WORKDIR ?? process.cwd();
|
|
856
|
+
return {
|
|
857
|
+
llm: {
|
|
858
|
+
baseUrl: llmUrl,
|
|
859
|
+
model: env.OPENFOX_MODEL_NAME,
|
|
860
|
+
timeout: 3e5,
|
|
861
|
+
// 5 minutes (deprecated, kept for backward compatibility)
|
|
862
|
+
idleTimeout: 3e5,
|
|
863
|
+
// 5 minutes of inactivity
|
|
864
|
+
backend: env.OPENFOX_BACKEND,
|
|
865
|
+
disableThinking: env.OPENFOX_DISABLE_THINKING
|
|
866
|
+
},
|
|
867
|
+
context: {
|
|
868
|
+
maxTokens: env.OPENFOX_MAX_CONTEXT,
|
|
869
|
+
compactionThreshold: 0.85,
|
|
870
|
+
compactionTarget: 0.6
|
|
871
|
+
},
|
|
872
|
+
agent: {
|
|
873
|
+
maxIterations: 10,
|
|
874
|
+
maxConsecutiveFailures: 3,
|
|
875
|
+
toolTimeout: 3e5
|
|
876
|
+
},
|
|
877
|
+
server: {
|
|
878
|
+
port: env.OPENFOX_PORT,
|
|
879
|
+
...env.OPENFOX_HOST !== void 0 ? { host: env.OPENFOX_HOST } : {}
|
|
880
|
+
},
|
|
881
|
+
database: {
|
|
882
|
+
path: env.OPENFOX_DB_PATH
|
|
883
|
+
},
|
|
884
|
+
mode: env.OPENFOX_DEV ? "development" : "production",
|
|
885
|
+
workdir
|
|
886
|
+
};
|
|
887
|
+
}
|
|
888
|
+
|
|
889
|
+
// src/server/runtime-config.ts
|
|
890
|
+
var runtimeConfig = null;
|
|
891
|
+
function setRuntimeConfig(config) {
|
|
892
|
+
runtimeConfig = config;
|
|
893
|
+
}
|
|
894
|
+
function getRuntimeConfig() {
|
|
895
|
+
return runtimeConfig ?? loadConfig();
|
|
896
|
+
}
|
|
897
|
+
|
|
794
898
|
// src/server/events/session.ts
|
|
795
899
|
function toSnapshotMessage(message) {
|
|
796
900
|
return {
|
|
@@ -873,6 +977,10 @@ function getCurrentContextWindowId(sessionId) {
|
|
|
873
977
|
const contextResult = foldContextState(events, "");
|
|
874
978
|
return contextResult.currentContextWindowId || void 0;
|
|
875
979
|
}
|
|
980
|
+
function getCurrentWindowMessageOptions(sessionId) {
|
|
981
|
+
const contextWindowId = getCurrentContextWindowId(sessionId);
|
|
982
|
+
return contextWindowId ? { contextWindowId } : void 0;
|
|
983
|
+
}
|
|
876
984
|
function getReadFilesCache(sessionId) {
|
|
877
985
|
const state = getSessionState(sessionId);
|
|
878
986
|
return state?.readFiles ?? [];
|
|
@@ -1097,11 +1205,11 @@ function emitChatError(sessionId, error, recoverable) {
|
|
|
1097
1205
|
data: { error, recoverable }
|
|
1098
1206
|
});
|
|
1099
1207
|
}
|
|
1100
|
-
function
|
|
1208
|
+
function emitPatternRetry(sessionId, messageId, pattern, field, attempt, maxAttempts, matchedContent) {
|
|
1101
1209
|
const eventStore = getEventStore();
|
|
1102
1210
|
eventStore.append(sessionId, {
|
|
1103
|
-
type: "
|
|
1104
|
-
data: { attempt, maxAttempts }
|
|
1211
|
+
type: "pattern.retry",
|
|
1212
|
+
data: { messageId, pattern, field, attempt, maxAttempts, matchedContent }
|
|
1105
1213
|
});
|
|
1106
1214
|
}
|
|
1107
1215
|
function emitTurnSnapshot(sessionId, snapshot) {
|
|
@@ -1227,10 +1335,14 @@ export {
|
|
|
1227
1335
|
listSessions,
|
|
1228
1336
|
listSessionsByProject,
|
|
1229
1337
|
deleteSession,
|
|
1338
|
+
loadConfig,
|
|
1339
|
+
setRuntimeConfig,
|
|
1340
|
+
getRuntimeConfig,
|
|
1230
1341
|
getSessionState,
|
|
1231
1342
|
getCurrentWindowMessages,
|
|
1232
1343
|
getContextMessages,
|
|
1233
1344
|
getCurrentContextWindowId,
|
|
1345
|
+
getCurrentWindowMessageOptions,
|
|
1234
1346
|
getReadFilesCache,
|
|
1235
1347
|
isFileInCache,
|
|
1236
1348
|
emitSessionInitialized,
|
|
@@ -1255,10 +1367,10 @@ export {
|
|
|
1255
1367
|
emitContextState,
|
|
1256
1368
|
emitChatDone,
|
|
1257
1369
|
emitChatError,
|
|
1258
|
-
|
|
1370
|
+
emitPatternRetry,
|
|
1259
1371
|
emitTurnSnapshot,
|
|
1260
1372
|
truncateSessionMessages,
|
|
1261
1373
|
compactContext,
|
|
1262
1374
|
getRecentUserPromptsForSession
|
|
1263
1375
|
};
|
|
1264
|
-
//# sourceMappingURL=chunk-
|
|
1376
|
+
//# sourceMappingURL=chunk-NPHYEUYE.js.map
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import {
|
|
2
2
|
detectModel
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-EMJGF3A7.js";
|
|
4
4
|
import {
|
|
5
5
|
detectBackend
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-7FDY3EOH.js";
|
|
7
7
|
import {
|
|
8
8
|
getGlobalConfigPath
|
|
9
9
|
} from "./chunk-CQGTEGKL.js";
|
|
@@ -435,4 +435,4 @@ export {
|
|
|
435
435
|
activateProvider,
|
|
436
436
|
mergeConfigs
|
|
437
437
|
};
|
|
438
|
-
//# sourceMappingURL=chunk-
|
|
438
|
+
//# sourceMappingURL=chunk-QUSUEN5R.js.map
|
|
@@ -33,7 +33,7 @@ Options:
|
|
|
33
33
|
}
|
|
34
34
|
async function runNetworkSetup(mode) {
|
|
35
35
|
const { loadAuthConfig, saveAuthConfig, encryptPassword } = await import("./auth-56SIRACI.js");
|
|
36
|
-
const { saveGlobalConfig } = await import("./config-
|
|
36
|
+
const { saveGlobalConfig } = await import("./config-VBBMTXJZ.js");
|
|
37
37
|
const { getAuthKeyPath } = await import("./paths-X46PPOI2.js");
|
|
38
38
|
const existingAuth = await loadAuthConfig(mode);
|
|
39
39
|
if (existingAuth) {
|
|
@@ -94,7 +94,7 @@ async function runNetworkSetup(mode) {
|
|
|
94
94
|
console.log("\u2713 Configuration saved!\n");
|
|
95
95
|
}
|
|
96
96
|
async function runConfig(mode) {
|
|
97
|
-
const { loadGlobalConfig, getActiveProvider, getDefaultModel } = await import("./config-
|
|
97
|
+
const { loadGlobalConfig, getActiveProvider, getDefaultModel } = await import("./config-VBBMTXJZ.js");
|
|
98
98
|
const { getGlobalConfigPath } = await import("./paths-X46PPOI2.js");
|
|
99
99
|
const config = await loadGlobalConfig(mode);
|
|
100
100
|
const configPath = getGlobalConfigPath(mode);
|
|
@@ -151,7 +151,7 @@ async function runCli(options) {
|
|
|
151
151
|
break;
|
|
152
152
|
}
|
|
153
153
|
case "provider": {
|
|
154
|
-
const { runProviderCommand } = await import("./provider-
|
|
154
|
+
const { runProviderCommand } = await import("./provider-NRWSSO55.js");
|
|
155
155
|
const [, subcommand] = positionals;
|
|
156
156
|
await runProviderCommand(mode, subcommand);
|
|
157
157
|
break;
|
|
@@ -188,12 +188,12 @@ async function runCli(options) {
|
|
|
188
188
|
break;
|
|
189
189
|
}
|
|
190
190
|
default: {
|
|
191
|
-
const { configFileExists } = await import("./config-
|
|
191
|
+
const { configFileExists } = await import("./config-VBBMTXJZ.js");
|
|
192
192
|
const configExists = await configFileExists(mode);
|
|
193
193
|
if (!configExists) {
|
|
194
194
|
await runNetworkSetup(mode);
|
|
195
195
|
}
|
|
196
|
-
const { runServe } = await import("./serve-
|
|
196
|
+
const { runServe } = await import("./serve-J6EM3G6N.js");
|
|
197
197
|
const serveOptions = { mode };
|
|
198
198
|
if (values.port) serveOptions.port = parseInt(values.port);
|
|
199
199
|
if (values["no-browser"] === true) serveOptions.openBrowser = false;
|
|
@@ -205,4 +205,4 @@ async function runCli(options) {
|
|
|
205
205
|
export {
|
|
206
206
|
runCli
|
|
207
207
|
};
|
|
208
|
-
//# sourceMappingURL=chunk-
|
|
208
|
+
//# sourceMappingURL=chunk-R3EK3ODJ.js.map
|
|
@@ -1,57 +1,78 @@
|
|
|
1
1
|
import {
|
|
2
|
-
BUILDER_KICKOFF_PROMPT,
|
|
3
2
|
PathAccessDeniedError,
|
|
4
3
|
TurnMetrics,
|
|
5
|
-
|
|
4
|
+
WORKFLOW_KICKOFF_PROMPT,
|
|
6
5
|
assembleAgentRequest,
|
|
7
6
|
buildAgentReminder,
|
|
7
|
+
createAssemblyResult,
|
|
8
8
|
createChatDoneEvent,
|
|
9
9
|
createMessageStartEvent,
|
|
10
|
-
executeSubAgent,
|
|
11
10
|
findAgentById,
|
|
11
|
+
getAllInstructions,
|
|
12
|
+
getConversationMessages,
|
|
13
|
+
getEnabledSkillMetadata,
|
|
12
14
|
getSubAgents,
|
|
13
15
|
getToolRegistryForAgent,
|
|
14
16
|
loadAllAgentsDefault,
|
|
17
|
+
processEventsForConversation,
|
|
15
18
|
runTopLevelAgentLoop
|
|
16
|
-
} from "./chunk-
|
|
19
|
+
} from "./chunk-FRCLNAE2.js";
|
|
17
20
|
import {
|
|
18
21
|
getCurrentContextWindowId,
|
|
19
|
-
|
|
20
|
-
|
|
22
|
+
getCurrentWindowMessageOptions,
|
|
23
|
+
getEventStore,
|
|
24
|
+
getRuntimeConfig
|
|
25
|
+
} from "./chunk-NPHYEUYE.js";
|
|
21
26
|
import {
|
|
22
27
|
buildSnapshotFromSessionState
|
|
23
|
-
} from "./chunk-
|
|
28
|
+
} from "./chunk-XJEOP6XU.js";
|
|
24
29
|
import {
|
|
25
30
|
logger
|
|
26
31
|
} from "./chunk-K44MW7JJ.js";
|
|
32
|
+
import {
|
|
33
|
+
getGlobalConfigDir
|
|
34
|
+
} from "./chunk-CQGTEGKL.js";
|
|
27
35
|
|
|
28
|
-
// src/server/
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
return `You stopped before finalizing verification. ${criteria.length} criteria still need a terminal verification result. Use criterion with action "pass" or "fail" for each remaining criterion: ${ids}.`;
|
|
37
|
-
}
|
|
38
|
-
function buildVerifierRestartContent(criteria) {
|
|
39
|
-
const ids = criteria.map((criterion) => criterion.id).join(", ");
|
|
40
|
-
return `${VERIFIER_STALL_REASON} Leaving remaining criteria unchanged so verification can restart in a fresh window: ${ids}.`;
|
|
41
|
-
}
|
|
42
|
-
function createVerifierNudgeConfig() {
|
|
43
|
-
return {
|
|
44
|
-
maxConsecutiveNudges: MAX_CONSECUTIVE_VERIFIER_NUDGES,
|
|
45
|
-
getCriteriaAwaiting: getCriteriaAwaitingVerification,
|
|
46
|
-
buildNudgeContent: buildVerifierNudgeContent,
|
|
47
|
-
buildRestartContent: buildVerifierRestartContent
|
|
48
|
-
};
|
|
36
|
+
// src/server/chat/dynamic-context.ts
|
|
37
|
+
import { createHash } from "crypto";
|
|
38
|
+
function computeDynamicContextHash(instructionContent, skills) {
|
|
39
|
+
const dynamicInputs = JSON.stringify({
|
|
40
|
+
instructions: instructionContent,
|
|
41
|
+
skills: skills.map((s) => s.id).sort()
|
|
42
|
+
});
|
|
43
|
+
return createHash("sha256").update(dynamicInputs).digest("hex");
|
|
49
44
|
}
|
|
50
45
|
|
|
51
46
|
// src/server/chat/orchestrator.ts
|
|
52
|
-
function
|
|
53
|
-
const
|
|
54
|
-
|
|
47
|
+
async function buildRetryPatterns() {
|
|
48
|
+
const { getSetting, SETTINGS_KEYS } = await import("./settings-6XX56F3F.js");
|
|
49
|
+
const raw = getSetting(SETTINGS_KEYS.RETRY_PATTERNS);
|
|
50
|
+
if (!raw) {
|
|
51
|
+
const oldXmlProtection = getSetting("llm.disableXmlProtection");
|
|
52
|
+
if (oldXmlProtection !== null) {
|
|
53
|
+
const disabled = oldXmlProtection === "true";
|
|
54
|
+
return {
|
|
55
|
+
retryPatterns: disabled ? [] : [{ field: "both", pattern: "<(tool_call|function=|/tool_call|parameter=)", action: "retry", active: true }],
|
|
56
|
+
maxRetriesPerTurn: 10
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
return { retryPatterns: [], maxRetriesPerTurn: 10 };
|
|
60
|
+
}
|
|
61
|
+
try {
|
|
62
|
+
const parsed = JSON.parse(raw);
|
|
63
|
+
return {
|
|
64
|
+
retryPatterns: Array.isArray(parsed.patterns) ? parsed.patterns : [],
|
|
65
|
+
maxRetriesPerTurn: typeof parsed.maxRetriesPerTurn === "number" ? parsed.maxRetriesPerTurn : 10
|
|
66
|
+
};
|
|
67
|
+
} catch {
|
|
68
|
+
return { retryPatterns: [], maxRetriesPerTurn: 10 };
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
function buildGetConversationMessages(sessionId, llmClient, append) {
|
|
72
|
+
return async () => {
|
|
73
|
+
const processedEvents = await processEventsForConversation(sessionId, llmClient, (event) => append(event));
|
|
74
|
+
return getConversationMessages({ type: "toplevel", sessionId }, { events: processedEvents });
|
|
75
|
+
};
|
|
55
76
|
}
|
|
56
77
|
function resolveStatsIdentity(options) {
|
|
57
78
|
const model = options.llmClient.getModel();
|
|
@@ -75,13 +96,11 @@ async function runChatTurn(options) {
|
|
|
75
96
|
const session = sessionManager.requireSession(sessionId);
|
|
76
97
|
const mode = session.mode;
|
|
77
98
|
logger.debug("Starting chat turn", { sessionId, mode });
|
|
99
|
+
sessionManager.setRunning(sessionId, true);
|
|
100
|
+
const append = (event) => eventStore.append(sessionId, event);
|
|
78
101
|
const turnMetrics = new TurnMetrics();
|
|
79
102
|
try {
|
|
80
|
-
|
|
81
|
-
await runBuilderTurn(options, turnMetrics);
|
|
82
|
-
} else {
|
|
83
|
-
await runGenericAgentTurn(options, turnMetrics, mode);
|
|
84
|
-
}
|
|
103
|
+
await runAgentTurn(options, turnMetrics, mode, append);
|
|
85
104
|
const snapshot = buildSnapshot(sessionManager, sessionId, turnMetrics.buildStats(statsIdentity, mode));
|
|
86
105
|
const snapshotEvent = eventStore.append(sessionId, { type: "turn.snapshot", data: snapshot });
|
|
87
106
|
const deletedCount = eventStore.cleanupOldEvents(sessionId);
|
|
@@ -147,18 +166,30 @@ async function runChatTurn(options) {
|
|
|
147
166
|
eventStore.append(sessionId, { type: "running.changed", data: { isRunning: false } });
|
|
148
167
|
}
|
|
149
168
|
}
|
|
169
|
+
function windowHasReminder(sessionId, windowId) {
|
|
170
|
+
const eventStore = getEventStore();
|
|
171
|
+
const events = eventStore.getEvents(sessionId);
|
|
172
|
+
return events.some((event) => {
|
|
173
|
+
if (event.type !== "message.start") return false;
|
|
174
|
+
const data = event.data;
|
|
175
|
+
return data.contextWindowId === windowId && data.messageKind === "auto-prompt" && typeof data.content === "string" && data.content.includes("<system-reminder>");
|
|
176
|
+
});
|
|
177
|
+
}
|
|
150
178
|
function injectModeReminderIfNeeded(sessionManager, sessionId, agentId, allAgents, _onMessage) {
|
|
151
179
|
const eventStore = getEventStore();
|
|
152
180
|
const session = sessionManager.requireSession(sessionId);
|
|
181
|
+
const currentWindowId = getCurrentContextWindowId(sessionId);
|
|
153
182
|
const lastModeReminder = session.executionState?.lastModeWithReminder;
|
|
154
183
|
if (lastModeReminder === agentId) {
|
|
155
|
-
|
|
184
|
+
if (!currentWindowId || windowHasReminder(sessionId, currentWindowId)) {
|
|
185
|
+
return;
|
|
186
|
+
}
|
|
156
187
|
}
|
|
157
188
|
const agentDef = findAgentById(agentId, allAgents);
|
|
158
189
|
if (!agentDef) return;
|
|
159
190
|
const reminderContent = buildAgentReminder(agentDef);
|
|
160
191
|
const reminderMsgId = crypto.randomUUID();
|
|
161
|
-
const currentWindowMessageOptions =
|
|
192
|
+
const currentWindowMessageOptions = currentWindowId ? { contextWindowId: currentWindowId } : void 0;
|
|
162
193
|
eventStore.append(sessionId, {
|
|
163
194
|
type: "message.start",
|
|
164
195
|
data: {
|
|
@@ -183,130 +214,88 @@ function injectModeReminderIfNeeded(sessionManager, sessionId, agentId, allAgent
|
|
|
183
214
|
lastModeWithReminder: agentId
|
|
184
215
|
});
|
|
185
216
|
}
|
|
186
|
-
async function
|
|
217
|
+
async function runAgentTurn(options, turnMetrics, agentId, append, callbacks) {
|
|
187
218
|
const statsIdentity = resolveStatsIdentity(options);
|
|
188
219
|
const allAgents = await loadAllAgentsDefault();
|
|
189
220
|
injectModeReminderIfNeeded(options.sessionManager, options.sessionId, agentId, allAgents, options.onMessage);
|
|
190
221
|
const agentDef = findAgentById(agentId, allAgents) ?? findAgentById("planner", allAgents);
|
|
191
222
|
const subAgentDefs = getSubAgents(allAgents);
|
|
192
|
-
await
|
|
223
|
+
const { content: instructionContent } = await getAllInstructions(
|
|
224
|
+
options.sessionManager.requireSession(options.sessionId).workdir,
|
|
225
|
+
options.sessionManager.requireSession(options.sessionId).projectId
|
|
226
|
+
);
|
|
227
|
+
const runtimeConfig = getRuntimeConfig();
|
|
228
|
+
const configDir = getGlobalConfigDir(runtimeConfig.mode ?? "production");
|
|
229
|
+
const skills = await getEnabledSkillMetadata(configDir, runtimeConfig.workdir);
|
|
230
|
+
return runTopLevelAgentLoop(
|
|
193
231
|
{
|
|
194
232
|
mode: agentId,
|
|
233
|
+
append,
|
|
234
|
+
...await buildRetryPatterns(),
|
|
195
235
|
sessionManager: options.sessionManager,
|
|
196
236
|
sessionId: options.sessionId,
|
|
197
237
|
llmClient: options.llmClient,
|
|
198
238
|
statsIdentity,
|
|
199
239
|
signal: options.signal,
|
|
200
240
|
onMessage: options.onMessage,
|
|
201
|
-
assembleRequest: (input) =>
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
function filterToolRegistryForStepDone(baseRegistry, _injectStepDone) {
|
|
208
|
-
return baseRegistry;
|
|
209
|
-
}
|
|
210
|
-
async function runBuilderTurn(options, turnMetrics) {
|
|
211
|
-
const { sessionManager, sessionId } = options;
|
|
212
|
-
const statsIdentity = resolveStatsIdentity(options);
|
|
213
|
-
const eventStore = getEventStore();
|
|
214
|
-
const allAgents = await loadAllAgentsDefault();
|
|
215
|
-
injectModeReminderIfNeeded(options.sessionManager, options.sessionId, "builder", allAgents, options.onMessage);
|
|
216
|
-
const builderDef = findAgentById("builder", allAgents);
|
|
217
|
-
const subAgentDefs = getSubAgents(allAgents);
|
|
218
|
-
let stepDoneCalled = false;
|
|
219
|
-
return {
|
|
220
|
-
...await runTopLevelAgentLoop(
|
|
221
|
-
{
|
|
222
|
-
mode: "builder",
|
|
223
|
-
sessionManager,
|
|
224
|
-
sessionId,
|
|
225
|
-
llmClient: options.llmClient,
|
|
226
|
-
statsIdentity,
|
|
227
|
-
signal: options.signal,
|
|
228
|
-
onMessage: options.onMessage,
|
|
229
|
-
assembleRequest: (input) => assembleAgentRequest({
|
|
230
|
-
...input,
|
|
231
|
-
agentDef: builderDef,
|
|
232
|
-
subAgentDefs,
|
|
233
|
-
modelName: options.llmClient.getModel()
|
|
234
|
-
}),
|
|
235
|
-
getToolRegistry: () => {
|
|
236
|
-
const baseRegistry = getToolRegistryForAgent(builderDef);
|
|
237
|
-
return filterToolRegistryForStepDone(baseRegistry, options.injectStepDone === true);
|
|
238
|
-
},
|
|
239
|
-
onToolExecuted: (toolCall, toolResult) => {
|
|
240
|
-
if (toolCall.name === "step_done" && toolResult.success) {
|
|
241
|
-
stepDoneCalled = true;
|
|
242
|
-
}
|
|
243
|
-
if (toolResult.success && ["write_file", "edit_file"].includes(toolCall.name)) {
|
|
244
|
-
const path = toolCall.arguments["path"];
|
|
245
|
-
sessionManager.addModifiedFile(sessionId, path);
|
|
241
|
+
assembleRequest: (input) => {
|
|
242
|
+
const cached = options.sessionManager.getCachedPrompt(options.sessionId);
|
|
243
|
+
if (cached) {
|
|
244
|
+
const currentHash = computeDynamicContextHash(instructionContent ?? "", skills);
|
|
245
|
+
if (cached.hash !== currentHash) {
|
|
246
|
+
options.sessionManager.setDynamicContextChanged(options.sessionId, true);
|
|
246
247
|
}
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
if (e.type !== "message.start") return false;
|
|
255
|
-
const data = e.data;
|
|
256
|
-
return data.messageKind === "auto-prompt" && data.content?.includes("fulfil the");
|
|
248
|
+
return createAssemblyResult({
|
|
249
|
+
systemPrompt: cached.systemPrompt,
|
|
250
|
+
messages: input.messages,
|
|
251
|
+
injectedFiles: input.injectedFiles,
|
|
252
|
+
requestTools: input.promptTools,
|
|
253
|
+
toolChoice: input.toolChoice,
|
|
254
|
+
disableThinking: false
|
|
257
255
|
});
|
|
258
|
-
if (!hasBuilderKickoff) {
|
|
259
|
-
const kickoffMsgId = crypto.randomUUID();
|
|
260
|
-
const kickoffContent = BUILDER_KICKOFF_PROMPT(session.criteria.length);
|
|
261
|
-
const msgMetadata = { type: "workflow", name: "Workflow", color: "#f59e0b" };
|
|
262
|
-
eventStore.append(
|
|
263
|
-
sessionId,
|
|
264
|
-
createMessageStartEvent(kickoffMsgId, "user", kickoffContent, {
|
|
265
|
-
...currentWindowMessageOptions ?? {},
|
|
266
|
-
isSystemGenerated: true,
|
|
267
|
-
messageKind: "auto-prompt",
|
|
268
|
-
metadata: msgMetadata
|
|
269
|
-
})
|
|
270
|
-
);
|
|
271
|
-
eventStore.append(sessionId, { type: "message.done", data: { messageId: kickoffMsgId } });
|
|
272
|
-
}
|
|
273
256
|
}
|
|
257
|
+
const result = assembleAgentRequest({
|
|
258
|
+
...input,
|
|
259
|
+
agentDef,
|
|
260
|
+
subAgentDefs,
|
|
261
|
+
modelName: options.llmClient.getModel()
|
|
262
|
+
});
|
|
263
|
+
const hash = computeDynamicContextHash(instructionContent ?? "", skills);
|
|
264
|
+
options.sessionManager.setCachedPrompt(options.sessionId, result.systemPrompt, hash);
|
|
265
|
+
return result;
|
|
274
266
|
},
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
267
|
+
getToolRegistry: () => getToolRegistryForAgent(agentDef),
|
|
268
|
+
getConversationMessages: buildGetConversationMessages(options.sessionId, options.llmClient, append),
|
|
269
|
+
injectModeReminder: () => injectModeReminderIfNeeded(options.sessionManager, options.sessionId, agentId, allAgents, options.onMessage),
|
|
270
|
+
...callbacks?.injectKickoff ? { injectKickoff: callbacks.injectKickoff } : {},
|
|
271
|
+
...callbacks?.onToolExecuted ? { onToolExecuted: callbacks.onToolExecuted } : {}
|
|
272
|
+
},
|
|
273
|
+
turnMetrics
|
|
274
|
+
);
|
|
279
275
|
}
|
|
280
|
-
|
|
281
|
-
const { sessionManager, sessionId, llmClient, signal, onMessage } = options;
|
|
282
|
-
const statsIdentity = resolveStatsIdentity(options);
|
|
276
|
+
function injectWorkflowKickoffIfNeeded(sessionManager, sessionId, eventStore) {
|
|
283
277
|
const session = sessionManager.requireSession(sessionId);
|
|
284
|
-
const
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
const verifierDef = findAgentById("verifier", allAgents);
|
|
291
|
-
const toolRegistry = getToolRegistryForAgent(verifierDef);
|
|
292
|
-
const result = await executeSubAgent({
|
|
293
|
-
subAgentType: "verifier",
|
|
294
|
-
prompt: VERIFIER_KICKOFF_PROMPT,
|
|
295
|
-
sessionManager,
|
|
296
|
-
sessionId,
|
|
297
|
-
llmClient,
|
|
298
|
-
toolRegistry,
|
|
299
|
-
turnMetrics,
|
|
300
|
-
statsIdentity,
|
|
301
|
-
signal,
|
|
302
|
-
onMessage,
|
|
303
|
-
nudgeConfig: createVerifierNudgeConfig()
|
|
278
|
+
const currentWindowMessageOptions = getCurrentContextWindowId(sessionId) ? { contextWindowId: getCurrentContextWindowId(sessionId) } : void 0;
|
|
279
|
+
const events = eventStore.getEvents(sessionId);
|
|
280
|
+
const hasKickoff = events.some((e) => {
|
|
281
|
+
if (e.type !== "message.start") return false;
|
|
282
|
+
const data = e.data;
|
|
283
|
+
return data.messageKind === "auto-prompt" && data.content?.includes("fulfil the");
|
|
304
284
|
});
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
285
|
+
if (!hasKickoff) {
|
|
286
|
+
const kickoffMsgId = crypto.randomUUID();
|
|
287
|
+
const kickoffContent = WORKFLOW_KICKOFF_PROMPT(session.criteria.length);
|
|
288
|
+
eventStore.append(
|
|
289
|
+
sessionId,
|
|
290
|
+
createMessageStartEvent(kickoffMsgId, "user", kickoffContent, {
|
|
291
|
+
...currentWindowMessageOptions ?? {},
|
|
292
|
+
isSystemGenerated: true,
|
|
293
|
+
messageKind: "auto-prompt",
|
|
294
|
+
metadata: { type: "workflow", name: "Workflow", color: "#f59e0b" }
|
|
295
|
+
})
|
|
296
|
+
);
|
|
297
|
+
eventStore.append(sessionId, { type: "message.done", data: { messageId: kickoffMsgId } });
|
|
298
|
+
}
|
|
310
299
|
}
|
|
311
300
|
function buildSnapshot(sessionManager, sessionId, _lastStats) {
|
|
312
301
|
const eventStore = getEventStore();
|
|
@@ -323,10 +312,9 @@ function buildSnapshot(sessionManager, sessionId, _lastStats) {
|
|
|
323
312
|
}
|
|
324
313
|
|
|
325
314
|
export {
|
|
326
|
-
|
|
315
|
+
computeDynamicContextHash,
|
|
327
316
|
runChatTurn,
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
runVerifierTurn
|
|
317
|
+
runAgentTurn,
|
|
318
|
+
injectWorkflowKickoffIfNeeded
|
|
331
319
|
};
|
|
332
|
-
//# sourceMappingURL=chunk-
|
|
320
|
+
//# sourceMappingURL=chunk-RBJ25FIR.js.map
|