@indexnetwork/protocol 3.10.0-rc.285.1 → 3.12.0-rc.287.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.
@@ -21,7 +21,7 @@ const approvedProfileDraftSchema = z.object({
21
21
  attributes: z.object({ interests: z.array(z.string()), skills: z.array(z.string()) }),
22
22
  });
23
23
  export function createProfileTools(defineTool, deps) {
24
- const { userDb, systemDb, graphs, enricher, grantDefaultSystemPermissions, reportToolError } = deps;
24
+ const { userDb, systemDb, graphs, enricher, grantDefaultSystemPermissions, reportToolError, getUserContextText } = deps;
25
25
  function trimToUndefined(value) {
26
26
  const trimmed = value?.trim();
27
27
  return trimmed && trimmed.length > 0 ? trimmed : undefined;
@@ -256,18 +256,18 @@ export function createProfileTools(defineTool, deps) {
256
256
  }
257
257
  const readUserProfiles = defineTool({
258
258
  name: "read_user_profiles",
259
- description: "Retrieves user profiles containing identity info (name, bio, location), skills, and interests. Profiles are used for semantic matching " +
260
- "in opportunity discovery — richer profiles produce better matches.\n\n" +
259
+ description: "Retrieves user profiles containing identity info (name, bio, location) plus a rich `context` paragraph (the user's synthesized identity text). " +
260
+ "Profiles are used for semantic matching in opportunity discovery — the richer the user's context, the better the matches.\n\n" +
261
261
  "**Usage modes:**\n" +
262
262
  "- With `query` (name search): finds members by name (case-insensitive substring) across the user's indexes. " +
263
- "This is the primary way to look up a person by name. Add `networkId` to restrict search to one index.\n" +
264
- "- With `userId`: returns that specific user's full profile (name, bio, skills, interests, location).\n" +
265
- "- With `networkId` alone: returns profiles of ALL members in that index.\n" +
266
- "- No parameters: returns the current user's own profile.\n\n" +
263
+ "This is the primary way to look up a person by name. Add `networkId` to restrict search to one index. (List results return thin identity only — no `context`.)\n" +
264
+ "- With `userId`: returns that specific user's profile name, bio, location, and their `context` paragraph.\n" +
265
+ "- With `networkId` alone: returns thin-identity profiles of ALL members in that index (no `context`).\n" +
266
+ "- No parameters: returns the current user's own profile, including their `context`.\n\n" +
267
267
  "**When to use:** Before creating introductions (need profiles of both parties), when the user asks about a person, " +
268
268
  "or to check if a profile exists before suggesting create_user_profile. " +
269
269
  "MCP agents should call this with no arguments at session start to fetch the caller's profile AND onboarding status.\n\n" +
270
- "**Returns:** Profile objects with name, bio, location, skills[], interests[]. Use userId from results with other tools like read_intents(userId, networkId). " +
270
+ "**Returns:** Profile objects with name, bio, location, and (for single-user reads) a `context` paragraph. Use userId from results with other tools like read_intents(userId, networkId). " +
271
271
  "When called for the current user (no args, or userId=self), the response also includes `onboardingComplete: boolean` and `onboardingCompletedAt?: string` — " +
272
272
  "use these as the source of truth for whether the user still needs onboarding (do not rely on local file state).",
273
273
  querySchema: z.object({
@@ -324,6 +324,8 @@ export function createProfileTools(defineTool, deps) {
324
324
  const profiles = await Promise.all(matched.map(async (m) => {
325
325
  try {
326
326
  const profile = await systemDb.getProfile(m.userId);
327
+ // Thin identity for list results. skills/interests are retired; the rich
328
+ // identity text (global user_context) is fetched per-user via a userId read.
327
329
  return {
328
330
  userId: m.userId,
329
331
  name: m.name,
@@ -333,8 +335,6 @@ export function createProfileTools(defineTool, deps) {
333
335
  name: profile.identity.name,
334
336
  bio: profile.identity.bio,
335
337
  location: profile.identity.location,
336
- skills: profile.attributes.skills,
337
- interests: profile.attributes.interests,
338
338
  }
339
339
  : undefined,
340
340
  };
@@ -367,6 +367,8 @@ export function createProfileTools(defineTool, deps) {
367
367
  const members = await systemDb.getNetworkMembers(effectiveIndexId);
368
368
  const profiles = await Promise.all(members.map(async (member) => {
369
369
  const profile = await systemDb.getProfile(member.userId);
370
+ // Thin identity for roster results. skills/interests are retired; fetch a
371
+ // member's global user_context text via a single-user (userId) read.
370
372
  return {
371
373
  userId: member.userId,
372
374
  name: member.name,
@@ -376,8 +378,6 @@ export function createProfileTools(defineTool, deps) {
376
378
  name: profile.identity.name,
377
379
  bio: profile.identity.bio,
378
380
  location: profile.identity.location,
379
- skills: profile.attributes.skills,
380
- interests: profile.attributes.interests,
381
381
  }
382
382
  : undefined,
383
383
  };
@@ -398,14 +398,16 @@ export function createProfileTools(defineTool, deps) {
398
398
  // Use systemDb for cross-user profile access (requires shared index)
399
399
  const profile = await systemDb.getProfile(targetUserId);
400
400
  if (profile) {
401
+ // Thin identity + the user's global user_context text (profile-replacing
402
+ // identity paragraph). skills/interests/narrative are retired (WS6).
403
+ const context = getUserContextText ? await getUserContextText(targetUserId) : '';
401
404
  return success({
402
405
  hasProfile: true,
403
406
  profile: {
404
407
  name: profile.identity.name,
405
408
  bio: profile.identity.bio,
406
409
  location: profile.identity.location,
407
- skills: profile.attributes.skills,
408
- interests: profile.attributes.interests,
410
+ context,
409
411
  },
410
412
  });
411
413
  }
@@ -430,7 +432,13 @@ export function createProfileTools(defineTool, deps) {
430
432
  ...(onboardingCompletedAt ? { onboardingCompletedAt } : {}),
431
433
  };
432
434
  if (result.readResult) {
433
- return success({ ...result.readResult, ...onboardingFields, _graphTimings: [{ name: 'profile', durationMs: _readProfileGraphMs, agents: result.agentTimings ?? [] }] });
435
+ // Augment the graph's thin-identity readResult with the caller's global
436
+ // user_context text (the rich, profile-replacing identity paragraph).
437
+ const readResult = result.readResult;
438
+ const withContext = readResult.hasProfile && readResult.profile
439
+ ? { ...readResult, profile: { ...readResult.profile, context: getUserContextText ? await getUserContextText(context.userId) : '' } }
440
+ : readResult;
441
+ return success({ ...withContext, ...onboardingFields, _graphTimings: [{ name: 'profile', durationMs: _readProfileGraphMs, agents: result.agentTimings ?? [] }] });
434
442
  }
435
443
  if (result.profile) {
436
444
  return success({
@@ -439,8 +447,7 @@ export function createProfileTools(defineTool, deps) {
439
447
  name: result.profile.identity.name,
440
448
  bio: result.profile.identity.bio,
441
449
  location: result.profile.identity.location,
442
- skills: result.profile.attributes.skills,
443
- interests: result.profile.attributes.interests,
450
+ context: getUserContextText ? await getUserContextText(context.userId) : '',
444
451
  },
445
452
  ...onboardingFields,
446
453
  _graphTimings: [{ name: 'profile', durationMs: _readProfileGraphMs, agents: result.agentTimings ?? [] }],