@yeaft/webchat-agent 1.0.299 → 1.0.301
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/context.js +1 -0
- package/index.js +9 -0
- package/local-runtime/server/database.js +1 -0
- package/local-runtime/server/db/connection.js +86 -0
- package/local-runtime/server/db/yeaft-project-db.js +225 -0
- package/local-runtime/server/handlers/agent-output.js +41 -5
- package/local-runtime/server/handlers/client-conversation.js +73 -0
- package/local-runtime/server/ws-utils.js +5 -1
- package/local-runtime/version.json +1 -1
- package/local-runtime/web/app.bundle.js +73 -78
- package/local-runtime/web/app.bundle.js.gz +0 -0
- package/local-runtime/web/index.html +2 -2
- package/local-runtime/web/style.bundle.css +1 -1
- package/local-runtime/web/style.bundle.css.gz +0 -0
- package/package.json +1 -1
- package/yeaft/cli-session-runner.js +3 -2
- package/yeaft/cli.js +20 -1
- package/yeaft/conversation/search.js +13 -7
- package/yeaft/engine.js +29 -5
- package/yeaft/managed-cli.js +618 -0
- package/yeaft/session.js +7 -0
- package/yeaft/sub-agent/runner.js +6 -0
- package/yeaft/tools/disk-usage.js +243 -0
- package/yeaft/tools/glob.js +84 -28
- package/yeaft/tools/grep.js +616 -152
- package/yeaft/tools/history-search.js +12 -3
- package/yeaft/tools/index.js +2 -0
- package/yeaft/tools/process-runner.js +211 -0
- package/yeaft/tools/search-paths.js +108 -0
- package/yeaft/tools/types.js +2 -0
- package/yeaft/web-bridge.js +93 -6
|
Binary file
|
package/package.json
CHANGED
|
@@ -23,7 +23,7 @@ function buildVpPersona(vpId, loaded) {
|
|
|
23
23
|
};
|
|
24
24
|
}
|
|
25
25
|
|
|
26
|
-
function
|
|
26
|
+
export function createCliVpEngine(loaded, sessionId, vpId) {
|
|
27
27
|
const effectiveConfig = resolveSessionConfig(
|
|
28
28
|
loaded.config,
|
|
29
29
|
loadSessionConfig(loaded.yeaftDir, sessionId),
|
|
@@ -41,6 +41,7 @@ function createEngine(loaded, sessionId, vpId) {
|
|
|
41
41
|
yeaftDir: loaded.yeaftDir,
|
|
42
42
|
toolStats: loaded.toolStats || null,
|
|
43
43
|
taskManager: loaded.taskManager || null,
|
|
44
|
+
managedCliReady: loaded.managedCliReady || null,
|
|
44
45
|
sessionId,
|
|
45
46
|
vpId,
|
|
46
47
|
});
|
|
@@ -58,7 +59,7 @@ export function createCliSessionRunner({
|
|
|
58
59
|
loaded,
|
|
59
60
|
sessionId,
|
|
60
61
|
workDir = process.cwd(),
|
|
61
|
-
engineFactory =
|
|
62
|
+
engineFactory = createCliVpEngine,
|
|
62
63
|
personaFactory = buildVpPersona,
|
|
63
64
|
} = {}) {
|
|
64
65
|
if (!loaded || !sessionId) return null;
|
package/yeaft/cli.js
CHANGED
|
@@ -40,6 +40,7 @@ import { loadSessionConfig, resolveSessionConfig } from './sessions/session-conf
|
|
|
40
40
|
import { validateSessionId } from './sessions/ids.js';
|
|
41
41
|
import { createJsonlWriter, JsonlInput, runStreamTurn, runStreamSessionTurn } from './stdio-protocol.js';
|
|
42
42
|
import { createCliSessionRunner } from './cli-session-runner.js';
|
|
43
|
+
import { ensureManagedCliTools, summarizeManagedCliResults } from './managed-cli.js';
|
|
43
44
|
|
|
44
45
|
// ─── Argument parsing ──────────────────────────────────────────
|
|
45
46
|
|
|
@@ -65,6 +66,7 @@ export function parseArgs(argv) {
|
|
|
65
66
|
outputFormat: 'text',
|
|
66
67
|
print: false,
|
|
67
68
|
prompt: null,
|
|
69
|
+
managedCliReady: Promise.resolve([]),
|
|
68
70
|
};
|
|
69
71
|
|
|
70
72
|
const rest = argv.slice(2);
|
|
@@ -346,6 +348,7 @@ async function runREPL(config, args) {
|
|
|
346
348
|
skipMCP: args.skipMCP,
|
|
347
349
|
skipSkills: args.skipSkills,
|
|
348
350
|
configOverrides: effectiveConfig,
|
|
351
|
+
managedCliReady: args.managedCliReady,
|
|
349
352
|
});
|
|
350
353
|
|
|
351
354
|
const { engine, conversationStore, trace, skillManager, mcpManager, toolRegistry } = session;
|
|
@@ -797,6 +800,7 @@ async function runStreamJson(config, args) {
|
|
|
797
800
|
...effectiveConfig,
|
|
798
801
|
...(effectiveConfig.modelEffort ? { modelEffort: effectiveConfig.modelEffort } : {}),
|
|
799
802
|
},
|
|
803
|
+
managedCliReady: args.managedCliReady,
|
|
800
804
|
});
|
|
801
805
|
const { engine, conversationStore, skillManager, toolRegistry } = loaded;
|
|
802
806
|
const sessionRunner = createCliSessionRunner({ loaded, sessionId, workDir });
|
|
@@ -885,6 +889,7 @@ async function runOnce(config, args) {
|
|
|
885
889
|
skipMCP: args.skipMCP,
|
|
886
890
|
skipSkills: args.skipSkills,
|
|
887
891
|
configOverrides: effectiveConfig,
|
|
892
|
+
managedCliReady: args.managedCliReady,
|
|
888
893
|
});
|
|
889
894
|
|
|
890
895
|
const { engine, conversationStore } = session;
|
|
@@ -993,7 +998,6 @@ async function main() {
|
|
|
993
998
|
language: args.language,
|
|
994
999
|
debug: args.debug || undefined,
|
|
995
1000
|
});
|
|
996
|
-
|
|
997
1001
|
// Handle --trace queries (no LLM needed, no session needed)
|
|
998
1002
|
if (args.trace) {
|
|
999
1003
|
await handleTraceQuery(args, config);
|
|
@@ -1010,8 +1014,20 @@ async function main() {
|
|
|
1010
1014
|
return;
|
|
1011
1015
|
}
|
|
1012
1016
|
|
|
1017
|
+
const prepareManagedCli = () => {
|
|
1018
|
+
args.managedCliReady = ensureManagedCliTools({ yeaftDir: config.dir });
|
|
1019
|
+
args.managedCliReady.then(results => {
|
|
1020
|
+
if (results.some(result => result.status === 'installed')) {
|
|
1021
|
+
console.error(`[Yeaft] managed CLI tools: ${summarizeManagedCliResults(results)}`);
|
|
1022
|
+
}
|
|
1023
|
+
}).catch(error => {
|
|
1024
|
+
console.error(`[Yeaft] managed CLI setup failed; using built-in fallbacks: ${error?.message || error}`);
|
|
1025
|
+
});
|
|
1026
|
+
};
|
|
1027
|
+
|
|
1013
1028
|
// Handle interactive mode
|
|
1014
1029
|
if (args.interactive) {
|
|
1030
|
+
prepareManagedCli();
|
|
1015
1031
|
await runREPL(config, args);
|
|
1016
1032
|
return;
|
|
1017
1033
|
}
|
|
@@ -1023,6 +1039,7 @@ async function main() {
|
|
|
1023
1039
|
if (!args.prompt && args.inputFormat !== 'stream-json' && process.stdin.isTTY) {
|
|
1024
1040
|
throw new Error('stream-json output requires a prompt, piped stdin, or --input-format stream-json');
|
|
1025
1041
|
}
|
|
1042
|
+
prepareManagedCli();
|
|
1026
1043
|
await runStreamJson(config, args);
|
|
1027
1044
|
return;
|
|
1028
1045
|
}
|
|
@@ -1032,6 +1049,7 @@ async function main() {
|
|
|
1032
1049
|
|
|
1033
1050
|
// Handle prompt (from args or stdin)
|
|
1034
1051
|
if (args.prompt) {
|
|
1052
|
+
prepareManagedCli();
|
|
1035
1053
|
await runOnce(config, args);
|
|
1036
1054
|
return;
|
|
1037
1055
|
}
|
|
@@ -1044,6 +1062,7 @@ async function main() {
|
|
|
1044
1062
|
}
|
|
1045
1063
|
args.prompt = input.trim();
|
|
1046
1064
|
if (args.prompt) {
|
|
1065
|
+
prepareManagedCli();
|
|
1047
1066
|
await runOnce(config, args);
|
|
1048
1067
|
return;
|
|
1049
1068
|
}
|
|
@@ -152,7 +152,7 @@ function sessionConversationDirs(dir) {
|
|
|
152
152
|
* @param {string} dir — Yeaft root directory (e.g. ~/.yeaft)
|
|
153
153
|
* @param {string} keyword — search terms
|
|
154
154
|
* @param {number} [limit=10] — max results
|
|
155
|
-
* @param {{telemetry?: {scannedFiles?: number, scannedBytes?: number, scannedMessages?: number}}} [options]
|
|
155
|
+
* @param {{telemetry?: {scannedFiles?: number, scannedBytes?: number, scannedMessages?: number}, sessionIds?: string[]}} [options]
|
|
156
156
|
* @returns {object[]} — matching messages, newest first
|
|
157
157
|
*/
|
|
158
158
|
export function searchMessages(dir, keyword, limit = 10, options = {}) {
|
|
@@ -167,18 +167,24 @@ export function searchMessages(dir, keyword, limit = 10, options = {}) {
|
|
|
167
167
|
telemetry.scannedMessages = 0;
|
|
168
168
|
}
|
|
169
169
|
|
|
170
|
-
const
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
170
|
+
const requestedSessionIds = Array.isArray(options.sessionIds)
|
|
171
|
+
? new Set(options.sessionIds.filter(id => typeof id === 'string' && id.trim()).map(id => id.trim()))
|
|
172
|
+
: null;
|
|
173
|
+
const scopedSessionDirs = sessionConversationDirs(dir)
|
|
174
|
+
.filter(source => !requestedSessionIds || requestedSessionIds.has(source.sessionId));
|
|
175
|
+
const conversationDirs = requestedSessionIds
|
|
176
|
+
? scopedSessionDirs
|
|
177
|
+
: [{ dir: join(dir, 'chat'), sessionId: null, kind: 'chat' }, ...scopedSessionDirs];
|
|
174
178
|
|
|
175
179
|
const markdownDirs = [
|
|
176
180
|
...conversationDirs.flatMap(source => [
|
|
177
181
|
{ ...source, dir: join(source.dir, 'messages') },
|
|
178
182
|
{ ...source, dir: join(source.dir, 'cold') },
|
|
179
183
|
]),
|
|
180
|
-
|
|
181
|
-
|
|
184
|
+
...(!requestedSessionIds ? [
|
|
185
|
+
{ dir: join(dir, 'conversation', 'messages'), sessionId: null, kind: 'legacy-conversation' },
|
|
186
|
+
{ dir: join(dir, 'conversation', 'cold'), sessionId: null, kind: 'legacy-conversation' },
|
|
187
|
+
] : []),
|
|
182
188
|
];
|
|
183
189
|
const segmentDirs = conversationDirs.map(source => ({ ...source, dir: join(source.dir, 'segments') }));
|
|
184
190
|
|
package/yeaft/engine.js
CHANGED
|
@@ -524,6 +524,9 @@ export class Engine {
|
|
|
524
524
|
|
|
525
525
|
/** @type {string|null} */
|
|
526
526
|
#yeaftDir;
|
|
527
|
+
|
|
528
|
+
/** @type {Promise<Array>|null} */
|
|
529
|
+
#managedCliReady;
|
|
527
530
|
/** @type {string|null} — set when this engine is bound to a specific group (per-VP fan-out path). */
|
|
528
531
|
#sessionId = null;
|
|
529
532
|
/** @type {string|null} — set when this engine is bound to a specific VP (per-VP fan-out path). */
|
|
@@ -716,9 +719,10 @@ export class Engine {
|
|
|
716
719
|
* mcpManager?: import('./mcp.js').MCPManager,
|
|
717
720
|
* yeaftDir?: string,
|
|
718
721
|
* toolStats?: import('./stats/tool-usage.js').ToolUsageStats,
|
|
722
|
+
* managedCliReady?: Promise<Array>,
|
|
719
723
|
* }} params
|
|
720
724
|
*/
|
|
721
|
-
constructor({ adapter, trace, config, conversationStore, memoryIndex, amsRegistry, toolRegistry, skillManager, mcpManager, yeaftDir, toolStats = null, taskManager = null, sessionId = null, vpId = null, chatId = null }) {
|
|
725
|
+
constructor({ adapter, trace, config, conversationStore, memoryIndex, amsRegistry, toolRegistry, skillManager, mcpManager, yeaftDir, toolStats = null, taskManager = null, sessionId = null, vpId = null, chatId = null, managedCliReady = null }) {
|
|
722
726
|
this.#adapter = adapter;
|
|
723
727
|
this.#trace = trace;
|
|
724
728
|
this.#config = config;
|
|
@@ -732,6 +736,7 @@ export class Engine {
|
|
|
732
736
|
this.#skillManager = skillManager || null;
|
|
733
737
|
this.#mcpManager = mcpManager || null;
|
|
734
738
|
this.#yeaftDir = yeaftDir || null;
|
|
739
|
+
this.#managedCliReady = managedCliReady || null;
|
|
735
740
|
this.#toolStats = toolStats || null;
|
|
736
741
|
// Per-VP fan-out (2026-06-01): engine instances in the group path are
|
|
737
742
|
// keyed by ${sessionId}::${vpId}::${threadId}, so binding the engine to
|
|
@@ -1260,6 +1265,7 @@ export class Engine {
|
|
|
1260
1265
|
return {
|
|
1261
1266
|
signal,
|
|
1262
1267
|
yeaftDir: this.#yeaftDir,
|
|
1268
|
+
managedCliReady: this.#managedCliReady,
|
|
1263
1269
|
runtimePlatform: getRuntimePlatformInfo(),
|
|
1264
1270
|
// Group-scoped working directory. Threaded from #runQuery({ workDir })
|
|
1265
1271
|
// → set by web-bridge runVpTurn from sessionMeta.workDir. Tools read
|
|
@@ -1279,6 +1285,9 @@ export class Engine {
|
|
|
1279
1285
|
config: this.#config,
|
|
1280
1286
|
taskManager: this.#taskManager,
|
|
1281
1287
|
sessionId: vpCtx?.sessionId || this.#sessionId || null,
|
|
1288
|
+
projectSessionIds: Array.isArray(vpCtx?.projectSessionIds)
|
|
1289
|
+
? vpCtx.projectSessionIds.slice()
|
|
1290
|
+
: [],
|
|
1282
1291
|
threadId: vpCtx?.threadId || this.#currentThreadId || MAIN_THREAD_ID,
|
|
1283
1292
|
currentVpId: vpCtx?.senderVpId || this.#vpId || null,
|
|
1284
1293
|
// task-704b: per-tool-result hard cap derives from this. Threaded
|
|
@@ -1338,10 +1347,14 @@ export class Engine {
|
|
|
1338
1347
|
skillManager: this.#skillManager,
|
|
1339
1348
|
mcpManager: this.#mcpManager,
|
|
1340
1349
|
yeaftDir: this.#yeaftDir,
|
|
1350
|
+
managedCliReady: this.#managedCliReady,
|
|
1341
1351
|
parentName: vpCtx?.senderVpId || 'parent',
|
|
1342
1352
|
parentVpId: vpCtx?.senderVpId || null,
|
|
1343
1353
|
parentVpPersona: vpCtx?.vpPersona || null,
|
|
1344
1354
|
parentSessionId: vpCtx?.sessionId || null,
|
|
1355
|
+
projectSessionIds: Array.isArray(vpCtx?.projectSessionIds)
|
|
1356
|
+
? vpCtx.projectSessionIds.slice()
|
|
1357
|
+
: [],
|
|
1345
1358
|
parentThreadId: vpCtx?.threadId || this.#currentThreadId || MAIN_THREAD_ID,
|
|
1346
1359
|
onEvent: this.#subAgentEventSink || null,
|
|
1347
1360
|
language: this.#config?.language || 'en',
|
|
@@ -1838,7 +1851,7 @@ export class Engine {
|
|
|
1838
1851
|
* string-prompt shape (no regression for existing callers).
|
|
1839
1852
|
* @yields {EngineEvent}
|
|
1840
1853
|
*/
|
|
1841
|
-
async *query({ prompt, promptParts = null, messages = [], signal, userEffort = null, scenario = 'chat', vpPersona, router, senderVpId, inboundEnvelope, taskId, taskMembers, sessionId, sessionMembers, sessionTopics = null, vpPlan, sessionAnnouncement, workCenterInstructions, workDir, userAlreadyPersisted = false, getCurrentTodos = null, setCurrentTodos = null, askUser = null, threadId = MAIN_THREAD_ID, vpTurnId = null, drainPendingUserMessages = null, prepareProviderRequest = null, startProviderRequest = null, finishProviderRequest = null, failProviderRequest = null, closePendingUserInput = null, collabToolPolicy = null } = {}) {
|
|
1854
|
+
async *query({ prompt, promptParts = null, messages = [], signal, userEffort = null, scenario = 'chat', vpPersona, router, senderVpId, inboundEnvelope, taskId, taskMembers, sessionId, sessionMembers, projectSessionIds = null, sessionTopics = null, vpPlan, sessionAnnouncement, workCenterInstructions, workDir, userAlreadyPersisted = false, getCurrentTodos = null, setCurrentTodos = null, askUser = null, threadId = MAIN_THREAD_ID, vpTurnId = null, drainPendingUserMessages = null, prepareProviderRequest = null, startProviderRequest = null, finishProviderRequest = null, failProviderRequest = null, closePendingUserInput = null, collabToolPolicy = null } = {}) {
|
|
1842
1855
|
if (!prompt || typeof prompt !== 'string' || !prompt.trim()) {
|
|
1843
1856
|
yield {
|
|
1844
1857
|
type: 'error',
|
|
@@ -1915,7 +1928,7 @@ export class Engine {
|
|
|
1915
1928
|
};
|
|
1916
1929
|
try {
|
|
1917
1930
|
this.#currentThreadId = threadId || MAIN_THREAD_ID;
|
|
1918
|
-
yield* this.#runQuery({ prompt: effectivePrompt, promptParts: effectivePromptParts, messages, signal: runSignal, userEffort: effectiveUserEffort, scenario, vpPersona, router, senderVpId, inboundEnvelope, taskId, taskMembers, sessionId, sessionMembers, sessionTopics, vpPlan, sessionAnnouncement, workCenterInstructions, workDir, userAlreadyPersisted, getCurrentTodos, setCurrentTodos, askUser, threadId: this.#currentThreadId, vpTurnId, drainPendingUserMessages, prepareProviderRequest, startProviderRequest, finishProviderRequest, failProviderRequest, closePendingUserInput, collabToolPolicy: effectiveCollabToolPolicy, explicitSkillName: parsedSkill.skillName, retryLifecycle });
|
|
1931
|
+
yield* this.#runQuery({ prompt: effectivePrompt, promptParts: effectivePromptParts, messages, signal: runSignal, userEffort: effectiveUserEffort, scenario, vpPersona, router, senderVpId, inboundEnvelope, taskId, taskMembers, sessionId, sessionMembers, projectSessionIds, sessionTopics, vpPlan, sessionAnnouncement, workCenterInstructions, workDir, userAlreadyPersisted, getCurrentTodos, setCurrentTodos, askUser, threadId: this.#currentThreadId, vpTurnId, drainPendingUserMessages, prepareProviderRequest, startProviderRequest, finishProviderRequest, failProviderRequest, closePendingUserInput, collabToolPolicy: effectiveCollabToolPolicy, explicitSkillName: parsedSkill.skillName, retryLifecycle });
|
|
1919
1932
|
} finally {
|
|
1920
1933
|
// Closing the async generator at a visible retry boundary means the
|
|
1921
1934
|
// continuation never reached a provider. Keep it out of history and
|
|
@@ -1963,7 +1976,7 @@ export class Engine {
|
|
|
1963
1976
|
* in a try/finally without indenting the whole loop.
|
|
1964
1977
|
* @private
|
|
1965
1978
|
*/
|
|
1966
|
-
async *#runQuery({ prompt, promptParts = null, messages, signal, userEffort = null, scenario = 'chat', vpPersona, router, senderVpId, inboundEnvelope, taskId, taskMembers, sessionId, sessionMembers, sessionTopics = null, vpPlan, sessionAnnouncement, workCenterInstructions, workDir, userAlreadyPersisted = false, getCurrentTodos = null, setCurrentTodos = null, askUser = null, threadId = MAIN_THREAD_ID, vpTurnId = null, drainPendingUserMessages = null, prepareProviderRequest = null, startProviderRequest = null, finishProviderRequest = null, failProviderRequest = null, closePendingUserInput = null, collabToolPolicy = null, explicitSkillName = null, retryLifecycle }) {
|
|
1979
|
+
async *#runQuery({ prompt, promptParts = null, messages, signal, userEffort = null, scenario = 'chat', vpPersona, router, senderVpId, inboundEnvelope, taskId, taskMembers, sessionId, sessionMembers, projectSessionIds = null, sessionTopics = null, vpPlan, sessionAnnouncement, workCenterInstructions, workDir, userAlreadyPersisted = false, getCurrentTodos = null, setCurrentTodos = null, askUser = null, threadId = MAIN_THREAD_ID, vpTurnId = null, drainPendingUserMessages = null, prepareProviderRequest = null, startProviderRequest = null, finishProviderRequest = null, failProviderRequest = null, closePendingUserInput = null, collabToolPolicy = null, explicitSkillName = null, retryLifecycle }) {
|
|
1967
1980
|
|
|
1968
1981
|
const effectiveCollabToolPolicy = collabToolPolicy === COLLAB_TOOL_POLICY.SINGLE_VP || collabToolPolicy === COLLAB_TOOL_POLICY.MULTI_VP
|
|
1969
1982
|
? collabToolPolicy
|
|
@@ -2022,12 +2035,22 @@ export class Engine {
|
|
|
2022
2035
|
let recallEntryCount = 0;
|
|
2023
2036
|
|
|
2024
2037
|
const topicScopesForMemory = await this.#loadSessionTopicScopes(sessionId);
|
|
2038
|
+
const projectScopesForMemory = Array.isArray(projectSessionIds)
|
|
2039
|
+
? projectSessionIds.flatMap(id => [
|
|
2040
|
+
`sessions/${id}`,
|
|
2041
|
+
`sessions/${id}/user`,
|
|
2042
|
+
`session/${id}`,
|
|
2043
|
+
`session/${id}/user`,
|
|
2044
|
+
`group/${id}`,
|
|
2045
|
+
`group/${id}/user`,
|
|
2046
|
+
])
|
|
2047
|
+
: [];
|
|
2025
2048
|
const recallResult = await this.#recallMemory(prompt, {
|
|
2026
2049
|
sessionId,
|
|
2027
2050
|
vpId: vpPersona && typeof vpPersona === 'object' && typeof vpPersona.vpId === 'string'
|
|
2028
2051
|
? vpPersona.vpId
|
|
2029
2052
|
: (typeof senderVpId === 'string' ? senderVpId : undefined),
|
|
2030
|
-
extraScopes: topicScopesForMemory,
|
|
2053
|
+
extraScopes: [...topicScopesForMemory, ...projectScopesForMemory],
|
|
2031
2054
|
});
|
|
2032
2055
|
recallEntryCount = recallResult && Array.isArray(recallResult.entries)
|
|
2033
2056
|
? recallResult.entries.length
|
|
@@ -3521,6 +3544,7 @@ export class Engine {
|
|
|
3521
3544
|
router,
|
|
3522
3545
|
senderVpId,
|
|
3523
3546
|
sessionId: runtimeSessionId,
|
|
3547
|
+
projectSessionIds,
|
|
3524
3548
|
threadId: runtimeThreadId,
|
|
3525
3549
|
inboundEnvelope,
|
|
3526
3550
|
taskId,
|