@indexnetwork/protocol 4.3.3-rc.308.1 → 4.3.4-rc.310.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/IMPLEMENTATION.md +2 -2
- package/dist/chat/chat.agent.d.ts +1 -1
- package/dist/chat/chat.agent.d.ts.map +1 -1
- package/dist/chat/chat.agent.js +12 -2
- package/dist/chat/chat.agent.js.map +1 -1
- package/dist/chat/chat.graph.d.ts +16 -0
- package/dist/chat/chat.graph.d.ts.map +1 -1
- package/dist/chat/chat.graph.js +5 -2
- package/dist/chat/chat.graph.js.map +1 -1
- package/dist/chat/chat.prompt.d.ts.map +1 -1
- package/dist/chat/chat.prompt.js +44 -37
- package/dist/chat/chat.prompt.js.map +1 -1
- package/dist/chat/chat.prompt.modules.js +8 -8
- package/dist/chat/chat.prompt.modules.js.map +1 -1
- package/dist/chat/chat.state.d.ts +7 -4
- package/dist/chat/chat.state.d.ts.map +1 -1
- package/dist/chat/chat.state.js +12 -3
- package/dist/chat/chat.state.js.map +1 -1
- package/dist/chat/chat.streamer.d.ts +5 -0
- package/dist/chat/chat.streamer.d.ts.map +1 -1
- package/dist/chat/chat.streamer.js +13 -4
- package/dist/chat/chat.streamer.js.map +1 -1
- package/dist/chat/tests/chat.graph.mocks.d.ts +1 -1
- package/dist/chat/tests/chat.graph.mocks.js +1 -1
- package/dist/chat/tests/chat.graph.mocks.js.map +1 -1
- package/dist/contact/contact.tools.js +6 -6
- package/dist/contact/contact.tools.js.map +1 -1
- package/dist/enrichment/enrichment.tools.d.ts.map +1 -1
- package/dist/enrichment/enrichment.tools.js +23 -26
- package/dist/enrichment/enrichment.tools.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/integration/integration.tools.js +1 -1
- package/dist/integration/integration.tools.js.map +1 -1
- package/dist/intent/intent.graph.d.ts.map +1 -1
- package/dist/intent/intent.graph.js +9 -9
- package/dist/intent/intent.graph.js.map +1 -1
- package/dist/intent/intent.indexer.d.ts +1 -1
- package/dist/intent/intent.indexer.js +4 -4
- package/dist/intent/intent.indexer.js.map +1 -1
- package/dist/intent/intent.state.d.ts +8 -8
- package/dist/intent/intent.state.js +8 -8
- package/dist/intent/intent.state.js.map +1 -1
- package/dist/intent/intent.tools.d.ts.map +1 -1
- package/dist/intent/intent.tools.js +87 -70
- package/dist/intent/intent.tools.js.map +1 -1
- package/dist/maintenance/maintenance.graph.d.ts +2 -2
- package/dist/maintenance/maintenance.graph.d.ts.map +1 -1
- package/dist/maintenance/maintenance.graph.js.map +1 -1
- package/dist/mcp/mcp.server.d.ts +5 -7
- package/dist/mcp/mcp.server.d.ts.map +1 -1
- package/dist/mcp/mcp.server.js +11 -20
- package/dist/mcp/mcp.server.js.map +1 -1
- package/dist/negotiation/negotiation.tools.d.ts.map +1 -1
- package/dist/negotiation/negotiation.tools.js +11 -7
- package/dist/negotiation/negotiation.tools.js.map +1 -1
- package/dist/network/indexer/indexer.graph.d.ts +2 -2
- package/dist/network/indexer/indexer.graph.d.ts.map +1 -1
- package/dist/network/indexer/indexer.graph.js +13 -13
- package/dist/network/indexer/indexer.graph.js.map +1 -1
- package/dist/network/indexer/indexer.state.d.ts +3 -3
- package/dist/network/indexer/indexer.state.d.ts.map +1 -1
- package/dist/network/indexer/indexer.state.js +4 -4
- package/dist/network/indexer/indexer.state.js.map +1 -1
- package/dist/network/membership/membership.graph.d.ts +1 -1
- package/dist/network/membership/membership.graph.js +21 -21
- package/dist/network/membership/membership.graph.js.map +1 -1
- package/dist/network/membership/membership.state.d.ts +2 -2
- package/dist/network/membership/membership.state.js +2 -2
- package/dist/network/membership/membership.state.js.map +1 -1
- package/dist/network/network.graph.d.ts +1 -1
- package/dist/network/network.graph.d.ts.map +1 -1
- package/dist/network/network.graph.js +13 -13
- package/dist/network/network.graph.js.map +1 -1
- package/dist/network/network.state.d.ts +3 -3
- package/dist/network/network.state.d.ts.map +1 -1
- package/dist/network/network.state.js +3 -3
- package/dist/network/network.state.js.map +1 -1
- package/dist/network/network.tools.js +68 -68
- package/dist/network/network.tools.js.map +1 -1
- package/dist/opportunity/opportunity.discover.d.ts +1 -1
- package/dist/opportunity/opportunity.discover.d.ts.map +1 -1
- package/dist/opportunity/opportunity.discover.js +1 -1
- package/dist/opportunity/opportunity.discover.js.map +1 -1
- package/dist/opportunity/opportunity.graph.js +11 -11
- package/dist/opportunity/opportunity.graph.js.map +1 -1
- package/dist/opportunity/opportunity.introducer.d.ts +3 -3
- package/dist/opportunity/opportunity.introducer.d.ts.map +1 -1
- package/dist/opportunity/opportunity.introducer.js +2 -2
- package/dist/opportunity/opportunity.introducer.js.map +1 -1
- package/dist/opportunity/opportunity.state.d.ts +1 -1
- package/dist/opportunity/opportunity.state.js +1 -1
- package/dist/opportunity/opportunity.state.js.map +1 -1
- package/dist/opportunity/opportunity.tools.d.ts.map +1 -1
- package/dist/opportunity/opportunity.tools.js +43 -47
- package/dist/opportunity/opportunity.tools.js.map +1 -1
- package/dist/premise/premise.indexer.d.ts +1 -1
- package/dist/premise/premise.indexer.js +5 -5
- package/dist/premise/premise.indexer.js.map +1 -1
- package/dist/questioner/questioner.tools.d.ts +1 -1
- package/dist/questioner/questioner.tools.d.ts.map +1 -1
- package/dist/questioner/questioner.tools.js +5 -6
- package/dist/questioner/questioner.tools.js.map +1 -1
- package/dist/shared/agent/tool.factory.d.ts +1 -1
- package/dist/shared/agent/tool.factory.d.ts.map +1 -1
- package/dist/shared/agent/tool.factory.js +10 -11
- package/dist/shared/agent/tool.factory.js.map +1 -1
- package/dist/shared/agent/tool.helpers.d.ts +6 -6
- package/dist/shared/agent/tool.helpers.d.ts.map +1 -1
- package/dist/shared/agent/tool.helpers.js +2 -2
- package/dist/shared/agent/tool.helpers.js.map +1 -1
- package/dist/shared/agent/tool.registry.js +1 -1
- package/dist/shared/agent/tool.registry.js.map +1 -1
- package/dist/shared/agent/tool.scope.d.ts +12 -0
- package/dist/shared/agent/tool.scope.d.ts.map +1 -1
- package/dist/shared/agent/tool.scope.js +14 -0
- package/dist/shared/agent/tool.scope.js.map +1 -1
- package/dist/shared/agent/utility.tools.js +20 -20
- package/dist/shared/agent/utility.tools.js.map +1 -1
- package/dist/shared/interfaces/auth.interface.d.ts +3 -3
- package/dist/shared/interfaces/auth.interface.js.map +1 -1
- package/dist/shared/interfaces/database.interface.d.ts +59 -59
- package/dist/shared/interfaces/database.interface.d.ts.map +1 -1
- package/dist/shared/interfaces/database.interface.js.map +1 -1
- package/dist/shared/interfaces/discovery-run.interface.d.ts +1 -1
- package/dist/shared/interfaces/discovery-run.interface.d.ts.map +1 -1
- package/dist/shared/interfaces/discovery-run.interface.js.map +1 -1
- package/dist/shared/interfaces/embedder.interface.d.ts +2 -2
- package/dist/shared/interfaces/embedder.interface.d.ts.map +1 -1
- package/dist/shared/interfaces/embedder.interface.js.map +1 -1
- package/dist/shared/interfaces/enrichment-run.interface.d.ts +1 -1
- package/dist/shared/interfaces/enrichment-run.interface.d.ts.map +1 -1
- package/dist/shared/interfaces/enrichment-run.interface.js.map +1 -1
- package/package.json +1 -1
|
@@ -25,7 +25,7 @@ export function createNetworkTools(defineTool, deps) {
|
|
|
25
25
|
"**Returns:** Up to three lists — `memberOf` (networks the user joined), `owns` (networks the user created), and `publicNetworks` " +
|
|
26
26
|
"(publicly joinable communities the user is not yet a member of). Entries in `memberOf` include `isPersonal` set to `true` for the user's " +
|
|
27
27
|
"personal network.\n\n" +
|
|
28
|
-
"**Note:** In
|
|
28
|
+
"**Note:** In network-scoped chats, only the scoped network is returned. During onboarding, `orderedNetworkIds` " +
|
|
29
29
|
"may be returned alongside `publicNetworks` \u2014 a ranked array of network IDs ordered by relevance to the user's profile (omitted when ranking is unavailable or fails).",
|
|
30
30
|
querySchema: z.object({
|
|
31
31
|
userId: z.string().optional().describe("Must be the current user's ID or omitted. Cannot list another user's indexes."),
|
|
@@ -63,7 +63,7 @@ export function createNetworkTools(defineTool, deps) {
|
|
|
63
63
|
scopeRestriction: {
|
|
64
64
|
isScoped: true,
|
|
65
65
|
scopedToIndex: context.indexName ?? context.networkId,
|
|
66
|
-
message: `Results are limited to "${context.indexName ?? 'this
|
|
66
|
+
message: `Results are limited to "${context.indexName ?? 'this network'}" because this chat is scoped to that community. The user may belong to other communities not shown here.`,
|
|
67
67
|
},
|
|
68
68
|
_graphTimings: [{ name: 'index', durationMs: _readIndexGraphMs, agents: result.agentTimings ?? [] }],
|
|
69
69
|
});
|
|
@@ -140,39 +140,39 @@ export function createNetworkTools(defineTool, deps) {
|
|
|
140
140
|
});
|
|
141
141
|
const readIndexMemberships = defineTool({
|
|
142
142
|
name: "read_network_memberships",
|
|
143
|
-
description: "Reads
|
|
143
|
+
description: "Reads network membership information — who is in which community. Essential for understanding the social graph before " +
|
|
144
144
|
"creating introductions or exploring intents.\n\n" +
|
|
145
145
|
"**Usage modes:**\n" +
|
|
146
146
|
"- With `networkId` only: lists ALL members of that index — returns userId, name, avatar, permissions (owner/member), intentCount, and joinedAt. " +
|
|
147
147
|
"Use this to see who's in a community before browsing their intents or creating introductions.\n" +
|
|
148
|
-
"- With `userId` only (or omit for self): lists all
|
|
148
|
+
"- With `userId` only (or omit for self): lists all networks that user belongs to — returns networkId, networkTitle, permissions, joinedAt.\n" +
|
|
149
149
|
"- With both `networkId` and `userId`: checks whether that specific user is a member of that specific index (returns isMember boolean).\n\n" +
|
|
150
|
-
"**When to use:** Before creating introductions (need to verify shared
|
|
150
|
+
"**When to use:** Before creating introductions (need to verify shared network membership), to explore community members, " +
|
|
151
151
|
"or to check if a user belongs to a specific index.\n\n" +
|
|
152
152
|
"**Returns:** Member list with user details, or membership list with index details, or a membership check result.\n\n" +
|
|
153
|
-
"**Personal
|
|
153
|
+
"**Personal network semantics.** The personal network (`isPersonal: true` on the membership) is the user's " +
|
|
154
154
|
"contact list — members of that index are the user's contacts. For another user, this tool only reveals the " +
|
|
155
155
|
"indexes you already share with them.\n\n" +
|
|
156
156
|
"**Shared-context pattern.** To find overlap with another user: (1) omit `userId` to read your own " +
|
|
157
|
-
"memberships, (2) call this tool with the other person's actual `userId` to get the shared
|
|
157
|
+
"memberships, (2) call this tool with the other person's actual `userId` to get the shared networks, " +
|
|
158
158
|
"(3) call read_intents for each shared network to see what each is looking for there, (4) call " +
|
|
159
159
|
"read_user_contexts for the other party. That sequence gives you enough to decide whether to propose a " +
|
|
160
160
|
"direct connection or an introduction.",
|
|
161
161
|
querySchema: z.object({
|
|
162
|
-
networkId: z.string().optional().describe("
|
|
163
|
-
userId: z.string().optional().describe("User ID — lists that user's
|
|
162
|
+
networkId: z.string().optional().describe("Network UUID — lists all members of this network. Get from read_networks. In network-scoped chats, only the scoped index can be queried."),
|
|
163
|
+
userId: z.string().optional().describe("User ID — lists that user's network memberships. Omit to get the current user's memberships. When combined with networkId, checks if this user is in that specific index."),
|
|
164
164
|
}),
|
|
165
165
|
handler: async ({ context, query }) => {
|
|
166
166
|
const networkId = query.networkId?.trim() || undefined;
|
|
167
167
|
const userId = query.userId?.trim() || undefined;
|
|
168
168
|
if (networkId && !UUID_REGEX.test(networkId)) {
|
|
169
|
-
return error("Invalid
|
|
169
|
+
return error("Invalid network ID format. Use the exact UUID from read_networks.");
|
|
170
170
|
}
|
|
171
171
|
// Mode 1: list members of an index
|
|
172
172
|
if (networkId && !userId) {
|
|
173
|
-
// Enforce strict scope: when chat is
|
|
173
|
+
// Enforce strict scope: when chat is network-scoped, only allow querying that index
|
|
174
174
|
if (context.networkId && networkId !== context.networkId) {
|
|
175
|
-
return error(`This chat is scoped to ${context.indexName ?? 'this
|
|
175
|
+
return error(`This chat is scoped to ${context.indexName ?? 'this network'}. You can only query members of this network.`);
|
|
176
176
|
}
|
|
177
177
|
const _readMembersGraphStart = Date.now();
|
|
178
178
|
const _readMembersTraceEmitter = requestContext.getStore()?.traceEmitter;
|
|
@@ -190,19 +190,19 @@ export function createNetworkTools(defineTool, deps) {
|
|
|
190
190
|
if (result.readResult) {
|
|
191
191
|
return success({ ...result.readResult, _graphTimings: [{ name: 'network_membership', durationMs: _readMembersGraphMs, agents: result.agentTimings ?? [] }] });
|
|
192
192
|
}
|
|
193
|
-
return error("Failed to fetch
|
|
193
|
+
return error("Failed to fetch network members.");
|
|
194
194
|
}
|
|
195
195
|
// Mode 2: list a user's memberships (indexes they belong to)
|
|
196
196
|
const targetUserId = userId || context.userId;
|
|
197
|
-
// Use userDb for own memberships, but systemDb access is implicit through shared
|
|
197
|
+
// Use userDb for own memberships, but systemDb access is implicit through shared network scope
|
|
198
198
|
let memberships;
|
|
199
199
|
if (targetUserId !== context.userId) {
|
|
200
|
-
// Cross-user access: systemDb will validate shared
|
|
200
|
+
// Cross-user access: systemDb will validate shared network membership
|
|
201
201
|
const callerMemberships = await userDb.getNetworkMemberships();
|
|
202
202
|
if (networkId) {
|
|
203
|
-
// Strict scope enforcement: when chat is
|
|
203
|
+
// Strict scope enforcement: when chat is network-scoped, only allow querying that index
|
|
204
204
|
if (context.networkId && networkId !== context.networkId) {
|
|
205
|
-
return error(`This chat is scoped to ${context.indexName ?? 'this
|
|
205
|
+
return error(`This chat is scoped to ${context.indexName ?? 'this network'}. You can only query membership in this community.`);
|
|
206
206
|
}
|
|
207
207
|
const callerInIndex = callerMemberships.some((m) => m.networkId === networkId);
|
|
208
208
|
if (!callerInIndex) {
|
|
@@ -213,10 +213,10 @@ export function createNetworkTools(defineTool, deps) {
|
|
|
213
213
|
if (isMember) {
|
|
214
214
|
return success({ isMember: true, userId: targetUserId, networkId });
|
|
215
215
|
}
|
|
216
|
-
return success({ isMember: false, userId: targetUserId, networkId, message: "User is not a member of this
|
|
216
|
+
return success({ isMember: false, userId: targetUserId, networkId, message: "User is not a member of this network." });
|
|
217
217
|
}
|
|
218
218
|
else {
|
|
219
|
-
// Strict scope enforcement: when chat is
|
|
219
|
+
// Strict scope enforcement: when chat is network-scoped, only check the scoped index
|
|
220
220
|
if (context.networkId) {
|
|
221
221
|
const isMember = await systemDb.isNetworkMember(context.networkId, targetUserId);
|
|
222
222
|
if (isMember) {
|
|
@@ -227,7 +227,7 @@ export function createNetworkTools(defineTool, deps) {
|
|
|
227
227
|
scopeRestriction: {
|
|
228
228
|
isScoped: true,
|
|
229
229
|
scopedToIndex: context.indexName ?? context.networkId,
|
|
230
|
-
message: `This chat is scoped to "${context.indexName ?? 'this
|
|
230
|
+
message: `This chat is scoped to "${context.indexName ?? 'this network'}". Only membership in this community is shown.`,
|
|
231
231
|
},
|
|
232
232
|
});
|
|
233
233
|
}
|
|
@@ -239,11 +239,11 @@ export function createNetworkTools(defineTool, deps) {
|
|
|
239
239
|
scopeRestriction: {
|
|
240
240
|
isScoped: true,
|
|
241
241
|
scopedToIndex: context.indexName ?? context.networkId,
|
|
242
|
-
message: `This chat is scoped to "${context.indexName ?? 'this
|
|
242
|
+
message: `This chat is scoped to "${context.indexName ?? 'this network'}". Only membership in this community was checked.`,
|
|
243
243
|
},
|
|
244
244
|
});
|
|
245
245
|
}
|
|
246
|
-
// Unscoped chat: show overlap with shared
|
|
246
|
+
// Unscoped chat: show overlap with shared networks (intersection of caller and target memberships)
|
|
247
247
|
const sharedIndexes = [];
|
|
248
248
|
for (const m of callerMemberships) {
|
|
249
249
|
if (await systemDb.isNetworkMember(m.networkId, targetUserId)) {
|
|
@@ -261,7 +261,7 @@ export function createNetworkTools(defineTool, deps) {
|
|
|
261
261
|
networkId: m.networkId,
|
|
262
262
|
networkTitle: m.networkTitle,
|
|
263
263
|
})),
|
|
264
|
-
note: "Only showing shared
|
|
264
|
+
note: "Only showing shared networks.",
|
|
265
265
|
});
|
|
266
266
|
}
|
|
267
267
|
}
|
|
@@ -271,16 +271,16 @@ export function createNetworkTools(defineTool, deps) {
|
|
|
271
271
|
// NOTE: context.networkId here is the *focus* of the scoped chat — it filters
|
|
272
272
|
// what we show, not what we can reach. indexScope is the reach; the bound
|
|
273
273
|
// network is one element of it. See IND-306 for the equivalent in read_intents.
|
|
274
|
-
// Strict scope enforcement: when chat is
|
|
274
|
+
// Strict scope enforcement: when chat is network-scoped, only return the scoped network membership
|
|
275
275
|
if (context.networkId && !networkId) {
|
|
276
276
|
memberships = memberships.filter((m) => m.networkId === context.networkId);
|
|
277
277
|
}
|
|
278
278
|
}
|
|
279
279
|
// If both networkId and userId: filter to that specific membership
|
|
280
280
|
if (networkId) {
|
|
281
|
-
// Strict scope enforcement: when chat is
|
|
281
|
+
// Strict scope enforcement: when chat is network-scoped, only allow querying that index
|
|
282
282
|
if (context.networkId && networkId !== context.networkId) {
|
|
283
|
-
return error(`This chat is scoped to ${context.indexName ?? 'this
|
|
283
|
+
return error(`This chat is scoped to ${context.indexName ?? 'this network'}. You can only query membership in this community.`);
|
|
284
284
|
}
|
|
285
285
|
const callerMemberships = await userDb.getNetworkMemberships();
|
|
286
286
|
const callerInIndex = targetUserId === context.userId ||
|
|
@@ -290,7 +290,7 @@ export function createNetworkTools(defineTool, deps) {
|
|
|
290
290
|
}
|
|
291
291
|
const match = memberships.find((m) => m.networkId === networkId);
|
|
292
292
|
if (!match) {
|
|
293
|
-
return success({ isMember: false, userId: targetUserId, networkId, message: "User is not a member of this
|
|
293
|
+
return success({ isMember: false, userId: targetUserId, networkId, message: "User is not a member of this network." });
|
|
294
294
|
}
|
|
295
295
|
return success({
|
|
296
296
|
isMember: true,
|
|
@@ -315,7 +315,7 @@ export function createNetworkTools(defineTool, deps) {
|
|
|
315
315
|
scopeRestriction: {
|
|
316
316
|
isScoped: true,
|
|
317
317
|
scopedToIndex: context.indexName ?? context.networkId,
|
|
318
|
-
message: `Results are limited to "${context.indexName ?? 'this
|
|
318
|
+
message: `Results are limited to "${context.indexName ?? 'this network'}" because this chat is scoped to that community. The user may belong to other communities not shown here.`,
|
|
319
319
|
},
|
|
320
320
|
});
|
|
321
321
|
}
|
|
@@ -340,16 +340,16 @@ export function createNetworkTools(defineTool, deps) {
|
|
|
340
340
|
}).strict();
|
|
341
341
|
const updateNetwork = defineTool({
|
|
342
342
|
name: "update_network",
|
|
343
|
-
description: "Updates settings of an existing
|
|
343
|
+
description: "Updates settings of an existing network (community). Only the network owner can perform updates.\n\n" +
|
|
344
344
|
"**Updatable fields:** title (display name), prompt (purpose description used for intent auto-assignment), " +
|
|
345
345
|
"imageUrl (community avatar), joinPolicy ('anyone' for open or 'invite_only'), allowGuestVibeCheck (allow non-members to preview).\n\n" +
|
|
346
|
-
"**When to use:** When
|
|
346
|
+
"**When to use:** When a network owner wants to change their community's settings — e.g. update the purpose description, " +
|
|
347
347
|
"change from invite-only to open, or update the community image.\n\n" +
|
|
348
|
-
"**Important:** Changing the prompt affects how future intents are evaluated for auto-assignment to this
|
|
349
|
-
"Existing intent-
|
|
348
|
+
"**Important:** Changing the prompt affects how future intents are evaluated for auto-assignment to this network. " +
|
|
349
|
+
"Existing intent-network links are not re-evaluated automatically.\n\n" +
|
|
350
350
|
"**Returns:** Confirmation with the list of settings that were updated.",
|
|
351
351
|
querySchema: z.object({
|
|
352
|
-
networkId: z.string().optional().describe("
|
|
352
|
+
networkId: z.string().optional().describe("Network UUID to update. Get from read_networks. Defaults to the scoped index in network-scoped chats."),
|
|
353
353
|
settings: updateNetworkSettingsSchema.describe("Object with fields to update. All fields are optional — only include the ones to change. title: display name. prompt: purpose description (used for intent auto-assignment). imageUrl: community image URL (null to remove). joinPolicy: 'anyone' or 'invite_only'. allowGuestVibeCheck: boolean."),
|
|
354
354
|
}),
|
|
355
355
|
handler: async ({ context, query }) => {
|
|
@@ -357,9 +357,9 @@ export function createNetworkTools(defineTool, deps) {
|
|
|
357
357
|
if (!effectiveIndexId || !UUID_REGEX.test(effectiveIndexId)) {
|
|
358
358
|
return error("Valid networkId required.");
|
|
359
359
|
}
|
|
360
|
-
// Strict scope enforcement: when chat is
|
|
360
|
+
// Strict scope enforcement: when chat is network-scoped, only allow updating that index
|
|
361
361
|
if (context.networkId && effectiveIndexId !== context.networkId) {
|
|
362
|
-
return error(`This chat is scoped to ${context.indexName ?? 'this
|
|
362
|
+
return error(`This chat is scoped to ${context.indexName ?? 'this network'}. You can only update this community's settings.`);
|
|
363
363
|
}
|
|
364
364
|
const _updateNetworkGraphStart = Date.now();
|
|
365
365
|
const _updateNetworkTraceEmitter = requestContext.getStore()?.traceEmitter;
|
|
@@ -380,15 +380,15 @@ export function createNetworkTools(defineTool, deps) {
|
|
|
380
380
|
});
|
|
381
381
|
const createNetwork = defineTool({
|
|
382
382
|
name: "create_network",
|
|
383
|
-
description: "Creates a new
|
|
384
|
-
"**What is
|
|
385
|
-
"(complementary matches) between members. The
|
|
383
|
+
description: "Creates a new network (community/group). The authenticated user becomes the owner with full control over settings and membership.\n\n" +
|
|
384
|
+
"**What is a network?** A shared space where members post intents (what they're looking for) and the system discovers opportunities " +
|
|
385
|
+
"(complementary matches) between members. The network's prompt guides what kinds of intents belong.\n\n" +
|
|
386
386
|
"**When to use:** When the user wants to create a new community — e.g. a professional network, interest group, or project team.\n\n" +
|
|
387
|
-
"**Returns:** The new
|
|
387
|
+
"**Returns:** The new network's networkId (UUID) and title. Use the networkId to add members (create_network_membership), " +
|
|
388
388
|
"link intents (create_intent_index), or run discovery (discover_opportunities with networkId).",
|
|
389
389
|
querySchema: z.object({
|
|
390
|
-
title: z.string().describe("Display name of the
|
|
391
|
-
prompt: z.string().optional().describe("Description of what this community is about (e.g. 'Early-stage AI/ML founders in Berlin looking for co-founders, advisors, and investors'). Used by the system to evaluate which intents belong in this
|
|
390
|
+
title: z.string().describe("Display name of the network (e.g. 'AI Founders Berlin', 'Design Co-op'). Required."),
|
|
391
|
+
prompt: z.string().optional().describe("Description of what this community is about (e.g. 'Early-stage AI/ML founders in Berlin looking for co-founders, advisors, and investors'). Used by the system to evaluate which intents belong in this network. Highly recommended for better auto-assignment."),
|
|
392
392
|
imageUrl: z.string().url().optional().describe("URL for the community's avatar/image. Optional."),
|
|
393
393
|
joinPolicy: z.enum(['anyone', 'invite_only']).optional().describe("'anyone' = open (any user can self-join), 'invite_only' = only the owner can add members. Defaults to 'invite_only'."),
|
|
394
394
|
}),
|
|
@@ -421,29 +421,29 @@ export function createNetworkTools(defineTool, deps) {
|
|
|
421
421
|
_graphTimings: [{ name: 'index', durationMs: _createNetworkGraphMs, agents: result.agentTimings ?? [] }],
|
|
422
422
|
});
|
|
423
423
|
}
|
|
424
|
-
return error(result.mutationResult.error || "Failed to create
|
|
424
|
+
return error(result.mutationResult.error || "Failed to create network.");
|
|
425
425
|
}
|
|
426
|
-
return error("Failed to create
|
|
426
|
+
return error("Failed to create network.");
|
|
427
427
|
},
|
|
428
428
|
});
|
|
429
429
|
const deleteNetwork = defineTool({
|
|
430
430
|
name: "delete_network",
|
|
431
|
-
description: "Permanently deletes
|
|
432
|
-
"(remove all members first with delete_network_membership). Personal
|
|
433
|
-
"**When to use:** When the owner wants to disband a community. This is irreversible — all intent-
|
|
431
|
+
description: "Permanently deletes a network (community). Only the owner can delete, and the network must have no other members " +
|
|
432
|
+
"(remove all members first with delete_network_membership). Personal networks cannot be deleted.\n\n" +
|
|
433
|
+
"**When to use:** When the owner wants to disband a community. This is irreversible — all intent-network links to this network are removed.\n\n" +
|
|
434
434
|
"**Prerequisites:** Must be the owner. Must be the sole remaining member (remove others first).\n\n" +
|
|
435
|
-
"**Returns:** Confirmation that the
|
|
435
|
+
"**Returns:** Confirmation that the network was deleted.",
|
|
436
436
|
querySchema: z.object({
|
|
437
|
-
networkId: z.string().optional().describe("
|
|
437
|
+
networkId: z.string().optional().describe("Network UUID to delete. Get from read_networks. Defaults to the scoped index in network-scoped chats. Cannot be a personal network."),
|
|
438
438
|
}),
|
|
439
439
|
handler: async ({ context, query }) => {
|
|
440
440
|
const networkId = query.networkId?.trim() || context.networkId;
|
|
441
441
|
if (!networkId || !UUID_REGEX.test(networkId)) {
|
|
442
442
|
return error("Valid networkId required.");
|
|
443
443
|
}
|
|
444
|
-
// Strict scope enforcement: when chat is
|
|
444
|
+
// Strict scope enforcement: when chat is network-scoped, only allow deleting that index
|
|
445
445
|
if (context.networkId && networkId !== context.networkId) {
|
|
446
|
-
return error(`This chat is scoped to ${context.indexName ?? 'this
|
|
446
|
+
return error(`This chat is scoped to ${context.indexName ?? 'this network'}. You can only delete this community.`);
|
|
447
447
|
}
|
|
448
448
|
const _deleteNetworkGraphStart = Date.now();
|
|
449
449
|
const _deleteNetworkTraceEmitter = requestContext.getStore()?.traceEmitter;
|
|
@@ -456,34 +456,34 @@ export function createNetworkTools(defineTool, deps) {
|
|
|
456
456
|
const _deleteNetworkGraphMs = Date.now() - _deleteNetworkGraphStart;
|
|
457
457
|
_deleteNetworkTraceEmitter?.({ type: "graph_end", name: "index", durationMs: _deleteNetworkGraphMs });
|
|
458
458
|
if (result.mutationResult && !result.mutationResult.success) {
|
|
459
|
-
return error(result.mutationResult.error || "Failed to delete
|
|
459
|
+
return error(result.mutationResult.error || "Failed to delete network.");
|
|
460
460
|
}
|
|
461
461
|
return success({ message: "Network deleted.", _graphTimings: [{ name: 'index', durationMs: _deleteNetworkGraphMs, agents: result.agentTimings ?? [] }] });
|
|
462
462
|
},
|
|
463
463
|
});
|
|
464
464
|
const createNetworkMembership = defineTool({
|
|
465
465
|
name: "create_network_membership",
|
|
466
|
-
description: "Adds a user as a member of
|
|
466
|
+
description: "Adds a user as a member of a network (community). Membership enables the user to post intents in the network and be discovered " +
|
|
467
467
|
"by other members through opportunity matching.\n\n" +
|
|
468
468
|
"**Usage modes:**\n" +
|
|
469
|
-
"- Omit userId: self-join (only works for
|
|
470
|
-
"- With userId: add another user (only the
|
|
471
|
-
"**When to use:** When the user wants to join an open community, or when
|
|
469
|
+
"- Omit userId: self-join (only works for networks with joinPolicy 'anyone').\n" +
|
|
470
|
+
"- With userId: add another user (only the network owner can do this for 'invite_only' indexes).\n\n" +
|
|
471
|
+
"**When to use:** When the user wants to join an open community, or when a network owner wants to invite someone.\n\n" +
|
|
472
472
|
"**Returns:** Confirmation that the member was added (or a note that they were already a member). " +
|
|
473
|
-
"After joining, the user's existing intents with autoAssign=true may be evaluated against the new
|
|
473
|
+
"After joining, the user's existing intents with autoAssign=true may be evaluated against the new network.",
|
|
474
474
|
querySchema: z.object({
|
|
475
|
-
userId: z.string().optional().describe("User ID to add as a member. Omit to join the
|
|
476
|
-
networkId: z.string().optional().describe("
|
|
475
|
+
userId: z.string().optional().describe("User ID to add as a member. Omit to join the network yourself. Get user IDs from read_user_contexts(query=name) or read_network_memberships."),
|
|
476
|
+
networkId: z.string().optional().describe("Network UUID to add the member to. Get from read_networks. Defaults to the scoped index in network-scoped chats."),
|
|
477
477
|
}),
|
|
478
478
|
handler: async ({ context, query }) => {
|
|
479
479
|
const networkId = query.networkId?.trim() || context.networkId;
|
|
480
480
|
const targetUserId = query.userId?.trim() || context.userId;
|
|
481
481
|
if (!networkId || !UUID_REGEX.test(networkId)) {
|
|
482
|
-
return error("Invalid
|
|
482
|
+
return error("Invalid network ID format. Use the exact UUID from read_networks.");
|
|
483
483
|
}
|
|
484
|
-
// Strict scope enforcement: when chat is
|
|
484
|
+
// Strict scope enforcement: when chat is network-scoped, only allow adding to that index
|
|
485
485
|
if (context.networkId && networkId !== context.networkId) {
|
|
486
|
-
return error(`This chat is scoped to ${context.indexName ?? 'this
|
|
486
|
+
return error(`This chat is scoped to ${context.indexName ?? 'this network'}. You can only add members to this community.`);
|
|
487
487
|
}
|
|
488
488
|
const _createMembershipGraphStart = Date.now();
|
|
489
489
|
const _createMembershipTraceEmitter = requestContext.getStore()?.traceEmitter;
|
|
@@ -512,15 +512,15 @@ export function createNetworkTools(defineTool, deps) {
|
|
|
512
512
|
});
|
|
513
513
|
const deleteNetworkMembership = defineTool({
|
|
514
514
|
name: "delete_network_membership",
|
|
515
|
-
description: "Removes a user from
|
|
515
|
+
description: "Removes a user from a network (community). After removal, the user's intents are unlinked from this network " +
|
|
516
516
|
"and they can no longer participate in opportunity discovery within it.\n\n" +
|
|
517
|
-
"**Permissions:** Only the
|
|
518
|
-
"**When to use:** When
|
|
517
|
+
"**Permissions:** Only the network owner can remove members. The owner themselves cannot be removed (delete the network instead).\n\n" +
|
|
518
|
+
"**When to use:** When a network owner wants to remove a member from the community. " +
|
|
519
519
|
"Use read_network_memberships(networkId) first to get the userId of the member to remove.\n\n" +
|
|
520
520
|
"**Returns:** Confirmation that the member was removed.",
|
|
521
521
|
querySchema: z.object({
|
|
522
|
-
userId: z.string().describe("User ID of the member to remove. Get from read_network_memberships(networkId). Cannot be the
|
|
523
|
-
networkId: z.string().optional().describe("
|
|
522
|
+
userId: z.string().describe("User ID of the member to remove. Get from read_network_memberships(networkId). Cannot be the network owner."),
|
|
523
|
+
networkId: z.string().optional().describe("Network UUID to remove the member from. Get from read_networks. Defaults to the scoped index in network-scoped chats."),
|
|
524
524
|
}),
|
|
525
525
|
handler: async ({ context, query }) => {
|
|
526
526
|
const networkId = query.networkId?.trim() || context.networkId;
|
|
@@ -531,9 +531,9 @@ export function createNetworkTools(defineTool, deps) {
|
|
|
531
531
|
if (!targetUserId) {
|
|
532
532
|
return error("userId is required.");
|
|
533
533
|
}
|
|
534
|
-
// Strict scope enforcement: when chat is
|
|
534
|
+
// Strict scope enforcement: when chat is network-scoped, only allow that index
|
|
535
535
|
if (context.networkId && networkId !== context.networkId) {
|
|
536
|
-
return error(`This chat is scoped to ${context.indexName ?? 'this
|
|
536
|
+
return error(`This chat is scoped to ${context.indexName ?? 'this network'}. You can only manage members of this community.`);
|
|
537
537
|
}
|
|
538
538
|
const _deleteMembershipGraphStart = Date.now();
|
|
539
539
|
const _deleteMembershipTraceEmitter = requestContext.getStore()?.traceEmitter;
|