@indexnetwork/protocol 3.7.0-rc.276.1 → 3.7.1-rc.278.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.
Files changed (95) hide show
  1. package/dist/agent/agent.tools.js +1 -1
  2. package/dist/agent/agent.tools.js.map +1 -1
  3. package/dist/chat/chat.agent.d.ts +6 -6
  4. package/dist/chat/chat.agent.d.ts.map +1 -1
  5. package/dist/chat/chat.agent.js +9 -9
  6. package/dist/chat/chat.agent.js.map +1 -1
  7. package/dist/chat/chat.graph.d.ts.map +1 -1
  8. package/dist/chat/chat.graph.js +3 -12
  9. package/dist/chat/chat.graph.js.map +1 -1
  10. package/dist/chat/chat.interrupt.classifier.d.ts.map +1 -1
  11. package/dist/chat/chat.interrupt.classifier.js +1 -3
  12. package/dist/chat/chat.interrupt.classifier.js.map +1 -1
  13. package/dist/chat/chat.suggester.js.map +1 -1
  14. package/dist/contact/contact.tools.d.ts.map +1 -1
  15. package/dist/contact/contact.tools.js +17 -5
  16. package/dist/contact/contact.tools.js.map +1 -1
  17. package/dist/context/context.generator.d.ts +2 -0
  18. package/dist/context/context.generator.d.ts.map +1 -1
  19. package/dist/context/context.generator.js +8 -6
  20. package/dist/context/context.generator.js.map +1 -1
  21. package/dist/integration/integration.tools.d.ts.map +1 -1
  22. package/dist/integration/integration.tools.js +6 -0
  23. package/dist/integration/integration.tools.js.map +1 -1
  24. package/dist/intent/intent.clarifier.d.ts +2 -0
  25. package/dist/intent/intent.clarifier.d.ts.map +1 -1
  26. package/dist/intent/intent.clarifier.js +9 -23
  27. package/dist/intent/intent.clarifier.js.map +1 -1
  28. package/dist/intent/intent.graph.d.ts.map +1 -1
  29. package/dist/intent/intent.graph.js +29 -26
  30. package/dist/intent/intent.graph.js.map +1 -1
  31. package/dist/intent/intent.tools.d.ts.map +1 -1
  32. package/dist/intent/intent.tools.js +18 -48
  33. package/dist/intent/intent.tools.js.map +1 -1
  34. package/dist/maintenance/maintenance.graph.d.ts.map +1 -1
  35. package/dist/maintenance/maintenance.graph.js +1 -2
  36. package/dist/maintenance/maintenance.graph.js.map +1 -1
  37. package/dist/mcp/mcp.server.d.ts.map +1 -1
  38. package/dist/mcp/mcp.server.js +2 -4
  39. package/dist/mcp/mcp.server.js.map +1 -1
  40. package/dist/negotiation/negotiation.graph.d.ts.map +1 -1
  41. package/dist/negotiation/negotiation.graph.js +13 -20
  42. package/dist/negotiation/negotiation.graph.js.map +1 -1
  43. package/dist/negotiation/negotiation.tools.d.ts.map +1 -1
  44. package/dist/negotiation/negotiation.tools.js +12 -12
  45. package/dist/negotiation/negotiation.tools.js.map +1 -1
  46. package/dist/network/indexer/indexer.graph.d.ts +9 -9
  47. package/dist/network/indexer/indexer.graph.d.ts.map +1 -1
  48. package/dist/network/indexer/indexer.graph.js.map +1 -1
  49. package/dist/network/network.graph.d.ts.map +1 -1
  50. package/dist/network/network.graph.js +19 -25
  51. package/dist/network/network.graph.js.map +1 -1
  52. package/dist/opportunity/feed/feed.categorizer.d.ts.map +1 -1
  53. package/dist/opportunity/feed/feed.categorizer.js +15 -20
  54. package/dist/opportunity/feed/feed.categorizer.js.map +1 -1
  55. package/dist/opportunity/feed/feed.graph.d.ts.map +1 -1
  56. package/dist/opportunity/feed/feed.graph.js +8 -10
  57. package/dist/opportunity/feed/feed.graph.js.map +1 -1
  58. package/dist/opportunity/opportunity.introducer.d.ts.map +1 -1
  59. package/dist/opportunity/opportunity.introducer.js +1 -2
  60. package/dist/opportunity/opportunity.introducer.js.map +1 -1
  61. package/dist/opportunity/opportunity.tools.d.ts.map +1 -1
  62. package/dist/opportunity/opportunity.tools.js +3 -2
  63. package/dist/opportunity/opportunity.tools.js.map +1 -1
  64. package/dist/profile/profile.enricher.d.ts +5 -7
  65. package/dist/profile/profile.enricher.d.ts.map +1 -1
  66. package/dist/profile/profile.enricher.js +8 -10
  67. package/dist/profile/profile.enricher.js.map +1 -1
  68. package/dist/profile/profile.generator.d.ts.map +1 -1
  69. package/dist/profile/profile.generator.js +1 -2
  70. package/dist/profile/profile.generator.js.map +1 -1
  71. package/dist/profile/profile.tools.js +1 -1
  72. package/dist/profile/profile.tools.js.map +1 -1
  73. package/dist/questioner/questioner.presets.d.ts.map +1 -1
  74. package/dist/questioner/questioner.presets.js +24 -38
  75. package/dist/questioner/questioner.presets.js.map +1 -1
  76. package/dist/shared/agent/tool.factory.d.ts.map +1 -1
  77. package/dist/shared/agent/tool.factory.js +2 -2
  78. package/dist/shared/agent/tool.factory.js.map +1 -1
  79. package/dist/shared/agent/tool.helpers.d.ts +14 -0
  80. package/dist/shared/agent/tool.helpers.d.ts.map +1 -1
  81. package/dist/shared/agent/tool.helpers.js.map +1 -1
  82. package/dist/shared/agent/tool.runtime.d.ts.map +1 -1
  83. package/dist/shared/agent/tool.runtime.js +20 -13
  84. package/dist/shared/agent/tool.runtime.js.map +1 -1
  85. package/dist/shared/hyde/hyde.graph.d.ts.map +1 -1
  86. package/dist/shared/hyde/hyde.graph.js +3 -2
  87. package/dist/shared/hyde/hyde.graph.js.map +1 -1
  88. package/dist/shared/hyde/hyde.strategies.d.ts +2 -1
  89. package/dist/shared/hyde/hyde.strategies.d.ts.map +1 -1
  90. package/dist/shared/hyde/hyde.strategies.js.map +1 -1
  91. package/dist/shared/observability/trace.d.ts +3 -3
  92. package/dist/shared/observability/trace.d.ts.map +1 -1
  93. package/dist/shared/observability/trace.js +19 -33
  94. package/dist/shared/observability/trace.js.map +1 -1
  95. package/package.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"tool.helpers.js","sourceRoot":"/","sources":["shared/agent/tool.helpers.ts"],"names":[],"mappings":"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","sourcesContent":["import { z } from \"zod\";\nimport type { ModelConfig } from \"./model.config.js\";\nimport type { ProfileDocument } from \"../schemas/profile.schema.js\";\nimport type { ChatGraphCompositeDatabase, NetworkMembership, UserRecord, UserDatabase, SystemDatabase, NegotiationGraphDatabase } from \"../interfaces/database.interface.js\";\nimport type { Scraper } from \"../interfaces/scraper.interface.js\";\nimport type { Cache, HydeCache } from \"../interfaces/cache.interface.js\";\nimport type { CompiledOpportunityGraph } from \"../../opportunity/opportunity.discover.js\";\nimport type { IntegrationAdapter } from \"../interfaces/integration.interface.js\";\nimport type { ContactServiceAdapter } from \"../interfaces/contact.interface.js\";\nimport type { ProfileEnricher } from \"../interfaces/enrichment.interface.js\";\nimport type { IntentGraphQueue } from \"../interfaces/queue.interface.js\";\nimport type { ChatSessionReader } from \"../interfaces/chat-session.interface.js\";\nimport type { ChatSummaryReader } from \"../interfaces/chat-summary.interface.js\";\nimport type { ChatMessageWriter } from \"../interfaces/chat-message-writer.interface.js\";\nimport type { QuestionGeneratorReader } from \"../interfaces/question-generator.interface.js\";\nimport type { NegotiationSummaryReader } from \"../interfaces/negotiation-summary.interface.js\";\nimport type { Embedder } from \"../interfaces/embedder.interface.js\";\nimport type { AgentDatabase } from \"../interfaces/agent.interface.js\";\nimport type { NegotiationTimeoutQueue } from \"../interfaces/negotiation-events.interface.js\";\nimport type { AgentDispatcher } from \"../interfaces/agent-dispatcher.interface.js\";\nimport type { DeliveryLedger } from \"../interfaces/delivery-ledger.interface.js\";\nimport type { MintConnectLink } from \"../interfaces/connect-link.interface.js\";\nimport type { QuestionerDatabase } from \"../interfaces/questioner.interface.js\";\nimport type { QuestionerEnqueueFn } from \"../../questioner/questioner.types.js\";\nimport type { PendingQuestionSummary } from \"../schemas/pending-question.schema.js\";\nimport type { QuestionMode } from \"../schemas/question.schema.js\";\nimport type { DiscoveryRunQueue, DiscoveryRunStore } from \"../interfaces/discovery-run.interface.js\";\nimport type { ProfileRunQueue, ProfileRunStore } from \"../interfaces/profile-run.interface.js\";\n\nexport type ProfileContext = ProfileDocument | null;\n\nexport interface ToolErrorReport {\n operation: string;\n subsystem?: string;\n toolName?: string;\n userId?: string;\n tags?: Record<string, string | number | boolean | null | undefined>;\n context?: Record<string, unknown>;\n}\n\n// ═══════════════════════════════════════════════════════════════════════════════\n// COMPILED GRAPH TYPE\n// ═══════════════════════════════════════════════════════════════════════════════\n\n/** Minimal interface for an invokable compiled LangGraph. */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport type CompiledGraph = { invoke: (input: any) => Promise<any> };\n\n// ═══════════════════════════════════════════════════════════════════════════════\n// TOOL CONTEXT TYPES\n// ═══════════════════════════════════════════════════════════════════════════════\n\n/**\n * Resolved context available to every tool handler.\n * Contains the current user and optional index identity, resolved from DB at init.\n * The LLM can see this context (via system prompt) but cannot change it.\n */\nexport interface ResolvedToolContext {\n // Legacy flat fields (kept for backwards compatibility in tools/prompts).\n userId: string;\n userName: string;\n userEmail: string;\n networkId?: string;\n indexName?: string;\n /** True when chat is index-scoped and the user owns the index. */\n isOwner?: boolean;\n // Rich identity context for prompt/tool orchestration.\n user: UserRecord;\n userProfile: ProfileContext;\n userNetworks: NetworkMembership[];\n /**\n * The set of index IDs this caller can reach in the current request.\n * For unscoped chats: every index the user is a member of.\n * For network-scoped agents: `[boundNetwork, personalIndex]`.\n * This is the same set used to clamp the DB-level systemDb.\n * Tools that filter intents/profiles default to this set; `networkId` is\n * the \"primary focus\" hint, not a read filter.\n */\n indexScope: string[];\n scopedIndex?: {\n id: string;\n title: string;\n prompt: string | null;\n type?: string;\n metadata?: Record<string, unknown>;\n permissions?: Record<string, unknown>;\n };\n scopedMembershipRole?: \"owner\" | \"member\";\n /** True when user has not completed onboarding (onboarding.completedAt is null). */\n isOnboarding: boolean;\n /** True when the user has a non-empty name. */\n hasName: boolean;\n /** Chat session ID when tools are used in a chat; used for draft opportunities (context.conversationId). */\n sessionId?: string;\n /** True when the request originates from an MCP transport (no interactive UI available). */\n isMcp?: boolean;\n /** Agent ID when the request originates from an API key linked to an agent. */\n agentId?: string;\n /**\n * Receiver's rendering surface declared by the MCP client via the\n * `x-index-surface` request header. `'telegram'` means the MCP response is\n * being rendered inside a Telegram chat; anything\n * else (including `undefined`) is treated as web. Forwarded into\n * `mintConnectLink` so the click-time redirect can branch.\n */\n clientSurface?: 'telegram' | 'web';\n}\n\n/**\n * Dependencies passed when creating tools for a user session.\n * Includes DB adapters, embedder, and scraper.\n *\n * Note: userDb and systemDb are optional inputs - if not provided, createChatTools\n * will create them internally from the chatDatabaseAdapter singleton.\n */\nexport interface ToolContext {\n userId: string;\n /** @deprecated Use userDb or systemDb instead. Kept for backwards compatibility. */\n database: ChatGraphCompositeDatabase;\n /** Context-bound database for accessing the authenticated user's own resources. Created internally if not provided. */\n userDb?: UserDatabase;\n /** Context-bound database for LLM/system operations on cross-user resources within shared indexes. Created internally if not provided. */\n systemDb?: SystemDatabase;\n embedder: Embedder;\n scraper: Scraper;\n /** When set, chat is scoped to this index; tools use it as default for read_intents and create_intent. */\n networkId?: string;\n /**\n * Optional override of the resolved `indexScope`. `resolveChatContext` always\n * computes `indexScope` from the user's memberships (clamped to [bound,\n * personal] when `networkId` is set). When the caller has already computed\n * a clamped scope — notably the MCP server, which clamps via\n * `applyNetworkScopeToContext` for network-scoped agents — passing it on\n * `ToolContext.indexScope` causes `createChatTools` (in tool.factory.ts) to\n * override `resolvedContext.indexScope` with this value rather than the\n * freshly computed one. See ResolvedToolContext.indexScope for the\n * resolved-side semantics.\n */\n indexScope?: string[];\n /** Chat session ID when creating tools for a chat; enables draft opportunities with context.conversationId. */\n sessionId?: string;\n\n // ─── Protocol-level dependencies (injected by composition root) ──────────\n /** General-purpose cache (e.g. for tool results). */\n cache: Cache;\n /** Dedicated cache for HyDE graph (may be same instance as cache). */\n hydeCache: HydeCache;\n /** External integration platform adapter (OAuth, tool actions). */\n integration: IntegrationAdapter;\n /** Queue for enqueuing follow-up intent processing (HyDE generation/deletion). */\n intentQueue: IntentGraphQueue;\n /** Contact management operations. */\n contactService: ContactServiceAdapter;\n /** Chat session reader for loading conversation history. */\n chatSession: ChatSessionReader;\n /** Read-through chat-session digest. Optional; consumers fall back to undefined `chatContext`. */\n chatSummary?: ChatSummaryReader;\n /** Writes user messages into the user's most-recent chat session (Slice 5 MCP elicitation). */\n chatMessageWriter?: ChatMessageWriter;\n /** Decision-question generator. Optional; consumers fall back to no `questions`. */\n questionGenerator?: QuestionGeneratorReader;\n /**\n * Optional async question enqueue callback. When provided, question generation\n * is dispatched asynchronously to the QuestionerQueue instead of running inline.\n * Injected by the composition root when QUESTIONER_ENABLED=true.\n */\n questionerEnqueue?: QuestionerEnqueueFn;\n /** Negotiation-digest summarizer. Optional; consumers fall back to deterministic digests. */\n negotiationSummary?: NegotiationSummaryReader;\n /** Profile enrichment from external data sources. */\n enricher: ProfileEnricher;\n /** Database adapter for negotiation/conversation operations. */\n negotiationDatabase: NegotiationGraphDatabase;\n /** Integration importer for bulk contact import from toolkits. */\n integrationImporter: {\n importContacts(userId: string, toolkit: string): Promise<{\n imported: number;\n skipped: number;\n newContacts: number;\n existingContacts: number;\n }>;\n };\n /** Factory for user-scoped database access. */\n createUserDatabase: (db: ChatGraphCompositeDatabase, userId: string) => UserDatabase;\n /** Factory for system-scoped database access. */\n createSystemDatabase: (db: ChatGraphCompositeDatabase, userId: string, indexScope: string[], embedder?: Embedder) => SystemDatabase;\n /** Optional runtime LLM config. Pass to override env vars for API key, model, etc. */\n modelConfig?: ModelConfig;\n /** Manages negotiation timeout jobs (optional — enables AI fallback on external agent timeout). */\n negotiationTimeoutQueue?: NegotiationTimeoutQueue;\n /** Agent registry database adapter (optional — absent when host does not support agents). */\n agentDatabase?: AgentDatabase;\n /** Grants the default system-agent permissions after onboarding (optional). */\n grantDefaultSystemPermissions?: (userId: string) => Promise<void>;\n /** Dispatcher for routing negotiation turns to personal agents (optional — falls back to system AI). */\n agentDispatcher?: AgentDispatcher;\n /** Enqueue a negotiate_existing job after introducer approval (optional). */\n queueNegotiateExisting?: (opportunityId: string, userId: string) => Promise<void>;\n /** Delivery ledger for committing opportunity delivery rows (optional — absent in chat context). */\n deliveryLedger?: DeliveryLedger;\n /** Persistence for async MCP discovery runs (optional — absent in non-MCP/test contexts). */\n discoveryRuns?: DiscoveryRunStore;\n /** Queue for async MCP discovery run execution (optional — absent in non-MCP/test contexts). */\n discoveryRunQueue?: DiscoveryRunQueue;\n /** Persistence for async MCP profile runs (optional — absent in non-MCP/test contexts). */\n profileRuns?: ProfileRunStore;\n /** Queue for async MCP profile run execution (optional — absent in non-MCP/test contexts). */\n profileRunQueue?: ProfileRunQueue;\n /**\n * Legacy direct-token minting for opportunity accept redirects.\n * Prefer `mintConnectLink` for user-facing links.\n */\n mintConnectToken?: (userId: string, opportunityId: string) => Promise<string>;\n /** Mints (or reuses) a short connect link, snapshotting the greeting (optional — absent in non-MCP contexts). */\n mintConnectLink?: MintConnectLink;\n /** Frontend base URL for building profile links (e.g. https://index.network, optional). */\n frontendUrl?: string;\n /** API base URL for building opportunity accept links (e.g. https://protocol.index.network, optional). */\n apiBaseUrl?: string;\n /** Persistence for structured questions generated by the QuestionerAgent (optional). */\n questionerDatabase?: QuestionerDatabase;\n /** Optional host-side error reporter for swallowed protocol/tool errors. */\n reportToolError?: (error: unknown, report: ToolErrorReport) => void;\n /**\n * Optional host-side per-principal MCP call throttle. Invoked once per MCP\n * tool dispatch (after identity resolves, before any DB work). When the\n * returned decision is `allowed: false`, the dispatch short-circuits with a\n * rate-limit error carrying `retryAfterSec`. Absent in chat/test contexts.\n */\n mcpRateLimiter?: (input: { userId: string; agentId?: string; toolName: string }) => Promise<{\n allowed: boolean;\n retryAfterSec?: number;\n limit?: number;\n scope?: 'tool' | 'principal';\n }>;\n /** Optional premise lifecycle event callbacks. Fired by premise tools after successful operations. */\n premiseEvents?: {\n onCreated?: (premiseId: string, userId: string) => void;\n onUpdated?: (premiseId: string, userId: string) => void;\n onRetracted?: (premiseId: string, userId: string) => void;\n };\n}\n\n/**\n * All external dependencies needed to initialize the protocol tool engine.\n * The host application (composition root) must provide concrete implementations.\n * This is the subset of ToolContext that is NOT per-request (no userId, indexId, sessionId).\n */\nexport type ProtocolDeps = Omit<ToolContext, 'userId' | 'indexId' | 'sessionId' | 'userDb' | 'systemDb'>;\n\n/**\n * Thrown when a requested chat scope is invalid for the authenticated user.\n * Controllers can map this to an HTTP status code.\n */\nexport class ChatContextAccessError extends Error {\n constructor(\n message: string,\n public readonly statusCode: number,\n public readonly code: \"USER_NOT_FOUND\" | \"INDEX_NOT_FOUND\" | \"INDEX_MEMBERSHIP_REQUIRED\"\n ) {\n super(message);\n this.name = \"ChatContextAccessError\";\n }\n}\n\n/**\n * Resolve the canonical context used by chat tools and system prompt.\n * This preloads user identity, profile, index memberships, and scoped index role.\n */\nexport async function resolveChatContext(params: {\n database: Pick<\n ChatGraphCompositeDatabase,\n \"getUser\" | \"getProfile\" | \"getNetworkMemberships\" | \"getNetworkMembership\" | \"getNetwork\" | \"isIndexOwner\" | \"isNetworkMember\"\n >;\n userId: string;\n networkId?: string;\n /** Chat session ID for draft opportunities (stored as context.conversationId). */\n sessionId?: string;\n}): Promise<ResolvedToolContext> {\n const { database, userId, networkId, sessionId } = params;\n\n const [user, rawProfile, userNetworks] = await Promise.all([\n database.getUser(userId),\n database.getProfile(userId),\n database.getNetworkMemberships(userId),\n ]);\n\n const userProfile: ProfileContext = rawProfile ?? null;\n\n if (!user) {\n throw new ChatContextAccessError(\n \"User not found\",\n 404,\n \"USER_NOT_FOUND\"\n );\n }\n\n let scopedIndex: ResolvedToolContext[\"scopedIndex\"] = undefined;\n let scopedMembershipRole: ResolvedToolContext[\"scopedMembershipRole\"] = undefined;\n let isOwner = false;\n let indexName: string | undefined;\n\n if (networkId) {\n const [index, isMember, owner] = await Promise.all([\n database.getNetwork(networkId),\n database.isNetworkMember(networkId, userId),\n database.isIndexOwner(networkId, userId),\n ]);\n\n if (!index) {\n throw new ChatContextAccessError(\n \"Index not found\",\n 404,\n \"INDEX_NOT_FOUND\"\n );\n }\n\n if (!isMember) {\n throw new ChatContextAccessError(\n \"You are not a member of this index\",\n 403,\n \"INDEX_MEMBERSHIP_REQUIRED\"\n );\n }\n\n let membership = userNetworks.find((m) => m.networkId === index.id);\n if (membership === undefined) {\n membership = (await database.getNetworkMembership(index.id, userId)) ?? undefined;\n }\n scopedIndex = {\n id: index.id,\n title: index.title,\n prompt: membership?.indexPrompt ?? null,\n type: index.type ?? 'community',\n metadata: index.metadata ?? {},\n permissions: index.permissions ?? {},\n };\n isOwner = owner;\n indexName = index.title;\n scopedMembershipRole = owner ? \"owner\" : \"member\";\n }\n\n const userName = user.name ?? \"Unknown\";\n const userEmail = user.email ?? \"\";\n const hasName = !!user.name?.trim();\n\n // When scoped to an index, clamp the caller's reach to [scopedIndex, personalIndex]\n // so the chat's data model matches its \"focus\" semantic: a chat scoped to a\n // community sees that community plus the user's personal index, not their\n // other unrelated memberships. Mirrors the MCP path's clamp for network-scoped\n // agents (see applyNetworkScopeToContext / computeAgentIndexScope).\n const indexScope = networkId\n ? userNetworks\n .filter((m) => m.networkId === networkId || m.isPersonal === true)\n .map((m) => m.networkId)\n : userNetworks.map((m) => m.networkId);\n\n return {\n userId,\n userName,\n userEmail,\n networkId,\n indexName,\n isOwner,\n user,\n userProfile,\n userNetworks,\n indexScope,\n scopedIndex,\n scopedMembershipRole,\n isOnboarding: !(user.onboarding?.completedAt),\n hasName,\n ...(sessionId !== undefined ? { sessionId } : {}),\n };\n}\n\n// ═══════════════════════════════════════════════════════════════════════════════\n// DEFINE TOOL TYPE\n// ═══════════════════════════════════════════════════════════════════════════════\n\n/**\n * Type for the `defineTool` closure created in `createChatTools`.\n * Auto-injects resolved context and provides uniform logging / error handling.\n */\nexport type DefineTool = <T extends z.ZodType>(opts: {\n name: string;\n description: string;\n querySchema: T;\n handler: (input: { context: ResolvedToolContext; query: z.infer<T> }) => Promise<string>;\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\n}) => any;\n\n/**\n * A raw tool definition before LangChain wrapping.\n * Used by the tool registry for direct HTTP invocation.\n */\nexport interface RawToolDefinition {\n name: string;\n description: string;\n schema: z.ZodType;\n handler: (input: { context: ResolvedToolContext; query: unknown }) => Promise<string>;\n}\n\n/**\n * Registry mapping tool names to their raw definitions.\n */\nexport type ToolRegistry = Map<string, RawToolDefinition>;\n\n// ═══════════════════════════════════════════════════════════════════════════════\n// TOOL DEPENDENCIES\n// ═══════════════════════════════════════════════════════════════════════════════\n\n/**\n * Shared dependencies available to all tool domain factories.\n * Passed by `createChatTools` after compiling all subgraphs.\n */\nexport interface ToolDeps {\n /** @deprecated Use userDb or systemDb instead. Kept for backwards compatibility. */\n database: ChatGraphCompositeDatabase;\n /** Context-bound database for accessing the authenticated user's own resources. */\n userDb: UserDatabase;\n /** Context-bound database for LLM/system operations on cross-user resources within shared indexes. */\n systemDb: SystemDatabase;\n scraper: Scraper;\n embedder: import('../interfaces/embedder.interface.js').Embedder;\n cache: Cache;\n integration: IntegrationAdapter;\n contactService: ContactServiceAdapter;\n integrationImporter: {\n importContacts(userId: string, toolkit: string): Promise<{\n imported: number;\n skipped: number;\n newContacts: number;\n existingContacts: number;\n }>;\n };\n enricher: ProfileEnricher;\n /** Database adapter for negotiation/conversation operations. */\n negotiationDatabase: NegotiationGraphDatabase;\n /** Chat session reader for exposing the caller's past conversations as MCP tools. */\n chatSession?: ChatSessionReader;\n /** Read-through chat-session digest. Optional; consumers fall back to undefined `chatContext`. */\n chatSummary?: ChatSummaryReader;\n /**\n * Test seam for opportunity discovery helpers. Production compositions leave\n * this unset so tools call the real discovery module directly.\n */\n opportunityDiscovery?: {\n runDiscoverFromQuery?: (input: unknown) => Promise<unknown>;\n continueDiscovery?: (input: unknown) => Promise<unknown>;\n };\n /**\n * Test seam for opportunity card presentation helpers. Production\n * compositions leave this unset so tools construct the real presenter.\n */\n opportunityPresentation?: {\n createPresenter?: () => { presentHomeCard(input: unknown): Promise<unknown> };\n gatherPresenterContext?: (...args: unknown[]) => Promise<unknown>;\n };\n /** Writes user messages into the user's most-recent chat session (Slice 5 MCP elicitation). */\n chatMessageWriter?: ChatMessageWriter;\n /** Decision-question generator. Optional; consumers fall back to no `questions`. */\n questionGenerator?: QuestionGeneratorReader;\n /**\n * Optional async question enqueue callback. When provided, question generation\n * is dispatched asynchronously to the QuestionerQueue instead of running inline\n * via the `questionGenerator`. Injected by the composition root when\n * QUESTIONER_ENABLED=true.\n */\n questionerEnqueue?: QuestionerEnqueueFn;\n /**\n * Lookup pending questions for a user, optionally filtered by source,\n * detection mode, or capped by count (hosts apply `limit` SQL-side).\n * Used by tools to attach contextually relevant questions to their results.\n * Injected by the composition root — absent when question delivery is disabled.\n */\n findPendingQuestions?: (\n userId: string,\n filters?: {\n sourceType?: string;\n sourceId?: string;\n /** Restrict to questions whose detection mode is in this set. */\n modes?: QuestionMode[];\n /** Maximum rows to return; hosts should apply this in the query. */\n limit?: number;\n },\n ) => Promise<PendingQuestionSummary[]>;\n /** Negotiation-digest summarizer. Optional; consumers fall back to deterministic digests. */\n negotiationSummary?: NegotiationSummaryReader;\n /** Manages negotiation timeout jobs (optional — enables AI fallback on external agent timeout). */\n negotiationTimeoutQueue?: NegotiationTimeoutQueue;\n /** Agent registry database adapter (optional — absent when host does not support agents). */\n agentDatabase?: AgentDatabase;\n /** Grants the default system-agent permissions after onboarding (optional). */\n grantDefaultSystemPermissions?: (userId: string) => Promise<void>;\n /** Dispatcher for routing negotiation turns to personal agents (optional — falls back to system AI). */\n agentDispatcher?: AgentDispatcher;\n /** Delivery ledger for committing opportunity delivery rows (optional — absent in chat context). */\n deliveryLedger?: DeliveryLedger;\n /** Persistence for async MCP discovery runs (optional — absent in non-MCP/test contexts). */\n discoveryRuns?: DiscoveryRunStore;\n /** Queue for async MCP discovery run execution (optional — absent in non-MCP/test contexts). */\n discoveryRunQueue?: DiscoveryRunQueue;\n /** Persistence for async MCP profile runs (optional — absent in non-MCP/test contexts). */\n profileRuns?: ProfileRunStore;\n /** Queue for async MCP profile run execution (optional — absent in non-MCP/test contexts). */\n profileRunQueue?: ProfileRunQueue;\n /**\n * Legacy direct-token minting for opportunity accept redirects.\n * Prefer `mintConnectLink` for user-facing links.\n */\n mintConnectToken?: (userId: string, opportunityId: string) => Promise<string>;\n /** Mints (or reuses) a short connect link, snapshotting the greeting (optional — absent in non-MCP contexts). */\n mintConnectLink?: MintConnectLink;\n /** Frontend base URL for building profile links (e.g. https://index.network, optional). */\n frontendUrl?: string;\n /** API base URL for building opportunity accept links (e.g. https://protocol.index.network, optional). */\n apiBaseUrl?: string;\n /** Optional host-side error reporter for swallowed protocol/tool errors. */\n reportToolError?: (error: unknown, report: ToolErrorReport) => void;\n /**\n * Optional host-side per-principal MCP call throttle. Invoked once per MCP\n * tool dispatch (after identity resolves, before any DB work). When the\n * returned decision is `allowed: false`, the dispatch short-circuits with a\n * rate-limit error carrying `retryAfterSec`. Absent in chat/test contexts.\n */\n mcpRateLimiter?: (input: { userId: string; agentId?: string; toolName: string }) => Promise<{\n allowed: boolean;\n retryAfterSec?: number;\n limit?: number;\n scope?: 'tool' | 'principal';\n }>;\n /** Optional premise lifecycle event callbacks. Fired by premise tools after successful operations. */\n premiseEvents?: {\n onCreated?: (premiseId: string, userId: string) => void;\n onUpdated?: (premiseId: string, userId: string) => void;\n onRetracted?: (premiseId: string, userId: string) => void;\n };\n graphs: {\n profile: CompiledGraph;\n intent: CompiledGraph;\n index: CompiledGraph;\n networkMembership: CompiledGraph;\n intentIndex: CompiledGraph;\n opportunity: CompiledOpportunityGraph;\n premise: CompiledGraph;\n };\n /**\n * Optional network ranking override for `read_networks`. Injected by tests or custom compositions.\n * When absent, defaults to `NetworkRecommender.invoke()` with a lazy module-level singleton.\n */\n networkRanker?: (input: {\n userProfile: { bio: string; location: string; interests: string[]; skills: string[] };\n networks: Array<{ networkId: string; renderedContext: string }>;\n }) => Promise<{ rankedNetworkIds: string[] } | null>;\n}\n\n// ═══════════════════════════════════════════════════════════════════════════════\n// TOOL RESULT HELPERS\n// ═══════════════════════════════════════════════════════════════════════════════\n\nexport function success<T>(data: T): string {\n return JSON.stringify({ success: true, data });\n}\n\nexport function error(\n message: string,\n debugSteps?: Array<{ step: string; detail?: string; data?: Record<string, unknown> }>\n): string {\n return JSON.stringify({\n success: false,\n error: message,\n ...(debugSteps?.length ? { debugSteps } : {}),\n });\n}\n\n/** Return needsClarification for missing required fields. */\nexport function needsClarification(params: {\n missingFields: string[];\n message: string;\n}): string {\n return JSON.stringify({\n success: false,\n needsClarification: true,\n ...params,\n });\n}\n\n// ═══════════════════════════════════════════════════════════════════════════════\n// CONSTANTS & UTILITIES\n// ═══════════════════════════════════════════════════════════════════════════════\n\n/** Matches http/https URLs in text; captures full URL. */\nconst URL_IN_TEXT_REGEX = /https?:\\/\\/[^\\s\"'<>)\\]]+/gi;\n\n/**\n * Matches bare domain URLs without protocol (e.g. github.com/foo, www.example.com).\n * Requires at least a SLD.TLD pattern followed by optional path.\n * Negative lookbehind ensures we don't double-match URLs already caught by URL_IN_TEXT_REGEX.\n */\nconst BARE_URL_REGEX = /(?<!\\w:\\/\\/)(?<![/\\w])(?:www\\.)?[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\\.(?:com|org|net|io|dev|co|ai|app|xyz|me|info|gg|so|sh|cc|ly|fm|tv|to|tech|design|network|world|edu|gov|mil|int|us|uk|eu|de|fr|ca|au|jp|cn|in|br|nl|se|no|fi|dk|ch|at|be|it|es|pt|pl|cz|ru|kr|tw|hk|sg|nz|za|mx|ar|cl|id|ph|th|vn|my|ie)(?:\\/[^\\s\"'<>)\\]]*)?/gi;\n\n/** UUID v4 format: 8-4-4-4-12 hex chars (e.g. c2505011-2e45-426e-81dd-b9abb9b72023) */\nexport const UUID_REGEX = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;\n\n/**\n * Resolves an array of network IDs to their display titles.\n * Skips any IDs that don't resolve (deleted or invalid networks).\n */\nexport async function resolveIndexNames(\n database: { getNetwork(id: string): Promise<{ id: string; title: string } | null> },\n networkIds: string[]\n): Promise<string[]> {\n if (networkIds.length === 0) return [];\n const results = await Promise.all(\n networkIds.map(id => database.getNetwork(id))\n );\n return results.filter(Boolean).map(idx => idx!.title);\n}\n\n/**\n * Normalize a URL string: if it lacks a protocol, prepend \"https://\".\n * Returns the normalized URL or null if the result is not a valid URL.\n */\nexport function normalizeUrl(raw: string): string | null {\n let url = raw.replace(/[.,;:!?)]+$/, \"\").trim();\n if (!/^https?:\\/\\//i.test(url)) {\n url = `https://${url}`;\n }\n try {\n new URL(url);\n return url;\n } catch {\n return null;\n }\n}\n\n/**\n * Extract unique, valid URLs from a string (e.g. user message or details).\n * Handles both full URLs (https://...) and bare domains (github.com/...).\n */\nexport function extractUrls(text: string): string[] {\n if (!text || typeof text !== \"string\") return [];\n\n const seen = new Set<string>();\n const out: string[] = [];\n\n // Pass 1: full protocol URLs\n const fullMatches = text.match(URL_IN_TEXT_REGEX) ?? [];\n for (const raw of fullMatches) {\n const url = normalizeUrl(raw);\n if (url && !seen.has(url)) {\n seen.add(url);\n out.push(url);\n }\n }\n\n // Pass 2: bare domain URLs (e.g. github.com/foo)\n const bareMatches = text.match(BARE_URL_REGEX) ?? [];\n for (const raw of bareMatches) {\n const url = normalizeUrl(raw);\n if (url && !seen.has(url)) {\n seen.add(url);\n out.push(url);\n }\n }\n\n return out;\n}\n\nconst SENSITIVE_FIELD_KEYS = new Set([\n \"secret\",\n \"webhooksecret\",\n \"password\",\n \"apikey\",\n \"token\",\n \"accesstoken\",\n \"refreshtoken\",\n \"privatekey\",\n \"authtoken\",\n \"bearertoken\",\n \"clientsecret\",\n]);\n\n/**\n * Recursively redacts sensitive field values from an arbitrary payload before\n * it is passed to a structured logger. Matches field names case-insensitively\n * and ignoring underscores, so `api_key`, `apiKey`, and `API_KEY` all match.\n * Non-sensitive fields are passed through unchanged. Never mutates the input —\n * returns a new value.\n *\n * Intended for structured-log redaction only. Do NOT use as a security\n * boundary for data in motion.\n *\n * @param value - Arbitrary JSON-like payload (query object, config blob, etc.)\n * @returns A new value with sensitive fields replaced by `\"[redacted]\"`.\n */\nexport function redactSensitiveFields(value: unknown): unknown {\n if (value === null || typeof value !== \"object\") return value;\n if (Array.isArray(value)) {\n return value.map((item) => redactSensitiveFields(item));\n }\n const out: Record<string, unknown> = {};\n for (const [key, inner] of Object.entries(value as Record<string, unknown>)) {\n const normalized = key.toLowerCase().replace(/_/g, \"\");\n if (SENSITIVE_FIELD_KEYS.has(normalized)) {\n out[key] = \"[redacted]\";\n } else {\n out[key] = redactSensitiveFields(inner);\n }\n }\n return out;\n}\n"]}
1
+ {"version":3,"file":"tool.helpers.js","sourceRoot":"/","sources":["shared/agent/tool.helpers.ts"],"names":[],"mappings":"AAiQA;;;GAGG;AACH,MAAM,OAAO,sBAAuB,SAAQ,KAAK;IAC/C,YACE,OAAe,EACC,UAAkB,EAClB,IAAwE;QAExF,KAAK,CAAC,OAAO,CAAC,CAAC;QAHC,eAAU,GAAV,UAAU,CAAQ;QAClB,SAAI,GAAJ,IAAI,CAAoE;QAGxF,IAAI,CAAC,IAAI,GAAG,wBAAwB,CAAC;IACvC,CAAC;CACF;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,kBAAkB,CAAC,MASxC;IACC,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,SAAS,EAAE,GAAG,MAAM,CAAC;IAE1D,MAAM,CAAC,IAAI,EAAE,UAAU,EAAE,YAAY,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;QACzD,QAAQ,CAAC,OAAO,CAAC,MAAM,CAAC;QACxB,QAAQ,CAAC,UAAU,CAAC,MAAM,CAAC;QAC3B,QAAQ,CAAC,qBAAqB,CAAC,MAAM,CAAC;KACvC,CAAC,CAAC;IAEH,MAAM,WAAW,GAAmB,UAAU,IAAI,IAAI,CAAC;IAEvD,IAAI,CAAC,IAAI,EAAE,CAAC;QACV,MAAM,IAAI,sBAAsB,CAC9B,gBAAgB,EAChB,GAAG,EACH,gBAAgB,CACjB,CAAC;IACJ,CAAC;IAED,IAAI,WAAW,GAAuC,SAAS,CAAC;IAChE,IAAI,oBAAoB,GAAgD,SAAS,CAAC;IAClF,IAAI,OAAO,GAAG,KAAK,CAAC;IACpB,IAAI,SAA6B,CAAC;IAElC,IAAI,SAAS,EAAE,CAAC;QACd,MAAM,CAAC,KAAK,EAAE,QAAQ,EAAE,KAAK,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;YACjD,QAAQ,CAAC,UAAU,CAAC,SAAS,CAAC;YAC9B,QAAQ,CAAC,eAAe,CAAC,SAAS,EAAE,MAAM,CAAC;YAC3C,QAAQ,CAAC,YAAY,CAAC,SAAS,EAAE,MAAM,CAAC;SACzC,CAAC,CAAC;QAEH,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,MAAM,IAAI,sBAAsB,CAC9B,iBAAiB,EACjB,GAAG,EACH,iBAAiB,CAClB,CAAC;QACJ,CAAC;QAED,IAAI,CAAC,QAAQ,EAAE,CAAC;YACd,MAAM,IAAI,sBAAsB,CAC9B,oCAAoC,EACpC,GAAG,EACH,2BAA2B,CAC5B,CAAC;QACJ,CAAC;QAED,IAAI,UAAU,GAAG,YAAY,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,KAAK,KAAK,CAAC,EAAE,CAAC,CAAC;QACpE,IAAI,UAAU,KAAK,SAAS,EAAE,CAAC;YAC7B,UAAU,GAAG,CAAC,MAAM,QAAQ,CAAC,oBAAoB,CAAC,KAAK,CAAC,EAAE,EAAE,MAAM,CAAC,CAAC,IAAI,SAAS,CAAC;QACpF,CAAC;QACD,WAAW,GAAG;YACZ,EAAE,EAAE,KAAK,CAAC,EAAE;YACZ,KAAK,EAAE,KAAK,CAAC,KAAK;YAClB,MAAM,EAAE,UAAU,EAAE,WAAW,IAAI,IAAI;YACvC,IAAI,EAAE,KAAK,CAAC,IAAI,IAAI,WAAW;YAC/B,QAAQ,EAAE,KAAK,CAAC,QAAQ,IAAI,EAAE;YAC9B,WAAW,EAAE,KAAK,CAAC,WAAW,IAAI,EAAE;SACrC,CAAC;QACF,OAAO,GAAG,KAAK,CAAC;QAChB,SAAS,GAAG,KAAK,CAAC,KAAK,CAAC;QACxB,oBAAoB,GAAG,KAAK,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,QAAQ,CAAC;IACpD,CAAC;IAED,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,IAAI,SAAS,CAAC;IACxC,MAAM,SAAS,GAAG,IAAI,CAAC,KAAK,IAAI,EAAE,CAAC;IACnC,MAAM,OAAO,GAAG,CAAC,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC;IAEpC,oFAAoF;IACpF,4EAA4E;IAC5E,0EAA0E;IAC1E,+EAA+E;IAC/E,oEAAoE;IACpE,MAAM,UAAU,GAAG,SAAS;QAC1B,CAAC,CAAC,YAAY;aACT,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,KAAK,SAAS,IAAI,CAAC,CAAC,UAAU,KAAK,IAAI,CAAC;aACjE,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC;QAC5B,CAAC,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;IAEzC,OAAO;QACL,MAAM;QACN,QAAQ;QACR,SAAS;QACT,SAAS;QACT,SAAS;QACT,OAAO;QACP,IAAI;QACJ,WAAW;QACX,YAAY;QACZ,UAAU;QACV,WAAW;QACX,oBAAoB;QACpB,YAAY,EAAE,CAAC,CAAC,IAAI,CAAC,UAAU,EAAE,WAAW,CAAC;QAC7C,OAAO;QACP,GAAG,CAAC,SAAS,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KAClD,CAAC;AACJ,CAAC;AA8LD,kFAAkF;AAClF,sBAAsB;AACtB,kFAAkF;AAElF,MAAM,UAAU,OAAO,CAAI,IAAO;IAChC,OAAO,IAAI,CAAC,SAAS,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;AACjD,CAAC;AAED,MAAM,UAAU,KAAK,CACnB,OAAe,EACf,UAAqF;IAErF,OAAO,IAAI,CAAC,SAAS,CAAC;QACpB,OAAO,EAAE,KAAK;QACd,KAAK,EAAE,OAAO;QACd,GAAG,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KAC9C,CAAC,CAAC;AACL,CAAC;AAED,6DAA6D;AAC7D,MAAM,UAAU,kBAAkB,CAAC,MAGlC;IACC,OAAO,IAAI,CAAC,SAAS,CAAC;QACpB,OAAO,EAAE,KAAK;QACd,kBAAkB,EAAE,IAAI;QACxB,GAAG,MAAM;KACV,CAAC,CAAC;AACL,CAAC;AAED,kFAAkF;AAClF,wBAAwB;AACxB,kFAAkF;AAElF,0DAA0D;AAC1D,MAAM,iBAAiB,GAAG,4BAA4B,CAAC;AAEvD;;;;GAIG;AACH,MAAM,cAAc,GAAG,+TAA+T,CAAC;AAEvV,uFAAuF;AACvF,MAAM,CAAC,MAAM,UAAU,GAAG,iEAAiE,CAAC;AAE5F;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,iBAAiB,CACrC,QAAmF,EACnF,UAAoB;IAEpB,IAAI,UAAU,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,CAAC;IACvC,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,GAAG,CAC/B,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC,QAAQ,CAAC,UAAU,CAAC,EAAE,CAAC,CAAC,CAC9C,CAAC;IACF,OAAO,OAAO,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,GAAI,CAAC,KAAK,CAAC,CAAC;AACxD,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,YAAY,CAAC,GAAW;IACtC,IAAI,GAAG,GAAG,GAAG,CAAC,OAAO,CAAC,aAAa,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;IAChD,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;QAC/B,GAAG,GAAG,WAAW,GAAG,EAAE,CAAC;IACzB,CAAC;IACD,IAAI,CAAC;QACH,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC;QACb,OAAO,GAAG,CAAC;IACb,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,WAAW,CAAC,IAAY;IACtC,IAAI,CAAC,IAAI,IAAI,OAAO,IAAI,KAAK,QAAQ;QAAE,OAAO,EAAE,CAAC;IAEjD,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;IAC/B,MAAM,GAAG,GAAa,EAAE,CAAC;IAEzB,6BAA6B;IAC7B,MAAM,WAAW,GAAG,IAAI,CAAC,KAAK,CAAC,iBAAiB,CAAC,IAAI,EAAE,CAAC;IACxD,KAAK,MAAM,GAAG,IAAI,WAAW,EAAE,CAAC;QAC9B,MAAM,GAAG,GAAG,YAAY,CAAC,GAAG,CAAC,CAAC;QAC9B,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;YAC1B,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;YACd,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAChB,CAAC;IACH,CAAC;IAED,iDAAiD;IACjD,MAAM,WAAW,GAAG,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,IAAI,EAAE,CAAC;IACrD,KAAK,MAAM,GAAG,IAAI,WAAW,EAAE,CAAC;QAC9B,MAAM,GAAG,GAAG,YAAY,CAAC,GAAG,CAAC,CAAC;QAC9B,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;YAC1B,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;YACd,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAChB,CAAC;IACH,CAAC;IAED,OAAO,GAAG,CAAC;AACb,CAAC;AAED,MAAM,oBAAoB,GAAG,IAAI,GAAG,CAAC;IACnC,QAAQ;IACR,eAAe;IACf,UAAU;IACV,QAAQ;IACR,OAAO;IACP,aAAa;IACb,cAAc;IACd,YAAY;IACZ,WAAW;IACX,aAAa;IACb,cAAc;CACf,CAAC,CAAC;AAEH;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,qBAAqB,CAAC,KAAc;IAClD,IAAI,KAAK,KAAK,IAAI,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO,KAAK,CAAC;IAC9D,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QACzB,OAAO,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,qBAAqB,CAAC,IAAI,CAAC,CAAC,CAAC;IAC1D,CAAC;IACD,MAAM,GAAG,GAA4B,EAAE,CAAC;IACxC,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,KAAgC,CAAC,EAAE,CAAC;QAC5E,MAAM,UAAU,GAAG,GAAG,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;QACvD,IAAI,oBAAoB,CAAC,GAAG,CAAC,UAAU,CAAC,EAAE,CAAC;YACzC,GAAG,CAAC,GAAG,CAAC,GAAG,YAAY,CAAC;QAC1B,CAAC;aAAM,CAAC;YACN,GAAG,CAAC,GAAG,CAAC,GAAG,qBAAqB,CAAC,KAAK,CAAC,CAAC;QAC1C,CAAC;IACH,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC","sourcesContent":["import { z } from \"zod\";\nimport type { ModelConfig } from \"./model.config.js\";\nimport type { ProfileDocument } from \"../schemas/profile.schema.js\";\nimport type { ChatGraphCompositeDatabase, NetworkMembership, UserRecord, UserDatabase, SystemDatabase, NegotiationGraphDatabase } from \"../interfaces/database.interface.js\";\nimport type { Scraper } from \"../interfaces/scraper.interface.js\";\nimport type { Cache, HydeCache } from \"../interfaces/cache.interface.js\";\nimport type { CompiledOpportunityGraph } from \"../../opportunity/opportunity.discover.js\";\nimport type { IntegrationAdapter } from \"../interfaces/integration.interface.js\";\nimport type { ContactServiceAdapter } from \"../interfaces/contact.interface.js\";\nimport type { ProfileEnricher } from \"../interfaces/enrichment.interface.js\";\nimport type { IntentGraphQueue } from \"../interfaces/queue.interface.js\";\nimport type { ChatSessionReader } from \"../interfaces/chat-session.interface.js\";\nimport type { ChatSummaryReader } from \"../interfaces/chat-summary.interface.js\";\nimport type { ChatMessageWriter } from \"../interfaces/chat-message-writer.interface.js\";\nimport type { QuestionGeneratorReader } from \"../interfaces/question-generator.interface.js\";\nimport type { NegotiationSummaryReader } from \"../interfaces/negotiation-summary.interface.js\";\nimport type { Embedder } from \"../interfaces/embedder.interface.js\";\nimport type { AgentDatabase } from \"../interfaces/agent.interface.js\";\nimport type { NegotiationTimeoutQueue } from \"../interfaces/negotiation-events.interface.js\";\nimport type { AgentDispatcher } from \"../interfaces/agent-dispatcher.interface.js\";\nimport type { DeliveryLedger } from \"../interfaces/delivery-ledger.interface.js\";\nimport type { MintConnectLink } from \"../interfaces/connect-link.interface.js\";\nimport type { QuestionerDatabase } from \"../interfaces/questioner.interface.js\";\nimport type { QuestionerEnqueueFn } from \"../../questioner/questioner.types.js\";\nimport type { PendingQuestionSummary } from \"../schemas/pending-question.schema.js\";\nimport type { QuestionMode } from \"../schemas/question.schema.js\";\nimport type { DiscoveryRunQueue, DiscoveryRunStore } from \"../interfaces/discovery-run.interface.js\";\nimport type { ProfileRunQueue, ProfileRunStore } from \"../interfaces/profile-run.interface.js\";\n\nexport type ProfileContext = ProfileDocument | null;\n\nexport interface ToolErrorReport {\n operation: string;\n subsystem?: string;\n toolName?: string;\n userId?: string;\n tags?: Record<string, string | number | boolean | null | undefined>;\n context?: Record<string, unknown>;\n}\n\n// ═══════════════════════════════════════════════════════════════════════════════\n// COMPILED GRAPH TYPE\n// ═══════════════════════════════════════════════════════════════════════════════\n\n/** Minimal interface for an invokable compiled LangGraph. */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport type CompiledGraph = { invoke: (input: any) => Promise<any> };\n\n// ═══════════════════════════════════════════════════════════════════════════════\n// TOOL CONTEXT TYPES\n// ═══════════════════════════════════════════════════════════════════════════════\n\n/**\n * Resolved context available to every tool handler.\n * Contains the current user and optional index identity, resolved from DB at init.\n * The LLM can see this context (via system prompt) but cannot change it.\n */\nexport interface ResolvedToolContext {\n // Legacy flat fields (kept for backwards compatibility in tools/prompts).\n userId: string;\n userName: string;\n userEmail: string;\n networkId?: string;\n indexName?: string;\n /** True when chat is index-scoped and the user owns the index. */\n isOwner?: boolean;\n // Rich identity context for prompt/tool orchestration.\n user: UserRecord;\n userProfile: ProfileContext;\n userNetworks: NetworkMembership[];\n /**\n * The set of index IDs this caller can reach in the current request.\n * For unscoped chats: every index the user is a member of.\n * For network-scoped agents: `[boundNetwork, personalIndex]`.\n * This is the same set used to clamp the DB-level systemDb.\n * Tools that filter intents/profiles default to this set; `networkId` is\n * the \"primary focus\" hint, not a read filter.\n */\n indexScope: string[];\n scopedIndex?: {\n id: string;\n title: string;\n prompt: string | null;\n type?: string;\n metadata?: Record<string, unknown>;\n permissions?: Record<string, unknown>;\n };\n scopedMembershipRole?: \"owner\" | \"member\";\n /** True when user has not completed onboarding (onboarding.completedAt is null). */\n isOnboarding: boolean;\n /** True when the user has a non-empty name. */\n hasName: boolean;\n /** Chat session ID when tools are used in a chat; used for draft opportunities (context.conversationId). */\n sessionId?: string;\n /** True when the request originates from an MCP transport (no interactive UI available). */\n isMcp?: boolean;\n /** Agent ID when the request originates from an API key linked to an agent. */\n agentId?: string;\n /**\n * Receiver's rendering surface declared by the MCP client via the\n * `x-index-surface` request header. `'telegram'` means the MCP response is\n * being rendered inside a Telegram chat; anything\n * else (including `undefined`) is treated as web. Forwarded into\n * `mintConnectLink` so the click-time redirect can branch.\n */\n clientSurface?: 'telegram' | 'web';\n}\n\n/**\n * Dependencies passed when creating tools for a user session.\n * Includes DB adapters, embedder, and scraper.\n *\n * Note: userDb and systemDb are optional inputs - if not provided, createChatTools\n * will create them internally from the chatDatabaseAdapter singleton.\n */\nexport interface ToolContext {\n userId: string;\n /** @deprecated Use userDb or systemDb instead. Kept for backwards compatibility. */\n database: ChatGraphCompositeDatabase;\n /** Context-bound database for accessing the authenticated user's own resources. Created internally if not provided. */\n userDb?: UserDatabase;\n /** Context-bound database for LLM/system operations on cross-user resources within shared indexes. Created internally if not provided. */\n systemDb?: SystemDatabase;\n embedder: Embedder;\n scraper: Scraper;\n /** When set, chat is scoped to this index; tools use it as default for read_intents and create_intent. */\n networkId?: string;\n /**\n * Optional override of the resolved `indexScope`. `resolveChatContext` always\n * computes `indexScope` from the user's memberships (clamped to [bound,\n * personal] when `networkId` is set). When the caller has already computed\n * a clamped scope — notably the MCP server, which clamps via\n * `applyNetworkScopeToContext` for network-scoped agents — passing it on\n * `ToolContext.indexScope` causes `createChatTools` (in tool.factory.ts) to\n * override `resolvedContext.indexScope` with this value rather than the\n * freshly computed one. See ResolvedToolContext.indexScope for the\n * resolved-side semantics.\n */\n indexScope?: string[];\n /** Chat session ID when creating tools for a chat; enables draft opportunities with context.conversationId. */\n sessionId?: string;\n\n // ─── Protocol-level dependencies (injected by composition root) ──────────\n /** General-purpose cache (e.g. for tool results). */\n cache: Cache;\n /** Dedicated cache for HyDE graph (may be same instance as cache). */\n hydeCache: HydeCache;\n /** External integration platform adapter (OAuth, tool actions). */\n integration: IntegrationAdapter;\n /** Queue for enqueuing follow-up intent processing (HyDE generation/deletion). */\n intentQueue: IntentGraphQueue;\n /** Contact management operations. */\n contactService: ContactServiceAdapter;\n /**\n * When false (or unset), the contact import / manual-add tools\n * (import_contacts, add_contact, import_gmail_contacts) are not registered.\n * Injected by the composition root from CONTACTS_ENABLED. Read/remove/search\n * contact tools are always registered.\n */\n contactsEnabled?: boolean;\n /** Chat session reader for loading conversation history. */\n chatSession: ChatSessionReader;\n /** Read-through chat-session digest. Optional; consumers fall back to undefined `chatContext`. */\n chatSummary?: ChatSummaryReader;\n /** Writes user messages into the user's most-recent chat session (Slice 5 MCP elicitation). */\n chatMessageWriter?: ChatMessageWriter;\n /** Decision-question generator. Optional; consumers fall back to no `questions`. */\n questionGenerator?: QuestionGeneratorReader;\n /**\n * Optional async question enqueue callback. When provided, question generation\n * is dispatched asynchronously to the QuestionerQueue instead of running inline.\n * Injected by the composition root when QUESTIONER_ENABLED=true.\n */\n questionerEnqueue?: QuestionerEnqueueFn;\n /** Negotiation-digest summarizer. Optional; consumers fall back to deterministic digests. */\n negotiationSummary?: NegotiationSummaryReader;\n /** Profile enrichment from external data sources. */\n enricher: ProfileEnricher;\n /** Database adapter for negotiation/conversation operations. */\n negotiationDatabase: NegotiationGraphDatabase;\n /** Integration importer for bulk contact import from toolkits. */\n integrationImporter: {\n importContacts(userId: string, toolkit: string): Promise<{\n imported: number;\n skipped: number;\n newContacts: number;\n existingContacts: number;\n }>;\n };\n /** Factory for user-scoped database access. */\n createUserDatabase: (db: ChatGraphCompositeDatabase, userId: string) => UserDatabase;\n /** Factory for system-scoped database access. */\n createSystemDatabase: (db: ChatGraphCompositeDatabase, userId: string, indexScope: string[], embedder?: Embedder) => SystemDatabase;\n /** Optional runtime LLM config. Pass to override env vars for API key, model, etc. */\n modelConfig?: ModelConfig;\n /** Manages negotiation timeout jobs (optional — enables AI fallback on external agent timeout). */\n negotiationTimeoutQueue?: NegotiationTimeoutQueue;\n /** Agent registry database adapter (optional — absent when host does not support agents). */\n agentDatabase?: AgentDatabase;\n /** Grants the default system-agent permissions after onboarding (optional). */\n grantDefaultSystemPermissions?: (userId: string) => Promise<void>;\n /** Dispatcher for routing negotiation turns to personal agents (optional — falls back to system AI). */\n agentDispatcher?: AgentDispatcher;\n /** Enqueue a negotiate_existing job after introducer approval (optional). */\n queueNegotiateExisting?: (opportunityId: string, userId: string) => Promise<void>;\n /** Delivery ledger for committing opportunity delivery rows (optional — absent in chat context). */\n deliveryLedger?: DeliveryLedger;\n /** Persistence for async MCP discovery runs (optional — absent in non-MCP/test contexts). */\n discoveryRuns?: DiscoveryRunStore;\n /** Queue for async MCP discovery run execution (optional — absent in non-MCP/test contexts). */\n discoveryRunQueue?: DiscoveryRunQueue;\n /** Persistence for async MCP profile runs (optional — absent in non-MCP/test contexts). */\n profileRuns?: ProfileRunStore;\n /** Queue for async MCP profile run execution (optional — absent in non-MCP/test contexts). */\n profileRunQueue?: ProfileRunQueue;\n /**\n * Legacy direct-token minting for opportunity accept redirects.\n * Prefer `mintConnectLink` for user-facing links.\n */\n mintConnectToken?: (userId: string, opportunityId: string) => Promise<string>;\n /** Mints (or reuses) a short connect link, snapshotting the greeting (optional — absent in non-MCP contexts). */\n mintConnectLink?: MintConnectLink;\n /** Frontend base URL for building profile links (e.g. https://index.network, optional). */\n frontendUrl?: string;\n /** API base URL for building opportunity accept links (e.g. https://protocol.index.network, optional). */\n apiBaseUrl?: string;\n /** Persistence for structured questions generated by the QuestionerAgent (optional). */\n questionerDatabase?: QuestionerDatabase;\n /** Optional host-side error reporter for swallowed protocol/tool errors. */\n reportToolError?: (error: unknown, report: ToolErrorReport) => void;\n /**\n * Optional host-side per-principal MCP call throttle. Invoked once per MCP\n * tool dispatch (after identity resolves, before any DB work). When the\n * returned decision is `allowed: false`, the dispatch short-circuits with a\n * rate-limit error carrying `retryAfterSec`. Absent in chat/test contexts.\n */\n mcpRateLimiter?: (input: { userId: string; agentId?: string; toolName: string }) => Promise<{\n allowed: boolean;\n retryAfterSec?: number;\n limit?: number;\n scope?: 'tool' | 'principal';\n }>;\n /** Optional premise lifecycle event callbacks. Fired by premise tools after successful operations. */\n premiseEvents?: {\n onCreated?: (premiseId: string, userId: string) => void;\n onUpdated?: (premiseId: string, userId: string) => void;\n onRetracted?: (premiseId: string, userId: string) => void;\n };\n}\n\n/**\n * All external dependencies needed to initialize the protocol tool engine.\n * The host application (composition root) must provide concrete implementations.\n * This is the subset of ToolContext that is NOT per-request (no userId, indexId, sessionId).\n */\nexport type ProtocolDeps = Omit<ToolContext, 'userId' | 'indexId' | 'sessionId' | 'userDb' | 'systemDb'>;\n\n/**\n * Thrown when a requested chat scope is invalid for the authenticated user.\n * Controllers can map this to an HTTP status code.\n */\nexport class ChatContextAccessError extends Error {\n constructor(\n message: string,\n public readonly statusCode: number,\n public readonly code: \"USER_NOT_FOUND\" | \"INDEX_NOT_FOUND\" | \"INDEX_MEMBERSHIP_REQUIRED\"\n ) {\n super(message);\n this.name = \"ChatContextAccessError\";\n }\n}\n\n/**\n * Resolve the canonical context used by chat tools and system prompt.\n * This preloads user identity, profile, index memberships, and scoped index role.\n */\nexport async function resolveChatContext(params: {\n database: Pick<\n ChatGraphCompositeDatabase,\n \"getUser\" | \"getProfile\" | \"getNetworkMemberships\" | \"getNetworkMembership\" | \"getNetwork\" | \"isIndexOwner\" | \"isNetworkMember\"\n >;\n userId: string;\n networkId?: string;\n /** Chat session ID for draft opportunities (stored as context.conversationId). */\n sessionId?: string;\n}): Promise<ResolvedToolContext> {\n const { database, userId, networkId, sessionId } = params;\n\n const [user, rawProfile, userNetworks] = await Promise.all([\n database.getUser(userId),\n database.getProfile(userId),\n database.getNetworkMemberships(userId),\n ]);\n\n const userProfile: ProfileContext = rawProfile ?? null;\n\n if (!user) {\n throw new ChatContextAccessError(\n \"User not found\",\n 404,\n \"USER_NOT_FOUND\"\n );\n }\n\n let scopedIndex: ResolvedToolContext[\"scopedIndex\"] = undefined;\n let scopedMembershipRole: ResolvedToolContext[\"scopedMembershipRole\"] = undefined;\n let isOwner = false;\n let indexName: string | undefined;\n\n if (networkId) {\n const [index, isMember, owner] = await Promise.all([\n database.getNetwork(networkId),\n database.isNetworkMember(networkId, userId),\n database.isIndexOwner(networkId, userId),\n ]);\n\n if (!index) {\n throw new ChatContextAccessError(\n \"Index not found\",\n 404,\n \"INDEX_NOT_FOUND\"\n );\n }\n\n if (!isMember) {\n throw new ChatContextAccessError(\n \"You are not a member of this index\",\n 403,\n \"INDEX_MEMBERSHIP_REQUIRED\"\n );\n }\n\n let membership = userNetworks.find((m) => m.networkId === index.id);\n if (membership === undefined) {\n membership = (await database.getNetworkMembership(index.id, userId)) ?? undefined;\n }\n scopedIndex = {\n id: index.id,\n title: index.title,\n prompt: membership?.indexPrompt ?? null,\n type: index.type ?? 'community',\n metadata: index.metadata ?? {},\n permissions: index.permissions ?? {},\n };\n isOwner = owner;\n indexName = index.title;\n scopedMembershipRole = owner ? \"owner\" : \"member\";\n }\n\n const userName = user.name ?? \"Unknown\";\n const userEmail = user.email ?? \"\";\n const hasName = !!user.name?.trim();\n\n // When scoped to an index, clamp the caller's reach to [scopedIndex, personalIndex]\n // so the chat's data model matches its \"focus\" semantic: a chat scoped to a\n // community sees that community plus the user's personal index, not their\n // other unrelated memberships. Mirrors the MCP path's clamp for network-scoped\n // agents (see applyNetworkScopeToContext / computeAgentIndexScope).\n const indexScope = networkId\n ? userNetworks\n .filter((m) => m.networkId === networkId || m.isPersonal === true)\n .map((m) => m.networkId)\n : userNetworks.map((m) => m.networkId);\n\n return {\n userId,\n userName,\n userEmail,\n networkId,\n indexName,\n isOwner,\n user,\n userProfile,\n userNetworks,\n indexScope,\n scopedIndex,\n scopedMembershipRole,\n isOnboarding: !(user.onboarding?.completedAt),\n hasName,\n ...(sessionId !== undefined ? { sessionId } : {}),\n };\n}\n\n// ═══════════════════════════════════════════════════════════════════════════════\n// DEFINE TOOL TYPE\n// ═══════════════════════════════════════════════════════════════════════════════\n\n/**\n * Type for the `defineTool` closure created in `createChatTools`.\n * Auto-injects resolved context and provides uniform logging / error handling.\n */\nexport type DefineTool = <T extends z.ZodType>(opts: {\n name: string;\n description: string;\n querySchema: T;\n handler: (input: { context: ResolvedToolContext; query: z.infer<T> }) => Promise<string>;\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\n}) => any;\n\n/**\n * A raw tool definition before LangChain wrapping.\n * Used by the tool registry for direct HTTP invocation.\n */\nexport interface RawToolDefinition {\n name: string;\n description: string;\n schema: z.ZodType;\n handler: (input: { context: ResolvedToolContext; query: unknown }) => Promise<string>;\n}\n\n/**\n * Registry mapping tool names to their raw definitions.\n */\nexport type ToolRegistry = Map<string, RawToolDefinition>;\n\n// ═══════════════════════════════════════════════════════════════════════════════\n// TOOL DEPENDENCIES\n// ═══════════════════════════════════════════════════════════════════════════════\n\n/**\n * Shared dependencies available to all tool domain factories.\n * Passed by `createChatTools` after compiling all subgraphs.\n */\nexport interface ToolDeps {\n /** @deprecated Use userDb or systemDb instead. Kept for backwards compatibility. */\n database: ChatGraphCompositeDatabase;\n /** Context-bound database for accessing the authenticated user's own resources. */\n userDb: UserDatabase;\n /** Context-bound database for LLM/system operations on cross-user resources within shared indexes. */\n systemDb: SystemDatabase;\n scraper: Scraper;\n embedder: import('../interfaces/embedder.interface.js').Embedder;\n cache: Cache;\n integration: IntegrationAdapter;\n contactService: ContactServiceAdapter;\n /**\n * When false (or unset), the contact import / manual-add tools\n * (import_contacts, add_contact, import_gmail_contacts) are not registered.\n * Injected by the composition root from CONTACTS_ENABLED. Read/remove/search\n * contact tools are always registered.\n */\n contactsEnabled?: boolean;\n integrationImporter: {\n importContacts(userId: string, toolkit: string): Promise<{\n imported: number;\n skipped: number;\n newContacts: number;\n existingContacts: number;\n }>;\n };\n enricher: ProfileEnricher;\n /** Database adapter for negotiation/conversation operations. */\n negotiationDatabase: NegotiationGraphDatabase;\n /** Chat session reader for exposing the caller's past conversations as MCP tools. */\n chatSession?: ChatSessionReader;\n /** Read-through chat-session digest. Optional; consumers fall back to undefined `chatContext`. */\n chatSummary?: ChatSummaryReader;\n /**\n * Test seam for opportunity discovery helpers. Production compositions leave\n * this unset so tools call the real discovery module directly.\n */\n opportunityDiscovery?: {\n runDiscoverFromQuery?: (input: unknown) => Promise<unknown>;\n continueDiscovery?: (input: unknown) => Promise<unknown>;\n };\n /**\n * Test seam for opportunity card presentation helpers. Production\n * compositions leave this unset so tools construct the real presenter.\n */\n opportunityPresentation?: {\n createPresenter?: () => { presentHomeCard(input: unknown): Promise<unknown> };\n gatherPresenterContext?: (...args: unknown[]) => Promise<unknown>;\n };\n /** Writes user messages into the user's most-recent chat session (Slice 5 MCP elicitation). */\n chatMessageWriter?: ChatMessageWriter;\n /** Decision-question generator. Optional; consumers fall back to no `questions`. */\n questionGenerator?: QuestionGeneratorReader;\n /**\n * Optional async question enqueue callback. When provided, question generation\n * is dispatched asynchronously to the QuestionerQueue instead of running inline\n * via the `questionGenerator`. Injected by the composition root when\n * QUESTIONER_ENABLED=true.\n */\n questionerEnqueue?: QuestionerEnqueueFn;\n /**\n * Lookup pending questions for a user, optionally filtered by source,\n * detection mode, or capped by count (hosts apply `limit` SQL-side).\n * Used by tools to attach contextually relevant questions to their results.\n * Injected by the composition root — absent when question delivery is disabled.\n */\n findPendingQuestions?: (\n userId: string,\n filters?: {\n sourceType?: string;\n sourceId?: string;\n /** Restrict to questions whose detection mode is in this set. */\n modes?: QuestionMode[];\n /** Maximum rows to return; hosts should apply this in the query. */\n limit?: number;\n },\n ) => Promise<PendingQuestionSummary[]>;\n /** Negotiation-digest summarizer. Optional; consumers fall back to deterministic digests. */\n negotiationSummary?: NegotiationSummaryReader;\n /** Manages negotiation timeout jobs (optional — enables AI fallback on external agent timeout). */\n negotiationTimeoutQueue?: NegotiationTimeoutQueue;\n /** Agent registry database adapter (optional — absent when host does not support agents). */\n agentDatabase?: AgentDatabase;\n /** Grants the default system-agent permissions after onboarding (optional). */\n grantDefaultSystemPermissions?: (userId: string) => Promise<void>;\n /** Dispatcher for routing negotiation turns to personal agents (optional — falls back to system AI). */\n agentDispatcher?: AgentDispatcher;\n /** Delivery ledger for committing opportunity delivery rows (optional — absent in chat context). */\n deliveryLedger?: DeliveryLedger;\n /** Persistence for async MCP discovery runs (optional — absent in non-MCP/test contexts). */\n discoveryRuns?: DiscoveryRunStore;\n /** Queue for async MCP discovery run execution (optional — absent in non-MCP/test contexts). */\n discoveryRunQueue?: DiscoveryRunQueue;\n /** Persistence for async MCP profile runs (optional — absent in non-MCP/test contexts). */\n profileRuns?: ProfileRunStore;\n /** Queue for async MCP profile run execution (optional — absent in non-MCP/test contexts). */\n profileRunQueue?: ProfileRunQueue;\n /**\n * Legacy direct-token minting for opportunity accept redirects.\n * Prefer `mintConnectLink` for user-facing links.\n */\n mintConnectToken?: (userId: string, opportunityId: string) => Promise<string>;\n /** Mints (or reuses) a short connect link, snapshotting the greeting (optional — absent in non-MCP contexts). */\n mintConnectLink?: MintConnectLink;\n /** Frontend base URL for building profile links (e.g. https://index.network, optional). */\n frontendUrl?: string;\n /** API base URL for building opportunity accept links (e.g. https://protocol.index.network, optional). */\n apiBaseUrl?: string;\n /** Optional host-side error reporter for swallowed protocol/tool errors. */\n reportToolError?: (error: unknown, report: ToolErrorReport) => void;\n /**\n * Optional host-side per-principal MCP call throttle. Invoked once per MCP\n * tool dispatch (after identity resolves, before any DB work). When the\n * returned decision is `allowed: false`, the dispatch short-circuits with a\n * rate-limit error carrying `retryAfterSec`. Absent in chat/test contexts.\n */\n mcpRateLimiter?: (input: { userId: string; agentId?: string; toolName: string }) => Promise<{\n allowed: boolean;\n retryAfterSec?: number;\n limit?: number;\n scope?: 'tool' | 'principal';\n }>;\n /** Optional premise lifecycle event callbacks. Fired by premise tools after successful operations. */\n premiseEvents?: {\n onCreated?: (premiseId: string, userId: string) => void;\n onUpdated?: (premiseId: string, userId: string) => void;\n onRetracted?: (premiseId: string, userId: string) => void;\n };\n graphs: {\n profile: CompiledGraph;\n intent: CompiledGraph;\n index: CompiledGraph;\n networkMembership: CompiledGraph;\n intentIndex: CompiledGraph;\n opportunity: CompiledOpportunityGraph;\n premise: CompiledGraph;\n };\n /**\n * Optional network ranking override for `read_networks`. Injected by tests or custom compositions.\n * When absent, defaults to `NetworkRecommender.invoke()` with a lazy module-level singleton.\n */\n networkRanker?: (input: {\n userProfile: { bio: string; location: string; interests: string[]; skills: string[] };\n networks: Array<{ networkId: string; renderedContext: string }>;\n }) => Promise<{ rankedNetworkIds: string[] } | null>;\n}\n\n// ═══════════════════════════════════════════════════════════════════════════════\n// TOOL RESULT HELPERS\n// ═══════════════════════════════════════════════════════════════════════════════\n\nexport function success<T>(data: T): string {\n return JSON.stringify({ success: true, data });\n}\n\nexport function error(\n message: string,\n debugSteps?: Array<{ step: string; detail?: string; data?: Record<string, unknown> }>\n): string {\n return JSON.stringify({\n success: false,\n error: message,\n ...(debugSteps?.length ? { debugSteps } : {}),\n });\n}\n\n/** Return needsClarification for missing required fields. */\nexport function needsClarification(params: {\n missingFields: string[];\n message: string;\n}): string {\n return JSON.stringify({\n success: false,\n needsClarification: true,\n ...params,\n });\n}\n\n// ═══════════════════════════════════════════════════════════════════════════════\n// CONSTANTS & UTILITIES\n// ═══════════════════════════════════════════════════════════════════════════════\n\n/** Matches http/https URLs in text; captures full URL. */\nconst URL_IN_TEXT_REGEX = /https?:\\/\\/[^\\s\"'<>)\\]]+/gi;\n\n/**\n * Matches bare domain URLs without protocol (e.g. github.com/foo, www.example.com).\n * Requires at least a SLD.TLD pattern followed by optional path.\n * Negative lookbehind ensures we don't double-match URLs already caught by URL_IN_TEXT_REGEX.\n */\nconst BARE_URL_REGEX = /(?<!\\w:\\/\\/)(?<![/\\w])(?:www\\.)?[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\\.(?:com|org|net|io|dev|co|ai|app|xyz|me|info|gg|so|sh|cc|ly|fm|tv|to|tech|design|network|world|edu|gov|mil|int|us|uk|eu|de|fr|ca|au|jp|cn|in|br|nl|se|no|fi|dk|ch|at|be|it|es|pt|pl|cz|ru|kr|tw|hk|sg|nz|za|mx|ar|cl|id|ph|th|vn|my|ie)(?:\\/[^\\s\"'<>)\\]]*)?/gi;\n\n/** UUID v4 format: 8-4-4-4-12 hex chars (e.g. c2505011-2e45-426e-81dd-b9abb9b72023) */\nexport const UUID_REGEX = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;\n\n/**\n * Resolves an array of network IDs to their display titles.\n * Skips any IDs that don't resolve (deleted or invalid networks).\n */\nexport async function resolveIndexNames(\n database: { getNetwork(id: string): Promise<{ id: string; title: string } | null> },\n networkIds: string[]\n): Promise<string[]> {\n if (networkIds.length === 0) return [];\n const results = await Promise.all(\n networkIds.map(id => database.getNetwork(id))\n );\n return results.filter(Boolean).map(idx => idx!.title);\n}\n\n/**\n * Normalize a URL string: if it lacks a protocol, prepend \"https://\".\n * Returns the normalized URL or null if the result is not a valid URL.\n */\nexport function normalizeUrl(raw: string): string | null {\n let url = raw.replace(/[.,;:!?)]+$/, \"\").trim();\n if (!/^https?:\\/\\//i.test(url)) {\n url = `https://${url}`;\n }\n try {\n new URL(url);\n return url;\n } catch {\n return null;\n }\n}\n\n/**\n * Extract unique, valid URLs from a string (e.g. user message or details).\n * Handles both full URLs (https://...) and bare domains (github.com/...).\n */\nexport function extractUrls(text: string): string[] {\n if (!text || typeof text !== \"string\") return [];\n\n const seen = new Set<string>();\n const out: string[] = [];\n\n // Pass 1: full protocol URLs\n const fullMatches = text.match(URL_IN_TEXT_REGEX) ?? [];\n for (const raw of fullMatches) {\n const url = normalizeUrl(raw);\n if (url && !seen.has(url)) {\n seen.add(url);\n out.push(url);\n }\n }\n\n // Pass 2: bare domain URLs (e.g. github.com/foo)\n const bareMatches = text.match(BARE_URL_REGEX) ?? [];\n for (const raw of bareMatches) {\n const url = normalizeUrl(raw);\n if (url && !seen.has(url)) {\n seen.add(url);\n out.push(url);\n }\n }\n\n return out;\n}\n\nconst SENSITIVE_FIELD_KEYS = new Set([\n \"secret\",\n \"webhooksecret\",\n \"password\",\n \"apikey\",\n \"token\",\n \"accesstoken\",\n \"refreshtoken\",\n \"privatekey\",\n \"authtoken\",\n \"bearertoken\",\n \"clientsecret\",\n]);\n\n/**\n * Recursively redacts sensitive field values from an arbitrary payload before\n * it is passed to a structured logger. Matches field names case-insensitively\n * and ignoring underscores, so `api_key`, `apiKey`, and `API_KEY` all match.\n * Non-sensitive fields are passed through unchanged. Never mutates the input —\n * returns a new value.\n *\n * Intended for structured-log redaction only. Do NOT use as a security\n * boundary for data in motion.\n *\n * @param value - Arbitrary JSON-like payload (query object, config blob, etc.)\n * @returns A new value with sensitive fields replaced by `\"[redacted]\"`.\n */\nexport function redactSensitiveFields(value: unknown): unknown {\n if (value === null || typeof value !== \"object\") return value;\n if (Array.isArray(value)) {\n return value.map((item) => redactSensitiveFields(item));\n }\n const out: Record<string, unknown> = {};\n for (const [key, inner] of Object.entries(value as Record<string, unknown>)) {\n const normalized = key.toLowerCase().replace(/_/g, \"\");\n if (SENSITIVE_FIELD_KEYS.has(normalized)) {\n out[key] = \"[redacted]\";\n } else {\n out[key] = redactSensitiveFields(inner);\n }\n }\n return out;\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"tool.runtime.d.ts","sourceRoot":"/","sources":["shared/agent/tool.runtime.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qCAAqC,CAAC;AAGxE,OAAO,KAAK,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAEhF,MAAM,MAAM,gBAAgB,GAAG,MAAM,GAAG,cAAc,GAAG,iBAAiB,CAAC;AAC3E,MAAM,MAAM,oBAAoB,GAAG,cAAc,GAAG,gBAAgB,GAAG,uBAAuB,CAAC;AAE/F,MAAM,WAAW,iBAAiB;IAChC,KAAK,EAAE,gBAAgB,CAAC;IACxB,SAAS,EAAE,MAAM,CAAC;IAClB,cAAc,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,0BAA0B;IACzC,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,IAAI,CAAC,iBAAiB,EAAE,SAAS,CAAC,CAAC;IACzC,OAAO,EAAE,mBAAmB,CAAC;IAC7B,KAAK,EAAE,OAAO,CAAC;IACf,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,YAAY,CAAC,EAAE,YAAY,CAAC;IAC5B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAmED,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,MAAM,GAAG,iBAAiB,CAoBxE;AAED,qBAAa,gBAAiB,SAAQ,KAAK;aAEvB,IAAI,EAAE,oBAAoB;aAE1B,QAAQ,EAAE,MAAM;aAChB,MAAM,EAAE,iBAAiB;gBAHzB,IAAI,EAAE,oBAAoB,EAC1C,OAAO,EAAE,MAAM,EACC,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,iBAAiB;CAK5C;AAkCD,wBAAsB,iBAAiB,CAAC,KAAK,EAAE,0BAA0B,GAAG,OAAO,CAAC,MAAM,CAAC,CAE1F;AA4ED,wBAAgB,wBAAwB,CAAC,GAAG,EAAE,OAAO,GAAG,MAAM,GAAG,IAAI,CAapE"}
1
+ {"version":3,"file":"tool.runtime.d.ts","sourceRoot":"/","sources":["shared/agent/tool.runtime.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qCAAqC,CAAC;AAGxE,OAAO,KAAK,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAEhF,MAAM,MAAM,gBAAgB,GAAG,MAAM,GAAG,cAAc,GAAG,iBAAiB,CAAC;AAC3E,MAAM,MAAM,oBAAoB,GAAG,cAAc,GAAG,gBAAgB,GAAG,uBAAuB,CAAC;AAE/F,MAAM,WAAW,iBAAiB;IAChC,KAAK,EAAE,gBAAgB,CAAC;IACxB,SAAS,EAAE,MAAM,CAAC;IAClB,cAAc,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,0BAA0B;IACzC,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,IAAI,CAAC,iBAAiB,EAAE,SAAS,CAAC,CAAC;IACzC,OAAO,EAAE,mBAAmB,CAAC;IAC7B,KAAK,EAAE,OAAO,CAAC;IACf,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,YAAY,CAAC,EAAE,YAAY,CAAC;IAC5B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAmED,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,MAAM,GAAG,iBAAiB,CA0BxE;AAED,qBAAa,gBAAiB,SAAQ,KAAK;aAEvB,IAAI,EAAE,oBAAoB;aAE1B,QAAQ,EAAE,MAAM;aAChB,MAAM,EAAE,iBAAiB;gBAHzB,IAAI,EAAE,oBAAoB,EAC1C,OAAO,EAAE,MAAM,EACC,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,iBAAiB;CAK5C;AA+CD,wBAAsB,iBAAiB,CAAC,KAAK,EAAE,0BAA0B,GAAG,OAAO,CAAC,MAAM,CAAC,CAE1F;AA4DD,wBAAgB,wBAAwB,CAAC,GAAG,EAAE,OAAO,GAAG,MAAM,GAAG,IAAI,CAapE"}
@@ -66,11 +66,17 @@ export function getToolTimeoutPolicy(toolName) {
66
66
  : ASYNC_CANDIDATE_TOOLS.has(toolName)
67
67
  ? "async_candidate"
68
68
  : "bounded_slow";
69
- const classDefault = classification === "fast"
70
- ? parsePositiveIntEnv("MCP_TOOL_TIMEOUT_FAST_MS", FAST_TIMEOUT_MS)
71
- : classification === "async_candidate"
72
- ? parsePositiveIntEnv("MCP_TOOL_TIMEOUT_ASYNC_CANDIDATE_MS", ASYNC_CANDIDATE_TIMEOUT_MS)
73
- : parsePositiveIntEnv("MCP_TOOL_TIMEOUT_BOUNDED_SLOW_MS", BOUNDED_SLOW_TIMEOUT_MS);
69
+ let classDefault;
70
+ switch (classification) {
71
+ case "fast":
72
+ classDefault = parsePositiveIntEnv("MCP_TOOL_TIMEOUT_FAST_MS", FAST_TIMEOUT_MS);
73
+ break;
74
+ case "async_candidate":
75
+ classDefault = parsePositiveIntEnv("MCP_TOOL_TIMEOUT_ASYNC_CANDIDATE_MS", ASYNC_CANDIDATE_TIMEOUT_MS);
76
+ break;
77
+ default:
78
+ classDefault = parsePositiveIntEnv("MCP_TOOL_TIMEOUT_BOUNDED_SLOW_MS", BOUNDED_SLOW_TIMEOUT_MS);
79
+ }
74
80
  const defaultMaxOutputBytes = parsePositiveIntEnv("MCP_TOOL_MAX_OUTPUT_BYTES", DEFAULT_MAX_OUTPUT_BYTES);
75
81
  return {
76
82
  class: classification,
@@ -87,6 +93,13 @@ export class ToolRuntimeError extends Error {
87
93
  this.name = "ToolRuntimeError";
88
94
  }
89
95
  }
96
+ /** Builds the typed timeout/cancellation error shared by the abort race and catch paths. */
97
+ function makeAbortError(timedOut, toolName, policy) {
98
+ const code = timedOut ? "TOOL_TIMEOUT" : "TOOL_CANCELLED";
99
+ return new ToolRuntimeError(code, code === "TOOL_TIMEOUT"
100
+ ? `Tool ${toolName} timed out after ${policy.timeoutMs}ms.`
101
+ : `Tool ${toolName} was cancelled before it completed.`, toolName, policy);
102
+ }
90
103
  function combineSignals(signals) {
91
104
  const controller = new AbortController();
92
105
  const listeners = [];
@@ -136,10 +149,7 @@ async function invokeToolRuntimeInner(input) {
136
149
  let removeAbortListener = () => { };
137
150
  const abortPromise = new Promise((_, reject) => {
138
151
  const onAbort = () => {
139
- const code = timedOut ? "TOOL_TIMEOUT" : "TOOL_CANCELLED";
140
- reject(new ToolRuntimeError(code, code === "TOOL_TIMEOUT"
141
- ? `Tool ${input.toolName} timed out after ${policy.timeoutMs}ms.`
142
- : `Tool ${input.toolName} was cancelled before it completed.`, input.toolName, policy));
152
+ reject(makeAbortError(timedOut, input.toolName, policy));
143
153
  };
144
154
  combined.signal.addEventListener("abort", onAbort, { once: true });
145
155
  removeAbortListener = () => combined.signal.removeEventListener("abort", onAbort);
@@ -162,10 +172,7 @@ async function invokeToolRuntimeInner(input) {
162
172
  if (err instanceof ToolRuntimeError)
163
173
  throw err;
164
174
  if (combined.signal.aborted) {
165
- const code = timedOut ? "TOOL_TIMEOUT" : "TOOL_CANCELLED";
166
- throw new ToolRuntimeError(code, code === "TOOL_TIMEOUT"
167
- ? `Tool ${input.toolName} timed out after ${policy.timeoutMs}ms.`
168
- : `Tool ${input.toolName} was cancelled before it completed.`, input.toolName, policy);
175
+ throw makeAbortError(timedOut, input.toolName, policy);
169
176
  }
170
177
  throw err;
171
178
  }
@@ -1 +1 @@
1
- {"version":3,"file":"tool.runtime.js","sourceRoot":"/","sources":["shared/agent/tool.runtime.ts"],"names":[],"mappings":"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","sourcesContent":["import { timed } from \"../observability/performance.js\";\nimport type { TraceEmitter } from \"../observability/request-context.js\";\nimport { requestContext } from \"../observability/request-context.js\";\n\nimport type { RawToolDefinition, ResolvedToolContext } from \"./tool.helpers.js\";\n\nexport type ToolTimeoutClass = \"fast\" | \"bounded_slow\" | \"async_candidate\";\nexport type ToolRuntimeErrorCode = \"TOOL_TIMEOUT\" | \"TOOL_CANCELLED\" | \"TOOL_OUTPUT_TOO_LARGE\";\n\nexport interface ToolTimeoutPolicy {\n class: ToolTimeoutClass;\n timeoutMs: number;\n maxOutputBytes: number;\n}\n\nexport interface ToolInvocationRuntimeInput {\n toolName: string;\n tool: Pick<RawToolDefinition, \"handler\">;\n context: ResolvedToolContext;\n query: unknown;\n signal?: AbortSignal;\n traceEmitter?: TraceEmitter;\n timeoutMs?: number;\n maxOutputBytes?: number;\n}\n\nconst FAST_TIMEOUT_MS = 10_000;\nconst BOUNDED_SLOW_TIMEOUT_MS = 45_000;\nconst ASYNC_CANDIDATE_TIMEOUT_MS = 50_000;\nconst DEFAULT_MAX_OUTPUT_BYTES = 1_000_000;\n\nconst FAST_TOOLS = new Set([\n \"record_onboarding_privacy_consent\",\n \"create_intent_index\",\n \"delete_intent_index\",\n \"search_intents\",\n \"read_networks\",\n \"update_network\",\n \"create_network\",\n \"delete_network\",\n \"create_network_membership\",\n \"delete_network_membership\",\n \"confirm_opportunity_delivery\",\n \"read_docs\",\n \"get_discovery_run\",\n \"cancel_discovery_run\",\n \"get_profile_run\",\n \"cancel_profile_run\",\n \"remove_contact\",\n \"register_agent\",\n \"list_agents\",\n \"update_agent\",\n \"delete_agent\",\n \"grant_agent_permission\",\n \"revoke_agent_permission\",\n \"retract_premise\",\n]);\n\nconst ASYNC_CANDIDATE_TOOLS = new Set([\n \"read_user_profiles\",\n \"preview_user_profile\",\n \"create_user_profile\",\n \"update_user_profile\",\n \"create_intent\",\n \"update_intent\",\n \"discover_opportunities\",\n \"scrape_url\",\n \"import_gmail_contacts\",\n \"import_contacts\",\n \"respond_to_negotiation\",\n \"create_premise\",\n \"update_premise\",\n]);\n\nfunction parsePositiveIntEnv(name: string, fallback: number): number {\n const raw = process.env[name];\n if (!raw) return fallback;\n const parsed = Number.parseInt(raw, 10);\n return Number.isFinite(parsed) && parsed > 0 && parsed <= Number.MAX_SAFE_INTEGER\n ? parsed\n : fallback;\n}\n\nfunction toolNameEnv(toolName: string): string {\n return `MCP_TOOL_TIMEOUT_${toolName.toUpperCase().replace(/[^A-Z0-9]+/g, \"_\")}_MS`;\n}\n\nfunction toolNameOutputEnv(toolName: string): string {\n return `MCP_TOOL_MAX_OUTPUT_${toolName.toUpperCase().replace(/[^A-Z0-9]+/g, \"_\")}_BYTES`;\n}\n\nexport function getToolTimeoutPolicy(toolName: string): ToolTimeoutPolicy {\n const classification: ToolTimeoutClass = FAST_TOOLS.has(toolName)\n ? \"fast\"\n : ASYNC_CANDIDATE_TOOLS.has(toolName)\n ? \"async_candidate\"\n : \"bounded_slow\";\n\n const classDefault = classification === \"fast\"\n ? parsePositiveIntEnv(\"MCP_TOOL_TIMEOUT_FAST_MS\", FAST_TIMEOUT_MS)\n : classification === \"async_candidate\"\n ? parsePositiveIntEnv(\"MCP_TOOL_TIMEOUT_ASYNC_CANDIDATE_MS\", ASYNC_CANDIDATE_TIMEOUT_MS)\n : parsePositiveIntEnv(\"MCP_TOOL_TIMEOUT_BOUNDED_SLOW_MS\", BOUNDED_SLOW_TIMEOUT_MS);\n\n const defaultMaxOutputBytes = parsePositiveIntEnv(\"MCP_TOOL_MAX_OUTPUT_BYTES\", DEFAULT_MAX_OUTPUT_BYTES);\n\n return {\n class: classification,\n timeoutMs: parsePositiveIntEnv(toolNameEnv(toolName), classDefault),\n maxOutputBytes: parsePositiveIntEnv(toolNameOutputEnv(toolName), defaultMaxOutputBytes),\n };\n}\n\nexport class ToolRuntimeError extends Error {\n constructor(\n public readonly code: ToolRuntimeErrorCode,\n message: string,\n public readonly toolName: string,\n public readonly policy: ToolTimeoutPolicy,\n ) {\n super(message);\n this.name = \"ToolRuntimeError\";\n }\n}\n\nfunction combineSignals(signals: Array<AbortSignal | undefined>): {\n signal: AbortSignal;\n abort: (reason?: unknown) => void;\n cleanup: () => void;\n} {\n const controller = new AbortController();\n const listeners: Array<() => void> = [];\n\n for (const source of signals) {\n if (!source) continue;\n if (source.aborted) {\n controller.abort(source.reason);\n break;\n }\n const onAbort = () => {\n if (!controller.signal.aborted) controller.abort(source.reason);\n };\n source.addEventListener(\"abort\", onAbort, { once: true });\n listeners.push(() => source.removeEventListener(\"abort\", onAbort));\n }\n\n return {\n signal: controller.signal,\n abort: (reason?: unknown) => {\n if (!controller.signal.aborted) controller.abort(reason);\n },\n cleanup: () => {\n for (const cleanup of listeners) cleanup();\n },\n };\n}\n\nexport async function invokeToolRuntime(input: ToolInvocationRuntimeInput): Promise<string> {\n return timed(`ToolRuntime.${input.toolName}`, () => invokeToolRuntimeInner(input));\n}\n\nasync function invokeToolRuntimeInner(input: ToolInvocationRuntimeInput): Promise<string> {\n const basePolicy = getToolTimeoutPolicy(input.toolName);\n const policy = {\n ...basePolicy,\n ...(input.timeoutMs !== undefined ? { timeoutMs: input.timeoutMs } : {}),\n ...(input.maxOutputBytes !== undefined ? { maxOutputBytes: input.maxOutputBytes } : {}),\n };\n const inherited = requestContext.getStore();\n const combined = combineSignals([input.signal, inherited?.abortSignal]);\n let timedOut = false;\n const timer = setTimeout(() => {\n timedOut = true;\n combined.abort(new Error(`Tool ${input.toolName} timed out after ${policy.timeoutMs}ms`));\n }, policy.timeoutMs);\n\n let removeAbortListener = () => {};\n const abortPromise = new Promise<never>((_, reject) => {\n const onAbort = () => {\n const code: ToolRuntimeErrorCode = timedOut ? \"TOOL_TIMEOUT\" : \"TOOL_CANCELLED\";\n reject(new ToolRuntimeError(\n code,\n code === \"TOOL_TIMEOUT\"\n ? `Tool ${input.toolName} timed out after ${policy.timeoutMs}ms.`\n : `Tool ${input.toolName} was cancelled before it completed.`,\n input.toolName,\n policy,\n ));\n };\n combined.signal.addEventListener(\"abort\", onAbort, { once: true });\n removeAbortListener = () => combined.signal.removeEventListener(\"abort\", onAbort);\n });\n\n try {\n const run = () => input.tool.handler({ context: input.context, query: input.query });\n const toolPromise = requestContext.run(\n {\n ...inherited,\n abortSignal: combined.signal,\n traceEmitter: input.traceEmitter ?? inherited?.traceEmitter,\n },\n run,\n );\n const result = await Promise.race([toolPromise, abortPromise]);\n const outputBytes = new TextEncoder().encode(result).byteLength;\n if (outputBytes > policy.maxOutputBytes) {\n throw new ToolRuntimeError(\n \"TOOL_OUTPUT_TOO_LARGE\",\n `Tool ${input.toolName} returned ${outputBytes} bytes, exceeding the ${policy.maxOutputBytes} byte limit.`,\n input.toolName,\n policy,\n );\n }\n return result;\n } catch (err) {\n if (err instanceof ToolRuntimeError) throw err;\n if (combined.signal.aborted) {\n const code: ToolRuntimeErrorCode = timedOut ? \"TOOL_TIMEOUT\" : \"TOOL_CANCELLED\";\n throw new ToolRuntimeError(\n code,\n code === \"TOOL_TIMEOUT\"\n ? `Tool ${input.toolName} timed out after ${policy.timeoutMs}ms.`\n : `Tool ${input.toolName} was cancelled before it completed.`,\n input.toolName,\n policy,\n );\n }\n throw err;\n } finally {\n clearTimeout(timer);\n removeAbortListener();\n combined.cleanup();\n }\n}\n\nexport function toolRuntimeErrorToResult(err: unknown): string | null {\n if (!(err instanceof ToolRuntimeError)) return null;\n return JSON.stringify({\n success: false,\n code: err.code,\n error: err.message,\n data: {\n tool: err.toolName,\n timeoutClass: err.policy.class,\n timeoutMs: err.policy.timeoutMs,\n maxOutputBytes: err.policy.maxOutputBytes,\n },\n });\n}\n"]}
1
+ {"version":3,"file":"tool.runtime.js","sourceRoot":"/","sources":["shared/agent/tool.runtime.ts"],"names":[],"mappings":"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","sourcesContent":["import { timed } from \"../observability/performance.js\";\nimport type { TraceEmitter } from \"../observability/request-context.js\";\nimport { requestContext } from \"../observability/request-context.js\";\n\nimport type { RawToolDefinition, ResolvedToolContext } from \"./tool.helpers.js\";\n\nexport type ToolTimeoutClass = \"fast\" | \"bounded_slow\" | \"async_candidate\";\nexport type ToolRuntimeErrorCode = \"TOOL_TIMEOUT\" | \"TOOL_CANCELLED\" | \"TOOL_OUTPUT_TOO_LARGE\";\n\nexport interface ToolTimeoutPolicy {\n class: ToolTimeoutClass;\n timeoutMs: number;\n maxOutputBytes: number;\n}\n\nexport interface ToolInvocationRuntimeInput {\n toolName: string;\n tool: Pick<RawToolDefinition, \"handler\">;\n context: ResolvedToolContext;\n query: unknown;\n signal?: AbortSignal;\n traceEmitter?: TraceEmitter;\n timeoutMs?: number;\n maxOutputBytes?: number;\n}\n\nconst FAST_TIMEOUT_MS = 10_000;\nconst BOUNDED_SLOW_TIMEOUT_MS = 45_000;\nconst ASYNC_CANDIDATE_TIMEOUT_MS = 50_000;\nconst DEFAULT_MAX_OUTPUT_BYTES = 1_000_000;\n\nconst FAST_TOOLS = new Set([\n \"record_onboarding_privacy_consent\",\n \"create_intent_index\",\n \"delete_intent_index\",\n \"search_intents\",\n \"read_networks\",\n \"update_network\",\n \"create_network\",\n \"delete_network\",\n \"create_network_membership\",\n \"delete_network_membership\",\n \"confirm_opportunity_delivery\",\n \"read_docs\",\n \"get_discovery_run\",\n \"cancel_discovery_run\",\n \"get_profile_run\",\n \"cancel_profile_run\",\n \"remove_contact\",\n \"register_agent\",\n \"list_agents\",\n \"update_agent\",\n \"delete_agent\",\n \"grant_agent_permission\",\n \"revoke_agent_permission\",\n \"retract_premise\",\n]);\n\nconst ASYNC_CANDIDATE_TOOLS = new Set([\n \"read_user_profiles\",\n \"preview_user_profile\",\n \"create_user_profile\",\n \"update_user_profile\",\n \"create_intent\",\n \"update_intent\",\n \"discover_opportunities\",\n \"scrape_url\",\n \"import_gmail_contacts\",\n \"import_contacts\",\n \"respond_to_negotiation\",\n \"create_premise\",\n \"update_premise\",\n]);\n\nfunction parsePositiveIntEnv(name: string, fallback: number): number {\n const raw = process.env[name];\n if (!raw) return fallback;\n const parsed = Number.parseInt(raw, 10);\n return Number.isFinite(parsed) && parsed > 0 && parsed <= Number.MAX_SAFE_INTEGER\n ? parsed\n : fallback;\n}\n\nfunction toolNameEnv(toolName: string): string {\n return `MCP_TOOL_TIMEOUT_${toolName.toUpperCase().replace(/[^A-Z0-9]+/g, \"_\")}_MS`;\n}\n\nfunction toolNameOutputEnv(toolName: string): string {\n return `MCP_TOOL_MAX_OUTPUT_${toolName.toUpperCase().replace(/[^A-Z0-9]+/g, \"_\")}_BYTES`;\n}\n\nexport function getToolTimeoutPolicy(toolName: string): ToolTimeoutPolicy {\n const classification: ToolTimeoutClass = FAST_TOOLS.has(toolName)\n ? \"fast\"\n : ASYNC_CANDIDATE_TOOLS.has(toolName)\n ? \"async_candidate\"\n : \"bounded_slow\";\n\n let classDefault: number;\n switch (classification) {\n case \"fast\":\n classDefault = parsePositiveIntEnv(\"MCP_TOOL_TIMEOUT_FAST_MS\", FAST_TIMEOUT_MS);\n break;\n case \"async_candidate\":\n classDefault = parsePositiveIntEnv(\"MCP_TOOL_TIMEOUT_ASYNC_CANDIDATE_MS\", ASYNC_CANDIDATE_TIMEOUT_MS);\n break;\n default:\n classDefault = parsePositiveIntEnv(\"MCP_TOOL_TIMEOUT_BOUNDED_SLOW_MS\", BOUNDED_SLOW_TIMEOUT_MS);\n }\n\n const defaultMaxOutputBytes = parsePositiveIntEnv(\"MCP_TOOL_MAX_OUTPUT_BYTES\", DEFAULT_MAX_OUTPUT_BYTES);\n\n return {\n class: classification,\n timeoutMs: parsePositiveIntEnv(toolNameEnv(toolName), classDefault),\n maxOutputBytes: parsePositiveIntEnv(toolNameOutputEnv(toolName), defaultMaxOutputBytes),\n };\n}\n\nexport class ToolRuntimeError extends Error {\n constructor(\n public readonly code: ToolRuntimeErrorCode,\n message: string,\n public readonly toolName: string,\n public readonly policy: ToolTimeoutPolicy,\n ) {\n super(message);\n this.name = \"ToolRuntimeError\";\n }\n}\n\n/** Builds the typed timeout/cancellation error shared by the abort race and catch paths. */\nfunction makeAbortError(timedOut: boolean, toolName: string, policy: ToolTimeoutPolicy): ToolRuntimeError {\n const code: ToolRuntimeErrorCode = timedOut ? \"TOOL_TIMEOUT\" : \"TOOL_CANCELLED\";\n return new ToolRuntimeError(\n code,\n code === \"TOOL_TIMEOUT\"\n ? `Tool ${toolName} timed out after ${policy.timeoutMs}ms.`\n : `Tool ${toolName} was cancelled before it completed.`,\n toolName,\n policy,\n );\n}\n\nfunction combineSignals(signals: Array<AbortSignal | undefined>): {\n signal: AbortSignal;\n abort: (reason?: unknown) => void;\n cleanup: () => void;\n} {\n const controller = new AbortController();\n const listeners: Array<() => void> = [];\n\n for (const source of signals) {\n if (!source) continue;\n if (source.aborted) {\n controller.abort(source.reason);\n break;\n }\n const onAbort = () => {\n if (!controller.signal.aborted) controller.abort(source.reason);\n };\n source.addEventListener(\"abort\", onAbort, { once: true });\n listeners.push(() => source.removeEventListener(\"abort\", onAbort));\n }\n\n return {\n signal: controller.signal,\n abort: (reason?: unknown) => {\n if (!controller.signal.aborted) controller.abort(reason);\n },\n cleanup: () => {\n for (const cleanup of listeners) cleanup();\n },\n };\n}\n\nexport async function invokeToolRuntime(input: ToolInvocationRuntimeInput): Promise<string> {\n return timed(`ToolRuntime.${input.toolName}`, () => invokeToolRuntimeInner(input));\n}\n\nasync function invokeToolRuntimeInner(input: ToolInvocationRuntimeInput): Promise<string> {\n const basePolicy = getToolTimeoutPolicy(input.toolName);\n const policy = {\n ...basePolicy,\n ...(input.timeoutMs !== undefined ? { timeoutMs: input.timeoutMs } : {}),\n ...(input.maxOutputBytes !== undefined ? { maxOutputBytes: input.maxOutputBytes } : {}),\n };\n const inherited = requestContext.getStore();\n const combined = combineSignals([input.signal, inherited?.abortSignal]);\n let timedOut = false;\n const timer = setTimeout(() => {\n timedOut = true;\n combined.abort(new Error(`Tool ${input.toolName} timed out after ${policy.timeoutMs}ms`));\n }, policy.timeoutMs);\n\n let removeAbortListener = () => {};\n const abortPromise = new Promise<never>((_, reject) => {\n const onAbort = () => {\n reject(makeAbortError(timedOut, input.toolName, policy));\n };\n combined.signal.addEventListener(\"abort\", onAbort, { once: true });\n removeAbortListener = () => combined.signal.removeEventListener(\"abort\", onAbort);\n });\n\n try {\n const run = () => input.tool.handler({ context: input.context, query: input.query });\n const toolPromise = requestContext.run(\n {\n ...inherited,\n abortSignal: combined.signal,\n traceEmitter: input.traceEmitter ?? inherited?.traceEmitter,\n },\n run,\n );\n const result = await Promise.race([toolPromise, abortPromise]);\n const outputBytes = new TextEncoder().encode(result).byteLength;\n if (outputBytes > policy.maxOutputBytes) {\n throw new ToolRuntimeError(\n \"TOOL_OUTPUT_TOO_LARGE\",\n `Tool ${input.toolName} returned ${outputBytes} bytes, exceeding the ${policy.maxOutputBytes} byte limit.`,\n input.toolName,\n policy,\n );\n }\n return result;\n } catch (err) {\n if (err instanceof ToolRuntimeError) throw err;\n if (combined.signal.aborted) {\n throw makeAbortError(timedOut, input.toolName, policy);\n }\n throw err;\n } finally {\n clearTimeout(timer);\n removeAbortListener();\n combined.cleanup();\n }\n}\n\nexport function toolRuntimeErrorToResult(err: unknown): string | null {\n if (!(err instanceof ToolRuntimeError)) return null;\n return JSON.stringify({\n success: false,\n code: err.code,\n error: err.message,\n data: {\n tool: err.toolName,\n timeoutClass: err.policy.class,\n timeoutMs: err.policy.timeoutMs,\n maxOutputBytes: err.policy.maxOutputBytes,\n },\n });\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"hyde.graph.d.ts","sourceRoot":"/","sources":["shared/hyde/hyde.graph.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAMH,OAAO,EAAkB,KAAK,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AACzE,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,qCAAqC,CAAC;AAC7E,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,qCAAqC,CAAC;AAC9E,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,kCAAkC,CAAC;AAKlE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oCAAoC,CAAC;AAyBzE;;;GAGG;AACH,qBAAa,gBAAgB;IAEzB,OAAO,CAAC,QAAQ;IAChB,OAAO,CAAC,QAAQ;IAChB,OAAO,CAAC,KAAK;IACb,OAAO,CAAC,QAAQ;IAChB,OAAO,CAAC,SAAS;gBAJT,QAAQ,EAAE,iBAAiB,EAC3B,QAAQ,EAAE,kBAAkB,EAC5B,KAAK,EAAE,SAAS,EAChB,QAAQ,EAAE,YAAY,EACtB,SAAS,EAAE,aAAa;IAGlC,WAAW;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAoOZ"}
1
+ {"version":3,"file":"hyde.graph.d.ts","sourceRoot":"/","sources":["shared/hyde/hyde.graph.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAMH,OAAO,EAAkB,KAAK,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AACzE,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,qCAAqC,CAAC;AAC7E,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,qCAAqC,CAAC;AAC9E,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,kCAAkC,CAAC;AAKlE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oCAAoC,CAAC;AAyBzE;;;GAGG;AACH,qBAAa,gBAAgB;IAEzB,OAAO,CAAC,QAAQ;IAChB,OAAO,CAAC,QAAQ;IAChB,OAAO,CAAC,KAAK;IACb,OAAO,CAAC,QAAQ;IAChB,OAAO,CAAC,SAAS;gBAJT,QAAQ,EAAE,iBAAiB,EAC3B,QAAQ,EAAE,kBAAkB,EAC5B,KAAK,EAAE,SAAS,EAChB,QAAQ,EAAE,YAAY,EACtB,SAAS,EAAE,aAAa;IAGlC,WAAW;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAqOZ"}
@@ -54,8 +54,9 @@ export class HydeGraphFactory {
54
54
  profileContext,
55
55
  maxLenses,
56
56
  });
57
- agentTimingsAccum.push({ name: 'lens.inferrer', durationMs: Date.now() - inferrerStart });
58
- _traceEmitterLens?.({ type: "agent_end", name: "lens-inferrer", durationMs: Date.now() - inferrerStart, summary: result.lenses.length > 0 ? `Inferred ${result.lenses.length} lens(es)` : "lens-inferrer completed" });
57
+ const _inferrerDuration = Date.now() - inferrerStart;
58
+ agentTimingsAccum.push({ name: 'lens.inferrer', durationMs: _inferrerDuration });
59
+ _traceEmitterLens?.({ type: "agent_end", name: "lens-inferrer", durationMs: _inferrerDuration, summary: result.lenses.length > 0 ? `Inferred ${result.lenses.length} lens(es)` : "lens-inferrer completed" });
59
60
  logger.verbose('Lenses inferred', {
60
61
  count: result.lenses.length,
61
62
  lenses: result.lenses.map(l => ({ label: l.label, corpus: l.corpus })),
@@ -1 +1 @@
1
- {"version":3,"file":"hyde.graph.js","sourceRoot":"/","sources":["shared/hyde/hyde.graph.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * HyDE Graph: cache-aware hypothetical document generation with lens inference.\n *\n * Flow: infer_lenses → check_cache → (generate_missing if needed) → embed → cache_results.\n * Constructor injects Database, Embedder, Cache, LensInferrer, HydeGenerator.\n */\n\nimport { StateGraph, START, END } from '@langchain/langgraph';\nimport { createHash } from 'crypto';\n\nimport { getAbortSignalConfig } from '../agent/model-signal.js';\nimport { HydeGraphState, type HydeDocumentState } from './hyde.state.js';\nimport { LensInferrer } from './lens.inferrer.js';\nimport { HydeGenerator } from './hyde.generator.js';\nimport type { HydeGraphDatabase } from '../interfaces/database.interface.js';\nimport type { EmbeddingGenerator } from '../interfaces/embedder.interface.js';\nimport type { HydeCache } from '../interfaces/cache.interface.js';\nimport { HYDE_DEFAULT_CACHE_TTL } from './hyde.strategies.js';\nimport { protocolLogger } from '../observability/protocol.logger.js';\nimport { timed } from '../observability/performance.js';\nimport { requestContext } from \"../observability/request-context.js\";\nimport type { DebugMetaAgent } from '../../chat/chat-streaming.types.js';\n\nconst logger = protocolLogger(\"HyDEGraphFactory\");\n\n/** Hash a lens label (+ optional corpus) to a short key for cache/DB indexing. */\nfunction lensHash(label: string, corpus?: string): string {\n const input = corpus\n ? `${label.toLowerCase().trim()}:${corpus}`\n : label.toLowerCase().trim();\n return createHash('sha256').update(input).digest('hex').slice(0, 16);\n}\n\n/** Build cache key for a specific lens. */\nfunction cacheKey(\n sourceType: string,\n sourceId: string | undefined,\n sourceText: string,\n lens: string,\n corpus?: string,\n): string {\n const entityKey =\n sourceId ?? `q:${createHash('sha256').update(sourceText).digest('hex').slice(0, 16)}`;\n return `hyde:${sourceType}:${entityKey}:${lensHash(lens, corpus)}`;\n}\n\n/**\n * Factory for the HyDE generation graph.\n * Injects Database, Embedder, Cache, LensInferrer, and HydeGenerator.\n */\nexport class HydeGraphFactory {\n constructor(\n private database: HydeGraphDatabase,\n private embedder: EmbeddingGenerator,\n private cache: HydeCache,\n private inferrer: LensInferrer,\n private generator: HydeGenerator,\n ) {}\n\n createGraph() {\n const self = this;\n\n /** Node 1: Infer lenses from source text + optional profile context. */\n const inferLensesNode = async (state: typeof HydeGraphState.State) => {\n return timed(\"HydeGraph.inferLenses\", async () => {\n const { sourceText, profileContext, maxLenses } = state;\n\n logger.verbose('Inferring lenses', { sourceTextLength: sourceText.length, hasProfileContext: !!profileContext });\n\n const agentTimingsAccum: DebugMetaAgent[] = [];\n\n try {\n const _traceEmitterLens = requestContext.getStore()?.traceEmitter;\n const inferrerStart = Date.now();\n _traceEmitterLens?.({ type: \"agent_start\", name: \"lens-inferrer\" });\n const result = await self.inferrer.infer({\n sourceText,\n profileContext,\n maxLenses,\n });\n agentTimingsAccum.push({ name: 'lens.inferrer', durationMs: Date.now() - inferrerStart });\n _traceEmitterLens?.({ type: \"agent_end\", name: \"lens-inferrer\", durationMs: Date.now() - inferrerStart, summary: result.lenses.length > 0 ? `Inferred ${result.lenses.length} lens(es)` : \"lens-inferrer completed\" });\n\n logger.verbose('Lenses inferred', {\n count: result.lenses.length,\n lenses: result.lenses.map(l => ({ label: l.label, corpus: l.corpus })),\n });\n\n return { lenses: result.lenses, agentTimings: agentTimingsAccum };\n } catch (error) {\n logger.error('Lens inference failed in graph node', { error });\n return { lenses: [], agentTimings: agentTimingsAccum };\n }\n });\n };\n\n /** Node 2: Check cache/DB for existing HyDE docs matching inferred lenses. */\n const checkCacheNode = async (state: typeof HydeGraphState.State) => {\n return timed(\"HydeGraph.checkCache\", async () => {\n const { sourceType, sourceId, sourceText, lenses, forceRegenerate } = state;\n\n if (forceRegenerate) {\n logger.verbose('Force regenerate - skipping cache');\n return { hydeDocuments: {} };\n }\n\n const cached: Record<string, HydeDocumentState> = {};\n\n for (const lens of lenses) {\n const key = cacheKey(sourceType, sourceId ?? undefined, sourceText, lens.label, lens.corpus);\n\n const fromCache = await self.cache.get<HydeDocumentState>(key);\n if (fromCache?.hydeText && fromCache.hydeEmbedding?.length) {\n logger.verbose('Cache hit', { lens: lens.label });\n cached[lens.label] = fromCache;\n continue;\n }\n\n // For entity sources, check DB for persisted docs\n if (sourceId) {\n const fromDb = await self.database.getHydeDocument(\n sourceType,\n sourceId,\n lensHash(lens.label, lens.corpus),\n );\n if (fromDb) {\n logger.verbose('DB hit', { lens: lens.label });\n cached[lens.label] = {\n lens: lens.label,\n targetCorpus: fromDb.targetCorpus as 'profiles' | 'intents',\n hydeText: fromDb.hydeText,\n hydeEmbedding: fromDb.hydeEmbedding,\n };\n }\n }\n }\n\n logger.verbose('Check cache done', {\n found: Object.keys(cached).length,\n requested: lenses.length,\n });\n return { hydeDocuments: cached };\n });\n };\n\n /** Conditional: decide whether to generate or skip to embed. */\n const shouldGenerate = (state: typeof HydeGraphState.State): string => {\n const { lenses, hydeDocuments } = state;\n const missing = lenses.filter((l) => !hydeDocuments[l.label]);\n if (missing.length > 0) {\n logger.verbose('Need to generate', { missing: missing.map(l => l.label) });\n return 'generate';\n }\n logger.verbose('All lenses cached, skipping generation');\n return 'skip';\n };\n\n /** Node 3: Generate HyDE documents for lenses not in cache. */\n const generateMissingNode = async (state: typeof HydeGraphState.State) => {\n return timed(\"HydeGraph.generateMissing\", async () => {\n const { sourceText, lenses, hydeDocuments } = state;\n const missing = lenses.filter((l) => !hydeDocuments[l.label]);\n\n logger.verbose('Generating HyDE documents', {\n count: missing.length,\n lenses: missing.map(l => l.label),\n });\n\n const agentTimingsAccum: DebugMetaAgent[] = [];\n const generated: Record<string, HydeDocumentState> = {};\n\n await Promise.all(\n missing.map(async (lens) => {\n const _traceEmitterHyde = requestContext.getStore()?.traceEmitter;\n const generatorStart = Date.now();\n _traceEmitterHyde?.({ type: \"agent_start\", name: \"hyde-generator\" });\n const out = await self.generator.generate({\n sourceText,\n lens: lens.label,\n corpus: lens.corpus,\n });\n const _hydeDuration = Date.now() - generatorStart;\n agentTimingsAccum.push({ name: 'hyde.generator', durationMs: _hydeDuration });\n _traceEmitterHyde?.({ type: \"agent_end\", name: \"hyde-generator\", durationMs: _hydeDuration, summary: `Generated: ${lens.label}` });\n generated[lens.label] = {\n lens: lens.label,\n targetCorpus: lens.corpus,\n hydeText: out.text,\n hydeEmbedding: [],\n };\n })\n );\n\n return { hydeDocuments: { ...state.hydeDocuments, ...generated }, agentTimings: agentTimingsAccum };\n });\n };\n\n /** Node 4: Embed all HyDE documents that don't have embeddings yet. */\n const embedNode = async (state: typeof HydeGraphState.State) => {\n return timed(\"HydeGraph.embed\", async () => {\n const { hydeDocuments } = state;\n const lensLabels = Object.keys(hydeDocuments);\n const toEmbed: { label: string; doc: HydeDocumentState }[] = [];\n const updated: Record<string, HydeDocumentState> = {};\n const hydeEmbeddings: Record<string, number[]> = {};\n\n for (const label of lensLabels) {\n const doc = hydeDocuments[label];\n if (!doc) continue;\n if (doc.hydeEmbedding?.length) {\n updated[label] = doc;\n hydeEmbeddings[label] = doc.hydeEmbedding;\n } else {\n toEmbed.push({ label, doc });\n }\n }\n\n if (toEmbed.length > 0) {\n logger.verbose('Embedding documents', { count: toEmbed.length });\n const texts = toEmbed.map((t) => t.doc.hydeText);\n const embeddings = await self.embedder.generate(texts, undefined, getAbortSignalConfig());\n const embeddingArray = Array.isArray(embeddings[0])\n ? (embeddings as number[][])\n : [embeddings as number[]];\n\n for (let i = 0; i < toEmbed.length; i++) {\n const { label, doc } = toEmbed[i];\n const embedding = embeddingArray[i] ?? [];\n updated[label] = { ...doc, hydeEmbedding: embedding };\n hydeEmbeddings[label] = embedding;\n }\n }\n\n return { hydeDocuments: updated, hydeEmbeddings };\n });\n };\n\n /** Node 5: Cache results in Redis; persist to DB for entity sources. */\n const cacheResultsNode = async (state: typeof HydeGraphState.State) => {\n return timed(\"HydeGraph.cacheResults\", async () => {\n const { sourceType, sourceId, sourceText, hydeDocuments } = state;\n\n for (const label of Object.keys(hydeDocuments)) {\n const doc = hydeDocuments[label];\n if (!doc) continue;\n\n const key = cacheKey(sourceType, sourceId ?? undefined, sourceText, label, doc.targetCorpus);\n await self.cache.set(key, doc, { ttl: HYDE_DEFAULT_CACHE_TTL });\n\n // Persist to DB for entity sources (intent/profile)\n if (sourceId) {\n await self.database.saveHydeDocument({\n sourceType,\n sourceId,\n strategy: lensHash(label, doc.targetCorpus),\n targetCorpus: doc.targetCorpus,\n hydeText: doc.hydeText,\n hydeEmbedding: doc.hydeEmbedding,\n });\n }\n }\n\n logger.verbose('Cached results', {\n count: Object.keys(hydeDocuments).length,\n });\n return {};\n });\n };\n\n const workflow = new StateGraph(HydeGraphState)\n .addNode('infer_lenses', inferLensesNode)\n .addNode('check_cache', checkCacheNode)\n .addNode('generate_missing', generateMissingNode)\n .addNode('embed', embedNode)\n .addNode('cache_results', cacheResultsNode)\n .addEdge(START, 'infer_lenses')\n .addEdge('infer_lenses', 'check_cache')\n .addConditionalEdges('check_cache', shouldGenerate, {\n generate: 'generate_missing',\n skip: 'embed',\n })\n .addEdge('generate_missing', 'embed')\n .addEdge('embed', 'cache_results')\n .addEdge('cache_results', END);\n\n return workflow.compile();\n }\n}\n"]}
1
+ {"version":3,"file":"hyde.graph.js","sourceRoot":"/","sources":["shared/hyde/hyde.graph.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * HyDE Graph: cache-aware hypothetical document generation with lens inference.\n *\n * Flow: infer_lenses → check_cache → (generate_missing if needed) → embed → cache_results.\n * Constructor injects Database, Embedder, Cache, LensInferrer, HydeGenerator.\n */\n\nimport { StateGraph, START, END } from '@langchain/langgraph';\nimport { createHash } from 'crypto';\n\nimport { getAbortSignalConfig } from '../agent/model-signal.js';\nimport { HydeGraphState, type HydeDocumentState } from './hyde.state.js';\nimport { LensInferrer } from './lens.inferrer.js';\nimport { HydeGenerator } from './hyde.generator.js';\nimport type { HydeGraphDatabase } from '../interfaces/database.interface.js';\nimport type { EmbeddingGenerator } from '../interfaces/embedder.interface.js';\nimport type { HydeCache } from '../interfaces/cache.interface.js';\nimport { HYDE_DEFAULT_CACHE_TTL } from './hyde.strategies.js';\nimport { protocolLogger } from '../observability/protocol.logger.js';\nimport { timed } from '../observability/performance.js';\nimport { requestContext } from \"../observability/request-context.js\";\nimport type { DebugMetaAgent } from '../../chat/chat-streaming.types.js';\n\nconst logger = protocolLogger(\"HyDEGraphFactory\");\n\n/** Hash a lens label (+ optional corpus) to a short key for cache/DB indexing. */\nfunction lensHash(label: string, corpus?: string): string {\n const input = corpus\n ? `${label.toLowerCase().trim()}:${corpus}`\n : label.toLowerCase().trim();\n return createHash('sha256').update(input).digest('hex').slice(0, 16);\n}\n\n/** Build cache key for a specific lens. */\nfunction cacheKey(\n sourceType: string,\n sourceId: string | undefined,\n sourceText: string,\n lens: string,\n corpus?: string,\n): string {\n const entityKey =\n sourceId ?? `q:${createHash('sha256').update(sourceText).digest('hex').slice(0, 16)}`;\n return `hyde:${sourceType}:${entityKey}:${lensHash(lens, corpus)}`;\n}\n\n/**\n * Factory for the HyDE generation graph.\n * Injects Database, Embedder, Cache, LensInferrer, and HydeGenerator.\n */\nexport class HydeGraphFactory {\n constructor(\n private database: HydeGraphDatabase,\n private embedder: EmbeddingGenerator,\n private cache: HydeCache,\n private inferrer: LensInferrer,\n private generator: HydeGenerator,\n ) {}\n\n createGraph() {\n const self = this;\n\n /** Node 1: Infer lenses from source text + optional profile context. */\n const inferLensesNode = async (state: typeof HydeGraphState.State) => {\n return timed(\"HydeGraph.inferLenses\", async () => {\n const { sourceText, profileContext, maxLenses } = state;\n\n logger.verbose('Inferring lenses', { sourceTextLength: sourceText.length, hasProfileContext: !!profileContext });\n\n const agentTimingsAccum: DebugMetaAgent[] = [];\n\n try {\n const _traceEmitterLens = requestContext.getStore()?.traceEmitter;\n const inferrerStart = Date.now();\n _traceEmitterLens?.({ type: \"agent_start\", name: \"lens-inferrer\" });\n const result = await self.inferrer.infer({\n sourceText,\n profileContext,\n maxLenses,\n });\n const _inferrerDuration = Date.now() - inferrerStart;\n agentTimingsAccum.push({ name: 'lens.inferrer', durationMs: _inferrerDuration });\n _traceEmitterLens?.({ type: \"agent_end\", name: \"lens-inferrer\", durationMs: _inferrerDuration, summary: result.lenses.length > 0 ? `Inferred ${result.lenses.length} lens(es)` : \"lens-inferrer completed\" });\n\n logger.verbose('Lenses inferred', {\n count: result.lenses.length,\n lenses: result.lenses.map(l => ({ label: l.label, corpus: l.corpus })),\n });\n\n return { lenses: result.lenses, agentTimings: agentTimingsAccum };\n } catch (error) {\n logger.error('Lens inference failed in graph node', { error });\n return { lenses: [], agentTimings: agentTimingsAccum };\n }\n });\n };\n\n /** Node 2: Check cache/DB for existing HyDE docs matching inferred lenses. */\n const checkCacheNode = async (state: typeof HydeGraphState.State) => {\n return timed(\"HydeGraph.checkCache\", async () => {\n const { sourceType, sourceId, sourceText, lenses, forceRegenerate } = state;\n\n if (forceRegenerate) {\n logger.verbose('Force regenerate - skipping cache');\n return { hydeDocuments: {} };\n }\n\n const cached: Record<string, HydeDocumentState> = {};\n\n for (const lens of lenses) {\n const key = cacheKey(sourceType, sourceId ?? undefined, sourceText, lens.label, lens.corpus);\n\n const fromCache = await self.cache.get<HydeDocumentState>(key);\n if (fromCache?.hydeText && fromCache.hydeEmbedding?.length) {\n logger.verbose('Cache hit', { lens: lens.label });\n cached[lens.label] = fromCache;\n continue;\n }\n\n // For entity sources, check DB for persisted docs\n if (sourceId) {\n const fromDb = await self.database.getHydeDocument(\n sourceType,\n sourceId,\n lensHash(lens.label, lens.corpus),\n );\n if (fromDb) {\n logger.verbose('DB hit', { lens: lens.label });\n cached[lens.label] = {\n lens: lens.label,\n targetCorpus: fromDb.targetCorpus as 'profiles' | 'intents',\n hydeText: fromDb.hydeText,\n hydeEmbedding: fromDb.hydeEmbedding,\n };\n }\n }\n }\n\n logger.verbose('Check cache done', {\n found: Object.keys(cached).length,\n requested: lenses.length,\n });\n return { hydeDocuments: cached };\n });\n };\n\n /** Conditional: decide whether to generate or skip to embed. */\n const shouldGenerate = (state: typeof HydeGraphState.State): string => {\n const { lenses, hydeDocuments } = state;\n const missing = lenses.filter((l) => !hydeDocuments[l.label]);\n if (missing.length > 0) {\n logger.verbose('Need to generate', { missing: missing.map(l => l.label) });\n return 'generate';\n }\n logger.verbose('All lenses cached, skipping generation');\n return 'skip';\n };\n\n /** Node 3: Generate HyDE documents for lenses not in cache. */\n const generateMissingNode = async (state: typeof HydeGraphState.State) => {\n return timed(\"HydeGraph.generateMissing\", async () => {\n const { sourceText, lenses, hydeDocuments } = state;\n const missing = lenses.filter((l) => !hydeDocuments[l.label]);\n\n logger.verbose('Generating HyDE documents', {\n count: missing.length,\n lenses: missing.map(l => l.label),\n });\n\n const agentTimingsAccum: DebugMetaAgent[] = [];\n const generated: Record<string, HydeDocumentState> = {};\n\n await Promise.all(\n missing.map(async (lens) => {\n const _traceEmitterHyde = requestContext.getStore()?.traceEmitter;\n const generatorStart = Date.now();\n _traceEmitterHyde?.({ type: \"agent_start\", name: \"hyde-generator\" });\n const out = await self.generator.generate({\n sourceText,\n lens: lens.label,\n corpus: lens.corpus,\n });\n const _hydeDuration = Date.now() - generatorStart;\n agentTimingsAccum.push({ name: 'hyde.generator', durationMs: _hydeDuration });\n _traceEmitterHyde?.({ type: \"agent_end\", name: \"hyde-generator\", durationMs: _hydeDuration, summary: `Generated: ${lens.label}` });\n generated[lens.label] = {\n lens: lens.label,\n targetCorpus: lens.corpus,\n hydeText: out.text,\n hydeEmbedding: [],\n };\n })\n );\n\n return { hydeDocuments: { ...state.hydeDocuments, ...generated }, agentTimings: agentTimingsAccum };\n });\n };\n\n /** Node 4: Embed all HyDE documents that don't have embeddings yet. */\n const embedNode = async (state: typeof HydeGraphState.State) => {\n return timed(\"HydeGraph.embed\", async () => {\n const { hydeDocuments } = state;\n const lensLabels = Object.keys(hydeDocuments);\n const toEmbed: { label: string; doc: HydeDocumentState }[] = [];\n const updated: Record<string, HydeDocumentState> = {};\n const hydeEmbeddings: Record<string, number[]> = {};\n\n for (const label of lensLabels) {\n const doc = hydeDocuments[label];\n if (!doc) continue;\n if (doc.hydeEmbedding?.length) {\n updated[label] = doc;\n hydeEmbeddings[label] = doc.hydeEmbedding;\n } else {\n toEmbed.push({ label, doc });\n }\n }\n\n if (toEmbed.length > 0) {\n logger.verbose('Embedding documents', { count: toEmbed.length });\n const texts = toEmbed.map((t) => t.doc.hydeText);\n const embeddings = await self.embedder.generate(texts, undefined, getAbortSignalConfig());\n const embeddingArray = Array.isArray(embeddings[0])\n ? (embeddings as number[][])\n : [embeddings as number[]];\n\n for (let i = 0; i < toEmbed.length; i++) {\n const { label, doc } = toEmbed[i];\n const embedding = embeddingArray[i] ?? [];\n updated[label] = { ...doc, hydeEmbedding: embedding };\n hydeEmbeddings[label] = embedding;\n }\n }\n\n return { hydeDocuments: updated, hydeEmbeddings };\n });\n };\n\n /** Node 5: Cache results in Redis; persist to DB for entity sources. */\n const cacheResultsNode = async (state: typeof HydeGraphState.State) => {\n return timed(\"HydeGraph.cacheResults\", async () => {\n const { sourceType, sourceId, sourceText, hydeDocuments } = state;\n\n for (const label of Object.keys(hydeDocuments)) {\n const doc = hydeDocuments[label];\n if (!doc) continue;\n\n const key = cacheKey(sourceType, sourceId ?? undefined, sourceText, label, doc.targetCorpus);\n await self.cache.set(key, doc, { ttl: HYDE_DEFAULT_CACHE_TTL });\n\n // Persist to DB for entity sources (intent/profile)\n if (sourceId) {\n await self.database.saveHydeDocument({\n sourceType,\n sourceId,\n strategy: lensHash(label, doc.targetCorpus),\n targetCorpus: doc.targetCorpus,\n hydeText: doc.hydeText,\n hydeEmbedding: doc.hydeEmbedding,\n });\n }\n }\n\n logger.verbose('Cached results', {\n count: Object.keys(hydeDocuments).length,\n });\n return {};\n });\n };\n\n const workflow = new StateGraph(HydeGraphState)\n .addNode('infer_lenses', inferLensesNode)\n .addNode('check_cache', checkCacheNode)\n .addNode('generate_missing', generateMissingNode)\n .addNode('embed', embedNode)\n .addNode('cache_results', cacheResultsNode)\n .addEdge(START, 'infer_lenses')\n .addEdge('infer_lenses', 'check_cache')\n .addConditionalEdges('check_cache', shouldGenerate, {\n generate: 'generate_missing',\n skip: 'embed',\n })\n .addEdge('generate_missing', 'embed')\n .addEdge('embed', 'cache_results')\n .addEdge('cache_results', END);\n\n return workflow.compile();\n }\n}\n"]}
@@ -6,6 +6,7 @@
6
6
  * infers free-text "lenses" dynamically. This file re-exports the lens
7
7
  * types and provides constants for the HyDE pipeline.
8
8
  */
9
+ import type { HydeTargetCorpus } from './lens.inferrer.js';
9
10
  export type { Lens, HydeTargetCorpus, LensInferenceInput, LensInferenceOutput } from './lens.inferrer.js';
10
11
  /** Default cache TTL for ephemeral HyDE documents (1 hour). */
11
12
  export declare const HYDE_DEFAULT_CACHE_TTL = 3600;
@@ -13,5 +14,5 @@ export declare const HYDE_DEFAULT_CACHE_TTL = 3600;
13
14
  * Prompt templates for HyDE document generation.
14
15
  * Keyed by target corpus — the lens label provides the semantic specificity.
15
16
  */
16
- export declare const HYDE_CORPUS_PROMPTS: Record<'profiles' | 'intents' | 'premises', (sourceText: string, lens: string) => string>;
17
+ export declare const HYDE_CORPUS_PROMPTS: Record<HydeTargetCorpus, (sourceText: string, lens: string) => string>;
17
18
  //# sourceMappingURL=hyde.strategies.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"hyde.strategies.d.ts","sourceRoot":"/","sources":["shared/hyde/hyde.strategies.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,YAAY,EAAE,IAAI,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAE1G,+DAA+D;AAC/D,eAAO,MAAM,sBAAsB,OAAO,CAAC;AAE3C;;;GAGG;AACH,eAAO,MAAM,mBAAmB,EAAE,MAAM,CAAC,UAAU,GAAG,SAAS,GAAG,UAAU,EAAE,CAAC,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,KAAK,MAAM,CAmBzH,CAAC"}
1
+ {"version":3,"file":"hyde.strategies.d.ts","sourceRoot":"/","sources":["shared/hyde/hyde.strategies.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAE3D,YAAY,EAAE,IAAI,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAE1G,+DAA+D;AAC/D,eAAO,MAAM,sBAAsB,OAAO,CAAC;AAE3C;;;GAGG;AACH,eAAO,MAAM,mBAAmB,EAAE,MAAM,CAAC,gBAAgB,EAAE,CAAC,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,KAAK,MAAM,CAmBtG,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"hyde.strategies.js","sourceRoot":"/","sources":["shared/hyde/hyde.strategies.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAIH,+DAA+D;AAC/D,MAAM,CAAC,MAAM,sBAAsB,GAAG,IAAI,CAAC;AAE3C;;;GAGG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAA8F;IAC5H,QAAQ,EAAE,CAAC,UAAU,EAAE,IAAI,EAAE,EAAE,CAAC;+EAC6C,UAAU;0EACf,IAAI;;;GAG3E;IACD,OAAO,EAAE,CAAC,UAAU,EAAE,IAAI,EAAE,EAAE,CAAC;+DAC8B,IAAI;6CACtB,UAAU;;;GAGpD;IACD,QAAQ,EAAE,CAAC,UAAU,EAAE,IAAI,EAAE,EAAE,CAAC;oGACkE,UAAU;0CACpE,IAAI;;;GAG3C;CACF,CAAC","sourcesContent":["/**\n * HyDE (Hypothetical Document Embeddings) type definitions.\n *\n * The system is now role-agnostic: instead of hardcoded strategy names\n * (mirror, reciprocal, mentor, investor, collaborator, hiree), an LLM\n * infers free-text \"lenses\" dynamically. This file re-exports the lens\n * types and provides constants for the HyDE pipeline.\n */\n\nexport type { Lens, HydeTargetCorpus, LensInferenceInput, LensInferenceOutput } from './lens.inferrer.js';\n\n/** Default cache TTL for ephemeral HyDE documents (1 hour). */\nexport const HYDE_DEFAULT_CACHE_TTL = 3600;\n\n/**\n * Prompt templates for HyDE document generation.\n * Keyed by target corpus — the lens label provides the semantic specificity.\n */\nexport const HYDE_CORPUS_PROMPTS: Record<'profiles' | 'intents' | 'premises', (sourceText: string, lens: string) => string> = {\n profiles: (sourceText, lens) => `\n Write a professional biography for someone who could fulfill this need: \"${sourceText}\".\n Focus on the specific expertise, background, and role described by: ${lens}.\n\n Write in first person. Include concrete skills, domain experience, and current professional focus that would make them a strong match.\n `,\n intents: (sourceText, lens) => `\n Write a goal or aspiration statement for someone who is: ${lens}.\n This person's needs would complement: \"${sourceText}\".\n\n Write in first person as if stating their own goal.\n `,\n premises: (sourceText, lens) => `\n Write a short self-description for someone whose identity, values, or worldview aligns with: \"${sourceText}\".\n Reflect the character described by: ${lens}.\n\n Write in first person as a stable statement of who this person is, not what they want.\n `,\n};\n"]}
1
+ {"version":3,"file":"hyde.strategies.js","sourceRoot":"/","sources":["shared/hyde/hyde.strategies.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAMH,+DAA+D;AAC/D,MAAM,CAAC,MAAM,sBAAsB,GAAG,IAAI,CAAC;AAE3C;;;GAGG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAA2E;IACzG,QAAQ,EAAE,CAAC,UAAU,EAAE,IAAI,EAAE,EAAE,CAAC;+EAC6C,UAAU;0EACf,IAAI;;;GAG3E;IACD,OAAO,EAAE,CAAC,UAAU,EAAE,IAAI,EAAE,EAAE,CAAC;+DAC8B,IAAI;6CACtB,UAAU;;;GAGpD;IACD,QAAQ,EAAE,CAAC,UAAU,EAAE,IAAI,EAAE,EAAE,CAAC;oGACkE,UAAU;0CACpE,IAAI;;;GAG3C;CACF,CAAC","sourcesContent":["/**\n * HyDE (Hypothetical Document Embeddings) type definitions.\n *\n * The system is now role-agnostic: instead of hardcoded strategy names\n * (mirror, reciprocal, mentor, investor, collaborator, hiree), an LLM\n * infers free-text \"lenses\" dynamically. This file re-exports the lens\n * types and provides constants for the HyDE pipeline.\n */\n\nimport type { HydeTargetCorpus } from './lens.inferrer.js';\n\nexport type { Lens, HydeTargetCorpus, LensInferenceInput, LensInferenceOutput } from './lens.inferrer.js';\n\n/** Default cache TTL for ephemeral HyDE documents (1 hour). */\nexport const HYDE_DEFAULT_CACHE_TTL = 3600;\n\n/**\n * Prompt templates for HyDE document generation.\n * Keyed by target corpus — the lens label provides the semantic specificity.\n */\nexport const HYDE_CORPUS_PROMPTS: Record<HydeTargetCorpus, (sourceText: string, lens: string) => string> = {\n profiles: (sourceText, lens) => `\n Write a professional biography for someone who could fulfill this need: \"${sourceText}\".\n Focus on the specific expertise, background, and role described by: ${lens}.\n\n Write in first person. Include concrete skills, domain experience, and current professional focus that would make them a strong match.\n `,\n intents: (sourceText, lens) => `\n Write a goal or aspiration statement for someone who is: ${lens}.\n This person's needs would complement: \"${sourceText}\".\n\n Write in first person as if stating their own goal.\n `,\n premises: (sourceText, lens) => `\n Write a short self-description for someone whose identity, values, or worldview aligns with: \"${sourceText}\".\n Reflect the character described by: ${lens}.\n\n Write in first person as a stable statement of who this person is, not what they want.\n `,\n};\n"]}
@@ -34,7 +34,7 @@ export declare function traceAgent<T>(name: string, fn: () => Promise<T>, summar
34
34
  * async run() { ... }
35
35
  * }
36
36
  */
37
- export declare function TraceGraph(name: string): (target: any, propertyKey: string, descriptor: PropertyDescriptor) => void;
37
+ export declare const TraceGraph: (name: string) => (target: any, propertyKey: string, descriptor: PropertyDescriptor) => void;
38
38
  /**
39
39
  * Method decorator. Wraps the decorated async method in `traceAgent(name, ...)`.
40
40
  * Use on class methods that represent a single agent step (one LLM call,
@@ -46,7 +46,7 @@ export declare function TraceGraph(name: string): (target: any, propertyKey: str
46
46
  * async run() { ... }
47
47
  * }
48
48
  */
49
- export declare function TraceAgent(name: string): (target: any, propertyKey: string, descriptor: PropertyDescriptor) => void;
49
+ export declare const TraceAgent: (name: string) => (target: any, propertyKey: string, descriptor: PropertyDescriptor) => void;
50
50
  /**
51
51
  * Method decorator. Wraps the decorated async method in `tracePhase(name, ...)`.
52
52
  * Use for logical groupings of inline work that aren't LangGraph state machines.
@@ -57,5 +57,5 @@ export declare function TraceAgent(name: string): (target: any, propertyKey: str
57
57
  * async run() { ... }
58
58
  * }
59
59
  */
60
- export declare function TracePhase(name: string): (target: any, propertyKey: string, descriptor: PropertyDescriptor) => void;
60
+ export declare const TracePhase: (name: string) => (target: any, propertyKey: string, descriptor: PropertyDescriptor) => void;
61
61
  //# sourceMappingURL=trace.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"trace.d.ts","sourceRoot":"/","sources":["shared/observability/trace.ts"],"names":[],"mappings":"AAuBA;;;;;;;;;GASG;AACH,wBAAsB,UAAU,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CASlF;AAED;;;;;;GAMG;AACH,wBAAsB,UAAU,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CASlF;AAED;;;;GAIG;AACH,wBAAsB,UAAU,CAAC,CAAC,EAChC,IAAI,EAAE,MAAM,EACZ,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,EACpB,SAAS,CAAC,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,MAAM,GAAG,SAAS,GAC3C,OAAO,CAAC,CAAC,CAAC,CAeZ;AAED;;;;;;;;;;GAUG;AAEH,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,CAAC,MAAM,EAAE,GAAG,EAAE,WAAW,EAAE,MAAM,EAAE,UAAU,EAAE,kBAAkB,KAAK,IAAI,CASnH;AAED;;;;;;;;;;GAUG;AAEH,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,CAAC,MAAM,EAAE,GAAG,EAAE,WAAW,EAAE,MAAM,EAAE,UAAU,EAAE,kBAAkB,KAAK,IAAI,CASnH;AAED;;;;;;;;;GASG;AAEH,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,CAAC,MAAM,EAAE,GAAG,EAAE,WAAW,EAAE,MAAM,EAAE,UAAU,EAAE,kBAAkB,KAAK,IAAI,CASnH"}
1
+ {"version":3,"file":"trace.d.ts","sourceRoot":"/","sources":["shared/observability/trace.ts"],"names":[],"mappings":"AAuBA;;;;;;;;;GASG;AACH,wBAAsB,UAAU,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CASlF;AAED;;;;;;GAMG;AACH,wBAAsB,UAAU,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CASlF;AAED;;;;GAIG;AACH,wBAAsB,UAAU,CAAC,CAAC,EAChC,IAAI,EAAE,MAAM,EACZ,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,EACpB,SAAS,CAAC,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,MAAM,GAAG,SAAS,GAC3C,OAAO,CAAC,CAAC,CAAC,CAeZ;AAsBD;;;;;;;;;;GAUG;AACH,eAAO,MAAM,UAAU,SAvBb,MAAM,KAAK,CAAC,MAAM,EAAE,GAAG,EAAE,WAAW,EAAE,MAAM,EAAE,UAAU,EAAE,kBAAkB,KAAK,IAuBvC,CAAC;AAErD;;;;;;;;;;GAUG;AACH,eAAO,MAAM,UAAU,SApCb,MAAM,KAAK,CAAC,MAAM,EAAE,GAAG,EAAE,WAAW,EAAE,MAAM,EAAE,UAAU,EAAE,kBAAkB,KAAK,IAoCvC,CAAC;AAErD;;;;;;;;;GASG;AACH,eAAO,MAAM,UAAU,SAhDb,MAAM,KAAK,CAAC,MAAM,EAAE,GAAG,EAAE,WAAW,EAAE,MAAM,EAAE,UAAU,EAAE,kBAAkB,KAAK,IAgDvC,CAAC"}