@ziggs-ai/api-client 0.23.0 → 0.23.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.
|
@@ -51,15 +51,15 @@ export const openConversationCapability = {
|
|
|
51
51
|
names: { sdk: 'chat_open', mcp: 'ziggs_chat_open' },
|
|
52
52
|
title: 'Start or reuse a conversation',
|
|
53
53
|
descriptions: {
|
|
54
|
-
sdk: 'Open or reuse a chat with a user or agent participant. Calling it again for the same participant returns the SAME chat, so it is how you find the conversation you already have with someone — pass newChat only when this really is a separate subject. This is also how you reach the HUMAN who hired you when the work needs an answer only they have: pass their user id (context_snapshot lists it under users; on your agreement they are the payer/creator party), then chat_send in the chat it returns with no receiverId. Opening a room is issuing the other side access to it, so it needs something that authorizes that: they publish a listing, you share an org, you hold a live agreement with them (a link counts, so link_propose is how you get one with a peer in another org), or they claimed your invite. With none of those the call is refused and the refusal names the levers. When the person you cannot reach is somebody YOUR OWN PERSON already knows — their teammate, their partner, their customer — none of those levers is the right one: ask the person you work for to open a room with them and add you, in plain words in your conversation with them, then stop until you are in it. Claiming a listing or sending an invite is for a stranger you are doing business with, and using it on somebody your person could introduce you to in two clicks costs them a negotiation instead. To list chats you can already read, use grant_list scopeKind=chat.',
|
|
55
|
-
mcp: 'Open or reuse a chat with a user or agent participant. Calling it again for the same participant returns the SAME chat; pass newChat only when this really is a separate subject. Opening a room is issuing the other side access to it, so it needs something that authorizes that: they publish a listing, you share an org, you hold a live agreement with them (a link counts, so ziggs_link_propose is how you get one with a peer in another org), or they claimed your invite. With none of those the call is refused and names the levers. When the person you cannot reach is somebody your own person already knows — their teammate, their partner, their customer — ask that person to open a room with them and add you, rather than reaching for a listing or an invite: those are for strangers you are doing business with.',
|
|
54
|
+
sdk: 'Open or reuse a chat with a user or agent participant. Calling it again for the same participant returns the SAME chat, so it is how you find the conversation you already have with someone — pass newChat only when this really is a separate subject. This is also how you reach the HUMAN who hired you when the work needs an answer only they have: pass their user id (context_snapshot lists it under users; on your agreement they are the payer/creator party), then chat_send in the chat it returns with no receiverId. Opening a room is issuing the other side access to it, so it needs something that authorizes that: they publish a listing, you share an org, you hold a live agreement with them (a link counts, so link_propose is how you get one with a peer in another org), or they claimed your invite. Someone else\'s agent is not opened directly, inside your org or outside it: open the chat with the person it answers for (their user id); which of their agents answers is theirs to decide, and an agent of theirs already in a room with you can be written to there. With none of those the call is refused and the refusal names the levers. When the person you cannot reach is somebody YOUR OWN PERSON already knows — their teammate, their partner, their customer — none of those levers is the right one: ask the person you work for to open a room with them and add you, in plain words in your conversation with them, then stop until you are in it. Claiming a listing or sending an invite is for a stranger you are doing business with, and using it on somebody your person could introduce you to in two clicks costs them a negotiation instead. To list chats you can already read, use grant_list scopeKind=chat.',
|
|
55
|
+
mcp: 'Open or reuse a chat with a user or agent participant. Calling it again for the same participant returns the SAME chat; pass newChat only when this really is a separate subject. Opening a room is issuing the other side access to it, so it needs something that authorizes that: they publish a listing, you share an org, you hold a live agreement with them (a link counts, so ziggs_link_propose is how you get one with a peer in another org), or they claimed your invite. Someone else\'s agent is not opened directly, inside your org or outside it: open the chat with the person it answers for (their user id); which of their agents answers is theirs to decide, and an agent of theirs already in a room with you can be written to there. With none of those the call is refused and names the levers. When the person you cannot reach is somebody your own person already knows — their teammate, their partner, their customer — ask that person to open a room with them and add you, rather than reaching for a listing or an invite: those are for strangers you are doing business with.',
|
|
56
56
|
},
|
|
57
57
|
annotation: 'write',
|
|
58
58
|
params: {
|
|
59
59
|
participantId: {
|
|
60
60
|
type: 'string',
|
|
61
61
|
required: true,
|
|
62
|
-
description: 'Known user or agent id from search, a directory, a chat, or an agreement. No existing chat is required; do not guess ids.',
|
|
62
|
+
description: 'Known user or agent id from search, a directory, a chat, or an agreement. For a teammate or a linked person, their user id, not an agent of theirs. No existing chat is required; do not guess ids.',
|
|
63
63
|
},
|
|
64
64
|
newChat: {
|
|
65
65
|
type: 'boolean',
|
|
@@ -5,15 +5,15 @@ export const agentSearchCapability = {
|
|
|
5
5
|
names: { sdk: 'agent_search', mcp: 'ziggs_agent_search' },
|
|
6
6
|
title: 'Search for agents',
|
|
7
7
|
descriptions: {
|
|
8
|
-
sdk: 'Search for agents by capability, name, or description. Returns ranked results with relevance scores. A keyword/natural-language query searches the published store
|
|
9
|
-
mcp: 'Find agents (AgentSearchClient). A keyword/natural-language query searches the published store
|
|
8
|
+
sdk: 'Search for agents by capability, name, or description. Returns ranked results with relevance scores. A keyword/natural-language query searches the published store, your org\'s own agents and your own agents, and it matches your teammates by name: a teammate comes back under `people` as a person to message (chat_open with their userId), never as a list of their agents. Someone else\'s agent is reached through the person it answers for, inside your org and outside it: you message the person, which of their agents answers is theirs to decide, and their agents become known to you by turning up in rooms. A link works the same way: reach a linked person through the link itself (link_list gives their addressable peer id, then chat_open). Passing an EXACT agent id resolves that one agent when you can reach it. Each row carries `doors` — its engagement doors: doors.listingAgreementId is a live listing to CLAIM (agreement_claim — the default, one hop from here) and doors.acceptsProposals says whether a direct proposal would even be accepted (most published agents are claim-only). Use returned agentId in grant/issue tools — do not guess ids.',
|
|
9
|
+
mcp: 'Find agents (AgentSearchClient). A keyword/natural-language query searches the published store, your org\'s own agents and your own agents. It also matches your teammates by name: a teammate comes back under `people` (userId and name) as a person to message with ziggs_chat_open participantId=<userId>, never as a list of their agents. Someone else\'s agent is reached through the person it answers for, inside your org and outside it: you message the person, which of their agents answers is theirs to decide, and their agents become known to you by turning up in rooms. A link works the same way: take a linked person\'s peer id from ziggs_link_list and ziggs_chat_open with that. Passing an EXACT agent id resolves that one agent when you can reach it — an id you cannot reach comes back `reachability: "restricted"` with no name/profile, and another person\'s unpublished agent is one of those. Each row carries `doors` — its engagement doors: doors.listingAgreementId is a live listing to CLAIM (ziggs_agreement_claim — the default, one hop from here) and doors.acceptsProposals says whether a direct proposal would even be accepted (most published agents are claim-only). Each result carries a per-row `reachability` field derived from HOW you can reach it — `published` (store directory), `same-org` (your org\'s own agent), `managed` (yours), or `engaged`; it is not a blanket "published" label. Use returned agentId in grant/issue tools — do not guess ids.',
|
|
10
10
|
},
|
|
11
11
|
annotation: 'read-only',
|
|
12
12
|
params: {
|
|
13
13
|
query: {
|
|
14
14
|
type: 'string',
|
|
15
15
|
required: true,
|
|
16
|
-
description:
|
|
16
|
+
description: "Keyword/natural-language search (published store, your org's own agents, your own agents, and teammates by name) OR an exact agent id (resolves that agent when you can reach it)",
|
|
17
17
|
},
|
|
18
18
|
limit: { type: 'number', description: 'Max results (default server-side)' },
|
|
19
19
|
minScore: { type: 'number', description: 'Minimum match score filter' },
|
|
@@ -31,27 +31,37 @@ export const agentSearchCapability = {
|
|
|
31
31
|
if (!result.success) {
|
|
32
32
|
throw new Error(result.error ?? result.message ?? 'search failed');
|
|
33
33
|
}
|
|
34
|
+
const chatOpen = env.surface === 'mcp' ? 'ziggs_chat_open' : 'chat_open';
|
|
35
|
+
const linkList = env.surface === 'mcp' ? 'ziggs_link_list' : 'link_list';
|
|
36
|
+
const people = result.people ?? [];
|
|
37
|
+
const messageThem = people.length
|
|
38
|
+
? {
|
|
39
|
+
people,
|
|
40
|
+
peopleNote: `These are teammates whose name matched. Message the person with ${chatOpen} participantId=<userId>; which of their agents answers is theirs to decide.`,
|
|
41
|
+
}
|
|
42
|
+
: {};
|
|
34
43
|
if (!result.agents?.length) {
|
|
35
44
|
// a bare {count: 0} reads as "discovery is down" to LLM
|
|
36
45
|
// callers — say what was searched and how to recover instead.
|
|
37
46
|
return {
|
|
38
47
|
count: 0,
|
|
39
48
|
agents: [],
|
|
49
|
+
...messageThem,
|
|
40
50
|
searched: [
|
|
41
51
|
'published store: agents by name, description and tags',
|
|
42
|
-
|
|
43
|
-
'your org: people by name (
|
|
52
|
+
"your org's own agents and your own agents: by name, description and tags",
|
|
53
|
+
'your org: people by name (returned under people, to message as people)',
|
|
44
54
|
],
|
|
45
|
-
hint: 'Zero
|
|
46
|
-
|
|
47
|
-
|
|
55
|
+
hint: 'Zero agents means no agent matched these terms; discovery itself is up. ' +
|
|
56
|
+
"People are not agents: a teammate is found by their name and comes back under people, never as their agents. " +
|
|
57
|
+
`To reach them, open a chat with that user id (${chatOpen} participantId). ` +
|
|
48
58
|
'Matching is lexical, so try shorter or different keywords. ' +
|
|
49
59
|
'If you already know the agent, pass its exact agent id as the query to resolve it directly. ' +
|
|
50
60
|
'Searching for someone you are LINKED with will always miss: a link makes the person addressable, ' +
|
|
51
|
-
|
|
61
|
+
`not their agents. Take their peer id from ${linkList} and open a chat with the person instead.`,
|
|
52
62
|
};
|
|
53
63
|
}
|
|
54
|
-
return { count: result.agents.length, agents: result.agents };
|
|
64
|
+
return { count: result.agents.length, agents: result.agents, ...messageThem };
|
|
55
65
|
},
|
|
56
66
|
sdkOptions: { isGenericFallback: true },
|
|
57
67
|
};
|
|
@@ -5,9 +5,18 @@ export interface AgentSearchOptions {
|
|
|
5
5
|
export interface AgentSearchResult {
|
|
6
6
|
success: boolean;
|
|
7
7
|
agents?: AgentProfile[];
|
|
8
|
+
/**
|
|
9
|
+
* Teammates whose name matched, as people to message. Their agents are not
|
|
10
|
+
* listed: someone else's agent is reached through the person it answers for.
|
|
11
|
+
*/
|
|
12
|
+
people?: AgentSearchPerson[];
|
|
8
13
|
error?: string;
|
|
9
14
|
message?: string;
|
|
10
15
|
}
|
|
16
|
+
export interface AgentSearchPerson {
|
|
17
|
+
userId: string;
|
|
18
|
+
displayName: string;
|
|
19
|
+
}
|
|
11
20
|
export interface AgentProfile {
|
|
12
21
|
agentId: string;
|
|
13
22
|
name: string;
|
|
@@ -33,8 +33,8 @@ export class AgentSearchClient {
|
|
|
33
33
|
runtimeLog.warn('AgentSearchClient', `⚠️ searchAgents failed agent=${this.agentId} ${response.status} ${response.statusText} url=${url} body=${errorText.slice(0, 200)}`);
|
|
34
34
|
return { success: false, error: `Search failed: ${response.status}`, message: errorText };
|
|
35
35
|
}
|
|
36
|
-
const { results = [] } = await response.json();
|
|
37
|
-
return { success: true, agents: results };
|
|
36
|
+
const { results = [], people = [] } = await response.json();
|
|
37
|
+
return { success: true, agents: results, people };
|
|
38
38
|
}
|
|
39
39
|
catch (error) {
|
|
40
40
|
runtimeLog.warn('AgentSearchClient', `⚠️ searchAgents error agent=${this.agentId} url=${url} message=${error.message}`);
|