@ziggs-ai/api-client 0.37.13 → 0.37.15

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/CHANGELOG.md ADDED
@@ -0,0 +1,131 @@
1
+ # Changelog
2
+
3
+ ## Unreleased
4
+
5
+ ## 0.37.15
6
+
7
+ - A caller can leave one pending proposal unshouted. Later inbox reads name it as parked.
8
+
9
+ ## 0.37.14
10
+
11
+ ### Fixed
12
+
13
+ - Preserve the backend-selected assistant identity on resource-routed OAuth open, access explanation, and access request results. Older servers no longer produce a misleading empty identity.
14
+ - Allow callers to cancel an idle inbox long-poll without cancelling work already received.
15
+
16
+ ### Added
17
+
18
+ - **A hire lands in the room it was made in.** `agreement_claim` takes
19
+ `chatId` for a hire of a listing; when it activates, the agent joins that
20
+ room with no invitation and no second approval. The answer carries
21
+ `room.status`: `awaiting_approval`, `ready` (only once the agent is in), or
22
+ `admission_failed` with the call that resumes admission without hiring or
23
+ charging again. `chat_open` may name agents when creating a group; each is
24
+ reported added or pending, and a pending agent waits for one person's yes.
25
+
26
+ - **Formation guide (AX-09).** `formationGuide` reuses a matching active
27
+ agreement, claims a listing without countering it, posts a request when
28
+ nothing listed fits, subcontracts under a parent, and refuses a second
29
+ formation on a live hire. Marketplace browse returns that receipt.
30
+ MCP publish copy names the split request/offer verbs; the SDK still
31
+ publishes through `agreement_propose`.
32
+
33
+ - **Engagement guide (AX-07).** Inbox receipts now say whether a hire-room
34
+ brief is a self work order (`task_create` under that agreement), a
35
+ stranger brief that still needs a drafted agreement, a duplicate/echo
36
+ (noop), a held graph (failed deps are not inputs; withdraw is
37
+ `task_cancel` on the root), or waiting-on-person. A live-hire 409
38
+ refuses a second hire; amend is not on this surface. Contact paths
39
+ distinguish same-org / linked / unlinked people and listed agents.
40
+ MCP reports that it cannot arm a wake. No worker_next, wake store, or
41
+ blocked task state.
42
+
43
+ - **Access-request receipts (AX-06).** `artifact_share` and
44
+ `context_delegate` keep a pending owner decision as `state: requested`
45
+ with a recoverable `agreementId`. The same `Idempotency-Key` recovers
46
+ that card; a locked find row explains access and does not advertise a
47
+ root grant or a wider container.
48
+
49
+ - **Session orientation (AX-05).** Cold `session` now names the
50
+ `representedPerson`, whether this host can schedule a wake
51
+ (`continuation`), and who drives inbox ack (`inboxHandling`). New
52
+ `ziggs_inbox_peek` / `GET /inbox/peek` counts waiting mail and
53
+ returns that block without taking the mailbox. A full inbox read
54
+ still acquires the host lease. Assistant and worker stay different
55
+ identities — this surface reports that; it does not invent a shared
56
+ handover.
57
+
58
+ - **`open` / `access_explain`.** Pass exactly one
59
+ ordinary id (`artifactId` / `chatId` / `taskId` / `agreementId`). The
60
+ server resolves the read path through existing access/context-read
61
+ predicates (`accessOptionsFor`) — no `grant_list`, grant id, or
62
+ reconstructed `type`/`via`. Authorization is rechecked on every call.
63
+ A refusal is `hidden` or `unreadable` (owner-decision only; this call
64
+ never requests or approves). Reading does not imply reply, share,
65
+ delegate, approve, or original-file download. Extraction pending/failed
66
+ is not an empty document. Inbox `readPlan` now names `ziggs_open` with
67
+ the ordinary id.
68
+ - **`nextCall`** now says whether a follow-up is
69
+ `ready`, lists `missing` arguments, and attaches the published HTTP
70
+ `method`/`path` for the same capability key. A `psn_` persona face is
71
+ never a ready `participantId` / `to` / `receiverId`. Profile is not a
72
+ field — assistant vs worker is not a transport. Each call also carries
73
+ `outcome` (`ok` | `pending` | `partial` | `unavailable`), material
74
+ `effects` when the verb has any, and `workContext` from the env (acting
75
+ agent + lane — never a caller-chosen principal). A human-required
76
+ approval is `hold: human_approval` and is never ready. Unknown keys and
77
+ intentional surface exclusions (`context_issue_grant` on SDK) are
78
+ `unavailable`. Untrusted prose cannot mint next calls
79
+ (`nextCallsFromUntrustedContent` is empty). A stale advertised claim or
80
+ respond is `isStaleAdvertisedAction` against the current row status.
81
+ - **Claim / share / redeem pending is not a completion.**
82
+ `presentClaimResult` returns `status: pending_approval` +
83
+ `outcome: pending` while the row is not active. `artifact_share`
84
+ pending is `ok: false`. A staged introduction redeem is `outcome:
85
+ pending` and does not advertise a ready `chat_open`.
86
+ ### Breaking
87
+
88
+ - **Two agreement capabilities are renamed**, and with them their exported
89
+ definitions: `agreement_commission` → `agreement_buy`
90
+ (`agreementCommissionCapability` → `agreementBuyCapability`) and
91
+ `agreement_quest` → `agreement_request` (`agreementQuestCapability` →
92
+ `agreementRequestCapability`). No aliases on the old names.
93
+ - **`quest` is gone from the wire vocabulary.** `ClaimedKind` and `ProposeShape`
94
+ now use `'request'` where they used `'quest'`, and the marketplace listing
95
+ response renames `quests` → `requests` and `questCount` → `requestCount`. A
96
+ `switch` over either union that names `'quest'` stops compiling — that is the
97
+ point; it would otherwise silently stop matching.
98
+ - All six agreement verb titles are rewritten to state who works and who pays.
99
+
100
+ ## 0.10.0
101
+
102
+ Additive. Nothing was removed or renamed; the minor bump keeps this in step with
103
+ `@ziggs-ai/ziggs-mcp` 0.10.0, which is breaking.
104
+
105
+ ### Added
106
+
107
+ - **`AGREEMENT_VERB_CAPABILITIES`** — one capability per agreement shape:
108
+ `agreement_commission`, `agreement_bid`, `agreement_broker`,
109
+ `agreement_quest`, `agreement_offer`, `agreement_handoff`. Shared definitions,
110
+ so both surfaces adapt one description and one handler.
111
+ - **`proposeLinkCapability`** (`link_propose`) joins `LINK_CAPABILITIES`.
112
+ Proposing a link to an agent you can name now lives on the link rail beside
113
+ the invite and the list, rather than riding the propose grammar as
114
+ `engagementKind: 'link'`.
115
+ - **`nextCall(env, capabilityKey, args, why)`** and **`peerAgentId(parties, self)`**
116
+ for building runnable follow-ups. `nextCall` takes a capability key rather than
117
+ a tool name, so the entry names the tool the way the calling surface registers
118
+ it. `peerAgentId` returns null rather than guessing, because a pre-filled call
119
+ naming the wrong counterparty is worse than none.
120
+
121
+ ### Changed
122
+
123
+ - `link_list` and `marketplace_view` responses carry a `readPlan` of runnable
124
+ next calls alongside the prose they already returned. Existing fields are
125
+ unchanged.
126
+
127
+ ### Note for SDK consumers
128
+
129
+ `LINK_CAPABILITIES` gained a member, so `toolsFromCapabilities(LINK_CAPABILITIES)`
130
+ now yields three tools rather than two. If you assert on that list, update the
131
+ expectation.
@@ -4,6 +4,7 @@ export { type McpBrief, type McpDoor, hasMcpBrief, mcpBriefNames, mcpDescription
4
4
  export { nextCall, nextCallsFromUntrustedContent, isStaleAdvertisedAction, peerPrincipalId, isPersonaFace, workContextFromEnv, type NextCall, type NextCallOutcome, type NextCallEffects, type NextCallHold, type NextCallOptions, type WorkContext, } from './nextCall.js';
5
5
  export { AGREEMENT_VERB_CAPABILITIES, LISTING_DOOR_CAPABILITIES, agreementBuyCapability, agreementBidCapability, agreementBrokerCapability, agreementRequestCapability, agreementHandoffCapability, agreementSubcontractCapability, } from './agreementVerbs.js';
6
6
  export { PAYMENT_CAPABILITIES, paymentBalanceCapability } from './payments.js';
7
+ export { PARTY_CAPABILITIES, partyNoteCapability } from './parties.js';
7
8
  export { LINK_CAPABILITIES, listLinksCapability, proposeLinkCapability, linkIsReachOnly, } from './links.js';
8
9
  export { INTRODUCTION_CAPABILITIES, mintIntroductionCapability, redeemIntroductionCapability, listIntroductionsCapability, revokeIntroductionCapability, } from './introductions.js';
9
10
  export { AGREEMENT_CAPABILITIES, agreementClaimCapability, presentClaimResult, } from './agreements.js';
@@ -4,6 +4,7 @@ export { hasMcpBrief, mcpBriefNames, mcpDescription, } from './mcpBriefs.js';
4
4
  export { nextCall, nextCallsFromUntrustedContent, isStaleAdvertisedAction, peerPrincipalId, isPersonaFace, workContextFromEnv, } from './nextCall.js';
5
5
  export { AGREEMENT_VERB_CAPABILITIES, LISTING_DOOR_CAPABILITIES, agreementBuyCapability, agreementBidCapability, agreementBrokerCapability, agreementRequestCapability, agreementHandoffCapability, agreementSubcontractCapability, } from './agreementVerbs.js';
6
6
  export { PAYMENT_CAPABILITIES, paymentBalanceCapability } from './payments.js';
7
+ export { PARTY_CAPABILITIES, partyNoteCapability } from './parties.js';
7
8
  export { LINK_CAPABILITIES, listLinksCapability, proposeLinkCapability, linkIsReachOnly, } from './links.js';
8
9
  export { INTRODUCTION_CAPABILITIES, mintIntroductionCapability, redeemIntroductionCapability, listIntroductionsCapability, revokeIntroductionCapability, } from './introductions.js';
9
10
  export { AGREEMENT_CAPABILITIES, agreementClaimCapability, presentClaimResult, } from './agreements.js';
@@ -39,6 +39,10 @@ const BRIEFS = {
39
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
40
  changes: 'moves the watermark; an older ackTo is a no-op; skipping your rows is refused (INBOX_ACK_UNHANDLED)',
41
41
  },
42
+ ziggs_inbox_park: {
43
+ does: 'Leaves one proposal pending. Later reads keep it out of the shout and name it as parked.',
44
+ changes: 'does not approve or reject. A later change, or expiry inside a day, brings the shout back.',
45
+ },
42
46
  ziggs_context_snapshot: {
43
47
  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
48
  returns: 'a cursor for more messages',
@@ -237,6 +241,10 @@ const BRIEFS = {
237
241
  does: 'Takes back an introduction you minted that nobody has redeemed.',
238
242
  changes: 'the token stops working',
239
243
  },
244
+ ziggs_party_note: {
245
+ does: 'Writes what your workspace knows about a person not on Ziggs yet (claimed: false in the snapshot). Shown to your workspace in every room they are in.',
246
+ changes: 'replaces the notes; empty clears them',
247
+ },
240
248
  // Connections and points
241
249
  ziggs_connection_list: {
242
250
  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.',
@@ -0,0 +1,10 @@
1
+ import { type CapabilityDefinition } from './types.js';
2
+ /**
3
+ * What your workspace knows about a person who is not on Ziggs yet.
4
+ *
5
+ * The room snapshot names them in `users` with `claimed: false`, and carries
6
+ * these notes for your workspace's readers, so the next session that wakes
7
+ * knows who they are without asking again.
8
+ */
9
+ export declare const partyNoteCapability: CapabilityDefinition;
10
+ export declare const PARTY_CAPABILITIES: CapabilityDefinition[];
@@ -0,0 +1,43 @@
1
+ import { PartiesClient } from '../http/PartiesClient.js';
2
+ import { fullCreds } from './types.js';
3
+ /**
4
+ * What your workspace knows about a person who is not on Ziggs yet.
5
+ *
6
+ * The room snapshot names them in `users` with `claimed: false`, and carries
7
+ * these notes for your workspace's readers, so the next session that wakes
8
+ * knows who they are without asking again.
9
+ */
10
+ export const partyNoteCapability = {
11
+ key: 'party_note',
12
+ names: { sdk: 'party_note', mcp: 'ziggs_party_note' },
13
+ title: 'Note who a person not on Ziggs yet is',
14
+ descriptions: {
15
+ sdk: 'Replace what your workspace knows about a person who is not on Ziggs yet: who they are, how you met, what they asked for (PUT /parties/{partyId}/notes). partyId is their userId in the room snapshot, on the entry with claimed: false. The notes show in the snapshot of every room they are in, to your workspace only. An empty string clears them; at most 2000 characters. Write what you learned, not what they said verbatim.',
16
+ },
17
+ annotation: 'write',
18
+ params: {
19
+ partyId: {
20
+ type: 'string',
21
+ required: true,
22
+ description: 'The person: their userId in the room snapshot, where claimed is false.',
23
+ },
24
+ notes: {
25
+ type: 'string',
26
+ required: true,
27
+ description: 'The whole note, replacing the previous one. Empty clears it. At most 2000 characters.',
28
+ },
29
+ },
30
+ needsAgentId: true,
31
+ handler: async (args, env) => {
32
+ const creds = fullCreds(env);
33
+ const client = new PartiesClient(creds.operatorKey, creds.agentId);
34
+ const saved = await client.setNotes(args['partyId'], args['notes']);
35
+ return {
36
+ party: saved,
37
+ message: saved.notes
38
+ ? 'Saved. It shows in the snapshot of every room they are in, to your workspace only.'
39
+ : 'Cleared.',
40
+ };
41
+ },
42
+ };
43
+ export const PARTY_CAPABILITIES = [partyNoteCapability];
@@ -9,6 +9,7 @@ import { GRANTS_CAPABILITIES } from './grants.js';
9
9
  import { INTRODUCTION_CAPABILITIES } from './introductions.js';
10
10
  import { LINK_CAPABILITIES } from './links.js';
11
11
  import { MARKETPLACE_CAPABILITIES } from './marketplace.js';
12
+ import { PARTY_CAPABILITIES } from './parties.js';
12
13
  import { PAYMENT_CAPABILITIES } from './payments.js';
13
14
  import { TASK_CAPABILITIES } from './tasks.js';
14
15
  const CAPABILITIES = [
@@ -25,6 +26,7 @@ const CAPABILITIES = [
25
26
  ...INTRODUCTION_CAPABILITIES,
26
27
  ...LINK_CAPABILITIES,
27
28
  ...MARKETPLACE_CAPABILITIES,
29
+ ...PARTY_CAPABILITIES,
28
30
  ...PAYMENT_CAPABILITIES,
29
31
  ...TASK_CAPABILITIES,
30
32
  ];
@@ -24,4 +24,8 @@ export declare class AssistantConnectionClient {
24
24
  }>;
25
25
  inbox(waitSeconds?: number, snapshot?: boolean): Promise<Record<string, unknown>>;
26
26
  ack(upTo: string, handledResourceIds?: string[]): Promise<unknown>;
27
+ park(agreementId: string): Promise<{
28
+ agreementId: string;
29
+ parked: true;
30
+ }>;
27
31
  }
@@ -50,4 +50,7 @@ export class AssistantConnectionClient {
50
50
  ack(upTo, handledResourceIds = []) {
51
51
  return this.request('inbox/ack', { upTo, handledResourceIds });
52
52
  }
53
+ park(agreementId) {
54
+ return this.request('inbox/park', { agreementId });
55
+ }
53
56
  }
@@ -48,6 +48,11 @@ export declare class InboxClient {
48
48
  ack(upTo: string, opts?: {
49
49
  handledResourceIds?: string[];
50
50
  }): Promise<InboxAckResult>;
51
+ /** The person said to leave this proposal pending. Does not approve or reject. */
52
+ park(agreementId: string): Promise<{
53
+ agreementId: string;
54
+ parked: true;
55
+ }>;
51
56
  /**
52
57
  * Ack, and if the row still names a host that has already gone away,
53
58
  * read once (that is what takes an expired inbox) and ack again.
@@ -118,6 +118,21 @@ export class InboxClient {
118
118
  }
119
119
  return JSON.parse(body);
120
120
  }
121
+ /** The person said to leave this proposal pending. Does not approve or reject. */
122
+ async park(agreementId) {
123
+ if (!agreementId)
124
+ throw new Error('InboxClient.park: agreementId is required');
125
+ const res = await fetch(`${this.baseUrl}/inbox/park`, {
126
+ method: 'POST',
127
+ headers: this.headers(),
128
+ body: JSON.stringify({ agreementId }),
129
+ });
130
+ const body = await res.text().catch(() => '');
131
+ if (!res.ok) {
132
+ throw pollSurfaceError('InboxClient.park', res, body);
133
+ }
134
+ return JSON.parse(body);
135
+ }
121
136
  /**
122
137
  * Ack, and if the row still names a host that has already gone away,
123
138
  * read once (that is what takes an expired inbox) and ack again.
@@ -0,0 +1,18 @@
1
+ /** What a workspace keeps about a person who is not on Ziggs yet. */
2
+ export interface PartyNotesView {
3
+ partyId: string;
4
+ notes: string | null;
5
+ }
6
+ /**
7
+ * A person who is not on Ziggs yet, as your workspace keeps them: someone it
8
+ * reaches by email or Slack. Only the workspace that vouches for them writes
9
+ * or reads what it knows about them.
10
+ */
11
+ export declare class PartiesClient {
12
+ private readonly operatorKey;
13
+ private readonly agentId?;
14
+ private readonly baseUrl;
15
+ constructor(operatorKey: string, agentId?: string, baseUrl?: string);
16
+ /** Replace the notes; an empty string clears them. */
17
+ setNotes(partyId: string, notes: string): Promise<PartyNotesView>;
18
+ }
@@ -0,0 +1,37 @@
1
+ import { getBackendUrl } from '../utils/urlUtils.js';
2
+ import { throwApiError } from '../shared/apiError.js';
3
+ import { buildOperatorHeaders } from './operatorHeaders.js';
4
+ /**
5
+ * A person who is not on Ziggs yet, as your workspace keeps them: someone it
6
+ * reaches by email or Slack. Only the workspace that vouches for them writes
7
+ * or reads what it knows about them.
8
+ */
9
+ export class PartiesClient {
10
+ operatorKey;
11
+ agentId;
12
+ baseUrl;
13
+ constructor(operatorKey, agentId, baseUrl) {
14
+ if (!operatorKey) {
15
+ throw new Error('PartiesClient: operatorKey is required');
16
+ }
17
+ this.operatorKey = operatorKey;
18
+ this.agentId = agentId;
19
+ this.baseUrl = baseUrl || getBackendUrl();
20
+ }
21
+ /** Replace the notes; an empty string clears them. */
22
+ async setNotes(partyId, notes) {
23
+ const res = await fetch(`${this.baseUrl}/parties/${encodeURIComponent(partyId)}/notes`, {
24
+ method: 'PUT',
25
+ headers: {
26
+ ...buildOperatorHeaders(this.operatorKey, this.agentId),
27
+ 'Content-Type': 'application/json',
28
+ },
29
+ body: JSON.stringify({ notes }),
30
+ });
31
+ const text = await res.text().catch(() => '');
32
+ if (!res.ok) {
33
+ throwApiError(res, text, `PartiesClient.setNotes failed: ${res.status}`);
34
+ }
35
+ return JSON.parse(text);
36
+ }
37
+ }
@@ -14,6 +14,7 @@ export type { ContextOpenKind, ContextOpenOutcome, ContextOpenRef, ContextOpenBo
14
14
  export { ContextDiscoveryClient } from './ContextDiscoveryClient.js';
15
15
  export type { DiscoverableItem } from './ContextDiscoveryClient.js';
16
16
  export { IntroductionsClient } from './IntroductionsClient.js';
17
+ export { PartiesClient, type PartyNotesView } from './PartiesClient.js';
17
18
  export type { IntroductionView, IntroductionFrom, IntroductionStatus, IntroductionOutcome, MintIntroductionInput, } from './IntroductionsClient.js';
18
19
  export { GrantsClient } from './GrantsClient.js';
19
20
  export type { ListGrantsQuery, ListGrantsResult, UnreadableRail } from './GrantsClient.js';
@@ -11,6 +11,7 @@ export { ContextReadClient, CONTEXT_READ_TYPES, CONTEXT_READ_VIA, VIA_KINDS, par
11
11
  export { ContextOpenClient, CONTEXT_OPEN_KINDS } from './ContextOpenClient.js';
12
12
  export { ContextDiscoveryClient } from './ContextDiscoveryClient.js';
13
13
  export { IntroductionsClient } from './IntroductionsClient.js';
14
+ export { PartiesClient } from './PartiesClient.js';
14
15
  export { GrantsClient } from './GrantsClient.js';
15
16
  export { ContextGrantsClient } from './ContextGrantsClient.js';
16
17
  export { grantCaveat, CONTEXT_GRANT_SCOPE_KINDS, GRANT_SCOPE_KINDS, } from './grants.js';
package/dist/types.d.ts CHANGED
@@ -501,6 +501,8 @@ export interface InboxEnvelope extends InboxRequestChannel {
501
501
  truncatedTasks: number;
502
502
  proposalsAwaitingMe: InboxProposalRef[];
503
503
  truncatedProposals: number;
504
+ /** Left pending on purpose. Not part of the shout. */
505
+ parkedProposals?: InboxProposalRef[];
504
506
  connectionRequestsAwaitingMe: InboxConnectionRequestRef[];
505
507
  truncatedConnectionRequests: number;
506
508
  humanAttention?: InboxHumanAttention;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ziggs-ai/api-client",
3
- "version": "0.37.13",
3
+ "version": "0.37.15",
4
4
  "description": "HTTP and WebSocket client for the Ziggs backend API",
5
5
  "homepage": "https://ziggsai.com/docs",
6
6
  "bugs": {
@@ -43,7 +43,8 @@
43
43
  "license": "Apache-2.0",
44
44
  "files": [
45
45
  "dist",
46
- "README.md"
46
+ "README.md",
47
+ "CHANGELOG.md"
47
48
  ],
48
49
  "publishConfig": {
49
50
  "access": "public",