feat: add note mode and workflow config

This commit is contained in:
shiyue
2026-06-12 16:39:44 +08:00
parent 5308a10b52
commit 8b2173be8f
93 changed files with 15292 additions and 50 deletions

View File

@@ -217,7 +217,26 @@ function createAgentRuntime(deps) {
return JSON.stringify(truncateObj(item, 1200));
}
function ensureCodexToolCall(entry, item) {
function sendRuntime(entry, sessionId, payload) {
wsSend(entry.ws, { ...payload, sessionId });
}
function appendCodexAgentText(entry, text) {
const nextText = String(text || '');
if (!nextText) return '';
const currentText = entry.fullText || '';
const hasExistingText = /\S/.test(currentText);
const hasParagraphBoundary = /\n\s*\n\s*$/.test(currentText) || /^\s*\n\s*\n/.test(nextText);
const separator = hasExistingText && !hasParagraphBoundary
? (/\n\s*$/.test(currentText) ? '\n' : '\n\n')
: '';
const chunk = separator + nextText;
entry.fullText += chunk;
return chunk;
}
function ensureCodexToolCall(entry, item, sessionId) {
let tc = entry.toolCalls.find((t) => t.id === item.id);
if (tc) {
tc.name = codexToolName(item);
@@ -235,7 +254,7 @@ function createAgentRuntime(deps) {
done: false,
};
entry.toolCalls.push(tc);
wsSend(entry.ws, {
sendRuntime(entry, sessionId, {
type: 'tool_start',
name: tc.name,
toolUseId: item.id,
@@ -267,12 +286,12 @@ function createAgentRuntime(deps) {
for (const block of content) {
if (block.type === 'text' && block.text) {
entry.fullText += block.text;
wsSend(entry.ws, { type: 'text_delta', text: block.text });
sendRuntime(entry, sessionId, { type: 'text_delta', text: block.text });
} else if (block.type === 'tool_use') {
const toolInput = sanitizeToolInput(block.name, block.input);
const tc = { name: block.name, id: block.id, input: toolInput, done: false };
entry.toolCalls.push(tc);
wsSend(entry.ws, { type: 'tool_start', name: block.name, toolUseId: block.id, input: tc.input });
sendRuntime(entry, sessionId, { type: 'tool_start', name: block.name, toolUseId: block.id, input: tc.input });
} else if (block.type === 'tool_result') {
const resultText = typeof block.content === 'string'
? block.content
@@ -284,7 +303,7 @@ function createAgentRuntime(deps) {
tc.done = true;
tc.result = resultText.slice(0, 2000);
}
wsSend(entry.ws, { type: 'tool_end', toolUseId: block.tool_use_id, result: resultText.slice(0, 2000) });
sendRuntime(entry, sessionId, { type: 'tool_end', toolUseId: block.tool_use_id, result: resultText.slice(0, 2000) });
}
}
@@ -307,7 +326,7 @@ function createAgentRuntime(deps) {
}
entry.lastCost = event.total_cost_usd || null;
if (entry.ws && event.total_cost_usd !== undefined) {
wsSend(entry.ws, { type: 'cost', costUsd: session?.totalCost || 0 });
sendRuntime(entry, sessionId, { type: 'cost', costUsd: session?.totalCost || 0 });
}
break;
}
@@ -331,19 +350,19 @@ function createAgentRuntime(deps) {
case 'item.started': {
const item = event.item;
if (!item || !item.id || item.type === 'agent_message') break;
ensureCodexToolCall(entry, item);
ensureCodexToolCall(entry, item, sessionId);
break;
}
case 'item.updated': {
const item = event.item;
if (!item || !item.id || item.type === 'agent_message') break;
const tc = ensureCodexToolCall(entry, item);
const tc = ensureCodexToolCall(entry, item, sessionId);
const resultText = codexToolResult(item).slice(0, 2000);
tc.done = false;
tc.result = resultText;
wsSend(entry.ws, {
sendRuntime(entry, sessionId, {
type: 'tool_update',
toolUseId: item.id,
name: tc.name,
@@ -369,21 +388,21 @@ function createAgentRuntime(deps) {
if (!entry.contentBlocks) entry.contentBlocks = [];
entry.contentBlocks.push(...parsedContent);
const textOnly = parsedContent.filter(b => b.type === 'text').map(b => b.text || '').join('');
entry.fullText += textOnly;
wsSend(entry.ws, { type: 'content_blocks', blocks: parsedContent });
appendCodexAgentText(entry, textOnly);
sendRuntime(entry, sessionId, { type: 'content_blocks', blocks: parsedContent });
} else {
entry.fullText += item.text;
wsSend(entry.ws, { type: 'text_delta', text: item.text });
const textChunk = appendCodexAgentText(entry, item.text);
sendRuntime(entry, sessionId, { type: 'text_delta', text: textChunk });
}
}
break;
}
const tc = ensureCodexToolCall(entry, item);
const tc = ensureCodexToolCall(entry, item, sessionId);
const resultText = codexToolResult(item).slice(0, 2000);
tc.done = true;
tc.result = resultText;
wsSend(entry.ws, {
sendRuntime(entry, sessionId, {
type: 'tool_end',
toolUseId: item.id,
result: resultText,
@@ -404,7 +423,7 @@ function createAgentRuntime(deps) {
outputTokens: (session.totalUsage?.outputTokens || 0) + (usage.output_tokens || 0),
};
saveSession(session);
wsSend(entry.ws, { type: 'usage', totalUsage: session.totalUsage });
sendRuntime(entry, sessionId, { type: 'usage', totalUsage: session.totalUsage });
}
break;
}
@@ -418,7 +437,7 @@ function createAgentRuntime(deps) {
case 'error':
if (event.message) {
if (/^Reconnecting\.\.\./.test(event.message)) {
wsSend(entry.ws, { type: 'system_message', message: event.message });
sendRuntime(entry, sessionId, { type: 'system_message', message: event.message });
} else {
entry.lastError = event.message;
}