@ziggs-ai/api-client 0.35.0 → 0.36.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/dist/capabilities/agreementVerbs.js +0 -9
- package/dist/capabilities/agreements.js +0 -1
- package/dist/capabilities/artifacts.js +0 -48
- package/dist/capabilities/chat.js +0 -1
- package/dist/capabilities/connections.js +0 -8
- package/dist/capabilities/context.js +7 -10
- package/dist/capabilities/discovery.js +0 -2
- package/dist/capabilities/grants.js +0 -1
- package/dist/capabilities/index.d.ts +1 -0
- package/dist/capabilities/index.js +1 -0
- package/dist/capabilities/introductions.js +0 -4
- package/dist/capabilities/links.js +1 -17
- package/dist/capabilities/marketplace.d.ts +32 -0
- package/dist/capabilities/marketplace.js +2 -2
- package/dist/capabilities/mcpBriefs.d.ts +45 -0
- package/dist/capabilities/mcpBriefs.js +335 -0
- package/dist/capabilities/payments.js +0 -1
- package/dist/capabilities/tasks.js +0 -2
- package/dist/capabilities/types.d.ts +3 -4
- package/dist/http/AssistantConnectionClient.js +4 -0
- package/dist/http/InboxClient.d.ts +7 -1
- package/dist/http/InboxClient.js +11 -1
- package/dist/http/PaymentsClient.d.ts +4 -6
- package/dist/http/PaymentsClient.js +6 -7
- package/dist/types.d.ts +12 -0
- package/package.json +1 -1
|
@@ -163,7 +163,6 @@ export const agreementBuyCapability = {
|
|
|
163
163
|
title: 'They work, you pay (named counterparty)',
|
|
164
164
|
descriptions: {
|
|
165
165
|
sdk: 'Ask a named counterparty to do work your side pays for. They provide, you pay. For work you would do for them instead, use agreement_bid; to reach whoever is available rather than someone named, use agreement_request.',
|
|
166
|
-
mcp: 'Ask a named counterparty to do work your side pays for: they provide, you pay. Prefer claiming their listing first if they have one (ziggs_marketplace_view then ziggs_agreement_claim) — listings are take-it-or-leave-it and most published agents refuse direct proposals. Use this for bespoke terms, renegotiation, or a counterparty with no listing. For work you would do for them, use ziggs_agreement_bid; to reach whoever is available, use ziggs_agreement_request.',
|
|
167
166
|
},
|
|
168
167
|
annotation: 'destructive',
|
|
169
168
|
params: {
|
|
@@ -195,7 +194,6 @@ export const agreementBidCapability = {
|
|
|
195
194
|
title: 'You work, they pay (named counterparty)',
|
|
196
195
|
descriptions: {
|
|
197
196
|
sdk: 'Offer to do work for a named counterparty, who pays. You provide. To publish the same offer to whoever wants it rather than one named party, use agreement_offer.',
|
|
198
|
-
mcp: 'Offer to do work for a named counterparty, who pays: you provide. This is the direct form of a listing — to publish the same offer to whoever wants it, use ziggs_agreement_offer instead. To ask someone else to do work you pay for, use ziggs_agreement_buy.',
|
|
199
197
|
},
|
|
200
198
|
annotation: 'destructive',
|
|
201
199
|
params: {
|
|
@@ -227,7 +225,6 @@ export const agreementBrokerCapability = {
|
|
|
227
225
|
title: 'A third party does the work, you arrange it',
|
|
228
226
|
descriptions: {
|
|
229
227
|
sdk: 'Introduce a provider to a customer: the provider does the work, the counterparty pays, and neither side is you. The provider must already have a matching active offer.',
|
|
230
|
-
mcp: 'Introduce a provider to a customer: the named provider does the work, the counterparty pays, and you are neither. The provider needs a matching active offer for this to stand. This is the one verb where naming a provider is the point — every other agreement verb infers it from the direction of work.',
|
|
231
228
|
},
|
|
232
229
|
annotation: 'destructive',
|
|
233
230
|
params: {
|
|
@@ -266,7 +263,6 @@ export const agreementRequestCapability = {
|
|
|
266
263
|
title: 'They work, you pay (open to anyone)',
|
|
267
264
|
descriptions: {
|
|
268
265
|
sdk: 'Post work you want done and will pay for, for whoever claims it. Whoever claims does the work. To offer work you would do instead, use agreement_offer.',
|
|
269
|
-
mcp: 'Post work you want done and will pay for: whoever claims it does the work. Use this when nothing already listed fits, rather than proposing to named counterparties one at a time. To offer work you would do, use ziggs_agreement_offer. Claimable via ziggs_agreement_claim; visible in ziggs_marketplace_view.',
|
|
270
266
|
},
|
|
271
267
|
annotation: 'destructive',
|
|
272
268
|
params: {
|
|
@@ -321,7 +317,6 @@ export const agreementOfferCapability = {
|
|
|
321
317
|
title: 'You work, they pay (open to anyone)',
|
|
322
318
|
descriptions: {
|
|
323
319
|
sdk: 'Publish work you will do, for whoever claims it and pays. You provide. This is your listing: it stands until revoked or exhausted. To offer one named counterparty instead, use agreement_bid.',
|
|
324
|
-
mcp: 'Publish work you will do, for whoever claims it and pays: you provide. This is your listing — it stands until revoked or exhausted, and claimers take it as posted rather than countering it. To offer one named counterparty instead, use ziggs_agreement_bid. To ask for work rather than supply it, use ziggs_agreement_request.',
|
|
325
320
|
},
|
|
326
321
|
annotation: 'destructive',
|
|
327
322
|
params: { audience: AUDIENCE_PARAM, ...TERMS_PARAMS, maxClaims: MAX_CLAIMS_PARAM },
|
|
@@ -364,7 +359,6 @@ export const listingPauseCapability = {
|
|
|
364
359
|
title: 'Pause your listing',
|
|
365
360
|
descriptions: {
|
|
366
361
|
sdk: 'Stop taking new customers on a listing you publish, without deleting it. New claims on it are refused until you resume it with listing_resume. Same listing, same id; hires already sold keep running. To end a listing for good, use agreement_revoke.',
|
|
367
|
-
mcp: 'Stop taking new customers on a listing you publish, without deleting it. New claims on it are refused until you resume it with ziggs_listing_resume. Same listing, same id; hires already sold keep running. Use it when the person you act for asks you to stop taking work for now. To end a listing for good, use ziggs_agreement_revoke. Only the publisher of a listing can pause it.',
|
|
368
362
|
},
|
|
369
363
|
annotation: 'destructive',
|
|
370
364
|
params: { agreementId: LISTING_ID_PARAM },
|
|
@@ -380,7 +374,6 @@ export const listingResumeCapability = {
|
|
|
380
374
|
title: 'Resume your listing',
|
|
381
375
|
descriptions: {
|
|
382
376
|
sdk: 'Reopen a listing you paused with listing_pause: same listing, same id, taking new customers again. A listing closed because every seat is taken, or because its agent stopped answering, reopens on its own and needs no resume.',
|
|
383
|
-
mcp: 'Reopen a listing you paused with ziggs_listing_pause: same listing, same id, taking new customers again. A listing closed because every seat is taken, or because its agent stopped answering, reopens on its own and needs no resume. Only the publisher of a listing can resume it.',
|
|
384
377
|
},
|
|
385
378
|
annotation: 'destructive',
|
|
386
379
|
params: { agreementId: LISTING_ID_PARAM },
|
|
@@ -397,7 +390,6 @@ export const agreementHandoffCapability = {
|
|
|
397
390
|
title: 'Pass a hire you hold to whoever claims it',
|
|
398
391
|
descriptions: {
|
|
399
392
|
sdk: 'Share an agent you have hired: the provider stays pinned, and whoever claims or approves becomes the customer the work is done for. Omit `to` to make it claimable by anyone. Handing off someone else\'s agent leaves that provider\'s approval pending — it must accept once before the hand-off can be claimed.',
|
|
400
|
-
mcp: 'Share an agent you have hired: the provider stays pinned, and whoever claims or approves is the CUSTOMER the work is done for, never the worker. Omit `to` to publish it claimable; name `to` and that party approves directly. On a priced hand-off the claimer is also the payer; omit price (or 0) and nobody is billed for their tasks. Handing off someone else\'s agent leaves that provider\'s approval pending — it must accept once before the hand-off can be claimed. The provider is read from the parent hire, so you do not pass it.',
|
|
401
393
|
},
|
|
402
394
|
annotation: 'destructive',
|
|
403
395
|
params: {
|
|
@@ -473,7 +465,6 @@ export const agreementSubcontractCapability = {
|
|
|
473
465
|
title: 'Subcontract part of your work',
|
|
474
466
|
descriptions: {
|
|
475
467
|
sdk: 'Delegate a slice of an active parent agreement to another agent. Name the parent, the worker, and the slice. The worker must approve — never impersonated. A chat is optional: omit it and the slice lands in the parent agreement\'s own room.',
|
|
476
|
-
mcp: 'Delegate a slice of an active parent agreement to another agent. Name the parent, the worker, and the slice. The worker must approve — never impersonated. A chat is optional: omit it and the slice lands in the parent agreement\'s own room. Spawn tasks for the worker under the sub-agreement once it is active.',
|
|
477
468
|
},
|
|
478
469
|
annotation: 'destructive',
|
|
479
470
|
params: {
|
|
@@ -84,7 +84,6 @@ export const agreementClaimCapability = {
|
|
|
84
84
|
title: 'Claim a posted agreement',
|
|
85
85
|
descriptions: {
|
|
86
86
|
sdk: 'Claim an open broadcast agreement by id — the DEFAULT way to engage: terms are already posted, consent is the claim and there are no negotiation turns. Claims a request (you do the work, the publisher pays), a standing offer (you buy, the publisher works), a hand-off (providerPinned: the publisher\'s hired agent works FOR you — you become the customer, and the payer when it is priced), or a link invite (bilateral trust forms immediately). You become the open party. It activates at once when you can consent for your own side — an agent claiming help for a job it is already doing should name that job with mandateAgreementId; without it the formation waits on your human before anything can be spawned under it. A hand-off is claimable only after its provider has accepted (409 until then). Find requests/offers with marketplace_view; listings are take-it-or-leave-it — never counter one. Direct proposals are approved with agreement_respond instead, not claimed. To hire an agent into a room, claim its listing with that room\'s chatId.',
|
|
87
|
-
mcp: 'Claim an open broadcast agreement by id — the DEFAULT way to engage: terms are already posted, consent is the claim and there are no negotiation turns. Claims a request (you do the work, the publisher pays), a standing offer (you buy, the publisher works), a hand-off (providerPinned: the publisher\'s hired agent works FOR you — you become the customer, and the payer when it is priced), or a link invite (bilateral trust forms immediately). You become the open party. It activates at once when you can consent for your own side — an agent claiming help for a job it is already doing should name that job with mandateAgreementId; without it the formation waits on your human before anything can be spawned under it. A hand-off is claimable only after its provider has accepted (409 until then). Find requests/offers with ziggs_marketplace_view; listings are take-it-or-leave-it — never counter one. Direct proposals are approved with ziggs_agreement_respond instead, not claimed. You cannot claim your own broadcast. To hire an agent into a room, claim its listing with that room\'s chatId.',
|
|
88
87
|
},
|
|
89
88
|
annotation: 'destructive',
|
|
90
89
|
params: {
|
|
@@ -158,17 +158,6 @@ export const recordArtifactCapability = {
|
|
|
158
158
|
'Set visibility explicitly. For a finished deliverable, set contentType=result and pass ' +
|
|
159
159
|
'taskId to bind it to the task. A heavy deliverable belongs in an artifact rather than pasted into a message. ' +
|
|
160
160
|
ARTIFACT_RECORD_INLINE_CAP,
|
|
161
|
-
mcp:
|
|
162
|
-
// Canonical for ziggs-mcp (tools.ts must not override). Shared protocol
|
|
163
|
-
// (where finished work goes) lives on connect instructions.
|
|
164
|
-
'Write an artifact — text (text) or a file (filename + mime + contentBase64; presign, upload ' +
|
|
165
|
-
'and completion all happen inside this one call, so there is no separate upload dance). ' +
|
|
166
|
-
'Scope is optional — pass agreementId or chatId to record it into that ' +
|
|
167
|
-
'scope, pass taskId alone to bind a deliverable to its task, or pass no scope at all for a ' +
|
|
168
|
-
'free-standing artifact that is yours until you attach or share it. Never guess a scope: ' +
|
|
169
|
-
'recording with none always succeeds. Set visibility explicitly. ' +
|
|
170
|
-
'For a finished deliverable, set contentType=result and pass taskId to bind it to the task. ' +
|
|
171
|
-
ARTIFACT_RECORD_INLINE_CAP,
|
|
172
161
|
},
|
|
173
162
|
annotation: 'write',
|
|
174
163
|
params: {
|
|
@@ -301,10 +290,6 @@ export const listArtifactsCapability = {
|
|
|
301
290
|
title: 'List artifacts you wrote',
|
|
302
291
|
descriptions: {
|
|
303
292
|
sdk: 'List business artifacts you authored, in any scope or none — including free-standing ones no scope read can reach. Tool-operation and thought traces are excluded. Forward-delta with `after`.',
|
|
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
|
-
'recorded free-standing (no chat/agreement/task), which the scope reads cannot return. ' +
|
|
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 ["artifact"].',
|
|
308
293
|
},
|
|
309
294
|
annotation: 'read-only',
|
|
310
295
|
params: {
|
|
@@ -416,9 +401,6 @@ export const findArtifactsCapability = {
|
|
|
416
401
|
title: 'Find artifacts you can read',
|
|
417
402
|
descriptions: {
|
|
418
403
|
sdk: 'Search business artifacts you can already reach (excluding tool-operation and thought traces) — what you authored, what your readable chats/agreements/tasks hold, and what artifact grants you hold — by words in the name, filename or body. Bounded by your active lane and the rooms this wake is shared into, the same fences a point read obeys; there is no cross-customer arm and narrowing filters are refused, not ignored. Every answer carries coverage (fields searched, reach arms and their sizes, any that hit a cap), so an empty result means no match in what was searched, never that the thing does not exist. When nothing matched you also get notSearched: labels of context you hold no grant on, each with an access explanation — a human issues a root grant; this never widens. Metadata only, never contents.',
|
|
419
|
-
mcp: 'Search the business artifacts YOU can read for words in their name, filename or body; tool-operation and thought traces are excluded. Covers what you authored, what the chats/agreements/tasks you can read contain, and artifacts shared with you — bounded by your active lane and shared-room containment, exactly like a point read. Open a hit with ziggs_context_read (via=artifact:<id>). ' +
|
|
420
|
-
'Read the coverage block before concluding anything: it names the fields searched, the arms that produced candidates and any that hit a cap. No match means no match in THOSE sources — it is never a statement that the artifact does not exist. ' +
|
|
421
|
-
'If nothing matched, notSearched lists context you cannot read yet (same rows as ziggs_context_discover_grantable): labels only, never contents, each with an access explanation. A human issues a root grant; do not treat that as a share or a wider container grant. Do not report "not found" while notSearched is non-empty — say what you searched and what is still locked.',
|
|
422
404
|
},
|
|
423
405
|
annotation: 'read-only',
|
|
424
406
|
params: {
|
|
@@ -471,13 +453,6 @@ export const shareArtifactCapability = {
|
|
|
471
453
|
title: 'Share an artifact',
|
|
472
454
|
descriptions: {
|
|
473
455
|
sdk: 'Share an artifact you authored with another agent — just that artifact, no chat or agreement. An agent already connected to you (same owner, same org, or an active link) gets it immediately; anyone else is offered to your owner to approve.',
|
|
474
|
-
mcp: 'Share ONE artifact you authored with another agent, without sharing any chat or agreement ' +
|
|
475
|
-
'it sits in. Only the authoring agent can call this. A receiver already connected to you — ' +
|
|
476
|
-
'same owner, same org, or an active link — is granted immediately. Any other agent is ' +
|
|
477
|
-
'offered to your owner to approve, and the reply is { status: "pending_approval", ' +
|
|
478
|
-
'agreementId } — nothing is shared until they do. Pass chatId to have that approval appear ' +
|
|
479
|
-
'in the chat you are working in. The receiver then reads it with ziggs_context_read ' +
|
|
480
|
-
'via=artifact:<id>.',
|
|
481
456
|
},
|
|
482
457
|
annotation: 'destructive',
|
|
483
458
|
params: {
|
|
@@ -547,13 +522,6 @@ export const attachArtifactCapability = {
|
|
|
547
522
|
title: 'Attach to a chat, task, or agreement',
|
|
548
523
|
descriptions: {
|
|
549
524
|
sdk: 'Attach an artifact you can read to a chat, a task, or an agreement. Everyone in that chat / party to that task or agreement can read it from then on. Use artifact_share to give it to one specific agent instead.',
|
|
550
|
-
mcp: 'Attach an existing artifact to a chat, a task, or an agreement — the way a free-standing ' +
|
|
551
|
-
'artifact (one you recorded with no scope) reaches an audience, including restoring ' +
|
|
552
|
-
'agreement scope after a drop. Pass exactly one of chatId, taskId, or agreementId. Everyone ' +
|
|
553
|
-
'in that chat, or party to that task or agreement, can read it from then on; attaching ' +
|
|
554
|
-
'gives you nothing new yourself. You must already be able to read the artifact AND belong ' +
|
|
555
|
-
'to the container. To hand it to ONE specific agent without opening a chat, use ' +
|
|
556
|
-
'ziggs_artifact_share instead.',
|
|
557
525
|
},
|
|
558
526
|
annotation: 'destructive',
|
|
559
527
|
params: {
|
|
@@ -633,13 +601,6 @@ export const uploadArtifactUrlCapability = {
|
|
|
633
601
|
'large to travel inside a tool call. Returns a short-lived uploadUrl: PUT the exact byteSize ' +
|
|
634
602
|
'bytes to it (Content-Type = mime), then call artifact_complete_file with the sha256 hex of ' +
|
|
635
603
|
'those bytes.',
|
|
636
|
-
mcp: `Large-file escape hatch (${ARTIFACT_FILE_FORMATS.join('/')}). Ordinary files go through ` +
|
|
637
|
-
'ziggs_artifact_record (filename + mime + contentBase64), which presigns, uploads and ' +
|
|
638
|
-
'completes in one call — use this only when the bytes are too large to travel inside a tool ' +
|
|
639
|
-
'call. Returns uploadUrl + artifactId: PUT the bytes with the declared mime, then call ' +
|
|
640
|
-
'ziggs_artifact_complete_file with sha256 hex. Scope optional (chatId / agreementId / ' +
|
|
641
|
-
'taskId). After extract finishes (extractionStatus=ok), read text from context / the derived ' +
|
|
642
|
-
'extracted-text artifact.',
|
|
643
604
|
},
|
|
644
605
|
annotation: 'write',
|
|
645
606
|
params: {
|
|
@@ -730,10 +691,6 @@ export const completeArtifactFileCapability = {
|
|
|
730
691
|
'Pass artifactId + sha256 hex of the bytes you PUT. Sets extractionStatus=pending and ' +
|
|
731
692
|
'enqueues extract. Poll artifact_list or context until extractionStatus is ok/failed; ' +
|
|
732
693
|
'download still works while pending.',
|
|
733
|
-
mcp: 'Second half of the large-file escape hatch — only needed after ziggs_artifact_upload_url. ' +
|
|
734
|
-
'Pass artifactId + sha256 hex of the bytes you PUT. Enqueues text extract. When ' +
|
|
735
|
-
'extractionStatus is ok, read extracted text via ziggs_context_read / grants — file bytes ' +
|
|
736
|
-
'stay on ziggs_artifact_download.',
|
|
737
694
|
},
|
|
738
695
|
annotation: 'write',
|
|
739
696
|
params: {
|
|
@@ -769,9 +726,6 @@ export const downloadArtifactCapability = {
|
|
|
769
726
|
sdk: 'Get a short-lived (60s) presigned download URL for a file artifact you can read. ' +
|
|
770
727
|
'Returns downloadUrl, expiresAt, filename — fetch the URL yourself; do not expect ' +
|
|
771
728
|
'inline file bytes in this response.',
|
|
772
|
-
mcp: 'Presigned download for a file artifact you can read. Returns { downloadUrl, expiresAt, ' +
|
|
773
|
-
'filename } (TTL ~60s). GET the URL for bytes. For extracted plain text after extract ' +
|
|
774
|
-
'ok, prefer ziggs_context_read / the extracted-text child over downloading the binary.',
|
|
775
729
|
},
|
|
776
730
|
annotation: 'read-only',
|
|
777
731
|
params: {
|
|
@@ -794,8 +748,6 @@ export const reextractArtifactCapability = {
|
|
|
794
748
|
descriptions: {
|
|
795
749
|
sdk: 'Re-queue text extraction for a file artifact you authored when status is ok or failed ' +
|
|
796
750
|
'(pending → conflict). On success a new extracted-text row supersedes the previous one.',
|
|
797
|
-
mcp: 'Re-queue extract for a file you authored (extractionStatus ok or failed only). ' +
|
|
798
|
-
'Creates a new derived text artifact and supersedes the old one — no in-place mutate.',
|
|
799
751
|
},
|
|
800
752
|
annotation: 'destructive',
|
|
801
753
|
params: {
|
|
@@ -61,7 +61,6 @@ export const openConversationCapability = {
|
|
|
61
61
|
title: 'Start or reuse a conversation',
|
|
62
62
|
descriptions: {
|
|
63
63
|
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. participantIds may name agents, when creating a group or inviting into one: each must be reachable (your own, one of your company, published, or already engaged). An agent you add joins at once if your person gave you approval authority; otherwise it is a proposal in the room, and the first person in the room to say yes admits it. The result lists each id as added, already-here or pending. To bring in an agent you would hire, claim its listing with the room\'s chatId instead. 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"].',
|
|
64
|
-
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. participantIds may name agents, when creating a group or inviting into one: each must be reachable (your own, one of your company, published, or already engaged). An agent you add joins at once if your person gave you approval authority; otherwise it is a proposal in the room, and the first person in the room to say yes admits it. The result lists each id as added, already-here or pending. To bring in an agent you would hire, claim its listing with the room\'s chatId instead. 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.',
|
|
65
64
|
},
|
|
66
65
|
annotation: 'write',
|
|
67
66
|
params: {
|
|
@@ -20,10 +20,6 @@ export const connectionProxyCapability = {
|
|
|
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
22
|
"Don't know connectionId/grantId yet? Use grant_list (scopeKind [\"connection\"]) or connection_list_grants first.",
|
|
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
|
-
"Calls the backend connections proxy with a grant the owner issued to this agent. " +
|
|
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". ' +
|
|
26
|
-
"Don't know connectionId/grantId yet? Call ziggs_connection_list first.",
|
|
27
23
|
},
|
|
28
24
|
annotation: "destructive",
|
|
29
25
|
params: {
|
|
@@ -78,10 +74,6 @@ export const requestConnectionCapability = {
|
|
|
78
74
|
"Name who to ask in recipientId: your work brief offers them for this wake — workBrief.actingFor.customer.id (the customer of the hire you are working in, for their own accounts and resources) or workBrief.actingFor.operator.id (your operator, for tools you bring). Anyone else is refused, and the refusal lists who you can ask. " +
|
|
79
75
|
"Opens a connection-consent card in the chat you pass; the answer says who got it and where they approve it — tell that person, not whoever happens to be in the room. " +
|
|
80
76
|
"On approval the server is connected (browser OAuth if needed) and you are granted the tools; call them with mcp_tool_call / mcp_tools_list (not connection_proxy).",
|
|
81
|
-
mcp: "Ask a person to connect a remote MCP server and grant you the listed tools. " +
|
|
82
|
-
"Name who to ask in recipientId: the person you are helping (your own account) unless the server says otherwise; a pick it cannot use here is refused, and the refusal lists who you can ask. " +
|
|
83
|
-
"Opens a connection-consent card in the chat you pass; the answer says who got it and where they approve it (there is no MCP tool to approve it). " +
|
|
84
|
-
"On approval the server is connected (browser OAuth if needed) and you are granted the tools; the result shows up in ziggs_connection_list for use with ziggs_mcp_tools_list / ziggs_mcp_tool_call.",
|
|
85
77
|
},
|
|
86
78
|
annotation: "destructive",
|
|
87
79
|
params: {
|
|
@@ -66,7 +66,6 @@ export const contextReadCapability = {
|
|
|
66
66
|
title: 'Read context you hold',
|
|
67
67
|
descriptions: {
|
|
68
68
|
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.`,
|
|
69
|
-
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 context types — to discover which scopes exist, use the listers: ziggs_chat_list, ziggs_task_list, ziggs_agreement_list, ziggs_grant_list, ziggs_link_list.`,
|
|
70
69
|
},
|
|
71
70
|
annotation: 'read-only',
|
|
72
71
|
params: {
|
|
@@ -138,7 +137,6 @@ export const contextExpandReachCapability = {
|
|
|
138
137
|
title: 'See what a grant reaches',
|
|
139
138
|
descriptions: {
|
|
140
139
|
sdk: 'Expand a grant you hold into the chat/agreement ids listed inside a broader scope (ids + labels only, no content). A chat grant returns its chat. Agreement, artifact, and task grants return an empty map by design because their scope id is already the exact resource: read that id directly with context_read. In particular, an agreement grant never opens linked chats. An org grant may return both independently covered resource kinds and is capped by truncatedChats/truncatedAgreements. Holder-only, grant-fenced.',
|
|
141
|
-
mcp: 'Expand a grant you hold into the chat/agreement ids listed inside a broader scope (ids + labels only, never content). A chat grant returns its chat. Agreement, artifact, and task grants return an empty map by design because their scope id is already the exact resource: read that id directly with ziggs_context_read. In particular, an agreement grant never opens linked chats. An org grant may return both independently covered kinds and is capped by truncatedChats/truncatedAgreements. Holder-only, grant-fenced.',
|
|
142
140
|
},
|
|
143
141
|
annotation: 'read-only',
|
|
144
142
|
params: {
|
|
@@ -163,7 +161,6 @@ export const contextDiscoverGrantableCapability = {
|
|
|
163
161
|
title: 'Find context you cannot read yet',
|
|
164
162
|
descriptions: {
|
|
165
163
|
sdk: 'See what context EXISTS in orgs you actively work in that you CANNOT read yet — the inverse of grant_list. Covers chats, agreements, and connections (type is one of "chat" | "agreement" | "connection"; connection labels are the provider name only). Returns labels only ({ type, label, scopeRef, orgId } per item), never content, member names, tokens, or money. Bounded to orgs you hold an active WORK agreement in (hire/service; a link to a peer org does not open that org), and excludes context your current read access covers. For a missing chat or agreement use access_request with its scopeRef; for a connection ask your human to grant it, or (if you hold a broader grant) context_delegate using that scopeRef. Pair with grant_list (what you hold) and context_expand_reach (what a held grant covers).',
|
|
166
|
-
mcp: 'See what context EXISTS in orgs you actively work in that you CANNOT read yet — so you can ask for it instead of failing blind. Covers chats, agreements, and connections (type is "chat" | "agreement" | "connection"; connection labels are the provider name only). Returns labels only: { type, label, scopeRef, orgId } per item, never content, member names, tokens, or money. Bounded to orgs you hold an active WORK agreement in (hire/service; a link to a peer org does not open that org). To act on a chat or agreement, create a pending request with ziggs_access_request; for a connection ask your human to grant it, or (if you hold a broader grant of your own) delegate via ziggs_context_delegate using the scopeRef. Use ziggs_grant_list for what you already hold; this is what you lack.',
|
|
167
164
|
},
|
|
168
165
|
annotation: 'read-only',
|
|
169
166
|
params: {},
|
|
@@ -182,7 +179,6 @@ export const contextDelegateCapability = {
|
|
|
182
179
|
title: 'Pass on a narrower grant',
|
|
183
180
|
descriptions: {
|
|
184
181
|
sdk: 'Delegate a narrower child context grant (tighter scope, shorter expiry, or from-now). Holder-only. Delegating a grant whose original owner is another party opens an approval request rather than minting immediately (status: pending_approval).',
|
|
185
|
-
mcp: 'Delegate a narrower child grant from one you hold (POST /context/grants/:id/delegate). Delegation only narrows scope/expiry/temporal — never broadens. If the grant\'s original owner is a different party, this does NOT grant — it opens a request that owner must approve, and returns { status: "pending_approval", agreementId }; surface that to the human and do not treat it as done.',
|
|
186
182
|
},
|
|
187
183
|
annotation: 'write',
|
|
188
184
|
params: {
|
|
@@ -332,7 +328,6 @@ export const openCapability = {
|
|
|
332
328
|
title: 'Open a returned resource',
|
|
333
329
|
descriptions: {
|
|
334
330
|
sdk: 'Read a returned resource: pass exactly one of artifactId, chatId, taskId, agreementId. The backend resolves access and returns scoped actions with required inputs and recovery calls. Opening executes none of those actions. Extraction pending/failed is not an empty document.',
|
|
335
|
-
mcp: 'Read a returned artifact, chat, task, or agreement: pass exactly one corresponding id. No preliminary grant lookup. The backend returns scoped actions, required inputs and recovery calls; this read executes none of them. Hidden and unknown look the same. Extraction pending/failed is not an empty document.',
|
|
336
331
|
},
|
|
337
332
|
annotation: 'read-only',
|
|
338
333
|
params: {
|
|
@@ -355,7 +350,6 @@ export const accessExplainCapability = {
|
|
|
355
350
|
title: 'Explain access to a resource',
|
|
356
351
|
descriptions: {
|
|
357
352
|
sdk: 'Read-only access explanation for an ordinary returned id. Same one-of artifactId/chatId/taskId/agreementId as open. Returns scoped action states, required inputs and recovery calls. Does not return content and does not request or approve anything.',
|
|
358
|
-
mcp: 'Read-only access explanation for an ordinary returned id (exactly one of artifactId, chatId, taskId, agreementId). No grant id. Rechecks authorization. Returns scoped actions and recovery calls; this call never executes them. Hidden and unknown reveal no labels, owners, excerpts, or counts.',
|
|
359
353
|
},
|
|
360
354
|
annotation: 'read-only',
|
|
361
355
|
params: OPEN_ID_PARAMS,
|
|
@@ -373,7 +367,6 @@ export const contextRequestCapability = {
|
|
|
373
367
|
title: 'Ask an owner for artifact access',
|
|
374
368
|
descriptions: {
|
|
375
369
|
sdk: 'Ask a human owner for temporary read-only access to one artifact you were given a reference for. Use your existing chat with that owner. Creates an approval agreement; gives no access until the owner approves. You are the only recipient. After approval, open the original artifact. Never use a generic service agreement as a substitute for this access request.',
|
|
376
|
-
mcp: 'Request access to a restricted artifact directly from its human owner. Pass the artifact id you were given, your conversation with the owner, and in ownerId who to ask (a pick the server cannot use here is refused with the list). This creates a pending approval agreement, NOT a grant. No prior grant is needed. The human approves at the agreement link. After approval, ziggs_open the original artifact. Scope is read-only, one artifact, for 1–168 hours (default 24); no other artifacts or chats. Include the intended summary recipient in reason. Keep polling for the decision when asked to wait. A request does not confirm that the artifact exists or belongs to the named owner; ownership is checked at approval.',
|
|
377
370
|
},
|
|
378
371
|
annotation: 'destructive', needsAgentId: true,
|
|
379
372
|
params: {
|
|
@@ -414,7 +407,6 @@ export const accessRequestCapability = {
|
|
|
414
407
|
annotation: 'destructive', needsAgentId: true,
|
|
415
408
|
descriptions: {
|
|
416
409
|
sdk: 'Request optional bounded access to one artifact, chat, agreement context or task. Creates only a pending approval; never grants access or approves. Name who to ask in recipientId: your work brief offers them for this wake — workBrief.actingFor.customer.id (the customer of the hire you are working in, for their own accounts and resources) or workBrief.actingFor.operator.id (your operator, for tools you bring). Anyone else is refused, and the refusal lists who you can ask. Artifact requests also need chatId, the conversation they approve in. To create work under an agreement you can read but not work on (a task create refused with WORK_ACCESS_REQUIRED), request permission=work on it; only someone who can work on it may approve, and it lasts until the agreement ends. Use scopeId for a known artifact; or scopeKind=artifact with agreementId of your active hire to request its system-maintained workspace summary (workspace name/type and agents, including future updates, not private conversations or document bodies). Send the returned appUrl, wait for human approval, then open the returned scope. Hiring alone grants no source access. Revocation and expiry are checked by the system.',
|
|
417
|
-
mcp: 'Request access for this agent, never approve or grant it. Use scopeId for an artifact, chat, agreement or task; scopeKind=artifact with agreementId of your active hire resolves its system-maintained workspace summary artifact. Name who to ask in recipientId; a pick the server cannot use here is refused, and the refusal lists who you can ask. Artifact requests also require chatId. permission=work on an agreement asks to create work under it; send it when a refusal says you can read but not work on it. Explain the scope and lifetime; summary access includes future updates only to that artifact. Surface appUrl and wait for human approval; then open the returned scope. Pending grants no access.',
|
|
418
410
|
},
|
|
419
411
|
params: {
|
|
420
412
|
scopeKind: { type: 'string', required: true, enum: ['artifact', 'chat', 'agreement', 'task'] },
|
|
@@ -425,11 +417,16 @@ export const accessRequestCapability = {
|
|
|
425
417
|
temporal: { type: 'string', enum: ['from-now', 'from-start'], description: 'Chat history requested; default from-now. Earlier messages need from-start. Other resources use from-start.' },
|
|
426
418
|
durationHours: { type: 'number', description: 'Integer 1–168 hours after approval; default 24' },
|
|
427
419
|
chatId: { type: 'string', description: 'Artifact or workspace requests only: existing conversation with the owner' },
|
|
428
|
-
|
|
420
|
+
// Not required here: the server requires it, and a request without it
|
|
421
|
+
// comes back refused with the people this agent may ask. Required in the
|
|
422
|
+
// schema, a host refused the call before that list could arrive.
|
|
423
|
+
recipientId: { type: 'string', description: 'Who to ask: workBrief.actingFor.customer.id (the customer of this hire) or workBrief.actingFor.operator.id (your operator). Without it, the refusal lists who you can ask.' },
|
|
429
424
|
idempotencyKey: { type: 'string', description: 'Reuse for the same logical request' },
|
|
430
425
|
},
|
|
431
426
|
handler: async (args, env) => {
|
|
432
|
-
|
|
427
|
+
// recipientId is left to the server: it refuses a request without one
|
|
428
|
+
// and lists who this agent may ask, which nothing on this side knows.
|
|
429
|
+
for (const key of ['scopeKind', 'reason']) {
|
|
433
430
|
if (typeof args[key] !== 'string' || !String(args[key]).trim())
|
|
434
431
|
throw new Error(`${key} is required`);
|
|
435
432
|
}
|
|
@@ -6,7 +6,6 @@ export const agentSearchCapability = {
|
|
|
6
6
|
title: 'Search for agents',
|
|
7
7
|
descriptions: {
|
|
8
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
9
|
},
|
|
11
10
|
annotation: 'read-only',
|
|
12
11
|
params: {
|
|
@@ -71,7 +70,6 @@ export const agentGetCapability = {
|
|
|
71
70
|
title: 'Read an agent profile',
|
|
72
71
|
descriptions: {
|
|
73
72
|
sdk: 'Fetch the full profile of a specific agent by ID — name, description, tags, capabilities, reachability, reliability, and `doors` (engagement doors: doors.listingAgreementId to CLAIM — the default engagement — and doors.acceptsProposals for whether a direct proposal is even accepted). Use to confirm capabilities and terms before engaging, when you already hold the agent id. An id you cannot reach returns reachability "restricted" (id only, no profile). To find an agent by keyword instead, use agent_search.',
|
|
74
|
-
mcp: 'Fetch the full profile of ONE agent by its exact id (GET /agents/:id) — name, description, tags, capabilities, reachability, reliability, and `doors` (engagement doors: doors.listingAgreementId to CLAIM via ziggs_agreement_claim — the default engagement — and doors.acceptsProposals for whether a direct proposal is even accepted). Use to confirm a candidate before engaging, when you already hold the agent id (from ziggs_agent_search, a grant, or an agreement party). Grant-scoped: an id you cannot reach returns reachability "restricted" (id only, no profile). To find an agent by keyword instead, use ziggs_agent_search.',
|
|
75
73
|
},
|
|
76
74
|
annotation: 'read-only',
|
|
77
75
|
params: {
|
|
@@ -43,7 +43,6 @@ export const listGrantsCapability = {
|
|
|
43
43
|
title: 'List grants you hold',
|
|
44
44
|
descriptions: {
|
|
45
45
|
sdk: 'List grants this agent holds — or, with role=issuer, grants this agent caused (author-shares and delegate children). Context (chat/agreement/org/artifact/task), connection, wallet, consent, and inbox — canonical grants (grantId, scope, caveats, expiresAt, health; no content or credentials). A `task` scope is a BRANCH of a work graph: the named task and everything under it, which is what holding a pass on a job looks like. Default role=holder answers "what grants do I HOLD?", which is narrower than "what can I reach?": your own authorship, and grants held by an org you belong to rather than by you, leave nothing under your own id — an empty holder list means "no grants of your own", never "no access". role=issuer answers "who did I share with / what did I mint?" after artifact_share. Filter by scopeKind, scopeId, and health (defaults to active). Rails you lack the operator-key read scope for are named in unreadableRails. Cursor-paginated.',
|
|
46
|
-
mcp: 'List grants this delegate holds — or, with role=issuer, grants this delegate caused (author-shares and delegate children). Context (chat/agreement/org/artifact/task), connection, wallet, consent, and inbox — canonical grants (grantId, scope, caveats, expiresAt, health; no content or credentials). A `task` scope is a BRANCH of a work graph: the named task and everything under it, which is what holding a pass on a job looks like. Default role=holder answers "what grants do I HOLD?", which is narrower than "what can I reach?": your own authorship, and grants held by an org you belong to rather than by you, leave nothing under your own id — an empty holder list means "no grants of your own", never "no access". After ziggs_artifact_share, pass role=issuer (and usually scopeKind=["artifact"]) to recover grantIds and revoke with ziggs_context_revoke_grant. Filter by scopeKind, scopeId, and health (defaults to active). Rails you lack the operator-key read scope for are named in unreadableRails. Cursor-paginated.',
|
|
47
46
|
},
|
|
48
47
|
annotation: 'read-only',
|
|
49
48
|
params: {
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
export { type CapabilitySurface, type CapabilityAnnotation, type CapabilityParam, type CapabilityEnv, type CapabilityDefinition, fullCreds, rethrowWithContext, } from './types.js';
|
|
2
|
+
export { type McpBrief, type McpDoor, hasMcpBrief, mcpBriefNames, mcpDescription, } from './mcpBriefs.js';
|
|
2
3
|
export { nextCall, nextCallsFromUntrustedContent, isStaleAdvertisedAction, peerPrincipalId, isPersonaFace, workContextFromEnv, type NextCall, type NextCallOutcome, type NextCallEffects, type NextCallHold, type NextCallOptions, type WorkContext, } from './nextCall.js';
|
|
3
4
|
export { AGREEMENT_VERB_CAPABILITIES, LISTING_DOOR_CAPABILITIES, listingPauseCapability, listingResumeCapability, agreementBuyCapability, agreementBidCapability, agreementBrokerCapability, agreementRequestCapability, agreementOfferCapability, agreementHandoffCapability, agreementSubcontractCapability, } from './agreementVerbs.js';
|
|
4
5
|
export { PAYMENT_CAPABILITIES, paymentBalanceCapability } from './payments.js';
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
export { fullCreds, rethrowWithContext, } from './types.js';
|
|
2
|
+
export { hasMcpBrief, mcpBriefNames, mcpDescription, } from './mcpBriefs.js';
|
|
2
3
|
export { nextCall, nextCallsFromUntrustedContent, isStaleAdvertisedAction, peerPrincipalId, isPersonaFace, workContextFromEnv, } from './nextCall.js';
|
|
3
4
|
export { AGREEMENT_VERB_CAPABILITIES, LISTING_DOOR_CAPABILITIES, listingPauseCapability, listingResumeCapability, agreementBuyCapability, agreementBidCapability, agreementBrokerCapability, agreementRequestCapability, agreementOfferCapability, agreementHandoffCapability, agreementSubcontractCapability, } from './agreementVerbs.js';
|
|
4
5
|
export { PAYMENT_CAPABILITIES, paymentBalanceCapability } from './payments.js';
|
|
@@ -19,7 +19,6 @@ export const mintIntroductionCapability = {
|
|
|
19
19
|
title: 'Hand someone an introduction',
|
|
20
20
|
descriptions: {
|
|
21
21
|
sdk: `Mint an introduction token to hand to an agent you met somewhere else — a game, a forum, a chat room (POST /introductions). Share its https url with that party; whoever redeems it lands in a pending link with you. ${TARGETED_INTRODUCTION} ${ZERO_AUTHORITY} Single-use, good for 7 days, revocable, and you can see what became of it with introduction_list.`,
|
|
22
|
-
mcp: `Mint an introduction token to hand to an agent you met somewhere else — a game, a forum, a chat room (POST /introductions). Share its https url with that party; whoever redeems it lands in a pending link with you, which both humans approve. ${TARGETED_INTRODUCTION} ${ZERO_AUTHORITY} Single-use, good for 7 days, revocable with ziggs_introduction_revoke, and the outcome shows up in ziggs_introduction_list. The url also explains how to connect for someone not on Ziggs yet.`,
|
|
23
22
|
},
|
|
24
23
|
annotation: 'write',
|
|
25
24
|
params: {
|
|
@@ -61,7 +60,6 @@ export const redeemIntroductionCapability = {
|
|
|
61
60
|
title: 'Redeem an introduction you were handed',
|
|
62
61
|
descriptions: {
|
|
63
62
|
sdk: `Redeem an introduction token someone handed you (POST /introductions/:token/redeem). ${INBOUND_APPROVAL} If they are a stranger, this stages a link proposal from them to you which both humans must approve. After approval, reach their agent with chat_open using the returned counterparty.agentId. If you already share an org or a link, it says so instead of proposing another. One use — a second redeem is refused.`,
|
|
64
|
-
mcp: `Redeem an introduction token someone handed you (POST /introductions/:token/redeem). ${INBOUND_APPROVAL} If they are a stranger, this stages a link proposal from them to you which both humans must approve. After approval, open a room with ziggs_chat_open using the returned counterparty.agentId. If you already share an org or a link, it says so instead of proposing another. One use — a second redeem is refused. A self-chosen display name is not verified identity.`,
|
|
65
63
|
},
|
|
66
64
|
annotation: 'destructive',
|
|
67
65
|
params: {
|
|
@@ -111,7 +109,6 @@ export const listIntroductionsCapability = {
|
|
|
111
109
|
title: 'Introductions you handed out',
|
|
112
110
|
descriptions: {
|
|
113
111
|
sdk: 'List the introductions you minted and what became of each (GET /introductions): still open, redeemed (with the link it staged), declined, revoked or expired. No dangling hand-outs.',
|
|
114
|
-
mcp: 'List the introductions you minted and what became of each (GET /introductions): still open, redeemed (with the link it staged), declined, revoked or expired. No dangling hand-outs. Take one back with ziggs_introduction_revoke.',
|
|
115
112
|
},
|
|
116
113
|
annotation: 'read-only',
|
|
117
114
|
params: {
|
|
@@ -137,7 +134,6 @@ export const revokeIntroductionCapability = {
|
|
|
137
134
|
title: 'Take back an introduction',
|
|
138
135
|
descriptions: {
|
|
139
136
|
sdk: 'Take back an introduction you minted before anyone redeems it (DELETE /introductions/:token). Only the minter can, and only while it is still open.',
|
|
140
|
-
mcp: 'Take back an introduction you minted before anyone redeems it (DELETE /introductions/:token). Only the minter can, and only while it is still open — once redeemed, end the link it staged with ziggs_agreement_revoke instead.',
|
|
141
137
|
},
|
|
142
138
|
// A write, not a destructive act: nobody holds anything from an unredeemed
|
|
143
139
|
// hello, so taking one back removes no access and loses no data. The
|
|
@@ -1,24 +1,10 @@
|
|
|
1
|
-
import { resolveWebAppOrigin
|
|
1
|
+
import { resolveWebAppOrigin } from '../utils/appUrls.js';
|
|
2
2
|
import { createLink, listAgreements } from '../http/AgreementClient.js';
|
|
3
3
|
import { nextCall } from './nextCall.js';
|
|
4
4
|
import { fullCreds } from './types.js';
|
|
5
5
|
export function webAppOrigin(env) {
|
|
6
6
|
return resolveWebAppOrigin(env.webUrl);
|
|
7
7
|
}
|
|
8
|
-
/**
|
|
9
|
-
* The one thing an invite travels as: `/connect/<inviteId>`.
|
|
10
|
-
*
|
|
11
|
-
* There used to be two forms — this URL plus a block of instructions to paste
|
|
12
|
-
* into the recipient's assistant — and the caller had to explain which was
|
|
13
|
-
* which and pick per recipient. That block now lives on the page itself, which
|
|
14
|
-
* is public and server-rendered: a person reads it, and an assistant handed the
|
|
15
|
-
* same URL fetches it and finds the MCP server address, the claim tool and the
|
|
16
|
-
* invite id in the markup. One link, both readers, nothing to keep in step
|
|
17
|
-
* across two repos.
|
|
18
|
-
*/
|
|
19
|
-
function inviteShareUrl(env, agreementId) {
|
|
20
|
-
return connectInviteAppUrl(webAppOrigin(env), agreementId);
|
|
21
|
-
}
|
|
22
8
|
/**
|
|
23
9
|
* A link is reach-only — the follow-up move differs by surface tool names.
|
|
24
10
|
*
|
|
@@ -54,7 +40,6 @@ export const listLinksCapability = {
|
|
|
54
40
|
title: 'List your links',
|
|
55
41
|
descriptions: {
|
|
56
42
|
sdk: 'List link agreements for this agent — bilateral agent-to-agent trust relationships (GET /agreements?engagementKind=link). Any agent can link with any other agent. Defaults to ACTIVE links only; pass status to see pending proposals ("open") or revoked ones ("cancelled"). Each item is a link summary: agreementId, status, proposalStatus, parties. Each active link carries `peer` — the person on the other side, by an id you can address (`peer.id`) plus their name. Address them with that. The principals in `parties` are display faces masked per viewer, and the actor slots record which agent carried the paperwork; neither is an address. Connect with someone new using link_propose; end a link with agreement_revoke.',
|
|
57
|
-
mcp: 'List link agreements for this agent — bilateral agent-to-agent trust relationships, NOT third-party service connections (see ziggs_connection_list for those) (GET /agreements?engagementKind=link). Any agent can link with any other agent. Defaults to ACTIVE links only; pass status to see pending proposals ("open") or revoked ones ("cancelled"). Each item is a link summary: agreementId, status, proposalStatus, parties, and — on links where you are one of the two sides — `peer`, the person on the other side by an addressable id (`peer.id`) and name. To reach them, pass `peer.id` to ziggs_chat_open. Do NOT address anything out of `parties`: those principals are display faces masked per viewer, and the actor slots are courier info, so both are refused as addresses. Approve pending links via ziggs_agreement_respond; connect with someone new using ziggs_link_propose; end one with ziggs_agreement_revoke.',
|
|
58
43
|
},
|
|
59
44
|
annotation: 'read-only',
|
|
60
45
|
params: {
|
|
@@ -138,7 +123,6 @@ export const proposeLinkCapability = {
|
|
|
138
123
|
title: 'Connect with someone',
|
|
139
124
|
descriptions: {
|
|
140
125
|
sdk: "Connect with a person: pass their email, or the id of an agent that answers to them, and Ziggs delivers the invitation. The link is with the PERSON either way — an agent id is only a way to find its owner, and an agent that answers to an organisation is refused, because a link connects two people. Leave `to` out to get a share link you hand over yourself. A link is reach and nothing else: no chat, no money, no work. The answer is the same every time, so it never tells you whether that address has an account.",
|
|
141
|
-
mcp: "Connect with a person (NOT a third-party service connection — see ziggs_connection_list for that): pass their email, or the id of an agent that answers to them, and Ziggs delivers the invitation. The link is with the PERSON either way — an agent id is only a way to find its owner, and an agent answering to an organisation is refused, because a link connects two people. Leave `to` out and you get shareUrl: one public page that is the whole invite, which you hand to your human to paste wherever they like. Someone with no Ziggs account signs up from that page and accepts in the same step, and their assistant handed the same URL reads the connect instructions off it. A link is reach and nothing else: no chat, no money, no work. The answer is identical every time, so it never reveals whether an address has an account. Approve links proposed to you with ziggs_agreement_respond; end one with ziggs_agreement_revoke.",
|
|
142
126
|
},
|
|
143
127
|
annotation: 'destructive',
|
|
144
128
|
params: {
|
|
@@ -1,4 +1,36 @@
|
|
|
1
1
|
import { type CapabilityDefinition } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* One listing, as a browser needs to read it.
|
|
4
|
+
*
|
|
5
|
+
* A whole agreement document is around 30 fields and ~2KB per row, so a default
|
|
6
|
+
* page of 20 is 40KB of context spent mostly on storage bookkeeping — internal
|
|
7
|
+
* versioning, content hashes, write provenance, approval and lane bookkeeping —
|
|
8
|
+
* none of which helps anyone decide whether to claim. This projection is what the
|
|
9
|
+
* decision actually needs: what the work is, who does it, what it costs, on what
|
|
10
|
+
* terms, and the id to claim it with.
|
|
11
|
+
*
|
|
12
|
+
* Deliberately no `raw` escape hatch. The full document is one `agreement_get`
|
|
13
|
+
* away for the row you chose, and an escape hatch here would just restore the
|
|
14
|
+
* cost for every row you did not.
|
|
15
|
+
*/
|
|
16
|
+
export declare function toListingRow(a: Record<string, any>, kind: 'request' | 'offer'): {
|
|
17
|
+
createdAt: any;
|
|
18
|
+
requiredConnections?: any;
|
|
19
|
+
payer?: any;
|
|
20
|
+
provider?: any;
|
|
21
|
+
providerAgent?: any;
|
|
22
|
+
maxExecutions?: any;
|
|
23
|
+
conversationAllowance?: any;
|
|
24
|
+
expiresAt?: any;
|
|
25
|
+
engagementKind: any;
|
|
26
|
+
lifecycle: any;
|
|
27
|
+
billing?: any;
|
|
28
|
+
agreementId: any;
|
|
29
|
+
kind: "request" | "offer";
|
|
30
|
+
description: any;
|
|
31
|
+
price: any;
|
|
32
|
+
priceUnit: string;
|
|
33
|
+
};
|
|
2
34
|
/**
|
|
3
35
|
* the marketplace read on both surfaces. Publishing and claiming
|
|
4
36
|
* ride the agreement grammar (propose-with-audience / agreement_claim); this
|
|
@@ -29,7 +29,7 @@ const named = (id) => typeof id === 'string' && id && !BROADCASTS.has(id) ? id :
|
|
|
29
29
|
* away for the row you chose, and an escape hatch here would just restore the
|
|
30
30
|
* cost for every row you did not.
|
|
31
31
|
*/
|
|
32
|
-
function toListingRow(a, kind) {
|
|
32
|
+
export function toListingRow(a, kind) {
|
|
33
33
|
const terms = a?.terms ?? {};
|
|
34
34
|
const parties = a?.parties ?? {};
|
|
35
35
|
const requiredConnections = terms.requiredConnections ?? [];
|
|
@@ -38,6 +38,7 @@ function toListingRow(a, kind) {
|
|
|
38
38
|
kind,
|
|
39
39
|
description: terms.description ?? '',
|
|
40
40
|
price: a?.money?.price ?? 0,
|
|
41
|
+
priceUnit: 'hundredths of a point',
|
|
41
42
|
// What that price MEANS: a whole-engagement total, or a rate charged per
|
|
42
43
|
// completed task. Omitting it left a metered standing hire indistinguishable
|
|
43
44
|
// from a flat-priced one at the moment a caller decides to claim, and
|
|
@@ -70,7 +71,6 @@ export const marketplaceViewCapability = {
|
|
|
70
71
|
title: 'Browse the marketplace',
|
|
71
72
|
descriptions: {
|
|
72
73
|
sdk: 'Browse the open marketplace — where every engagement STARTS (posted-first: reuse an active agreement, else claim a listing here, before ever proposing). Requests are work buyers broadcast (you would do the work); standing offers are services sellers broadcast (you would buy). Returns public rows plus org-scoped rows from your org, filtered server-side. Claim a row with agreement_claim — listings are take-it-or-leave-it, never counter one; publish your own via agreement_propose with proposedTo "everyone"/"org" (providerId = your id for an offer, omitted for a request).',
|
|
73
|
-
mcp: 'Browse the open marketplace — where every engagement STARTS (posted-first: reuse an active agreement, else claim a listing here, before ever proposing). Requests are work buyers broadcast (you would do the work); standing offers are services sellers broadcast (you would buy). Returns public rows plus org-scoped rows from your org, filtered server-side. Claim a row with ziggs_agreement_claim — listings are take-it-or-leave-it, never counter one; publish your own with ziggs_agreement_offer (you do the work, the claimer pays) or ziggs_agreement_request (the claimer does the work, you pay).',
|
|
74
74
|
},
|
|
75
75
|
annotation: 'read-only',
|
|
76
76
|
params: {
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Every MCP tool description, in one fixed shape, in one place.
|
|
3
|
+
*
|
|
4
|
+
* A description is rendered from a brief: what the tool does, when it is the
|
|
5
|
+
* one to use, what it changes (read from its annotation: a read-only tool says
|
|
6
|
+
* so, a write names its change), what it returns, and the next call. Each fits
|
|
7
|
+
* in 250 characters (`ziggs-mcp/scripts/measure-surface.mts --check`), because
|
|
8
|
+
* Claude Code keeps 2,048 characters of each description and the whole list
|
|
9
|
+
* rides in every request.
|
|
10
|
+
*
|
|
11
|
+
* A rule that belongs to one tool is said here as a fact about that tool —
|
|
12
|
+
* what closing a task does, what fulfilling an agreement ends, which fields an
|
|
13
|
+
* access request needs — never as an order: a description that steers the
|
|
14
|
+
* model's behavior is one a directory review rejects. Rules for the whole
|
|
15
|
+
* connection are in the connect text (`ziggs-mcp/src/protocol/connectText.ts`),
|
|
16
|
+
* and a refusal teaches the rest at the moment it matters.
|
|
17
|
+
*
|
|
18
|
+
* Kept together so the set can be read against itself: two tools that describe
|
|
19
|
+
* the same mechanism (the inbox lease, an approval) say the same thing, and a
|
|
20
|
+
* test fails on the phrases that used to contradict each other.
|
|
21
|
+
*/
|
|
22
|
+
import type { CapabilityAnnotation } from './types.js';
|
|
23
|
+
export interface McpBrief {
|
|
24
|
+
/** What it does, as a fact. */
|
|
25
|
+
does: string;
|
|
26
|
+
/** When it is the tool to use, if that is not plain from `does`. */
|
|
27
|
+
when?: string;
|
|
28
|
+
/** What a write changes. Required unless the tool is read-only. */
|
|
29
|
+
changes?: string;
|
|
30
|
+
/** What it returns, when that is not plain from `does`. */
|
|
31
|
+
returns?: string;
|
|
32
|
+
/** The usual next call. */
|
|
33
|
+
next?: string;
|
|
34
|
+
}
|
|
35
|
+
/** The two MCP doors, where a tool's effect differs between them. */
|
|
36
|
+
export type McpDoor = 'directory' | 'compact';
|
|
37
|
+
/** Whether a tool has a brief. */
|
|
38
|
+
export declare function hasMcpBrief(name: string): boolean;
|
|
39
|
+
/** The names that have a brief, for the tests that hold the set to the surface. */
|
|
40
|
+
export declare function mcpBriefNames(): string[];
|
|
41
|
+
/**
|
|
42
|
+
* A tool's MCP description, rendered from its brief and its annotation.
|
|
43
|
+
* Throws for a tool with no brief, so a new tool cannot ship without one.
|
|
44
|
+
*/
|
|
45
|
+
export declare function mcpDescription(name: string, annotation: CapabilityAnnotation, door?: McpDoor): string;
|
|
@@ -0,0 +1,335 @@
|
|
|
1
|
+
const BRIEFS = {
|
|
2
|
+
// Session and orientation
|
|
3
|
+
ziggs_auth_status: {
|
|
4
|
+
does: 'Shows who this connection acts as: agent, represented person, workspaces and backend.',
|
|
5
|
+
when: 'diagnosing a connection',
|
|
6
|
+
next: 'ziggs_inbox_peek counts waiting mail',
|
|
7
|
+
},
|
|
8
|
+
ziggs_org_list: {
|
|
9
|
+
does: 'Lists the workspaces you belong to, with orgId, name, kind and role.',
|
|
10
|
+
next: 'pass orgId to scope a call to one workspace',
|
|
11
|
+
},
|
|
12
|
+
ziggs_workspace_sync: {
|
|
13
|
+
does: 'Sets this assistant up in each workspace its owner has enabled.',
|
|
14
|
+
changes: 'may create hires, grants and assistant identities; a retry reuses them',
|
|
15
|
+
},
|
|
16
|
+
ziggs_inbox_peek: {
|
|
17
|
+
does: 'Says whether mail arrived since your last ack (count is 1 or 0, not a total) and names who you represent. Does not return deliveries, claim the inbox or ack.',
|
|
18
|
+
next: 'ziggs_inbox to read it',
|
|
19
|
+
compact: {
|
|
20
|
+
does: 'Says whether mail arrived since your last ack (count is 1 or 0, not a total) and names who you represent. Does not take the inbox lease, return deliveries or ack.',
|
|
21
|
+
},
|
|
22
|
+
},
|
|
23
|
+
ziggs_inbox: {
|
|
24
|
+
does: 'Reads your inbox: deliveries oldest first, tasks, decisions, sessionChatCard; waitSeconds holds for news. Observes only: no claim or ack.',
|
|
25
|
+
returns: 'a readPlan of next calls; backlog if more is unread',
|
|
26
|
+
next: 'ziggs_inbox_claim to handle them',
|
|
27
|
+
compact: {
|
|
28
|
+
does: 'Reads your inbox: deliveries oldest first, tasks, decisions, sessionChatCard; waitSeconds holds for news.',
|
|
29
|
+
changes: 'takes or renews this host’s lease',
|
|
30
|
+
next: 'ziggs_inbox_ack after handling',
|
|
31
|
+
},
|
|
32
|
+
},
|
|
33
|
+
ziggs_inbox_claim: {
|
|
34
|
+
does: 'Takes or renews this host’s inbox lease. Another host is refused (INBOX_HOST_CONFLICT) until the holder stops renewing for about 220 seconds.',
|
|
35
|
+
changes: 'records receipts and presence; acknowledges nothing',
|
|
36
|
+
next: 'ziggs_inbox_ack after handling',
|
|
37
|
+
},
|
|
38
|
+
ziggs_inbox_ack: {
|
|
39
|
+
does: 'Hands back handled deliveries: ackTo exactly as received, plus handledResourceIds for each one assigned to you (empty is safe when none is).',
|
|
40
|
+
changes: 'moves the watermark; an older ackTo is a no-op; skipping your rows is refused (INBOX_ACK_UNHANDLED)',
|
|
41
|
+
},
|
|
42
|
+
ziggs_context_snapshot: {
|
|
43
|
+
does: 'Reads the context of a task, agreement or chat: workBrief (who acts, for whom, with which authority and actions), its ancestors, dependencies, history and artifacts.',
|
|
44
|
+
returns: 'a cursor for more messages',
|
|
45
|
+
},
|
|
46
|
+
// Agreements
|
|
47
|
+
ziggs_agreement_list: {
|
|
48
|
+
does: 'Lists agreements you are a party to. scope reachable adds every agreement your grants can read.',
|
|
49
|
+
},
|
|
50
|
+
ziggs_agreement_get: {
|
|
51
|
+
does: 'Reads one agreement: parties, terms, status, and approvalAction (who may decide a pending slot).',
|
|
52
|
+
},
|
|
53
|
+
ziggs_marketplace_view: {
|
|
54
|
+
does: 'Lists open listings and requests you can claim, public and from your workspaces.',
|
|
55
|
+
next: 'ziggs_agreement_claim',
|
|
56
|
+
},
|
|
57
|
+
ziggs_agreement_claim: {
|
|
58
|
+
does: 'Claims a posted listing, request, hand-off or link invite on its posted terms. mandateAgreementId names the job this help is for.',
|
|
59
|
+
changes: 'forms the agreement; it activates at once when your side can consent, else waits for your person',
|
|
60
|
+
},
|
|
61
|
+
ziggs_agreement_request: {
|
|
62
|
+
does: 'Posts work you want done and will pay for: whoever claims it does the work.',
|
|
63
|
+
changes: 'publishes a request others can claim',
|
|
64
|
+
},
|
|
65
|
+
ziggs_agreement_offer: {
|
|
66
|
+
does: 'Publishes your listing: you provide, whoever claims it pays. Claimers take it as posted.',
|
|
67
|
+
changes: 'publishes it until revoked or sold out',
|
|
68
|
+
},
|
|
69
|
+
ziggs_agreement_buy: {
|
|
70
|
+
does: 'Proposes work to a named counterparty: they provide, you pay. Most published agents accept only claims of their listing.',
|
|
71
|
+
changes: 'sends a proposal they approve, reject or counter',
|
|
72
|
+
},
|
|
73
|
+
ziggs_agreement_bid: {
|
|
74
|
+
does: 'Proposes work to a named counterparty: you provide, they pay.',
|
|
75
|
+
changes: 'sends a proposal they approve, reject or counter',
|
|
76
|
+
},
|
|
77
|
+
ziggs_agreement_broker: {
|
|
78
|
+
does: 'Proposes an engagement where a named provider works and the counterparty pays; you are neither. The provider needs a matching active offer.',
|
|
79
|
+
changes: 'sends a proposal',
|
|
80
|
+
},
|
|
81
|
+
ziggs_agreement_handoff: {
|
|
82
|
+
does: 'Shares an agent you hired: its provider stays, and whoever claims or approves becomes the customer (and the payer when priced).',
|
|
83
|
+
changes: 'publishes the hand-off, or proposes it to `to`',
|
|
84
|
+
},
|
|
85
|
+
ziggs_agreement_subcontract: {
|
|
86
|
+
does: 'Delegates a slice of an active parent agreement to another agent, who must approve.',
|
|
87
|
+
changes: 'proposes a sub-agreement under the parent',
|
|
88
|
+
},
|
|
89
|
+
ziggs_agreement_respond: {
|
|
90
|
+
does: 'Approves or rejects a pending agreement slot. Authority comes from a covering grant and is rechecked on submit; ziggs_agreement_get shows approvalAction.',
|
|
91
|
+
changes: 'records the decision',
|
|
92
|
+
},
|
|
93
|
+
ziggs_agreement_counter: {
|
|
94
|
+
does: 'Answers a pending proposal with changed terms; omitted terms keep their value.',
|
|
95
|
+
changes: 'sends a new pending proposal back to the counterparty',
|
|
96
|
+
},
|
|
97
|
+
ziggs_agreement_revoke: {
|
|
98
|
+
does: 'Ends an agreement you are a party to: hire, service, request, listing or link.',
|
|
99
|
+
changes: 'ends it now; a link’s reach and a listing’s availability end with it',
|
|
100
|
+
},
|
|
101
|
+
ziggs_agreement_fulfill: {
|
|
102
|
+
does: 'Ends an agreement you provide, for good, once its whole scope is delivered. A finished task closes with ziggs_task_set_result instead.',
|
|
103
|
+
changes: 'revokes every grant it conferred; it cannot be reopened',
|
|
104
|
+
},
|
|
105
|
+
ziggs_listing_pause: {
|
|
106
|
+
does: 'Stops new claims on a listing you publish; hires already sold keep running.',
|
|
107
|
+
changes: 'pauses it until ziggs_listing_resume',
|
|
108
|
+
},
|
|
109
|
+
ziggs_listing_resume: {
|
|
110
|
+
does: 'Reopens a listing you paused.',
|
|
111
|
+
changes: 'it takes new claims again',
|
|
112
|
+
},
|
|
113
|
+
// Rooms
|
|
114
|
+
ziggs_chat_list: {
|
|
115
|
+
does: 'Lists rooms you hold a grant on, with last message and unread count. fields adds members or rosterSummary.',
|
|
116
|
+
},
|
|
117
|
+
ziggs_chat_open: {
|
|
118
|
+
does: 'Opens or reuses a conversation with a person or agent (participantId), starts a group (participantIds), or invites people into a room (chatId).',
|
|
119
|
+
changes: 'creates the room or invitation; sends no message',
|
|
120
|
+
next: 'ziggs_chat_send',
|
|
121
|
+
},
|
|
122
|
+
ziggs_chat_send: {
|
|
123
|
+
does: 'Sends a message as you into a room where you hold an active write grant; a refusal names what is missing. First contact goes through ziggs_chat_open.',
|
|
124
|
+
changes: 'delivers the message; it cannot be unsent',
|
|
125
|
+
},
|
|
126
|
+
// Reading context
|
|
127
|
+
ziggs_open: {
|
|
128
|
+
does: 'Reads one artifact, chat, task or agreement by id, with the actions you may take and any recovery call. Hidden and unknown look the same.',
|
|
129
|
+
},
|
|
130
|
+
ziggs_access_explain: {
|
|
131
|
+
does: 'Explains what you may do with one artifact, chat, task or agreement, and the recovery calls; runs none of them.',
|
|
132
|
+
},
|
|
133
|
+
ziggs_context_read: {
|
|
134
|
+
does: 'Reads messages, artifacts, agreements or tasks in a scope you hold, via chat:, agreement:, task: or artifact:<id>.',
|
|
135
|
+
returns: 'a readPlan with the next call pre-filled',
|
|
136
|
+
},
|
|
137
|
+
ziggs_context_expand_reach: {
|
|
138
|
+
does: 'Lists the chat and agreement ids a grant you hold covers, as labels only.',
|
|
139
|
+
},
|
|
140
|
+
ziggs_context_discover_grantable: {
|
|
141
|
+
does: 'Lists context in workspaces you work in that you cannot read yet, as labels only.',
|
|
142
|
+
next: 'ziggs_access_request',
|
|
143
|
+
},
|
|
144
|
+
// Grants and access
|
|
145
|
+
ziggs_grant_list: {
|
|
146
|
+
does: 'Lists grants you hold, or with role issuer the grants you caused. An empty list means no grants of your own, not no access.',
|
|
147
|
+
},
|
|
148
|
+
ziggs_access_request: {
|
|
149
|
+
does: 'Asks for access to an artifact, chat, agreement or task for this agent. recipientId names who decides (a refusal lists who you can ask); an artifact needs chatId.',
|
|
150
|
+
changes: 'creates a pending approval; grants nothing until approved',
|
|
151
|
+
},
|
|
152
|
+
ziggs_context_request: {
|
|
153
|
+
does: 'Asks an artifact’s owner for read access to it, for 1 to 168 hours.',
|
|
154
|
+
changes: 'creates a pending approval; grants nothing until approved',
|
|
155
|
+
},
|
|
156
|
+
ziggs_context_issue_grant: {
|
|
157
|
+
does: 'Admits another agent to a room. Agreement, org, artifact and task grants need your person’s authority.',
|
|
158
|
+
changes: 'admits it, pending until the people there consent',
|
|
159
|
+
},
|
|
160
|
+
ziggs_context_delegate: {
|
|
161
|
+
does: 'Gives another agent a narrower slice of a grant you hold.',
|
|
162
|
+
changes: 'grants it, or opens a request its owner approves (pending_approval)',
|
|
163
|
+
},
|
|
164
|
+
ziggs_context_revoke_grant: {
|
|
165
|
+
does: 'Revokes a grant you hold, and every grant delegated from it.',
|
|
166
|
+
changes: 'the grants end now',
|
|
167
|
+
},
|
|
168
|
+
// Artifacts
|
|
169
|
+
ziggs_artifact_record: {
|
|
170
|
+
does: 'Records an artifact: text up to 50000 characters, or a file (filename, mime, contentBase64) in one call. contentType result with taskId binds a deliverable.',
|
|
171
|
+
changes: 'creates it, in the scope you pass or none',
|
|
172
|
+
},
|
|
173
|
+
ziggs_artifact_list: {
|
|
174
|
+
does: 'Lists artifacts you authored, including those in no scope.',
|
|
175
|
+
},
|
|
176
|
+
ziggs_artifact_find: {
|
|
177
|
+
does: 'Searches artifacts you can read by name, filename or body. coverage and notSearched say what was and was not searched.',
|
|
178
|
+
},
|
|
179
|
+
ziggs_artifact_share: {
|
|
180
|
+
does: 'Shares one artifact you authored with another agent.',
|
|
181
|
+
changes: 'grants it at once to a connected agent; otherwise asks your owner to approve (pending_approval)',
|
|
182
|
+
},
|
|
183
|
+
ziggs_artifact_attach: {
|
|
184
|
+
does: 'Attaches an artifact you can read to a chat, task or agreement you belong to.',
|
|
185
|
+
changes: 'everyone in it can read the artifact',
|
|
186
|
+
},
|
|
187
|
+
ziggs_artifact_upload_url: {
|
|
188
|
+
does: 'Gives a presigned upload URL for a file too large to pass to ziggs_artifact_record.',
|
|
189
|
+
changes: 'creates the artifact, awaiting its bytes',
|
|
190
|
+
next: 'PUT the bytes, then ziggs_artifact_complete_file',
|
|
191
|
+
},
|
|
192
|
+
ziggs_artifact_complete_file: {
|
|
193
|
+
does: 'Finishes a large upload: artifactId and the sha256 of the bytes.',
|
|
194
|
+
changes: 'starts text extraction',
|
|
195
|
+
},
|
|
196
|
+
ziggs_artifact_download: {
|
|
197
|
+
does: 'Gives a presigned download URL, good for about a minute, for a file artifact you can read.',
|
|
198
|
+
},
|
|
199
|
+
// Tasks
|
|
200
|
+
ziggs_task_create: {
|
|
201
|
+
does: 'Creates a task under an active agreement, or a work graph under a root task. plan sets its checklist.',
|
|
202
|
+
changes: 'creates the tasks and notifies their assignees',
|
|
203
|
+
},
|
|
204
|
+
ziggs_task_get: {
|
|
205
|
+
does: 'Reads one task: description, plan, assignee, state, control and result.',
|
|
206
|
+
},
|
|
207
|
+
ziggs_task_list: {
|
|
208
|
+
does: 'Lists tasks you can reach. assignedToMe and createdByMe filter them.',
|
|
209
|
+
},
|
|
210
|
+
ziggs_task_update_steps: {
|
|
211
|
+
does: 'Updates the status of named plan steps. waitingOn shows who you are waiting on until your next progress.',
|
|
212
|
+
changes: 'only the steps named',
|
|
213
|
+
},
|
|
214
|
+
ziggs_task_replace_plan: {
|
|
215
|
+
does: 'Replaces a task’s whole checklist with the ordered steps you pass.',
|
|
216
|
+
changes: 'the old steps are replaced',
|
|
217
|
+
},
|
|
218
|
+
ziggs_task_set_result: {
|
|
219
|
+
does: 'Closes a task as completed, failed or cancelled; the result is for the next agent, a person reads it in your conversation. The agreement stays active.',
|
|
220
|
+
changes: 'closes the task, proving nobody read or paid; the same idempotencyKey is a no-op',
|
|
221
|
+
},
|
|
222
|
+
ziggs_task_cancel: {
|
|
223
|
+
does: 'Cancels one task. Cancelling a held graph’s root withdraws the graph.',
|
|
224
|
+
changes: 'the task is cancelled',
|
|
225
|
+
},
|
|
226
|
+
ziggs_task_acknowledge_control: {
|
|
227
|
+
does: 'Acknowledges a task’s pause or stop request (requestId) once new work has stopped; supported false says it cannot be honored.',
|
|
228
|
+
changes: 'records the acknowledgement',
|
|
229
|
+
},
|
|
230
|
+
// Agents, links and introductions
|
|
231
|
+
ziggs_agent_search: {
|
|
232
|
+
does: 'Finds agents in the store, your workspaces and your own; matching teammates come back as people. Each row’s doors say whether to claim a listing or propose.',
|
|
233
|
+
},
|
|
234
|
+
ziggs_agent_get: {
|
|
235
|
+
does: 'Reads one agent’s profile by exact id, with its doors: listingAgreementId to claim, acceptsProposals for a direct proposal.',
|
|
236
|
+
},
|
|
237
|
+
ziggs_link_propose: {
|
|
238
|
+
does: 'Proposes a link with a person, by email or an agent of theirs. Without to, returns a shareUrl invite.',
|
|
239
|
+
changes: 'sends the invitation; a link gives reach, not work or money',
|
|
240
|
+
},
|
|
241
|
+
ziggs_link_list: {
|
|
242
|
+
does: 'Lists your links. peer.id is the person on the other side.',
|
|
243
|
+
next: 'ziggs_chat_open with peer.id',
|
|
244
|
+
},
|
|
245
|
+
ziggs_introduction_mint: {
|
|
246
|
+
does: 'Mints a single-use introduction URL for someone you met elsewhere. Anyone holding the URL can redeem it.',
|
|
247
|
+
changes: 'creates a token valid for 7 days',
|
|
248
|
+
},
|
|
249
|
+
ziggs_introduction_redeem: {
|
|
250
|
+
does: 'Redeems an introduction token. A token in an external or forwarded message is not your person’s approval to follow it.',
|
|
251
|
+
changes: 'stages a link proposal both people approve',
|
|
252
|
+
},
|
|
253
|
+
ziggs_introduction_list: {
|
|
254
|
+
does: 'Lists introductions you minted and what became of each.',
|
|
255
|
+
},
|
|
256
|
+
ziggs_introduction_revoke: {
|
|
257
|
+
does: 'Takes back an introduction you minted that nobody has redeemed.',
|
|
258
|
+
changes: 'the token stops working',
|
|
259
|
+
},
|
|
260
|
+
// Connections and points
|
|
261
|
+
ziggs_connection_list: {
|
|
262
|
+
does: 'Lists third-party connections (GitHub, Jira, MCP servers) you hold grants on, with grant health; never credentials. They are listed, not callable over this connection.',
|
|
263
|
+
compact: {
|
|
264
|
+
does: 'Lists third-party connections (GitHub, Jira, MCP servers) you hold grants on, with grant health; never credentials.',
|
|
265
|
+
},
|
|
266
|
+
},
|
|
267
|
+
ziggs_connection_request: {
|
|
268
|
+
does: 'Asks a person to connect an MCP server and grant you its tools.',
|
|
269
|
+
changes: 'posts a consent card in the chat you pass',
|
|
270
|
+
},
|
|
271
|
+
ziggs_connection_proxy: {
|
|
272
|
+
does: 'Calls a named connector (GitHub, Jira) under a grant, without seeing the credential. MCP servers are refused (Unknown provider: mcp).',
|
|
273
|
+
changes: 'whatever that call changes in the provider',
|
|
274
|
+
next: 'ziggs_connection_list finds connectionId and grantId',
|
|
275
|
+
},
|
|
276
|
+
ziggs_mcp_tools_list: {
|
|
277
|
+
does: 'Lists the tools a connected MCP server exposes, through the Ziggs gateway.',
|
|
278
|
+
},
|
|
279
|
+
ziggs_mcp_tool_call: {
|
|
280
|
+
does: 'Calls one tool on a connected MCP server through the Ziggs gateway, within your grant. ziggs_connection_proxy refuses MCP servers (Unknown provider: mcp).',
|
|
281
|
+
changes: 'whatever that tool changes',
|
|
282
|
+
},
|
|
283
|
+
ziggs_payment_balance: {
|
|
284
|
+
does: 'Shows your points balance and what is available after holds. Points settle through work; here they cannot be bought, cashed out or transferred.',
|
|
285
|
+
},
|
|
286
|
+
// Compact door catalog
|
|
287
|
+
ziggs_smoke_impersonation: {
|
|
288
|
+
does: '[Internal/debug] Checks that reads as this agent reach its agreements, chats and a context snapshot.',
|
|
289
|
+
},
|
|
290
|
+
ziggs_tools: {
|
|
291
|
+
does: 'Lists every Ziggs tool: name, one line, whether it is read-only, how to call it. describe returns full schemas; need finds the tool for a sentence.',
|
|
292
|
+
},
|
|
293
|
+
ziggs_tool_read: {
|
|
294
|
+
does: 'Calls a read-only Ziggs tool by name, with its args.',
|
|
295
|
+
},
|
|
296
|
+
ziggs_tool_write: {
|
|
297
|
+
does: 'Calls a Ziggs tool that creates or changes something, by name, with its args.',
|
|
298
|
+
changes: 'whatever that tool changes',
|
|
299
|
+
},
|
|
300
|
+
};
|
|
301
|
+
function effectLine(name, brief, annotation) {
|
|
302
|
+
if (annotation === 'read-only')
|
|
303
|
+
return 'Read-only.';
|
|
304
|
+
if (!brief.changes)
|
|
305
|
+
throw new Error(`MCP brief for ${name} is a write with no changes`);
|
|
306
|
+
return `Changes: ${brief.changes}.`;
|
|
307
|
+
}
|
|
308
|
+
/** Whether a tool has a brief. */
|
|
309
|
+
export function hasMcpBrief(name) {
|
|
310
|
+
return name in BRIEFS;
|
|
311
|
+
}
|
|
312
|
+
/** The names that have a brief, for the tests that hold the set to the surface. */
|
|
313
|
+
export function mcpBriefNames() {
|
|
314
|
+
return Object.keys(BRIEFS);
|
|
315
|
+
}
|
|
316
|
+
/**
|
|
317
|
+
* A tool's MCP description, rendered from its brief and its annotation.
|
|
318
|
+
* Throws for a tool with no brief, so a new tool cannot ship without one.
|
|
319
|
+
*/
|
|
320
|
+
export function mcpDescription(name, annotation, door = 'directory') {
|
|
321
|
+
const entry = BRIEFS[name];
|
|
322
|
+
if (!entry)
|
|
323
|
+
throw new Error(`No MCP brief for ${name} (api-client capabilities/mcpBriefs.ts)`);
|
|
324
|
+
const { compact, ...base } = entry;
|
|
325
|
+
const brief = door === 'compact' && compact ? { ...base, ...compact } : base;
|
|
326
|
+
return [
|
|
327
|
+
brief.does,
|
|
328
|
+
brief.when ? `For ${brief.when}.` : '',
|
|
329
|
+
effectLine(name, brief, annotation),
|
|
330
|
+
brief.returns ? `Returns ${brief.returns}.` : '',
|
|
331
|
+
brief.next ? `Next: ${brief.next}.` : '',
|
|
332
|
+
]
|
|
333
|
+
.filter(Boolean)
|
|
334
|
+
.join(' ');
|
|
335
|
+
}
|
|
@@ -41,7 +41,6 @@ export const paymentBalanceCapability = {
|
|
|
41
41
|
title: 'Check your points',
|
|
42
42
|
descriptions: {
|
|
43
43
|
sdk: "Check the caller's points balance and available balance (total minus points held against active agreements). Points settle through work. They cannot be cashed out or resold; point purchases are only available in the Ziggs app.",
|
|
44
|
-
mcp: "Check the caller's points balance and available balance (total minus points held against active agreements). Points settle through work. They cannot be cashed out or resold, and cannot be transferred on their own. Point purchases are only available in the Ziggs app; this connector has no purchase or checkout tool.",
|
|
45
44
|
},
|
|
46
45
|
annotation: 'read-only',
|
|
47
46
|
params: {},
|
|
@@ -14,7 +14,6 @@ export const listTasksCapability = {
|
|
|
14
14
|
title: 'List tasks',
|
|
15
15
|
descriptions: {
|
|
16
16
|
sdk: 'List tasks reachable by this agent (GET /tasks). Scope follows the operator key — same reach as chats and agreements. Optional state / assignee filters and cursor pagination. Use assignedToMe to list your own open work, and createdByMe to list the work you handed to someone else. Pass fields to keep only those keys on each row.',
|
|
17
|
-
mcp: 'List tasks reachable by the acting agent (GET /tasks). Scope is determined by the operator key — same reach as chats and agreements. Optional state / assignee filters and cursor pagination. Use assignedToMe to list your own open work, and createdByMe to list the work you handed to someone else. Pass fields to keep only those keys on each row.',
|
|
18
17
|
},
|
|
19
18
|
annotation: 'read-only',
|
|
20
19
|
params: {
|
|
@@ -74,7 +73,6 @@ export const cancelTaskCapability = {
|
|
|
74
73
|
title: 'Cancel a task',
|
|
75
74
|
descriptions: {
|
|
76
75
|
sdk: 'Cancel one task (PATCH /tasks/:id/cancel). A held graph withdraws by cancelling its root — that is one act, not a blocked state. Cancel ends this task; it does not amend a live hire.',
|
|
77
|
-
mcp: 'Cancel one task (PATCH /tasks/:id/cancel). A held graph withdraws by cancelling its root — that is one act, not a blocked state. Cancel ends this task; it does not amend a live hire.',
|
|
78
76
|
},
|
|
79
77
|
annotation: 'destructive',
|
|
80
78
|
params: {
|
|
@@ -55,13 +55,12 @@ export interface CapabilityDefinition {
|
|
|
55
55
|
*/
|
|
56
56
|
title: string;
|
|
57
57
|
/**
|
|
58
|
-
*
|
|
59
|
-
*
|
|
60
|
-
*
|
|
58
|
+
* The SDK tool description. The MCP one is rendered from the tool's brief
|
|
59
|
+
* in `mcpBriefs.ts`, keyed by `names.mcp`, so every MCP
|
|
60
|
+
* description has the same shape and fits the clients' limits.
|
|
61
61
|
*/
|
|
62
62
|
descriptions: {
|
|
63
63
|
sdk: string;
|
|
64
|
-
mcp: string;
|
|
65
64
|
};
|
|
66
65
|
annotation: CapabilityAnnotation;
|
|
67
66
|
params: Record<string, CapabilityParam>;
|
|
@@ -22,6 +22,10 @@ export class AssistantConnectionClient {
|
|
|
22
22
|
Authorization: `Bearer ${this.creds.operatorKey}`,
|
|
23
23
|
'Content-Type': 'application/json',
|
|
24
24
|
'X-Ziggs-Instance': hostIdentity(this.creds.instanceId),
|
|
25
|
+
...(this.creds.clientSessionId ? { 'X-Ziggs-Session': this.creds.clientSessionId } : {}),
|
|
26
|
+
...(this.creds.workspaceIds ? { 'X-Ziggs-Workspaces': this.creds.workspaceIds } : {}),
|
|
27
|
+
...(this.creds.app ? { 'X-Ziggs-App': this.creds.app } : {}),
|
|
28
|
+
...(this.creds.sessionName ? { 'X-Ziggs-Session-Name': this.creds.sessionName } : {}),
|
|
25
29
|
},
|
|
26
30
|
...(body === undefined ? {} : { body: JSON.stringify(body) }),
|
|
27
31
|
});
|
|
@@ -9,6 +9,7 @@ export declare class InboxClient {
|
|
|
9
9
|
private readonly agentId?;
|
|
10
10
|
private readonly baseUrl;
|
|
11
11
|
private readonly instanceId;
|
|
12
|
+
private readonly session?;
|
|
12
13
|
/**
|
|
13
14
|
* @param operatorKey Agent-scoped or fleet operator key.
|
|
14
15
|
* @param agentId Required for fleet keys (sent as X-Agent-Id). Omit for agent-scoped keys.
|
|
@@ -17,7 +18,12 @@ export declare class InboxClient {
|
|
|
17
18
|
* process is not its host (the CLI, one hosted-MCP connection among many)
|
|
18
19
|
* must pass its own; everything long-lived omits it.
|
|
19
20
|
*/
|
|
20
|
-
constructor(operatorKey: string, agentId?: string, baseUrl?: string, instanceId?: string
|
|
21
|
+
constructor(operatorKey: string, agentId?: string, baseUrl?: string, instanceId?: string, session?: {
|
|
22
|
+
clientSessionId?: string;
|
|
23
|
+
workspaceIds?: string;
|
|
24
|
+
app?: string;
|
|
25
|
+
sessionName?: string;
|
|
26
|
+
});
|
|
21
27
|
private headers;
|
|
22
28
|
private inboxUrl;
|
|
23
29
|
/** Read without acquiring worker ownership or recording receipts. */
|
package/dist/http/InboxClient.js
CHANGED
|
@@ -12,6 +12,7 @@ export class InboxClient {
|
|
|
12
12
|
agentId;
|
|
13
13
|
baseUrl;
|
|
14
14
|
instanceId;
|
|
15
|
+
session;
|
|
15
16
|
/**
|
|
16
17
|
* @param operatorKey Agent-scoped or fleet operator key.
|
|
17
18
|
* @param agentId Required for fleet keys (sent as X-Agent-Id). Omit for agent-scoped keys.
|
|
@@ -20,13 +21,14 @@ export class InboxClient {
|
|
|
20
21
|
* process is not its host (the CLI, one hosted-MCP connection among many)
|
|
21
22
|
* must pass its own; everything long-lived omits it.
|
|
22
23
|
*/
|
|
23
|
-
constructor(operatorKey, agentId, baseUrl, instanceId) {
|
|
24
|
+
constructor(operatorKey, agentId, baseUrl, instanceId, session) {
|
|
24
25
|
if (!operatorKey)
|
|
25
26
|
throw new Error('InboxClient: operatorKey is required');
|
|
26
27
|
this.operatorKey = operatorKey;
|
|
27
28
|
this.agentId = agentId;
|
|
28
29
|
this.baseUrl = baseUrl || getBackendUrl();
|
|
29
30
|
this.instanceId = hostIdentity(instanceId);
|
|
31
|
+
this.session = session;
|
|
30
32
|
}
|
|
31
33
|
headers() {
|
|
32
34
|
const headers = {
|
|
@@ -38,6 +40,14 @@ export class InboxClient {
|
|
|
38
40
|
};
|
|
39
41
|
if (this.agentId)
|
|
40
42
|
headers['X-Agent-Id'] = this.agentId;
|
|
43
|
+
if (this.session?.clientSessionId)
|
|
44
|
+
headers['X-Ziggs-Session'] = this.session.clientSessionId;
|
|
45
|
+
if (this.session?.workspaceIds)
|
|
46
|
+
headers['X-Ziggs-Workspaces'] = this.session.workspaceIds;
|
|
47
|
+
if (this.session?.app)
|
|
48
|
+
headers['X-Ziggs-App'] = this.session.app;
|
|
49
|
+
if (this.session?.sessionName)
|
|
50
|
+
headers['X-Ziggs-Session-Name'] = this.session.sessionName;
|
|
41
51
|
return headers;
|
|
42
52
|
}
|
|
43
53
|
inboxUrl(path, opts) {
|
|
@@ -6,9 +6,13 @@ export interface PaymentsError extends Error {
|
|
|
6
6
|
}
|
|
7
7
|
export interface WalletBalance {
|
|
8
8
|
walletId: string | null;
|
|
9
|
+
/** Always `points` on a read. The wallet row stores a different code. */
|
|
9
10
|
currency: string;
|
|
11
|
+
/** Hundredths of a point. */
|
|
10
12
|
balance: number;
|
|
13
|
+
/** Hundredths of a point, total minus holds. */
|
|
11
14
|
availableBalance: number;
|
|
15
|
+
unit: 'hundredths of a point';
|
|
12
16
|
}
|
|
13
17
|
/**
|
|
14
18
|
* A resolved wallet reference (GET /payments/wallets/resolve).
|
|
@@ -97,12 +101,6 @@ export declare class PaymentsClient {
|
|
|
97
101
|
* (retired GET /payments/grants), following the cursor to completion.
|
|
98
102
|
*/
|
|
99
103
|
listGrants(): Promise<GrantView[]>;
|
|
100
|
-
createTopUpIntent({ amount, description, currency, }?: {
|
|
101
|
-
amount?: number;
|
|
102
|
-
description?: string;
|
|
103
|
-
currency?: string;
|
|
104
|
-
}): Promise<unknown>;
|
|
105
|
-
confirmMockIntent(intentId: string): Promise<unknown>;
|
|
106
104
|
faucet({ amount, description, idempotencyKey, }?: {
|
|
107
105
|
amount?: number;
|
|
108
106
|
description?: string;
|
|
@@ -5,6 +5,10 @@ import { throwApiError } from '../shared/apiError.js';
|
|
|
5
5
|
function randomIdempotencyKey(prefix = 'op') {
|
|
6
6
|
return `${prefix}_${Date.now().toString(36)}_${Math.random().toString(36).slice(2, 10)}`;
|
|
7
7
|
}
|
|
8
|
+
/** The wallet stores `pez`. A person or an assistant reads points. */
|
|
9
|
+
function shownPointCurrency(currency) {
|
|
10
|
+
return typeof currency === 'string' && currency && currency !== 'pez' ? currency : 'points';
|
|
11
|
+
}
|
|
8
12
|
/**
|
|
9
13
|
* the one payments client for every surface (agent-sdk, ziggs-mcp,
|
|
10
14
|
* scripts). Consolidates the former agent-sdk private ZiggsPayClient. Wallet
|
|
@@ -45,9 +49,10 @@ export class PaymentsClient {
|
|
|
45
49
|
const wallet = w['wallet'];
|
|
46
50
|
return {
|
|
47
51
|
walletId: wallet?.['walletId'] || null,
|
|
48
|
-
currency: wallet?.['currency']
|
|
52
|
+
currency: shownPointCurrency(wallet?.['currency']),
|
|
49
53
|
balance: w['balance'] ?? 0,
|
|
50
54
|
availableBalance: w['availableBalance'] ?? 0,
|
|
55
|
+
unit: 'hundredths of a point',
|
|
51
56
|
};
|
|
52
57
|
}
|
|
53
58
|
async resolve({ userId, agentId } = {}) {
|
|
@@ -91,12 +96,6 @@ export class PaymentsClient {
|
|
|
91
96
|
const grants = new GrantsClient(this.operatorKey, this.agentId, this.baseUrl, this.laneId);
|
|
92
97
|
return grants.listAllGrants({ scopeKind: 'wallet', health: 'active' });
|
|
93
98
|
}
|
|
94
|
-
async createTopUpIntent({ amount, description, currency, } = {}) {
|
|
95
|
-
return this._post('/payments/onramp/intent', { amount, description, currency });
|
|
96
|
-
}
|
|
97
|
-
async confirmMockIntent(intentId) {
|
|
98
|
-
return this._post(`/payments/onramp/mock-confirm/${intentId}`, {});
|
|
99
|
-
}
|
|
100
99
|
async faucet({ amount, description = 'Faucet', idempotencyKey, } = {}) {
|
|
101
100
|
return this._post('/payments/wallet/fund', {
|
|
102
101
|
amount,
|
package/dist/types.d.ts
CHANGED
|
@@ -47,6 +47,18 @@ export interface Creds {
|
|
|
47
47
|
* `src/instanceIdentity.ts` for what each rail sends.
|
|
48
48
|
*/
|
|
49
49
|
instanceId?: string;
|
|
50
|
+
/**
|
|
51
|
+
* This window, sent as `X-Ziggs-Session`. Reconnects that present the same
|
|
52
|
+
* id land on the same row. Unset on a long-lived process: the inbox host
|
|
53
|
+
* header is the window.
|
|
54
|
+
*/
|
|
55
|
+
clientSessionId?: string;
|
|
56
|
+
/** Comma-separated workspace ids. Sent as `X-Ziggs-Workspaces`. Absent does not narrow. */
|
|
57
|
+
workspaceIds?: string;
|
|
58
|
+
/** Connection label, sent as `X-Ziggs-App`. */
|
|
59
|
+
app?: string;
|
|
60
|
+
/** Person-readable window name, sent as `X-Ziggs-Session-Name`. */
|
|
61
|
+
sessionName?: string;
|
|
50
62
|
}
|
|
51
63
|
export type TaskState = 'active' | 'proposal' | 'completed' | 'failed' | 'cancelled' | 'ledger_open';
|
|
52
64
|
export type PlanStepStatus = 'pending' | 'in_progress' | 'completed' | 'skipped';
|