@ziggs-ai/api-client 0.26.0 → 0.28.0
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/dist/capabilities/artifacts.js +1 -1
- package/dist/capabilities/chat.js +28 -8
- package/dist/capabilities/connections.js +2 -2
- package/dist/capabilities/context.js +1 -1
- package/dist/engagementGuide.js +1 -1
- package/dist/http/ChatClient.d.ts +23 -0
- package/dist/http/ChatClient.js +22 -0
- package/package.json +1 -1
|
@@ -304,7 +304,7 @@ export const listArtifactsCapability = {
|
|
|
304
304
|
mcp: 'List business artifacts YOU authored, across every scope and none; tool-operation and thought traces are excluded. Use this to find something you ' +
|
|
305
305
|
'recorded free-standing (no chat/agreement/task), which the scope reads cannot return. ' +
|
|
306
306
|
'To read an artifact someone shared WITH you, use ziggs_context_read with via=artifact:<id>; ' +
|
|
307
|
-
'to see what has been shared with you, use ziggs_grant_list with scopeKind
|
|
307
|
+
'to see what has been shared with you, use ziggs_grant_list with scopeKind ["artifact"].',
|
|
308
308
|
},
|
|
309
309
|
annotation: 'read-only',
|
|
310
310
|
params: {
|
|
@@ -33,9 +33,12 @@ export function presentSendResult(result, env) {
|
|
|
33
33
|
const destination = delivery.broadcast
|
|
34
34
|
? 'the humans in the room, not one addressee'
|
|
35
35
|
: `${delivery.to.id} (${delivery.to.type})`;
|
|
36
|
+
// What counted it, in the server's words: a stranger's free messages with a
|
|
37
|
+
// listed agent run out, and the person writing needs to know before they do.
|
|
38
|
+
const counted = result.coverage?.message ? ` ${result.coverage.message}` : '';
|
|
36
39
|
return {
|
|
37
40
|
...base,
|
|
38
|
-
delivered: `Message ${result.messageId} was accepted into chat ${result.chatId}, addressed to ${destination}. Mailbox routing is unconfirmed; a person may be covered by an assistant. Accepted is not read and does not confirm a wake or reply
|
|
41
|
+
delivered: `Message ${result.messageId} was accepted into chat ${result.chatId}, addressed to ${destination}. Mailbox routing is unconfirmed; a person may be covered by an assistant. Accepted is not read and does not confirm a wake or reply.${counted}`,
|
|
39
42
|
to: delivery.to,
|
|
40
43
|
};
|
|
41
44
|
}
|
|
@@ -51,8 +54,8 @@ export const openConversationCapability = {
|
|
|
51
54
|
names: { sdk: 'chat_open', mcp: 'ziggs_chat_open' },
|
|
52
55
|
title: 'Start or reuse a conversation',
|
|
53
56
|
descriptions: {
|
|
54
|
-
sdk: 'Open a conversation or explicitly invite people to a room. participantId opens/reuses the acting agent’s pair conversation with one person or agent; newChat opens a separate subject. participantIds creates a separate group with the acting caller and those people; include a stable idempotencyKey for retries. chatId plus participantIds invites people into that exact room, requiring room access and admission authority. Every person needs a valid contact basis: shared organization membership, a link, or an applicable agreement. Each participant keeps their own agent and work relationships; opening a group selects no service agreement. Group creation never expands an existing private DM. Invited teammates read from admission onward.
|
|
55
|
-
mcp: 'Open a conversation or explicitly invite people to a room. participantId opens/reuses the acting agent’s pair conversation with one person or agent; newChat opens a separate subject. participantIds creates a separate group with the acting caller and those people; include a stable idempotencyKey for retries. chatId plus participantIds invites people into that exact room, requiring room access and admission authority. Every person needs a valid contact basis: shared organization membership, a link, or an applicable agreement. Each participant keeps their own agent and work relationships; opening a group selects no service agreement. Group creation never expands an existing private DM. Invited teammates read from admission onward.
|
|
57
|
+
sdk: 'Open a conversation or explicitly invite people to a room. participantId opens/reuses the acting agent’s pair conversation with one person or agent; newChat opens a separate subject. participantIds creates a separate group with the acting caller and those people; include a stable idempotencyKey for retries. chatId plus participantIds invites people into that exact room, requiring room access and admission authority. Every person needs a valid contact basis: shared organization membership, a link, or an applicable agreement. Each participant keeps their own agent and work relationships; opening a group selects no service agreement. Group creation never expands an existing private DM. Invited teammates read from admission onward. A new group is opened with people. With chatId, participantIds may also name agents: each joins through the same admission as the web app, so it must be reachable (your own, one of your company, published, or already engaged), and an agent you invite waits until the people in the room approve it in the app; the result lists each id as added, already-here or pending. Your own missing seat is asked for with access_request. Reach another person through their user id, not an unpublished agent of theirs. If you cannot reach someone your person knows, ask your person to introduce you in a room. Opening does not send a message; chat_send must name its intended receiverId to guarantee a target. To list accessible rooms, use grant_list with scopeKind ["chat"].',
|
|
58
|
+
mcp: 'Open a conversation or explicitly invite people to a room. participantId opens/reuses the acting agent’s pair conversation with one person or agent; newChat opens a separate subject. participantIds creates a separate group with the acting caller and those people; include a stable idempotencyKey for retries. chatId plus participantIds invites people into that exact room, requiring room access and admission authority. Every person needs a valid contact basis: shared organization membership, a link, or an applicable agreement. Each participant keeps their own agent and work relationships; opening a group selects no service agreement. Group creation never expands an existing private DM. Invited teammates read from admission onward. A new group is opened with people. With chatId, participantIds may also name agents: each joins through the same admission as the web app, so it must be reachable (your own, one of your company, published, or already engaged), and an agent you invite waits until the people in the room approve it in the app; the result lists each id as added, already-here or pending. Your own missing seat is asked for with ziggs_access_request. Reach another person through their user id, not an unpublished agent of theirs. For missing access to a known room, use ziggs_access_request; opening another room does not recover its history. Opening does not send a message; ziggs_chat_send must name its intended receiverId to guarantee a target.',
|
|
56
59
|
},
|
|
57
60
|
annotation: 'write',
|
|
58
61
|
params: {
|
|
@@ -60,7 +63,7 @@ export const openConversationCapability = {
|
|
|
60
63
|
type: 'string',
|
|
61
64
|
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.',
|
|
62
65
|
},
|
|
63
|
-
participantIds: { type: 'array', items: { type: 'string' }, description: '1–20 known
|
|
66
|
+
participantIds: { type: 'array', items: { type: 'string' }, description: '1–20 known ids. Without chatId: people, for a separate group. With chatId: people or agents to invite into that room (an agent waits for the room\'s people to approve). Use instead of participantId. Each invitation is authorized separately.' },
|
|
64
67
|
chatId: { type: 'string', description: 'Existing room to invite participantIds into. Never creates another room. Omit creation options and agreementId.' },
|
|
65
68
|
idempotencyKey: { type: 'string', description: 'Required for group creation: a unique key for this conversation, reused unchanged on retries. A different participant set needs a new key.' },
|
|
66
69
|
createIfMissing: { type: 'boolean', description: 'Set false to reuse only an existing room for this acting agent and participant. A missing room is refused without creating a replacement.' },
|
|
@@ -87,7 +90,7 @@ export const openConversationCapability = {
|
|
|
87
90
|
if (args.participantId !== undefined || !Array.isArray(args.participantIds) ||
|
|
88
91
|
args.participantIds.length < 1 || args.participantIds.length > 20 ||
|
|
89
92
|
args.participantIds.some(id => typeof id !== 'string' || !id.trim())) {
|
|
90
|
-
throw new Error('Use participantIds containing 1–20
|
|
93
|
+
throw new Error('Use participantIds containing 1–20 ids, without participantId');
|
|
91
94
|
}
|
|
92
95
|
if (!args.chatId && (typeof args.idempotencyKey !== 'string' || !args.idempotencyKey.trim())) {
|
|
93
96
|
throw new Error('Group creation requires an idempotencyKey; reuse it when retrying');
|
|
@@ -96,7 +99,7 @@ export const openConversationCapability = {
|
|
|
96
99
|
else if (args.chatId || args.idempotencyKey) {
|
|
97
100
|
throw new Error('chatId and idempotencyKey require participantIds');
|
|
98
101
|
}
|
|
99
|
-
const { chatId, reused } = await openConversation({
|
|
102
|
+
const { chatId, reused, invited } = await openConversation({
|
|
100
103
|
...(typeof args.participantId === 'string' ? { participantId: args.participantId } : {}),
|
|
101
104
|
...(Array.isArray(args.participantIds) ? { participantIds: args.participantIds } : {}),
|
|
102
105
|
...(typeof args.chatId === 'string' ? { chatId: args.chatId } : {}),
|
|
@@ -106,14 +109,14 @@ export const openConversationCapability = {
|
|
|
106
109
|
...(typeof args.agreementId === 'string' && args.agreementId ? { agreementId: args.agreementId } : {}),
|
|
107
110
|
}, fullCreds(env));
|
|
108
111
|
const lister = env.surface === 'mcp' ? 'ziggs_grant_list' : 'grant_list';
|
|
109
|
-
const grantNote = `Use ${lister} scopeKind
|
|
112
|
+
const grantNote = `Use ${lister} with scopeKind ["chat"] to inspect your room grants. Opening a conversation does not send a message or confirm that anyone has read it.`;
|
|
110
113
|
// word the note from the outcome instead of covering both cases.
|
|
111
114
|
// "Open (or reused)" told the agent the distinction existed and then
|
|
112
115
|
// withheld it — worse than silence, because the agent cannot even tell
|
|
113
116
|
// there is something to look up. A backend too old to report it keeps the
|
|
114
117
|
// old both-cases wording, and `reused` is simply absent from the result.
|
|
115
118
|
const outcomeNote = args.chatId
|
|
116
|
-
?
|
|
119
|
+
? inviteNote(invited)
|
|
117
120
|
: reused === true
|
|
118
121
|
? 'Reused the conversation you already had with the named participants, so it may already hold history — read it before you speak.'
|
|
119
122
|
: reused === false
|
|
@@ -123,8 +126,25 @@ export const openConversationCapability = {
|
|
|
123
126
|
chatId,
|
|
124
127
|
actingAgentId: fullCreds(env).agentId,
|
|
125
128
|
...(typeof reused === 'boolean' ? { reused } : {}),
|
|
129
|
+
...(invited ? { invited } : {}),
|
|
126
130
|
note: `${outcomeNote} ${grantNote}`,
|
|
127
131
|
};
|
|
128
132
|
},
|
|
129
133
|
};
|
|
134
|
+
/** Say what happened to each invited id, so the agent reports it truthfully. */
|
|
135
|
+
function inviteNote(invited) {
|
|
136
|
+
if (!invited?.length) {
|
|
137
|
+
return 'The named people can participate in this room. Their history access remains bounded by their grants.';
|
|
138
|
+
}
|
|
139
|
+
const ids = (status) => invited.filter((row) => row.status === status).map((row) => row.id);
|
|
140
|
+
const parts = [];
|
|
141
|
+
if (ids('added').length)
|
|
142
|
+
parts.push(`Added: ${ids('added').join(', ')}.`);
|
|
143
|
+
if (ids('already-here').length)
|
|
144
|
+
parts.push(`Already in the room: ${ids('already-here').join(', ')}.`);
|
|
145
|
+
if (ids('pending').length) {
|
|
146
|
+
parts.push(`Waiting for the people in the room to approve: ${ids('pending').join(', ')}. They see it in the app; the agent cannot read or write here until then, and asking again does not make a second request.`);
|
|
147
|
+
}
|
|
148
|
+
return `${parts.join(' ')} Invited people read from now on.`;
|
|
149
|
+
}
|
|
130
150
|
export const CHAT_CAPABILITIES = [openConversationCapability];
|
|
@@ -19,7 +19,7 @@ export const connectionProxyCapability = {
|
|
|
19
19
|
sdk: "Use a named-connector stored connection (e.g. the owner's GitHub/Jira) without ever seeing the credential. " +
|
|
20
20
|
"Calls the backend connections proxy with a grant the owner issued to this agent. " +
|
|
21
21
|
'Not for remote MCP servers (provider "mcp") — those use mcp_tool_call / mcp_tools_list; proxy refuses them with "Unknown provider: mcp". ' +
|
|
22
|
-
"Don't know connectionId/grantId yet? Use grant_list (scopeKind
|
|
22
|
+
"Don't know connectionId/grantId yet? Use grant_list (scopeKind [\"connection\"]) or connection_list_grants first.",
|
|
23
23
|
mcp: "Use a named-connector stored connection (e.g. the owner's GitHub/Jira — NOT an agent-to-agent Link, see ziggs_link_list) without ever seeing the credential. " +
|
|
24
24
|
"Calls the backend connections proxy with a grant the owner issued to this agent. " +
|
|
25
25
|
'Not for remote MCP servers (provider "mcp") — those use ziggs_mcp_tool_call / ziggs_mcp_tools_list; proxy refuses them with "Unknown provider: mcp". ' +
|
|
@@ -128,7 +128,7 @@ export const requestConnectionCapability = {
|
|
|
128
128
|
? "A connection-consent card is now in the chat awaiting your principal. Tell the human now (pull-only MCP has no push) — they approve it right in the chat. " +
|
|
129
129
|
"Once approved, the connection + grant appear in ziggs_connection_list for ziggs_mcp_tools_list / ziggs_mcp_tool_call."
|
|
130
130
|
: "A connection-consent card is now in the chat awaiting your principal — they approve it right there. " +
|
|
131
|
-
"Once approved, the connection + grant appear in grant_list (scopeKind
|
|
131
|
+
"Once approved, the connection + grant appear in grant_list (scopeKind [\"connection\"]) / connection_list_grants for mcp_tools_list / mcp_tool_call.",
|
|
132
132
|
};
|
|
133
133
|
}
|
|
134
134
|
catch (e) {
|
|
@@ -64,7 +64,7 @@ export const contextReadCapability = {
|
|
|
64
64
|
title: 'Read context you hold',
|
|
65
65
|
descriptions: {
|
|
66
66
|
sdk: `Read the contents of a scope you already hold a grant for: ${CONTEXT_READ_TYPES.join(' | ')}. Each type reads through its own entries — ${VIA_BY_TYPE}. Use grant_list first to see which scopes your grants cover, then read through any of them. ${ARTIFACT_VIA_NOTE}. Cursored; all access is grant-fenced server-side.`,
|
|
67
|
-
mcp: `Read the contents of a scope you already hold: ${CONTEXT_READ_TYPES.join(' | ')} (the type param). Each type accepts its own via entries — ${VIA_BY_TYPE} — and any other pairing is refused. ${ARTIFACT_VIA_NOTE} (e.g. an artifact someone shared with you; ziggs_grant_list scopeKind
|
|
67
|
+
mcp: `Read the contents of a scope you already hold: ${CONTEXT_READ_TYPES.join(' | ')} (the type param). Each type accepts its own via entries — ${VIA_BY_TYPE} — and any other pairing is refused. ${ARTIFACT_VIA_NOTE} (e.g. an artifact someone shared with you; ziggs_grant_list with scopeKind ["artifact"] shows those). Forward-delta with after+direction=forward; cursor pagination; contextGrantId pins a grant. The response carries a \`readPlan\` with the next page and/or forward-delta call pre-filled (after=this page's latestSequence), so you can keep reading without rebuilding args. This is the single read path for all four types — to discover which scopes exist, use the listers: ziggs_chat_list, ziggs_task_list, ziggs_agreement_list, ziggs_grant_list, ziggs_link_list.`,
|
|
68
68
|
},
|
|
69
69
|
annotation: 'read-only',
|
|
70
70
|
params: {
|
package/dist/engagementGuide.js
CHANGED
|
@@ -272,7 +272,7 @@ export function strangerBriefGuide(env, chatId) {
|
|
|
272
272
|
kind: 'stranger_brief',
|
|
273
273
|
outcome: 'pending',
|
|
274
274
|
chatId,
|
|
275
|
-
summary: "A stranger's brief is not a work order.
|
|
275
|
+
summary: "A stranger's brief is not a work order. They hire you through your store listing, or through an agreement you draft when you have none; do not create a task under a hire you do not have.",
|
|
276
276
|
next: nextCall(env, 'agreement_request', undefined, 'draft the agreement this brief would ride', { definition: agreementRequestCapability }),
|
|
277
277
|
};
|
|
278
278
|
}
|
|
@@ -13,6 +13,14 @@ import { type Creds } from '../types.js';
|
|
|
13
13
|
* with without a second call.
|
|
14
14
|
*/
|
|
15
15
|
export type ChatSummary = ChatReadDto;
|
|
16
|
+
/** What happened to one id when chat_open invited into an existing room. */
|
|
17
|
+
export interface ChatOpenInvite {
|
|
18
|
+
id: string;
|
|
19
|
+
kind: 'person' | 'agent';
|
|
20
|
+
/** pending: an agent's joining waits for the people in the room to approve it. */
|
|
21
|
+
status: 'added' | 'already-here' | 'pending';
|
|
22
|
+
admissionId?: string;
|
|
23
|
+
}
|
|
16
24
|
export interface OpenConversationInput {
|
|
17
25
|
participantId?: string;
|
|
18
26
|
participantIds?: string[];
|
|
@@ -29,6 +37,7 @@ export declare function openConversation(participant: string | OpenConversationI
|
|
|
29
37
|
}): Promise<{
|
|
30
38
|
chatId: string;
|
|
31
39
|
reused?: boolean;
|
|
40
|
+
invited?: ChatOpenInvite[];
|
|
32
41
|
}>;
|
|
33
42
|
export interface SendChatMessageInput {
|
|
34
43
|
/**
|
|
@@ -84,7 +93,20 @@ export type { MessageDelivery } from '@ziggs-ai/contracts';
|
|
|
84
93
|
*/
|
|
85
94
|
export type SendChatMessageResult = Omit<WireSendChatMessageResult, 'delivery'> & {
|
|
86
95
|
delivery?: MessageDelivery;
|
|
96
|
+
/**
|
|
97
|
+
* What covers this message, when something counts it: a hire's shared
|
|
98
|
+
* allowance, or a listed agent's free messages for a stranger ("2 of 3 free
|
|
99
|
+
* messages used with seo-growth."). Absent for ordinary conversation.
|
|
100
|
+
*/
|
|
101
|
+
coverage?: ConversationCoverageReceipt;
|
|
87
102
|
};
|
|
103
|
+
/** The server's receipt for a counted message. */
|
|
104
|
+
export interface ConversationCoverageReceipt {
|
|
105
|
+
agreementId: string;
|
|
106
|
+
messagesUsed: number;
|
|
107
|
+
messageLimit: number | null;
|
|
108
|
+
message: string;
|
|
109
|
+
}
|
|
88
110
|
export type ContextTemporal = 'from-now' | 'from-start';
|
|
89
111
|
export interface AddChatMemberInput {
|
|
90
112
|
chatId: string;
|
|
@@ -135,6 +157,7 @@ export declare class ChatClient {
|
|
|
135
157
|
}): Promise<{
|
|
136
158
|
chatId: string;
|
|
137
159
|
reused?: boolean;
|
|
160
|
+
invited?: ChatOpenInvite[];
|
|
138
161
|
}>;
|
|
139
162
|
addMember(input: AddChatMemberInput): Promise<AddChatMemberResult>;
|
|
140
163
|
sendMessage(input: SendChatMessageInput): Promise<SendChatMessageResult>;
|
package/dist/http/ChatClient.js
CHANGED
|
@@ -38,11 +38,31 @@ export async function openConversation(participant, creds, { newChat = false, ag
|
|
|
38
38
|
// the room — defaulting to false would report a reused conversation as fresh,
|
|
39
39
|
// which is worse than saying nothing.
|
|
40
40
|
const reused = data['reused'];
|
|
41
|
+
const invited = Array.isArray(data['invited'])
|
|
42
|
+
? data['invited']
|
|
43
|
+
: undefined;
|
|
41
44
|
return {
|
|
42
45
|
chatId: data['chatId'],
|
|
43
46
|
...(typeof reused === 'boolean' ? { reused } : {}),
|
|
47
|
+
...(invited ? { invited } : {}),
|
|
44
48
|
};
|
|
45
49
|
}
|
|
50
|
+
function coverageFrom(value) {
|
|
51
|
+
if (!value || typeof value !== 'object')
|
|
52
|
+
return null;
|
|
53
|
+
const row = value;
|
|
54
|
+
return typeof row['agreementId'] === 'string' &&
|
|
55
|
+
typeof row['message'] === 'string' &&
|
|
56
|
+
typeof row['messagesUsed'] === 'number' &&
|
|
57
|
+
(row['messageLimit'] === null || typeof row['messageLimit'] === 'number')
|
|
58
|
+
? {
|
|
59
|
+
agreementId: row['agreementId'],
|
|
60
|
+
messagesUsed: row['messagesUsed'],
|
|
61
|
+
messageLimit: row['messageLimit'],
|
|
62
|
+
message: row['message'],
|
|
63
|
+
}
|
|
64
|
+
: null;
|
|
65
|
+
}
|
|
46
66
|
/**
|
|
47
67
|
* POST /chats/:chatId/members — add user/agent; agent-invite may return pending admission.
|
|
48
68
|
*/
|
|
@@ -115,6 +135,7 @@ export async function sendChatMessage(input, creds) {
|
|
|
115
135
|
}
|
|
116
136
|
const data = (await res.json().catch(() => null));
|
|
117
137
|
const delivery = data?.['delivery'];
|
|
138
|
+
const coverage = coverageFrom(data?.['coverage']);
|
|
118
139
|
return {
|
|
119
140
|
success: Boolean(data?.['success']),
|
|
120
141
|
message: String(data?.['message'] ?? 'ok'),
|
|
@@ -126,6 +147,7 @@ export async function sendChatMessage(input, creds) {
|
|
|
126
147
|
...(delivery && typeof delivery === 'object'
|
|
127
148
|
? { delivery: delivery }
|
|
128
149
|
: {}),
|
|
150
|
+
...(coverage ? { coverage } : {}),
|
|
129
151
|
};
|
|
130
152
|
}
|
|
131
153
|
export async function listMyChats(creds) {
|