Some checks failed
build-packages / resolve bundled mosh-client (push) Has been cancelled
build-packages / resolve bundled et-client (push) Has been cancelled
build-packages / build-macos (push) Has been cancelled
build-packages / build-windows (push) Has been cancelled
build-packages / build-linux-x64 (push) Has been cancelled
build-packages / build-linux-arm64 (push) Has been cancelled
build-packages / release (push) Has been cancelled
build-packages / update Nix release metadata (push) Has been cancelled
build-packages / bump homebrew tap (push) Has been cancelled
test / lint-and-test (push) Has been cancelled
AI automation / Route event (push) Has been cancelled
AI automation / Hand reopened issue to maintainers (push) Has been cancelled
AI automation / Clean source issue state (push) Has been cancelled
AI automation / Reconcile handoffs (push) Has been cancelled
AI automation / Classify issue (push) Has been cancelled
AI automation / Claude Code smoke (push) Has been cancelled
AI automation / Review issue follow-up (push) Has been cancelled
AI automation / Publish issue follow-up (push) Has been cancelled
AI automation / Implement with Claude Code (push) Has been cancelled
AI automation / Publish implement PR (push) Has been cancelled
AI automation / Continue queued issue comments (push) Has been cancelled
AI automation / Codex review loop (push) Has been cancelled
AI automation / Publish Codex fix (push) Has been cancelled
AI automation / Clear Codex dispatch marker (push) Has been cancelled
AI automation / Own PR re-request Codex (push) Has been cancelled
AI automation / External PR re-request Codex (push) Has been cancelled
AI automation / Poll Codex reaction / retry (push) Has been cancelled
build-et-binaries / build-linux-x64 (push) Has been cancelled
build-et-binaries / build-linux-arm64 (push) Has been cancelled
build-et-binaries / build-macos-universal (push) Has been cancelled
build-et-binaries / build-windows-x64 (push) Has been cancelled
build-et-binaries / release (push) Has been cancelled
107 lines
3.3 KiB
TypeScript
107 lines
3.3 KiB
TypeScript
import assert from 'node:assert/strict';
|
|
import test from 'node:test';
|
|
import { CattyTurnDriver } from './turnDrivers/cattyTurnDriver';
|
|
import type { TurnDriverContext, TurnInput } from './turnDrivers/types';
|
|
|
|
const mcpServerBridge = await import('../../../electron/bridges/mcpServerBridge.cjs');
|
|
|
|
function createTurnContext(): TurnDriverContext {
|
|
return {
|
|
turnId: 'turn-1',
|
|
chatSessionId: 'chat-1',
|
|
sessionId: 'chat-1',
|
|
backend: 'catty',
|
|
signal: new AbortController().signal,
|
|
emit: () => {},
|
|
toolOutputStore: {
|
|
store: () => ({ id: 'handle-1', contentLength: 0 }),
|
|
read: () => null,
|
|
clearSession: () => {},
|
|
},
|
|
toolResultDedup: {
|
|
fingerprintFor: () => 'fingerprint',
|
|
check: () => null,
|
|
remember: () => {},
|
|
buildCachedNotice: () => ({}),
|
|
clearTurn: () => {},
|
|
},
|
|
sessionStateStore: {
|
|
mergeFromUserGoal: () => {},
|
|
toReinjectionText: () => undefined,
|
|
get: () => ({ decisions: [], activeHosts: {}, blockers: [], updatedAt: Date.now() }),
|
|
clear: () => {},
|
|
updateFromToolResult: () => {},
|
|
mergeFromAssistantContent: () => {},
|
|
},
|
|
} as TurnDriverContext;
|
|
}
|
|
|
|
test('Catty turn registers current message file attachments for attachment tools', async (t) => {
|
|
mcpServerBridge.cleanup();
|
|
const csvText = 'label,hostname,username\nprod,prod.example.com,root\n';
|
|
const bridge = {
|
|
aiSetChatSessionCancelled: async () => ({ ok: true }),
|
|
aiMcpUpdateSessions: async () => undefined,
|
|
aiMcpUpdateAttachments: async (
|
|
attachments: Array<{ base64Data?: string; mediaType?: string; filename?: string; filePath?: string }>,
|
|
chatSessionId?: string,
|
|
) => {
|
|
mcpServerBridge.updateAttachmentMetadata(attachments, chatSessionId);
|
|
return { ok: true };
|
|
},
|
|
};
|
|
t.after(() => mcpServerBridge.cleanup());
|
|
|
|
const controller = new AbortController();
|
|
const input: TurnInput = {
|
|
backend: 'catty',
|
|
chatSessionId: 'chat-1',
|
|
sendScopeKey: 'chat-1',
|
|
userText: '把这些主机都导入到 vault',
|
|
signal: controller.signal,
|
|
currentSession: undefined,
|
|
assistantMsgId: 'assistant-1',
|
|
context: {
|
|
activeProvider: undefined,
|
|
activeModelId: '',
|
|
scopeType: 'terminal',
|
|
globalPermissionMode: 'confirm',
|
|
terminalSessions: [],
|
|
autoTitleSession: () => {},
|
|
},
|
|
attachments: [{
|
|
filename: 'hosts_export_2026-06-25.csv',
|
|
mediaType: 'text/csv',
|
|
base64Data: Buffer.from(csvText).toString('base64'),
|
|
filePath: '/tmp/hosts_export_2026-06-25.csv',
|
|
}],
|
|
maxIterations: 5,
|
|
bridge,
|
|
ui: {
|
|
addMessageToSession: () => {},
|
|
updateLastMessage: () => {},
|
|
updateMessageById: () => {},
|
|
reportStreamError: () => {},
|
|
setStreamingForScope: () => {},
|
|
},
|
|
};
|
|
|
|
await new CattyTurnDriver().run(input, createTurnContext());
|
|
|
|
const listed = mcpServerBridge.handleListAttachments({ chatSessionId: 'chat-1' });
|
|
assert.equal(listed.ok, true);
|
|
assert.deepEqual(listed.attachments, [{
|
|
filename: 'hosts_export_2026-06-25.csv',
|
|
mediaType: 'text/csv',
|
|
filePath: '/tmp/hosts_export_2026-06-25.csv',
|
|
sizeBytes: Buffer.byteLength(csvText),
|
|
}]);
|
|
|
|
const read = mcpServerBridge.handleReadAttachment({
|
|
chatSessionId: 'chat-1',
|
|
filename: 'hosts_export_2026-06-25.csv',
|
|
});
|
|
assert.equal(read.ok, true);
|
|
assert.equal(read.text, csvText);
|
|
});
|