causantic 0.6.1 → 0.7.1
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/cli/skill-templates.d.ts.map +1 -1
- package/dist/cli/skill-templates.js +23 -4
- package/dist/cli/skill-templates.js.map +1 -1
- package/dist/config/loader.d.ts +6 -0
- package/dist/config/loader.d.ts.map +1 -1
- package/dist/config/loader.js +18 -0
- package/dist/config/loader.js.map +1 -1
- package/dist/config/memory-config.d.ts +7 -0
- package/dist/config/memory-config.d.ts.map +1 -1
- package/dist/config/memory-config.js +4 -0
- package/dist/config/memory-config.js.map +1 -1
- package/dist/hooks/pre-compact.js +2 -2
- package/dist/hooks/pre-compact.js.map +1 -1
- package/dist/ingest/edge-creator.d.ts +13 -0
- package/dist/ingest/edge-creator.d.ts.map +1 -1
- package/dist/ingest/edge-creator.js +36 -0
- package/dist/ingest/edge-creator.js.map +1 -1
- package/dist/ingest/index.d.ts +5 -1
- package/dist/ingest/index.d.ts.map +1 -1
- package/dist/ingest/index.js +5 -1
- package/dist/ingest/index.js.map +1 -1
- package/dist/ingest/ingest-session.d.ts +6 -0
- package/dist/ingest/ingest-session.d.ts.map +1 -1
- package/dist/ingest/ingest-session.js +263 -33
- package/dist/ingest/ingest-session.js.map +1 -1
- package/dist/ingest/team-detector.d.ts +52 -0
- package/dist/ingest/team-detector.d.ts.map +1 -0
- package/dist/ingest/team-detector.js +241 -0
- package/dist/ingest/team-detector.js.map +1 -0
- package/dist/ingest/team-edge-detector.d.ts +47 -0
- package/dist/ingest/team-edge-detector.d.ts.map +1 -0
- package/dist/ingest/team-edge-detector.js +246 -0
- package/dist/ingest/team-edge-detector.js.map +1 -0
- package/dist/mcp/tools.d.ts.map +1 -1
- package/dist/mcp/tools.js +49 -0
- package/dist/mcp/tools.js.map +1 -1
- package/dist/parser/session-reader.d.ts +4 -0
- package/dist/parser/session-reader.d.ts.map +1 -1
- package/dist/parser/session-reader.js +45 -2
- package/dist/parser/session-reader.js.map +1 -1
- package/dist/retrieval/chain-assembler.d.ts +2 -0
- package/dist/retrieval/chain-assembler.d.ts.map +1 -1
- package/dist/retrieval/chain-assembler.js +6 -3
- package/dist/retrieval/chain-assembler.js.map +1 -1
- package/dist/retrieval/chain-walker.d.ts +4 -0
- package/dist/retrieval/chain-walker.d.ts.map +1 -1
- package/dist/retrieval/chain-walker.js +36 -14
- package/dist/retrieval/chain-walker.js.map +1 -1
- package/dist/retrieval/cluster-expander.d.ts +1 -1
- package/dist/retrieval/cluster-expander.d.ts.map +1 -1
- package/dist/retrieval/cluster-expander.js +7 -1
- package/dist/retrieval/cluster-expander.js.map +1 -1
- package/dist/retrieval/context-assembler.d.ts +2 -0
- package/dist/retrieval/context-assembler.d.ts.map +1 -1
- package/dist/retrieval/context-assembler.js +3 -0
- package/dist/retrieval/context-assembler.js.map +1 -1
- package/dist/retrieval/search-assembler.d.ts +2 -0
- package/dist/retrieval/search-assembler.d.ts.map +1 -1
- package/dist/retrieval/search-assembler.js +34 -15
- package/dist/retrieval/search-assembler.js.map +1 -1
- package/dist/retrieval/session-reconstructor.d.ts +3 -0
- package/dist/retrieval/session-reconstructor.d.ts.map +1 -1
- package/dist/retrieval/session-reconstructor.js +18 -2
- package/dist/retrieval/session-reconstructor.js.map +1 -1
- package/dist/storage/chunk-store.d.ts +2 -1
- package/dist/storage/chunk-store.d.ts.map +1 -1
- package/dist/storage/chunk-store.js +19 -7
- package/dist/storage/chunk-store.js.map +1 -1
- package/dist/storage/keyword-store.d.ts +1 -1
- package/dist/storage/keyword-store.d.ts.map +1 -1
- package/dist/storage/keyword-store.js +13 -8
- package/dist/storage/keyword-store.js.map +1 -1
- package/dist/storage/migrations.d.ts.map +1 -1
- package/dist/storage/migrations.js +39 -0
- package/dist/storage/migrations.js.map +1 -1
- package/dist/storage/schema.sql +8 -3
- package/dist/storage/types.d.ts +5 -1
- package/dist/storage/types.d.ts.map +1 -1
- package/dist/storage/vector-store.d.ts +13 -1
- package/dist/storage/vector-store.d.ts.map +1 -1
- package/dist/storage/vector-store.js +66 -5
- package/dist/storage/vector-store.js.map +1 -1
- package/package.json +2 -2
|
@@ -0,0 +1,241 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Team topology detection for agent team sessions.
|
|
3
|
+
*
|
|
4
|
+
* Detects whether a session uses agent teams by scanning for:
|
|
5
|
+
* - TeamCreate tool calls (explicit team creation)
|
|
6
|
+
* - Task tool calls with team_name (team member spawning)
|
|
7
|
+
* - SendMessage tool calls (inter-agent messaging)
|
|
8
|
+
*
|
|
9
|
+
* Resolves hex agent IDs to human-readable teammate names and
|
|
10
|
+
* groups multi-file teammates for consolidated ingestion.
|
|
11
|
+
*/
|
|
12
|
+
import { createLogger } from '../utils/logger.js';
|
|
13
|
+
const log = createLogger('team-detector');
|
|
14
|
+
/**
|
|
15
|
+
* Detect team topology from main session turns and sub-agent info.
|
|
16
|
+
*
|
|
17
|
+
* Scans assistant blocks for TeamCreate, Task (with team_name), and
|
|
18
|
+
* SendMessage tool calls. Resolves hex IDs to human names using a
|
|
19
|
+
* priority chain: Task.name > Task result parsing > SendMessage routing > XML fallback.
|
|
20
|
+
*/
|
|
21
|
+
export function detectTeamTopology(mainTurns, subAgents) {
|
|
22
|
+
let teamName = null;
|
|
23
|
+
const teammates = new Map(); // hexId -> humanName
|
|
24
|
+
const teamAgentIds = new Set();
|
|
25
|
+
let hasTeamSignals = false;
|
|
26
|
+
// Build a set of known sub-agent hex IDs for matching
|
|
27
|
+
const knownHexIds = new Set(subAgents.map((sa) => sa.agentId));
|
|
28
|
+
// Track Task tool calls with team_name for name resolution
|
|
29
|
+
const taskToolUseIds = new Map(); // toolUseId -> humanName from input.name
|
|
30
|
+
for (const turn of mainTurns) {
|
|
31
|
+
for (const block of turn.assistantBlocks) {
|
|
32
|
+
if (block.type !== 'tool_use')
|
|
33
|
+
continue;
|
|
34
|
+
const toolUse = block;
|
|
35
|
+
// 1. TeamCreate — extract team name
|
|
36
|
+
if (toolUse.name === 'TeamCreate') {
|
|
37
|
+
const input = toolUse.input;
|
|
38
|
+
if (typeof input.team_name === 'string') {
|
|
39
|
+
teamName = input.team_name;
|
|
40
|
+
hasTeamSignals = true;
|
|
41
|
+
log.debug('Detected TeamCreate', { teamName });
|
|
42
|
+
}
|
|
43
|
+
continue;
|
|
44
|
+
}
|
|
45
|
+
// 2. Task with team_name — team member spawn
|
|
46
|
+
if (toolUse.name === 'Task') {
|
|
47
|
+
const input = toolUse.input;
|
|
48
|
+
if (typeof input.team_name === 'string') {
|
|
49
|
+
hasTeamSignals = true;
|
|
50
|
+
const humanName = typeof input.name === 'string' ? input.name : null;
|
|
51
|
+
if (humanName) {
|
|
52
|
+
taskToolUseIds.set(toolUse.id, humanName);
|
|
53
|
+
}
|
|
54
|
+
// Try to resolve hex ID from tool exchange results
|
|
55
|
+
const exchange = turn.toolExchanges.find((e) => e.toolUseId === toolUse.id);
|
|
56
|
+
if (exchange) {
|
|
57
|
+
const hexId = resolveHexIdFromResult(exchange.result, knownHexIds);
|
|
58
|
+
if (hexId && humanName) {
|
|
59
|
+
teammates.set(hexId, humanName);
|
|
60
|
+
teamAgentIds.add(hexId);
|
|
61
|
+
log.debug('Resolved teammate from Task result', { hexId, humanName });
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
continue;
|
|
66
|
+
}
|
|
67
|
+
// 3. SendMessage — inter-agent messaging signal
|
|
68
|
+
if (toolUse.name === 'SendMessage') {
|
|
69
|
+
hasTeamSignals = true;
|
|
70
|
+
// SendMessage results may contain sender routing metadata
|
|
71
|
+
const exchange = turn.toolExchanges.find((e) => e.toolUseId === toolUse.id);
|
|
72
|
+
if (exchange) {
|
|
73
|
+
const senderInfo = parseSenderFromResult(exchange.result);
|
|
74
|
+
if (senderInfo && knownHexIds.has(senderInfo.hexId)) {
|
|
75
|
+
teamAgentIds.add(senderInfo.hexId);
|
|
76
|
+
if (senderInfo.name && !teammates.has(senderInfo.hexId)) {
|
|
77
|
+
teammates.set(senderInfo.hexId, senderInfo.name);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
// 4. Fallback: Parse <teammate-message> XML tags in user messages
|
|
84
|
+
if (hasTeamSignals) {
|
|
85
|
+
parseTeammateMessagesFromTurn(turn, knownHexIds, teammates, teamAgentIds);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
// If we have team signals but some agent IDs are still unresolved,
|
|
89
|
+
// try to infer from sub-agent files that match known patterns
|
|
90
|
+
if (hasTeamSignals && teammates.size > 0) {
|
|
91
|
+
resolveRemainingAgentIds(subAgents, teammates, teamAgentIds, taskToolUseIds, mainTurns);
|
|
92
|
+
}
|
|
93
|
+
return {
|
|
94
|
+
isTeamSession: hasTeamSignals,
|
|
95
|
+
teamName,
|
|
96
|
+
teammates,
|
|
97
|
+
teamAgentIds,
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Try to extract a hex agent ID from a Task tool result.
|
|
102
|
+
*
|
|
103
|
+
* Task results may contain "name@description" format or reference the agent ID directly.
|
|
104
|
+
*/
|
|
105
|
+
function resolveHexIdFromResult(result, knownHexIds) {
|
|
106
|
+
// Check if result directly contains a known hex ID
|
|
107
|
+
for (const hexId of knownHexIds) {
|
|
108
|
+
if (result.includes(hexId)) {
|
|
109
|
+
return hexId;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
return null;
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Parse sender routing metadata from SendMessage result text.
|
|
116
|
+
*/
|
|
117
|
+
function parseSenderFromResult(result) {
|
|
118
|
+
// Look for sender field in result
|
|
119
|
+
try {
|
|
120
|
+
const parsed = JSON.parse(result);
|
|
121
|
+
if (typeof parsed === 'object' && parsed !== null) {
|
|
122
|
+
const sender = parsed.sender;
|
|
123
|
+
if (typeof sender === 'string') {
|
|
124
|
+
return { hexId: sender, name: null };
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
catch {
|
|
129
|
+
// Not JSON, try regex patterns
|
|
130
|
+
}
|
|
131
|
+
// Look for patterns like sender: "hexId" or from: "hexId"
|
|
132
|
+
const senderMatch = result.match(/(?:sender|from)["':\s]+([a-f0-9-]{8,})/i);
|
|
133
|
+
if (senderMatch) {
|
|
134
|
+
return { hexId: senderMatch[1], name: null };
|
|
135
|
+
}
|
|
136
|
+
return null;
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* Parse <teammate-message> XML tags from user messages in a turn.
|
|
140
|
+
* Format: <teammate-message teammate_id="name" summary="...">
|
|
141
|
+
*/
|
|
142
|
+
function parseTeammateMessagesFromTurn(turn, knownHexIds, teammates, teamAgentIds) {
|
|
143
|
+
for (const msg of turn.rawMessages) {
|
|
144
|
+
if (msg.type !== 'user' || !msg.message?.content)
|
|
145
|
+
continue;
|
|
146
|
+
const content = typeof msg.message.content === 'string'
|
|
147
|
+
? msg.message.content
|
|
148
|
+
: msg.message.content
|
|
149
|
+
.filter((b) => b.type === 'text')
|
|
150
|
+
.map((b) => b.text)
|
|
151
|
+
.join('\n');
|
|
152
|
+
// Match <teammate-message teammate_id="name">
|
|
153
|
+
const tmRegex = /<teammate-message\s+teammate_id="([^"]+)"/g;
|
|
154
|
+
let match;
|
|
155
|
+
while ((match = tmRegex.exec(content)) !== null) {
|
|
156
|
+
const teammateId = match[1];
|
|
157
|
+
// teammate_id is the human name — map it to hex IDs via other signals
|
|
158
|
+
// This acts as a fallback name source: if we see a teammate_id that
|
|
159
|
+
// matches a name we already know, it confirms it.
|
|
160
|
+
// If we see a new name, store it for later resolution.
|
|
161
|
+
for (const [hexId, name] of teammates) {
|
|
162
|
+
if (name === teammateId) {
|
|
163
|
+
teamAgentIds.add(hexId);
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
/**
|
|
170
|
+
* Attempt to resolve remaining unmatched agent IDs.
|
|
171
|
+
*
|
|
172
|
+
* Uses progress messages and cross-referencing to map hex IDs
|
|
173
|
+
* that weren't resolved from Task tool results.
|
|
174
|
+
*/
|
|
175
|
+
function resolveRemainingAgentIds(subAgents, teammates, teamAgentIds, taskToolUseIds, mainTurns) {
|
|
176
|
+
// Extract agent spawns from progress messages (same pattern as brief-debrief-detector)
|
|
177
|
+
for (const turn of mainTurns) {
|
|
178
|
+
for (const msg of turn.rawMessages) {
|
|
179
|
+
if (msg.type !== 'progress')
|
|
180
|
+
continue;
|
|
181
|
+
if (!msg.data || msg.data.type !== 'agent_progress')
|
|
182
|
+
continue;
|
|
183
|
+
const agentId = msg.data.agentId;
|
|
184
|
+
const parentToolUseId = msg.parentToolUseID;
|
|
185
|
+
if (agentId && parentToolUseId && !teammates.has(agentId)) {
|
|
186
|
+
// Check if this toolUseId maps to a known team Task spawn
|
|
187
|
+
const humanName = taskToolUseIds.get(parentToolUseId);
|
|
188
|
+
if (humanName) {
|
|
189
|
+
teammates.set(agentId, humanName);
|
|
190
|
+
teamAgentIds.add(agentId);
|
|
191
|
+
log.debug('Resolved teammate via progress message', { agentId, humanName });
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
// For any sub-agents that are in teamAgentIds but don't have a name,
|
|
197
|
+
// assign a fallback name based on index
|
|
198
|
+
let unnamedCount = 0;
|
|
199
|
+
for (const sa of subAgents) {
|
|
200
|
+
if (teamAgentIds.has(sa.agentId) && !teammates.has(sa.agentId)) {
|
|
201
|
+
unnamedCount++;
|
|
202
|
+
teammates.set(sa.agentId, `teammate-${unnamedCount}`);
|
|
203
|
+
log.debug('Assigned fallback name to teammate', {
|
|
204
|
+
agentId: sa.agentId,
|
|
205
|
+
name: `teammate-${unnamedCount}`,
|
|
206
|
+
});
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
/**
|
|
211
|
+
* Group sub-agent files by resolved teammate name.
|
|
212
|
+
*
|
|
213
|
+
* Only includes files that belong to the team (in teamAgentIds).
|
|
214
|
+
* Filters out dead-end files. Groups multiple files per teammate
|
|
215
|
+
* when a teammate has been respawned.
|
|
216
|
+
*/
|
|
217
|
+
export function groupTeammateFiles(subAgents, topology) {
|
|
218
|
+
const groups = new Map();
|
|
219
|
+
for (const sa of subAgents) {
|
|
220
|
+
// Skip non-team agents
|
|
221
|
+
if (!topology.teamAgentIds.has(sa.agentId))
|
|
222
|
+
continue;
|
|
223
|
+
// Skip dead ends
|
|
224
|
+
if (sa.isDeadEnd)
|
|
225
|
+
continue;
|
|
226
|
+
const humanName = topology.teammates.get(sa.agentId) ?? sa.agentId;
|
|
227
|
+
const existing = groups.get(humanName) ?? [];
|
|
228
|
+
existing.push(sa);
|
|
229
|
+
groups.set(humanName, existing);
|
|
230
|
+
}
|
|
231
|
+
const result = [];
|
|
232
|
+
for (const [humanName, files] of groups) {
|
|
233
|
+
result.push({ humanName, files });
|
|
234
|
+
}
|
|
235
|
+
log.debug('Grouped teammate files', {
|
|
236
|
+
groupCount: result.length,
|
|
237
|
+
groups: result.map((g) => `${g.humanName}: ${g.files.length} files`),
|
|
238
|
+
});
|
|
239
|
+
return result;
|
|
240
|
+
}
|
|
241
|
+
//# sourceMappingURL=team-detector.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"team-detector.js","sourceRoot":"","sources":["../../src/ingest/team-detector.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Team edge detection for agent team sessions.
|
|
3
|
+
*
|
|
4
|
+
* Detects three types of edges between team members:
|
|
5
|
+
* - team-spawn: Lead spawns a teammate (Task with team_name)
|
|
6
|
+
* - peer-message: Teammate sends a message to another teammate (SendMessage)
|
|
7
|
+
* - team-report: Teammate sends results back to the lead (SendMessage to lead)
|
|
8
|
+
*
|
|
9
|
+
* Matching uses tool call metadata and falls back to timestamp proximity.
|
|
10
|
+
*/
|
|
11
|
+
import type { Turn } from '../parser/types.js';
|
|
12
|
+
import type { ChunkInput } from '../storage/types.js';
|
|
13
|
+
import type { TeamTopology } from './team-detector.js';
|
|
14
|
+
/**
|
|
15
|
+
* A detected edge point between team members.
|
|
16
|
+
*/
|
|
17
|
+
export interface TeamEdgePoint {
|
|
18
|
+
/** Agent ID of the sender */
|
|
19
|
+
sourceAgentId: string;
|
|
20
|
+
/** Agent ID of the receiver */
|
|
21
|
+
targetAgentId: string;
|
|
22
|
+
/** Chunk IDs from the source agent for this edge */
|
|
23
|
+
sourceChunkIds: string[];
|
|
24
|
+
/** Chunk IDs from the target agent for this edge */
|
|
25
|
+
targetChunkIds: string[];
|
|
26
|
+
/** Type of team edge */
|
|
27
|
+
edgeType: 'team-spawn' | 'team-report' | 'peer-message';
|
|
28
|
+
/** ISO timestamp of the event */
|
|
29
|
+
timestamp: string;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Detect team edges from session data.
|
|
33
|
+
*
|
|
34
|
+
* Scans main session for team-spawn events (Task with team_name)
|
|
35
|
+
* and agent files for peer-message/team-report events (SendMessage).
|
|
36
|
+
*
|
|
37
|
+
* @param mainTurns - Turns from the main (lead) session
|
|
38
|
+
* @param mainChunks - Chunks from the main session
|
|
39
|
+
* @param agentData - Map of agentId/humanName → { turns, chunks } for each teammate
|
|
40
|
+
* @param topology - Detected team topology
|
|
41
|
+
* @returns Array of team edge points
|
|
42
|
+
*/
|
|
43
|
+
export declare function detectTeamEdges(mainTurns: Turn[], mainChunks: ChunkInput[], agentData: Map<string, {
|
|
44
|
+
turns: Turn[];
|
|
45
|
+
chunks: ChunkInput[];
|
|
46
|
+
}>, topology: TeamTopology): TeamEdgePoint[];
|
|
47
|
+
//# sourceMappingURL=team-edge-detector.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"team-edge-detector.d.ts","sourceRoot":"","sources":["../../src/ingest/team-edge-detector.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,IAAI,EAAgB,MAAM,oBAAoB,CAAC;AAC7D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AACtD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAQvD;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,6BAA6B;IAC7B,aAAa,EAAE,MAAM,CAAC;IACtB,+BAA+B;IAC/B,aAAa,EAAE,MAAM,CAAC;IACtB,oDAAoD;IACpD,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,oDAAoD;IACpD,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,wBAAwB;IACxB,QAAQ,EAAE,YAAY,GAAG,aAAa,GAAG,cAAc,CAAC;IACxD,iCAAiC;IACjC,SAAS,EAAE,MAAM,CAAC;CACnB;AAgDD;;;;;;;;;;;GAWG;AACH,wBAAgB,eAAe,CAC7B,SAAS,EAAE,IAAI,EAAE,EACjB,UAAU,EAAE,UAAU,EAAE,EACxB,SAAS,EAAE,GAAG,CAAC,MAAM,EAAE;IAAE,KAAK,EAAE,IAAI,EAAE,CAAC;IAAC,MAAM,EAAE,UAAU,EAAE,CAAA;CAAE,CAAC,EAC/D,QAAQ,EAAE,YAAY,GACrB,aAAa,EAAE,CAiBjB"}
|
|
@@ -0,0 +1,246 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Team edge detection for agent team sessions.
|
|
3
|
+
*
|
|
4
|
+
* Detects three types of edges between team members:
|
|
5
|
+
* - team-spawn: Lead spawns a teammate (Task with team_name)
|
|
6
|
+
* - peer-message: Teammate sends a message to another teammate (SendMessage)
|
|
7
|
+
* - team-report: Teammate sends results back to the lead (SendMessage to lead)
|
|
8
|
+
*
|
|
9
|
+
* Matching uses tool call metadata and falls back to timestamp proximity.
|
|
10
|
+
*/
|
|
11
|
+
import { createLogger } from '../utils/logger.js';
|
|
12
|
+
const log = createLogger('team-edge-detector');
|
|
13
|
+
/** Timestamp proximity window for fallback matching (10 seconds). */
|
|
14
|
+
const TIMESTAMP_PROXIMITY_MS = 10_000;
|
|
15
|
+
/**
|
|
16
|
+
* Find the chunk containing a specific turn index.
|
|
17
|
+
*/
|
|
18
|
+
function findChunkForTurn(chunks, turnIndex) {
|
|
19
|
+
return chunks.find((c) => c.turnIndices.includes(turnIndex));
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Find the chunk closest to a timestamp.
|
|
23
|
+
*/
|
|
24
|
+
function findChunkNearTimestamp(chunks, timestamp, windowMs) {
|
|
25
|
+
const targetMs = new Date(timestamp).getTime();
|
|
26
|
+
let bestChunk;
|
|
27
|
+
let bestDist = Infinity;
|
|
28
|
+
let matchCount = 0;
|
|
29
|
+
for (const chunk of chunks) {
|
|
30
|
+
const startMs = new Date(chunk.startTime).getTime();
|
|
31
|
+
const endMs = new Date(chunk.endTime).getTime();
|
|
32
|
+
const dist = Math.min(Math.abs(startMs - targetMs), Math.abs(endMs - targetMs));
|
|
33
|
+
if (dist <= windowMs) {
|
|
34
|
+
matchCount++;
|
|
35
|
+
if (dist < bestDist) {
|
|
36
|
+
bestDist = dist;
|
|
37
|
+
bestChunk = chunk;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
if (matchCount > 1) {
|
|
42
|
+
log.warn('Multiple chunks matched within timestamp proximity window', {
|
|
43
|
+
timestamp,
|
|
44
|
+
matchCount,
|
|
45
|
+
windowMs,
|
|
46
|
+
selectedChunkId: bestChunk?.id,
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
return bestChunk;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Detect team edges from session data.
|
|
53
|
+
*
|
|
54
|
+
* Scans main session for team-spawn events (Task with team_name)
|
|
55
|
+
* and agent files for peer-message/team-report events (SendMessage).
|
|
56
|
+
*
|
|
57
|
+
* @param mainTurns - Turns from the main (lead) session
|
|
58
|
+
* @param mainChunks - Chunks from the main session
|
|
59
|
+
* @param agentData - Map of agentId/humanName → { turns, chunks } for each teammate
|
|
60
|
+
* @param topology - Detected team topology
|
|
61
|
+
* @returns Array of team edge points
|
|
62
|
+
*/
|
|
63
|
+
export function detectTeamEdges(mainTurns, mainChunks, agentData, topology) {
|
|
64
|
+
const edges = [];
|
|
65
|
+
// 1. Detect team-spawn edges (lead → teammate)
|
|
66
|
+
detectTeamSpawnEdges(mainTurns, mainChunks, agentData, topology, edges);
|
|
67
|
+
// 2. Detect peer-message and team-report edges (agent → agent or agent → lead)
|
|
68
|
+
detectMessageEdges(mainTurns, mainChunks, agentData, topology, edges);
|
|
69
|
+
log.debug('Detected team edges', {
|
|
70
|
+
total: edges.length,
|
|
71
|
+
spawn: edges.filter((e) => e.edgeType === 'team-spawn').length,
|
|
72
|
+
report: edges.filter((e) => e.edgeType === 'team-report').length,
|
|
73
|
+
peer: edges.filter((e) => e.edgeType === 'peer-message').length,
|
|
74
|
+
});
|
|
75
|
+
return edges;
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Detect team-spawn edges: lead spawns teammate via Task tool with team_name.
|
|
79
|
+
*/
|
|
80
|
+
function detectTeamSpawnEdges(mainTurns, mainChunks, agentData, topology, edges) {
|
|
81
|
+
for (let ti = 0; ti < mainTurns.length; ti++) {
|
|
82
|
+
const turn = mainTurns[ti];
|
|
83
|
+
for (const block of turn.assistantBlocks) {
|
|
84
|
+
if (block.type !== 'tool_use')
|
|
85
|
+
continue;
|
|
86
|
+
const toolUse = block;
|
|
87
|
+
if (toolUse.name !== 'Task')
|
|
88
|
+
continue;
|
|
89
|
+
const input = toolUse.input;
|
|
90
|
+
if (typeof input.team_name !== 'string')
|
|
91
|
+
continue;
|
|
92
|
+
// Find which teammate this spawned
|
|
93
|
+
const humanName = typeof input.name === 'string' ? input.name : null;
|
|
94
|
+
if (!humanName)
|
|
95
|
+
continue;
|
|
96
|
+
// Find source chunk (lead's chunk containing this turn)
|
|
97
|
+
const sourceChunk = findChunkForTurn(mainChunks, turn.index);
|
|
98
|
+
if (!sourceChunk)
|
|
99
|
+
continue;
|
|
100
|
+
// Find target chunk (teammate's first chunk)
|
|
101
|
+
const targetData = agentData.get(humanName);
|
|
102
|
+
if (!targetData || targetData.chunks.length === 0)
|
|
103
|
+
continue;
|
|
104
|
+
const targetChunk = targetData.chunks[0];
|
|
105
|
+
edges.push({
|
|
106
|
+
sourceAgentId: 'lead',
|
|
107
|
+
targetAgentId: humanName,
|
|
108
|
+
sourceChunkIds: [sourceChunk.id],
|
|
109
|
+
targetChunkIds: [targetChunk.id],
|
|
110
|
+
edgeType: 'team-spawn',
|
|
111
|
+
timestamp: turn.startTime,
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Detect peer-message and team-report edges from SendMessage calls in agent files.
|
|
118
|
+
*/
|
|
119
|
+
function detectMessageEdges(mainTurns, mainChunks, agentData, topology, edges) {
|
|
120
|
+
for (const [senderName, senderData] of agentData) {
|
|
121
|
+
for (let ti = 0; ti < senderData.turns.length; ti++) {
|
|
122
|
+
const turn = senderData.turns[ti];
|
|
123
|
+
for (const block of turn.assistantBlocks) {
|
|
124
|
+
if (block.type !== 'tool_use')
|
|
125
|
+
continue;
|
|
126
|
+
const toolUse = block;
|
|
127
|
+
if (toolUse.name !== 'SendMessage')
|
|
128
|
+
continue;
|
|
129
|
+
const input = toolUse.input;
|
|
130
|
+
const recipientName = typeof input.recipient === 'string' ? input.recipient : null;
|
|
131
|
+
const summary = typeof input.summary === 'string' ? input.summary : null;
|
|
132
|
+
if (!recipientName)
|
|
133
|
+
continue;
|
|
134
|
+
// Find source chunk in sender's data
|
|
135
|
+
const sourceChunk = findChunkForTurn(senderData.chunks, turn.index);
|
|
136
|
+
if (!sourceChunk)
|
|
137
|
+
continue;
|
|
138
|
+
// Determine if this is a team-report (to lead) or peer-message
|
|
139
|
+
const isToLead = recipientName === 'team-lead' || recipientName === 'lead';
|
|
140
|
+
const edgeType = isToLead ? 'team-report' : 'peer-message';
|
|
141
|
+
// Find target chunk
|
|
142
|
+
let targetChunk;
|
|
143
|
+
if (isToLead) {
|
|
144
|
+
// team-report: find matching <teammate-message> in main turns
|
|
145
|
+
targetChunk = findReceiveChunkInMain(mainTurns, mainChunks, senderName, summary, turn.startTime);
|
|
146
|
+
}
|
|
147
|
+
else {
|
|
148
|
+
// peer-message: find matching receive in target agent's data
|
|
149
|
+
const targetData = agentData.get(recipientName);
|
|
150
|
+
if (targetData) {
|
|
151
|
+
targetChunk = findReceiveChunkInAgent(targetData.turns, targetData.chunks, senderName, summary, turn.startTime);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
if (!targetChunk)
|
|
155
|
+
continue;
|
|
156
|
+
const targetAgentId = isToLead ? 'lead' : recipientName;
|
|
157
|
+
edges.push({
|
|
158
|
+
sourceAgentId: senderName,
|
|
159
|
+
targetAgentId,
|
|
160
|
+
sourceChunkIds: [sourceChunk.id],
|
|
161
|
+
targetChunkIds: [targetChunk.id],
|
|
162
|
+
edgeType,
|
|
163
|
+
timestamp: turn.startTime,
|
|
164
|
+
});
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
/**
|
|
170
|
+
* Find the chunk in main session that received a teammate message.
|
|
171
|
+
*
|
|
172
|
+
* Matches by <teammate-message> XML tag with matching teammate_id and summary,
|
|
173
|
+
* falling back to timestamp proximity.
|
|
174
|
+
*/
|
|
175
|
+
function findReceiveChunkInMain(mainTurns, mainChunks, senderName, summary, sendTimestamp) {
|
|
176
|
+
// Try exact match via <teammate-message> XML
|
|
177
|
+
for (let ti = 0; ti < mainTurns.length; ti++) {
|
|
178
|
+
const turn = mainTurns[ti];
|
|
179
|
+
if (matchesTeammateMessage(turn, senderName, summary)) {
|
|
180
|
+
const chunk = findChunkForTurn(mainChunks, turn.index);
|
|
181
|
+
if (chunk)
|
|
182
|
+
return chunk;
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
// Fallback: timestamp proximity
|
|
186
|
+
log.warn('No XML match for teammate message in main session, falling back to timestamp proximity', {
|
|
187
|
+
sender: senderName,
|
|
188
|
+
summary,
|
|
189
|
+
sendTimestamp,
|
|
190
|
+
});
|
|
191
|
+
return findChunkNearTimestamp(mainChunks, sendTimestamp, TIMESTAMP_PROXIMITY_MS);
|
|
192
|
+
}
|
|
193
|
+
/**
|
|
194
|
+
* Find the chunk in a teammate's session that received a message.
|
|
195
|
+
*
|
|
196
|
+
* Matches by <teammate-message> XML tag, falling back to timestamp proximity.
|
|
197
|
+
*/
|
|
198
|
+
function findReceiveChunkInAgent(turns, chunks, senderName, summary, sendTimestamp) {
|
|
199
|
+
// Try exact match via <teammate-message> XML
|
|
200
|
+
for (let ti = 0; ti < turns.length; ti++) {
|
|
201
|
+
const turn = turns[ti];
|
|
202
|
+
if (matchesTeammateMessage(turn, senderName, summary)) {
|
|
203
|
+
const chunk = findChunkForTurn(chunks, turn.index);
|
|
204
|
+
if (chunk)
|
|
205
|
+
return chunk;
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
// Fallback: timestamp proximity
|
|
209
|
+
log.warn('No XML match for teammate message in agent session, falling back to timestamp proximity', {
|
|
210
|
+
sender: senderName,
|
|
211
|
+
summary,
|
|
212
|
+
sendTimestamp,
|
|
213
|
+
});
|
|
214
|
+
return findChunkNearTimestamp(chunks, sendTimestamp, TIMESTAMP_PROXIMITY_MS);
|
|
215
|
+
}
|
|
216
|
+
/**
|
|
217
|
+
* Check if a turn contains a <teammate-message> from the given sender.
|
|
218
|
+
*/
|
|
219
|
+
function matchesTeammateMessage(turn, senderName, summary) {
|
|
220
|
+
for (const msg of turn.rawMessages) {
|
|
221
|
+
if (msg.type !== 'user' || !msg.message?.content)
|
|
222
|
+
continue;
|
|
223
|
+
const content = typeof msg.message.content === 'string'
|
|
224
|
+
? msg.message.content
|
|
225
|
+
: msg.message.content
|
|
226
|
+
.filter((b) => b.type === 'text')
|
|
227
|
+
.map((b) => b.text)
|
|
228
|
+
.join('\n');
|
|
229
|
+
// Check for <teammate-message teammate_id="senderName" summary="...">
|
|
230
|
+
const escaped = senderName.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
231
|
+
const regex = new RegExp(`<teammate-message\\s+teammate_id="${escaped}"`, 'i');
|
|
232
|
+
if (regex.test(content)) {
|
|
233
|
+
// If summary provided, also check it matches
|
|
234
|
+
if (summary) {
|
|
235
|
+
const summaryEscaped = summary.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
236
|
+
const summaryRegex = new RegExp(`summary="${summaryEscaped}"`, 'i');
|
|
237
|
+
if (summaryRegex.test(content))
|
|
238
|
+
return true;
|
|
239
|
+
// Even without summary match, teammate_id match is good enough
|
|
240
|
+
}
|
|
241
|
+
return true;
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
return false;
|
|
245
|
+
}
|
|
246
|
+
//# sourceMappingURL=team-edge-detector.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"team-edge-detector.js","sourceRoot":"","sources":["../../src/ingest/team-edge-detector.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAKH,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAElD,MAAM,GAAG,GAAG,YAAY,CAAC,oBAAoB,CAAC,CAAC;AAE/C,qEAAqE;AACrE,MAAM,sBAAsB,GAAG,MAAM,CAAC;AAoBtC;;GAEG;AACH,SAAS,gBAAgB,CAAC,MAAoB,EAAE,SAAiB;IAC/D,OAAO,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC;AAC/D,CAAC;AAED;;GAEG;AACH,SAAS,sBAAsB,CAC7B,MAAoB,EACpB,SAAiB,EACjB,QAAgB;IAEhB,MAAM,QAAQ,GAAG,IAAI,IAAI,CAAC,SAAS,CAAC,CAAC,OAAO,EAAE,CAAC;IAC/C,IAAI,SAAiC,CAAC;IACtC,IAAI,QAAQ,GAAG,QAAQ,CAAC;IACxB,IAAI,UAAU,GAAG,CAAC,CAAC;IAEnB,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QAC3B,MAAM,OAAO,GAAG,IAAI,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,OAAO,EAAE,CAAC;QACpD,MAAM,KAAK,GAAG,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,OAAO,EAAE,CAAC;QAChD,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,OAAO,GAAG,QAAQ,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,KAAK,GAAG,QAAQ,CAAC,CAAC,CAAC;QAEhF,IAAI,IAAI,IAAI,QAAQ,EAAE,CAAC;YACrB,UAAU,EAAE,CAAC;YACb,IAAI,IAAI,GAAG,QAAQ,EAAE,CAAC;gBACpB,QAAQ,GAAG,IAAI,CAAC;gBAChB,SAAS,GAAG,KAAK,CAAC;YACpB,CAAC;QACH,CAAC;IACH,CAAC;IAED,IAAI,UAAU,GAAG,CAAC,EAAE,CAAC;QACnB,GAAG,CAAC,IAAI,CAAC,2DAA2D,EAAE;YACpE,SAAS;YACT,UAAU;YACV,QAAQ;YACR,eAAe,EAAE,SAAS,EAAE,EAAE;SAC/B,CAAC,CAAC;IACL,CAAC;IAED,OAAO,SAAS,CAAC;AACnB,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,eAAe,CAC7B,SAAiB,EACjB,UAAwB,EACxB,SAA+D,EAC/D,QAAsB;IAEtB,MAAM,KAAK,GAAoB,EAAE,CAAC;IAElC,+CAA+C;IAC/C,oBAAoB,CAAC,SAAS,EAAE,UAAU,EAAE,SAAS,EAAE,QAAQ,EAAE,KAAK,CAAC,CAAC;IAExE,+EAA+E;IAC/E,kBAAkB,CAAC,SAAS,EAAE,UAAU,EAAE,SAAS,EAAE,QAAQ,EAAE,KAAK,CAAC,CAAC;IAEtE,GAAG,CAAC,KAAK,CAAC,qBAAqB,EAAE;QAC/B,KAAK,EAAE,KAAK,CAAC,MAAM;QACnB,KAAK,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,YAAY,CAAC,CAAC,MAAM;QAC9D,MAAM,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,aAAa,CAAC,CAAC,MAAM;QAChE,IAAI,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,cAAc,CAAC,CAAC,MAAM;KAChE,CAAC,CAAC;IAEH,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;GAEG;AACH,SAAS,oBAAoB,CAC3B,SAAiB,EACjB,UAAwB,EACxB,SAA+D,EAC/D,QAAsB,EACtB,KAAsB;IAEtB,KAAK,IAAI,EAAE,GAAG,CAAC,EAAE,EAAE,GAAG,SAAS,CAAC,MAAM,EAAE,EAAE,EAAE,EAAE,CAAC;QAC7C,MAAM,IAAI,GAAG,SAAS,CAAC,EAAE,CAAC,CAAC;QAE3B,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,eAAe,EAAE,CAAC;YACzC,IAAI,KAAK,CAAC,IAAI,KAAK,UAAU;gBAAE,SAAS;YACxC,MAAM,OAAO,GAAG,KAAqB,CAAC;YAEtC,IAAI,OAAO,CAAC,IAAI,KAAK,MAAM;gBAAE,SAAS;YACtC,MAAM,KAAK,GAAG,OAAO,CAAC,KAAgC,CAAC;YACvD,IAAI,OAAO,KAAK,CAAC,SAAS,KAAK,QAAQ;gBAAE,SAAS;YAElD,mCAAmC;YACnC,MAAM,SAAS,GAAG,OAAO,KAAK,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC;YACrE,IAAI,CAAC,SAAS;gBAAE,SAAS;YAEzB,wDAAwD;YACxD,MAAM,WAAW,GAAG,gBAAgB,CAAC,UAAU,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC;YAC7D,IAAI,CAAC,WAAW;gBAAE,SAAS;YAE3B,6CAA6C;YAC7C,MAAM,UAAU,GAAG,SAAS,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;YAC5C,IAAI,CAAC,UAAU,IAAI,UAAU,CAAC,MAAM,CAAC,MAAM,KAAK,CAAC;gBAAE,SAAS;YAE5D,MAAM,WAAW,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;YAEzC,KAAK,CAAC,IAAI,CAAC;gBACT,aAAa,EAAE,MAAM;gBACrB,aAAa,EAAE,SAAS;gBACxB,cAAc,EAAE,CAAC,WAAW,CAAC,EAAE,CAAC;gBAChC,cAAc,EAAE,CAAC,WAAW,CAAC,EAAE,CAAC;gBAChC,QAAQ,EAAE,YAAY;gBACtB,SAAS,EAAE,IAAI,CAAC,SAAS;aAC1B,CAAC,CAAC;QACL,CAAC;IACH,CAAC;AACH,CAAC;AAED;;GAEG;AACH,SAAS,kBAAkB,CACzB,SAAiB,EACjB,UAAwB,EACxB,SAA+D,EAC/D,QAAsB,EACtB,KAAsB;IAEtB,KAAK,MAAM,CAAC,UAAU,EAAE,UAAU,CAAC,IAAI,SAAS,EAAE,CAAC;QACjD,KAAK,IAAI,EAAE,GAAG,CAAC,EAAE,EAAE,GAAG,UAAU,CAAC,KAAK,CAAC,MAAM,EAAE,EAAE,EAAE,EAAE,CAAC;YACpD,MAAM,IAAI,GAAG,UAAU,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;YAElC,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,eAAe,EAAE,CAAC;gBACzC,IAAI,KAAK,CAAC,IAAI,KAAK,UAAU;oBAAE,SAAS;gBACxC,MAAM,OAAO,GAAG,KAAqB,CAAC;gBACtC,IAAI,OAAO,CAAC,IAAI,KAAK,aAAa;oBAAE,SAAS;gBAE7C,MAAM,KAAK,GAAG,OAAO,CAAC,KAAgC,CAAC;gBACvD,MAAM,aAAa,GAAG,OAAO,KAAK,CAAC,SAAS,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC;gBACnF,MAAM,OAAO,GAAG,OAAO,KAAK,CAAC,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC;gBACzE,IAAI,CAAC,aAAa;oBAAE,SAAS;gBAE7B,qCAAqC;gBACrC,MAAM,WAAW,GAAG,gBAAgB,CAAC,UAAU,CAAC,MAAM,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC;gBACpE,IAAI,CAAC,WAAW;oBAAE,SAAS;gBAE3B,+DAA+D;gBAC/D,MAAM,QAAQ,GAAG,aAAa,KAAK,WAAW,IAAI,aAAa,KAAK,MAAM,CAAC;gBAC3E,MAAM,QAAQ,GAAG,QAAQ,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,cAAc,CAAC;gBAE3D,oBAAoB;gBACpB,IAAI,WAAmC,CAAC;gBAExC,IAAI,QAAQ,EAAE,CAAC;oBACb,8DAA8D;oBAC9D,WAAW,GAAG,sBAAsB,CAClC,SAAS,EACT,UAAU,EACV,UAAU,EACV,OAAO,EACP,IAAI,CAAC,SAAS,CACf,CAAC;gBACJ,CAAC;qBAAM,CAAC;oBACN,6DAA6D;oBAC7D,MAAM,UAAU,GAAG,SAAS,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC;oBAChD,IAAI,UAAU,EAAE,CAAC;wBACf,WAAW,GAAG,uBAAuB,CACnC,UAAU,CAAC,KAAK,EAChB,UAAU,CAAC,MAAM,EACjB,UAAU,EACV,OAAO,EACP,IAAI,CAAC,SAAS,CACf,CAAC;oBACJ,CAAC;gBACH,CAAC;gBAED,IAAI,CAAC,WAAW;oBAAE,SAAS;gBAE3B,MAAM,aAAa,GAAG,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,aAAa,CAAC;gBAExD,KAAK,CAAC,IAAI,CAAC;oBACT,aAAa,EAAE,UAAU;oBACzB,aAAa;oBACb,cAAc,EAAE,CAAC,WAAW,CAAC,EAAE,CAAC;oBAChC,cAAc,EAAE,CAAC,WAAW,CAAC,EAAE,CAAC;oBAChC,QAAQ;oBACR,SAAS,EAAE,IAAI,CAAC,SAAS;iBAC1B,CAAC,CAAC;YACL,CAAC;QACH,CAAC;IACH,CAAC;AACH,CAAC;AAED;;;;;GAKG;AACH,SAAS,sBAAsB,CAC7B,SAAiB,EACjB,UAAwB,EACxB,UAAkB,EAClB,OAAsB,EACtB,aAAqB;IAErB,6CAA6C;IAC7C,KAAK,IAAI,EAAE,GAAG,CAAC,EAAE,EAAE,GAAG,SAAS,CAAC,MAAM,EAAE,EAAE,EAAE,EAAE,CAAC;QAC7C,MAAM,IAAI,GAAG,SAAS,CAAC,EAAE,CAAC,CAAC;QAC3B,IAAI,sBAAsB,CAAC,IAAI,EAAE,UAAU,EAAE,OAAO,CAAC,EAAE,CAAC;YACtD,MAAM,KAAK,GAAG,gBAAgB,CAAC,UAAU,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC;YACvD,IAAI,KAAK;gBAAE,OAAO,KAAK,CAAC;QAC1B,CAAC;IACH,CAAC;IAED,gCAAgC;IAChC,GAAG,CAAC,IAAI,CACN,wFAAwF,EACxF;QACE,MAAM,EAAE,UAAU;QAClB,OAAO;QACP,aAAa;KACd,CACF,CAAC;IACF,OAAO,sBAAsB,CAAC,UAAU,EAAE,aAAa,EAAE,sBAAsB,CAAC,CAAC;AACnF,CAAC;AAED;;;;GAIG;AACH,SAAS,uBAAuB,CAC9B,KAAa,EACb,MAAoB,EACpB,UAAkB,EAClB,OAAsB,EACtB,aAAqB;IAErB,6CAA6C;IAC7C,KAAK,IAAI,EAAE,GAAG,CAAC,EAAE,EAAE,GAAG,KAAK,CAAC,MAAM,EAAE,EAAE,EAAE,EAAE,CAAC;QACzC,MAAM,IAAI,GAAG,KAAK,CAAC,EAAE,CAAC,CAAC;QACvB,IAAI,sBAAsB,CAAC,IAAI,EAAE,UAAU,EAAE,OAAO,CAAC,EAAE,CAAC;YACtD,MAAM,KAAK,GAAG,gBAAgB,CAAC,MAAM,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC;YACnD,IAAI,KAAK;gBAAE,OAAO,KAAK,CAAC;QAC1B,CAAC;IACH,CAAC;IAED,gCAAgC;IAChC,GAAG,CAAC,IAAI,CACN,yFAAyF,EACzF;QACE,MAAM,EAAE,UAAU;QAClB,OAAO;QACP,aAAa;KACd,CACF,CAAC;IACF,OAAO,sBAAsB,CAAC,MAAM,EAAE,aAAa,EAAE,sBAAsB,CAAC,CAAC;AAC/E,CAAC;AAED;;GAEG;AACH,SAAS,sBAAsB,CAAC,IAAU,EAAE,UAAkB,EAAE,OAAsB;IACpF,KAAK,MAAM,GAAG,IAAI,IAAI,CAAC,WAAW,EAAE,CAAC;QACnC,IAAI,GAAG,CAAC,IAAI,KAAK,MAAM,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,OAAO;YAAE,SAAS;QAE3D,MAAM,OAAO,GACX,OAAO,GAAG,CAAC,OAAO,CAAC,OAAO,KAAK,QAAQ;YACrC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,OAAO;YACrB,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,OAAO;iBAChB,MAAM,CAAC,CAAC,CAAC,EAAuC,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,MAAM,CAAC;iBACrE,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;iBAClB,IAAI,CAAC,IAAI,CAAC,CAAC;QAEpB,sEAAsE;QACtE,MAAM,OAAO,GAAG,UAAU,CAAC,OAAO,CAAC,qBAAqB,EAAE,MAAM,CAAC,CAAC;QAClE,MAAM,KAAK,GAAG,IAAI,MAAM,CAAC,qCAAqC,OAAO,GAAG,EAAE,GAAG,CAAC,CAAC;QAC/E,IAAI,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;YACxB,6CAA6C;YAC7C,IAAI,OAAO,EAAE,CAAC;gBACZ,MAAM,cAAc,GAAG,OAAO,CAAC,OAAO,CAAC,qBAAqB,EAAE,MAAM,CAAC,CAAC;gBACtE,MAAM,YAAY,GAAG,IAAI,MAAM,CAAC,YAAY,cAAc,GAAG,EAAE,GAAG,CAAC,CAAC;gBACpE,IAAI,YAAY,CAAC,IAAI,CAAC,OAAO,CAAC;oBAAE,OAAO,IAAI,CAAC;gBAC5C,+DAA+D;YACjE,CAAC;YACD,OAAO,IAAI,CAAC;QACd,CAAC;IACH,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC"}
|
package/dist/mcp/tools.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["../../src/mcp/tools.ts"],"names":[],"mappings":"AAAA;;GAEG;
|
|
1
|
+
{"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["../../src/mcp/tools.ts"],"names":[],"mappings":"AAAA;;GAEG;AAkCH;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE;QACX,IAAI,EAAE,QAAQ,CAAC;QACf,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE;YAAE,IAAI,EAAE,MAAM,CAAC;YAAC,WAAW,EAAE,MAAM,CAAA;SAAE,CAAC,CAAC;QAClE,QAAQ,EAAE,MAAM,EAAE,CAAC;KACpB,CAAC;IACF,OAAO,EAAE,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;CAC7D;AAmCD;;GAEG;AACH,eAAO,MAAM,UAAU,EAAE,cAsCxB,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,UAAU,EAAE,cAqCxB,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,WAAW,EAAE,cAkDzB,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,gBAAgB,EAAE,cA+B9B,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,gBAAgB,EAAE,cA2D9B,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,eAAe,EAAE,cAuE7B,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,cAAc,EAAE,cAa5B,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,SAAS,EAAE,cA0EvB,CAAC;AA+FF;;GAEG;AACH,eAAO,MAAM,UAAU,EAAE,cAuHxB,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,KAAK,EAAE,cAAc,EAUjC,CAAC;AAEF;;GAEG;AACH,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,cAAc,GAAG,SAAS,CAEhE"}
|