@indexnetwork/protocol 6.6.4-rc.390.1 → 6.7.0-rc.392.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 (37) hide show
  1. package/CHANGELOG.md +2 -0
  2. package/IMPLEMENTATION.md +5 -1
  3. package/dist/chat/negotiator.prompt.d.ts.map +1 -1
  4. package/dist/chat/negotiator.prompt.js +5 -2
  5. package/dist/chat/negotiator.prompt.js.map +1 -1
  6. package/dist/chat/onboarding.persona.d.ts +30 -0
  7. package/dist/chat/onboarding.persona.d.ts.map +1 -0
  8. package/dist/chat/onboarding.persona.js +102 -0
  9. package/dist/chat/onboarding.persona.js.map +1 -0
  10. package/dist/chat/onboarding.prompt.d.ts +7 -0
  11. package/dist/chat/onboarding.prompt.d.ts.map +1 -0
  12. package/dist/chat/onboarding.prompt.js +74 -0
  13. package/dist/chat/onboarding.prompt.js.map +1 -0
  14. package/dist/chat/signal.persona.d.ts +1 -1
  15. package/dist/chat/signal.persona.d.ts.map +1 -1
  16. package/dist/chat/signal.persona.js.map +1 -1
  17. package/dist/chat/signal.prompt.d.ts +2 -2
  18. package/dist/chat/signal.prompt.d.ts.map +1 -1
  19. package/dist/chat/signal.prompt.js +2 -2
  20. package/dist/chat/signal.prompt.js.map +1 -1
  21. package/dist/enrichment/enrichment.tools.d.ts.map +1 -1
  22. package/dist/enrichment/enrichment.tools.js +63 -17
  23. package/dist/enrichment/enrichment.tools.js.map +1 -1
  24. package/dist/index.d.ts +2 -1
  25. package/dist/index.d.ts.map +1 -1
  26. package/dist/index.js +1 -0
  27. package/dist/index.js.map +1 -1
  28. package/dist/mcp/mcp.server.d.ts.map +1 -1
  29. package/dist/mcp/mcp.server.js +4 -2
  30. package/dist/mcp/mcp.server.js.map +1 -1
  31. package/dist/negotiation/negotiation.tools.d.ts.map +1 -1
  32. package/dist/negotiation/negotiation.tools.js +125 -9
  33. package/dist/negotiation/negotiation.tools.js.map +1 -1
  34. package/dist/shared/interfaces/database.interface.d.ts +19 -1
  35. package/dist/shared/interfaces/database.interface.d.ts.map +1 -1
  36. package/dist/shared/interfaces/database.interface.js.map +1 -1
  37. package/package.json +1 -1
@@ -35,6 +35,105 @@ function readTaskNetworkId(meta) {
35
35
  return null;
36
36
  }
37
37
  const SCOPE_DENIAL = 'Access denied: this negotiation is not in your bound network scope.';
38
+ const DIRECT_CONVERSATION_EVIDENCE_UNAVAILABLE = 'not_provided';
39
+ /**
40
+ * Builds additive, lifecycle-explicit narration metadata. Task completion only
41
+ * means the agents concluded; it never establishes owner acceptance or an H2H
42
+ * conversation.
43
+ */
44
+ function buildLifecycleNarration(negotiationStatus, opportunity) {
45
+ const agentNegotiation = negotiationStatus === 'completed'
46
+ ? 'concluded'
47
+ : negotiationStatus === 'active'
48
+ ? 'in_progress'
49
+ : negotiationStatus === 'waiting_for_agent'
50
+ ? 'awaiting_agent'
51
+ : 'unknown';
52
+ const common = {
53
+ agentNegotiation,
54
+ opportunityStatus: opportunity?.status ?? null,
55
+ ownerAction: opportunity?.acceptedByOwner ? 'accepted' : 'not_recorded',
56
+ directConversationEvidence: DIRECT_CONVERSATION_EVIDENCE_UNAVAILABLE,
57
+ };
58
+ switch (opportunity?.status) {
59
+ case 'pending':
60
+ return {
61
+ ...common,
62
+ connectionState: 'potential_match_awaiting_owner_review',
63
+ lifecycleLabel: negotiationStatus === 'completed'
64
+ ? "Agents concluded with a potential match; awaiting the owner's review."
65
+ : "A potential match is awaiting the owner's review.",
66
+ };
67
+ case 'accepted':
68
+ return opportunity.acceptedByOwner
69
+ ? {
70
+ ...common,
71
+ connectionState: 'owner_accepted',
72
+ lifecycleLabel: 'The owner explicitly accepted this opportunity.',
73
+ }
74
+ : {
75
+ ...common,
76
+ connectionState: 'accepted_without_owner_evidence',
77
+ lifecycleLabel: 'The opportunity is accepted; this result does not record an owner acceptance.',
78
+ };
79
+ case 'rejected':
80
+ return {
81
+ ...common,
82
+ connectionState: 'rejected',
83
+ lifecycleLabel: 'The opportunity was rejected; no connection was established.',
84
+ };
85
+ case 'stalled':
86
+ return {
87
+ ...common,
88
+ connectionState: 'negotiation_stalled',
89
+ lifecycleLabel: 'The agent negotiation stalled; no connection was established.',
90
+ };
91
+ case 'draft':
92
+ return {
93
+ ...common,
94
+ connectionState: 'draft_not_sent',
95
+ lifecycleLabel: 'The opportunity is still a draft; it has not been sent or accepted.',
96
+ };
97
+ case 'expired':
98
+ return {
99
+ ...common,
100
+ connectionState: 'expired',
101
+ lifecycleLabel: 'The opportunity expired; no connection was established.',
102
+ };
103
+ case 'negotiating':
104
+ return {
105
+ ...common,
106
+ connectionState: 'agents_negotiating',
107
+ lifecycleLabel: 'The agents are still negotiating; no owner decision is recorded.',
108
+ };
109
+ case 'latent':
110
+ return {
111
+ ...common,
112
+ connectionState: 'latent',
113
+ lifecycleLabel: 'The potential match is latent; no owner decision is recorded.',
114
+ };
115
+ default:
116
+ return {
117
+ ...common,
118
+ connectionState: 'unknown',
119
+ lifecycleLabel: negotiationStatus === 'completed'
120
+ ? 'The agent negotiation concluded; the current opportunity lifecycle is unavailable.'
121
+ : 'The current opportunity lifecycle is unavailable.',
122
+ };
123
+ }
124
+ }
125
+ /** Reads lifecycle evidence without making older host adapters mandatory. */
126
+ async function readOpportunityLifecycles(database, opportunityIds, ownerUserId) {
127
+ if (opportunityIds.length === 0 || !database.getOpportunityLifecyclesForNegotiations)
128
+ return {};
129
+ try {
130
+ return await database.getOpportunityLifecyclesForNegotiations(opportunityIds, ownerUserId);
131
+ }
132
+ catch (err) {
133
+ logger.warn('Failed to load opportunity lifecycle for negotiation narration', { err });
134
+ return {};
135
+ }
136
+ }
38
137
  /** Extracts the ordered NegotiationTurn list from A2A message data parts. */
39
138
  function turnsFromMessages(messages) {
40
139
  return messages
@@ -58,7 +157,10 @@ export function createNegotiationTools(defineTool, deps) {
58
157
  '**Statuses:**\n' +
59
158
  '- `active` — Negotiation is in progress, agents are exchanging turns.\n' +
60
159
  '- `waiting_for_agent` — The graph has yielded and is waiting for an agent response (e.g. from the user via respond_to_negotiation) or a timeout.\n' +
61
- '- `completed` — Negotiation has concluded (accepted, rejected, or reached turn cap).\n\n' +
160
+ '- `completed` — The agent negotiation has concluded (agent-side accept/reject, or turn cap). This is not a completed connection or an owner decision.\n\n' +
161
+ '**Lifecycle narration:** Every result includes additive `lifecycle` fields that distinguish the agent-negotiation state, ' +
162
+ 'current opportunity status, and persisted owner acceptance. Agent-side `accept` means only that agents found a potential match; ' +
163
+ '`pending` still awaits owner review. `directConversationEvidence` is `not_provided`, so this tool never establishes that an H2H message thread exists.\n\n' +
62
164
  '**When to use:** To see ongoing and past negotiations, check which negotiations need attention, ' +
63
165
  'or find a negotiation ID for get_negotiation or respond_to_negotiation.',
64
166
  querySchema: z.object({
@@ -90,6 +192,11 @@ export function createNegotiationTools(defineTool, deps) {
90
192
  : stateFilter === 'completed' ? 'completed'
91
193
  : undefined;
92
194
  const tasks = await negotiationDatabase.getTasksForUser(context.userId, dbState ? { state: dbState } : undefined);
195
+ const opportunityIds = [...new Set(tasks
196
+ .map((task) => task.metadata?.opportunityId)
197
+ .filter((opportunityId) => typeof opportunityId === 'string' && opportunityId.trim().length > 0)
198
+ .map((opportunityId) => opportunityId.trim()))];
199
+ const opportunityLifecycles = await readOpportunityLifecycles(negotiationDatabase, opportunityIds, context.userId);
93
200
  const scopedNetworkId = focusedNetworkId(context);
94
201
  const pinnedIntentId = focusedIntentId(context);
95
202
  const effectiveScope = query.scope ?? (pinnedIntentId ? 'signal' : 'all');
@@ -97,9 +204,7 @@ export function createNegotiationTools(defineTool, deps) {
97
204
  return error('Signal scope requires a pinned intent.');
98
205
  }
99
206
  const signalIntentIdsByOpportunity = effectiveScope === 'signal'
100
- ? await negotiationDatabase.getIntentIdsForOpportunities([...new Set(tasks
101
- .map((task) => task.metadata?.opportunityId)
102
- .filter((opportunityId) => typeof opportunityId === 'string' && opportunityId.trim().length > 0))], context.userId)
207
+ ? await negotiationDatabase.getIntentIdsForOpportunities(opportunityIds, context.userId)
103
208
  : null;
104
209
  const scopeMetadata = effectiveScope === 'signal'
105
210
  ? { scope: 'signal', intentId: pinnedIntentId }
@@ -158,7 +263,9 @@ export function createNegotiationTools(defineTool, deps) {
158
263
  isContinuation: meta.isContinuation ?? false,
159
264
  priorTurnCount: meta.priorTurnCount ?? 0,
160
265
  latestAction: lastTurnData?.action ?? null,
266
+ latestActionActor: 'agent',
161
267
  latestMessagePreview: lastTurnData?.message ?? null,
268
+ lifecycle: buildLifecycleNarration(status, opportunityLifecycles[opportunityId]),
162
269
  createdAt: task.createdAt,
163
270
  updatedAt: task.updatedAt,
164
271
  };
@@ -178,6 +285,7 @@ export function createNegotiationTools(defineTool, deps) {
178
285
  speaker,
179
286
  role: speaker === (isSource ? 'source' : 'candidate') ? 'own' : 'other',
180
287
  action: td?.action ?? 'unknown',
288
+ actionActor: 'agent',
181
289
  message: td?.message ?? null,
182
290
  };
183
291
  });
@@ -232,9 +340,12 @@ export function createNegotiationTools(defineTool, deps) {
232
340
  'Negotiations are bilateral exchanges where two AI agents negotiate on behalf of users. Each turn contains an action ' +
233
341
  '(propose, accept, reject, counter, question), an assessment with reasoning and suggested roles, and an optional message.\n\n' +
234
342
  '**Access control:** You must be a party to the negotiation (source or candidate) to view it.\n\n' +
235
- '**Statuses:** `active` — in progress. `waiting_for_agent` — waiting for an agent response or timeout. `completed` — concluded.\n\n' +
236
- '**When to use:** To review the full negotiation history before responding, to understand why a negotiation was ' +
237
- 'accepted or rejected, or to see the current state of an active negotiation.\n\n' +
343
+ '**Statuses:** `active` — in progress. `waiting_for_agent` — waiting for an agent response or timeout. `completed` — the agents concluded, not that the owner accepted or a connection/message thread exists.\n\n' +
344
+ '**Lifecycle narration:** The additive `lifecycle` object is authoritative for user-facing wording. A turn action of `accept` is agent-side; ' +
345
+ 'only `lifecycle.ownerAction=accepted` records this owner as the human acceptor. `conversationType=agent_negotiation` identifies the returned ' +
346
+ 'conversationId as the A2A negotiation transcript; this result does not provide H2H conversation evidence.\n\n' +
347
+ '**When to use:** To review the full negotiation history before responding, to understand why the agents ' +
348
+ 'accepted or rejected a potential match, or to see the current state of an active negotiation.\n\n' +
238
349
  '**Negotiation-turn-mode usage.** If you are running as a silent background subagent (dispatched by the ' +
239
350
  "openclaw runtime's poller in response to a claimed negotiation turn), call this tool FIRST with the " +
240
351
  'negotiationId from your task prompt. This returns the current state, both parties\' context, and the ' +
@@ -286,10 +397,12 @@ export function createNegotiationTools(defineTool, deps) {
286
397
  ...(tc.discoveryQuery && { discoveryQuery: tc.discoveryQuery }),
287
398
  };
288
399
  }
289
- // Load messages and artifacts
290
- const [messages, artifacts] = await Promise.all([
400
+ const lifecycleOpportunityId = meta.opportunityId?.trim() || undefined;
401
+ // Load messages, artifacts, and the independently persisted opportunity lifecycle.
402
+ const [messages, artifacts, opportunityLifecycles] = await Promise.all([
291
403
  negotiationDatabase.getMessagesForConversation(task.conversationId),
292
404
  negotiationDatabase.getArtifactsForTask(task.id),
405
+ readOpportunityLifecycles(negotiationDatabase, lifecycleOpportunityId ? [lifecycleOpportunityId] : [], context.userId),
293
406
  ]);
294
407
  // Parse turns from messages (speaker from senderId, not parity —
295
408
  // continuations can start with either side speaking first)
@@ -305,6 +418,7 @@ export function createNegotiationTools(defineTool, deps) {
305
418
  speaker,
306
419
  senderId: m.senderId,
307
420
  action: turnData?.action ?? 'unknown',
421
+ actionActor: 'agent',
308
422
  reasoning: turnData?.assessment?.reasoning ?? null,
309
423
  suggestedRoles: turnData?.assessment?.suggestedRoles ?? null,
310
424
  message: turnData?.message ?? null,
@@ -338,6 +452,7 @@ export function createNegotiationTools(defineTool, deps) {
338
452
  return success({
339
453
  id: task.id,
340
454
  conversationId: task.conversationId,
455
+ conversationType: 'agent_negotiation',
341
456
  status,
342
457
  role: isSource ? 'source' : 'candidate',
343
458
  seat,
@@ -351,6 +466,7 @@ export function createNegotiationTools(defineTool, deps) {
351
466
  turnsAdded: turnCount - priorTurnCount,
352
467
  turns,
353
468
  outcome,
469
+ lifecycle: buildLifecycleNarration(status, lifecycleOpportunityId ? opportunityLifecycles[lifecycleOpportunityId] : undefined),
354
470
  context: negotiationContext,
355
471
  createdAt: task.createdAt,
356
472
  updatedAt: task.updatedAt,