@indexnetwork/protocol 1.26.3-rc.223.1 → 1.26.3-rc.225.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.
@@ -1 +1 @@
1
- {"version":3,"file":"profile.tools.d.ts","sourceRoot":"/","sources":["profile/profile.tools.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,UAAU,EAAuB,QAAQ,EAAE,MAAM,iCAAiC,CAAC;AAwBjG,wBAAgB,kBAAkB,CAAC,UAAU,EAAE,UAAU,EAAE,IAAI,EAAE,QAAQ,0DAynCxE"}
1
+ {"version":3,"file":"profile.tools.d.ts","sourceRoot":"/","sources":["profile/profile.tools.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,UAAU,EAAuB,QAAQ,EAAE,MAAM,iCAAiC,CAAC;AAgCjG,wBAAgB,kBAAkB,CAAC,UAAU,EAAE,UAAU,EAAE,IAAI,EAAE,QAAQ,0DAysCxE"}
@@ -15,6 +15,11 @@ function isMeaningfulEnrichment(enrichment) {
15
15
  enrichment.attributes.skills.length > 0 ||
16
16
  enrichment.attributes.interests.length > 0);
17
17
  }
18
+ const approvedProfileDraftSchema = z.object({
19
+ identity: z.object({ name: z.string(), bio: z.string(), location: z.string() }),
20
+ narrative: z.object({ context: z.string() }),
21
+ attributes: z.object({ interests: z.array(z.string()), skills: z.array(z.string()) }),
22
+ });
18
23
  export function createProfileTools(defineTool, deps) {
19
24
  const { userDb, systemDb, database, graphs, enricher, grantDefaultSystemPermissions, reportToolError } = deps;
20
25
  function trimToUndefined(value) {
@@ -182,6 +187,71 @@ export function createProfileTools(defineTool, deps) {
182
187
  interests: profile.attributes.interests,
183
188
  };
184
189
  }
190
+ function buildApprovedDraftProfileInput(draft) {
191
+ return [
192
+ draft.identity.name ? `My name is ${draft.identity.name}.` : '',
193
+ draft.identity.location ? `I am based in ${draft.identity.location}.` : '',
194
+ draft.identity.bio || '',
195
+ draft.narrative.context || '',
196
+ draft.attributes.skills.length ? `My skills include ${draft.attributes.skills.join(', ')}.` : '',
197
+ draft.attributes.interests.length ? `My interests include ${draft.attributes.interests.join(', ')}.` : '',
198
+ ].filter((part) => part.trim().length > 0).join('\n');
199
+ }
200
+ async function decomposeApprovedDraftProfile(context, profile) {
201
+ const input = buildApprovedDraftProfileInput(profile);
202
+ if (!input.trim())
203
+ return;
204
+ const traceEmitter = requestContext.getStore()?.traceEmitter;
205
+ const graphStart = Date.now();
206
+ traceEmitter?.({ type: "graph_start", name: "profile" });
207
+ try {
208
+ const graphInput = {
209
+ userId: context.userId,
210
+ operationMode: 'write',
211
+ input,
212
+ forceUpdate: true,
213
+ };
214
+ const result = context.isMcp
215
+ ? await graphs.profile.invoke(graphInput)
216
+ : await invokeWithAbortSignal(graphs.profile, graphInput);
217
+ if (result.error) {
218
+ const err = new Error(result.error);
219
+ logger.error('Approved draft premise decomposition failed', {
220
+ userId: context.userId,
221
+ error: result.error,
222
+ });
223
+ reportToolError?.(err, {
224
+ subsystem: 'profile',
225
+ operation: 'profile.confirm_draft_decompose',
226
+ toolName: 'confirm_user_profile',
227
+ userId: context.userId,
228
+ tags: { toolName: 'confirm_user_profile', execution: context.isMcp ? 'background' : 'sync' },
229
+ });
230
+ return;
231
+ }
232
+ // The write graph's decompose → aggregate → generate → save_profile
233
+ // pipeline persists the aggregate profile. The approved draft was already
234
+ // saved before decomposition started, so the DB is consistent regardless
235
+ // of graph outcome. Do not re-save here — the graph's save_profile is
236
+ // authoritative, and a concurrent user-driven profile update could race.
237
+ }
238
+ catch (err) {
239
+ logger.error('Approved draft premise decomposition failed', {
240
+ userId: context.userId,
241
+ error: err instanceof Error ? err.message : String(err),
242
+ });
243
+ reportToolError?.(err, {
244
+ subsystem: 'profile',
245
+ operation: 'profile.confirm_draft_decompose',
246
+ toolName: 'confirm_user_profile',
247
+ userId: context.userId,
248
+ tags: { toolName: 'confirm_user_profile', execution: context.isMcp ? 'background' : 'sync' },
249
+ });
250
+ }
251
+ finally {
252
+ traceEmitter?.({ type: "graph_end", name: "profile", durationMs: Date.now() - graphStart });
253
+ }
254
+ }
185
255
  const readUserProfiles = defineTool({
186
256
  name: "read_user_profiles",
187
257
  description: "Retrieves user profiles containing identity info (name, bio, location), skills, and interests. Profiles are used for semantic matching " +
@@ -510,11 +580,7 @@ export function createProfileTools(defineTool, deps) {
510
580
  description: "Saves an explicitly approved onboarding profile draft. Call this only after the user has seen the draft from preview_user_profile and approved it or provided corrections. " +
511
581
  "This path uses only the approved draft/explicit correction text and does not scrape or run public lookup.",
512
582
  querySchema: z.object({
513
- draft: z.object({
514
- identity: z.object({ name: z.string(), bio: z.string(), location: z.string() }),
515
- narrative: z.object({ context: z.string() }),
516
- attributes: z.object({ interests: z.array(z.string()), skills: z.array(z.string()) }),
517
- }).optional().describe("The structured profile draft returned by preview_user_profile after user approval."),
583
+ draft: approvedProfileDraftSchema.optional().describe("The structured profile draft returned by preview_user_profile after user approval."),
518
584
  bioOrDescription: z.string().optional().describe("Approved correction or explicit profile text if not passing a structured draft."),
519
585
  name: z.string().optional().describe("Approved name correction."),
520
586
  location: z.string().optional().describe("Approved location correction."),
@@ -525,9 +591,22 @@ export function createProfileTools(defineTool, deps) {
525
591
  const profile = { ...query.draft, userId: context.userId };
526
592
  await userDb.saveProfile(profile);
527
593
  await persistApprovedProfileContext(profile, user, context.networkId);
594
+ if (context.isMcp) {
595
+ decomposeApprovedDraftProfile(context, profile).catch((err) => {
596
+ logger.error('Approved draft premise decomposition failed', {
597
+ userId: context.userId,
598
+ error: err instanceof Error ? err.message : String(err),
599
+ });
600
+ });
601
+ }
602
+ else {
603
+ await decomposeApprovedDraftProfile(context, profile);
604
+ }
528
605
  return success({
529
606
  created: true,
530
- message: "Profile saved from approved draft.",
607
+ message: context.isMcp
608
+ ? "Profile saved from approved draft. Premise extraction is running in the background."
609
+ : "Profile saved from approved draft.",
531
610
  profile: toProfileSummary(profile),
532
611
  });
533
612
  }