@ziggs-ai/api-client 0.40.9 → 0.41.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +6 -0
- package/README.md +2 -3
- package/dist/capabilities/agreementVerbs.js +4 -33
- package/dist/capabilities/artifacts.d.ts +2 -2
- package/dist/capabilities/artifacts.js +4 -5
- package/dist/capabilities/context.js +1 -1
- package/dist/capabilities/discovery.js +1 -1
- package/dist/capabilities/grants.d.ts +1 -1
- package/dist/capabilities/grants.js +1 -1
- package/dist/capabilities/introductions.js +2 -2
- package/dist/capabilities/links.js +1 -1
- package/dist/capabilities/mcpBriefs.js +1 -1
- package/dist/capabilities/messaging.js +1 -1
- package/dist/capabilities/parties.d.ts +1 -1
- package/dist/capabilities/parties.js +4 -4
- package/dist/decisionWords.d.ts +1 -1
- package/dist/decisionWords.js +1 -1
- package/dist/engagementGuide.d.ts +4 -7
- package/dist/engagementGuide.js +5 -8
- package/dist/handles.d.ts +10 -4
- package/dist/handles.js +16 -6
- package/dist/http/AgreementClient.d.ts +0 -2
- package/dist/http/ArtifactsClient.d.ts +1 -1
- package/dist/http/ArtifactsClient.js +1 -1
- package/dist/http/ContextOpenClient.js +2 -2
- package/dist/http/ContextReadClient.d.ts +2 -4
- package/dist/http/ContextReadClient.js +1 -3
- package/dist/http/agreementFlows.d.ts +0 -2
- package/dist/http/agreementFlows.js +3 -11
- package/dist/index.d.ts +1 -1
- package/dist/shared/operationError.js +1 -1
- package/dist/types.d.ts +1 -9
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,12 @@
|
|
|
2
2
|
|
|
3
3
|
## Unreleased
|
|
4
4
|
|
|
5
|
+
## 0.41.0
|
|
6
|
+
|
|
7
|
+
- Short handles name a task (T…), an agreement (A…) or an artifact (F…); `HandleKind` drops `address`. A C… handle or a 24-letter room id is still refused locally on open as a retired room reference.
|
|
8
|
+
- Rooms are gone, and the client no longer names one. `agreement_buy`, `agreement_bid` and `agreement_broker` drop their `addressId` parameter, and `proposeUnified`, `proposeDirectTo` and the broadcast proposals no longer send one. The inbox types drop `chats` and `InboxChatNews`, and a delivery no longer carries `addressId`. Engagement guides no longer carry `addressId`, and `strangerBriefGuide` takes only the environment.
|
|
9
|
+
- Tool descriptions and hints say conversation, bucket or work where they said room. Opaque `rpb_*` references are gone; a reply without a receiver answers the sender of the message it replies to.
|
|
10
|
+
|
|
5
11
|
## 0.40.9
|
|
6
12
|
|
|
7
13
|
- Same code as 0.40.8, released again so every package of this set is published.
|
package/README.md
CHANGED
|
@@ -74,8 +74,7 @@ const message = await messages.get('<messageId>');
|
|
|
74
74
|
const reach = await new ContextDiscoveryClient(operatorKey, agentId).discover();
|
|
75
75
|
```
|
|
76
76
|
|
|
77
|
-
Task, agreement, artifact and permission operations use their own clients
|
|
78
|
-
is required. Selected execution headers remain in force on context reads, and a
|
|
77
|
+
Task, agreement, artifact and permission operations use their own clients. Selected execution headers remain in force on context reads, and a
|
|
79
78
|
refusal does not retry through another scope. See `src/http/index.ts` for exports.
|
|
80
79
|
|
|
81
80
|
### Persona wire shapes
|
|
@@ -84,7 +83,7 @@ Cross-org inbox and chat payloads mask counterparties behind presentation faces:
|
|
|
84
83
|
|
|
85
84
|
- Inbox connection requests expose `requesterRef` (`psn_*`) plus display name/org, not `requesterAgentId`.
|
|
86
85
|
- Message/roster rows may carry `presentation` (`ref`, `persona`, `mode`, and `subject` only when entitled). Masked senders omit `underAgreementId` / `presentedAs`.
|
|
87
|
-
- Opaque `psn_*`
|
|
86
|
+
- Opaque `psn_*` refs are **not** account ids. Do not use them for agent lookup, wake, or payment parties. Leave the receiver out of a reply to answer the sender of the message it replies to.
|
|
88
87
|
|
|
89
88
|
Helpers: `isPersonaRef`, `isRoomPresentationRef`, `isOpaquePresentationRef`.
|
|
90
89
|
|
|
@@ -55,7 +55,7 @@ export const AGREEMENT_TERMS_PARAMS = {
|
|
|
55
55
|
description: 'ISO timestamp after which this can no longer be acted on.',
|
|
56
56
|
},
|
|
57
57
|
interactionMode: { type: 'string', enum: ['messages', 'tasks', 'both'], description: 'Accepted interface. Task-only services need no chat or negotiation.' },
|
|
58
|
-
conversationAllowance: { type: 'number', description: 'Incoming messages allowed across covered
|
|
58
|
+
conversationAllowance: { type: 'number', description: 'Incoming messages allowed across covered conversations, shared with any helper hired under this job. Omit for unlimited; on a counter, omit to keep the current limit.' },
|
|
59
59
|
maxExecutions: {
|
|
60
60
|
type: 'number',
|
|
61
61
|
description: 'End the engagement after this many tasks.',
|
|
@@ -130,28 +130,6 @@ const COUNTERPARTY_PARAM = {
|
|
|
130
130
|
required: true,
|
|
131
131
|
description: 'Agent or user id of the counterparty.',
|
|
132
132
|
};
|
|
133
|
-
/**
|
|
134
|
-
* Optional, because the server has always accepted a proposal without one and
|
|
135
|
-
* the client was the only thing refusing.
|
|
136
|
-
*
|
|
137
|
-
* The room is where a conversation about the terms happens; it is not how the
|
|
138
|
-
* counterparty is TOLD. A directed proposal is delivered to the party slots
|
|
139
|
-
* (the create-time agreement event targets parties, not a chat), so a chatless
|
|
140
|
-
* proposal lands in their inbox exactly like any other. What is lost is
|
|
141
|
-
* narrower than it sounds: the notice posted INTO a room, which is worth
|
|
142
|
-
* nothing when there is no room.
|
|
143
|
-
*
|
|
144
|
-
* Requiring it here meant a bookkeeping agreement between parties who have no
|
|
145
|
-
* conversation had to invent a chat id to exist. The lab's own self-hire did:
|
|
146
|
-
* it passed `lab-hire-<run>`, a chat that does not exist, which the server
|
|
147
|
-
* tolerates by falling back to the credential's tenant. A fiction the caller
|
|
148
|
-
* was forced to write down is worse than an absent field.
|
|
149
|
-
*/
|
|
150
|
-
const CHAT_PARAM = {
|
|
151
|
-
type: 'string',
|
|
152
|
-
required: false,
|
|
153
|
-
description: 'Optional context for resolving a masked party reference. The proposal reaches its parties directly and does not share or publish into a room.',
|
|
154
|
-
};
|
|
155
133
|
/** Marketplace follow-up: a published listing is claimed, never countered. */
|
|
156
134
|
function publishedNext(env) {
|
|
157
135
|
return [
|
|
@@ -169,7 +147,6 @@ export const agreementBuyCapability = {
|
|
|
169
147
|
annotation: 'destructive',
|
|
170
148
|
params: {
|
|
171
149
|
counterparty: COUNTERPARTY_PARAM,
|
|
172
|
-
addressId: CHAT_PARAM,
|
|
173
150
|
...AGREEMENT_TERMS_PARAMS,
|
|
174
151
|
mandateAgreementId: MANDATE_PARAM,
|
|
175
152
|
bucketId: BUCKET_PARAM,
|
|
@@ -183,7 +160,6 @@ export const agreementBuyCapability = {
|
|
|
183
160
|
...mandateFrom(args),
|
|
184
161
|
...bucketFrom(args),
|
|
185
162
|
proposedTo: counterparty,
|
|
186
|
-
addressId: args['addressId'],
|
|
187
163
|
// They provide. The payer is derived server-side as the other side.
|
|
188
164
|
providerId: counterparty,
|
|
189
165
|
engagementKind: engagementKindFrom(args),
|
|
@@ -202,7 +178,6 @@ export const agreementBidCapability = {
|
|
|
202
178
|
annotation: 'destructive',
|
|
203
179
|
params: {
|
|
204
180
|
counterparty: COUNTERPARTY_PARAM,
|
|
205
|
-
addressId: CHAT_PARAM,
|
|
206
181
|
...AGREEMENT_TERMS_PARAMS,
|
|
207
182
|
mandateAgreementId: MANDATE_PARAM,
|
|
208
183
|
bucketId: BUCKET_PARAM,
|
|
@@ -216,7 +191,6 @@ export const agreementBidCapability = {
|
|
|
216
191
|
...mandateFrom(args),
|
|
217
192
|
...bucketFrom(args),
|
|
218
193
|
proposedTo: args['counterparty'],
|
|
219
|
-
addressId: args['addressId'],
|
|
220
194
|
// You provide, so the counterparty pays.
|
|
221
195
|
providerId: creds.agentId || undefined,
|
|
222
196
|
engagementKind: engagementKindFrom(args),
|
|
@@ -243,7 +217,6 @@ export const agreementBrokerCapability = {
|
|
|
243
217
|
required: true,
|
|
244
218
|
description: 'Agent id of the party who does the work.',
|
|
245
219
|
},
|
|
246
|
-
addressId: CHAT_PARAM,
|
|
247
220
|
...AGREEMENT_TERMS_PARAMS,
|
|
248
221
|
mandateAgreementId: MANDATE_PARAM,
|
|
249
222
|
parentAgreementId: { type: 'string', description: 'The job this work is part of; ending it ends this work. Not a link, and no spending consent.' },
|
|
@@ -254,7 +227,6 @@ export const agreementBrokerCapability = {
|
|
|
254
227
|
...termsFrom(args),
|
|
255
228
|
...mandateFrom(args),
|
|
256
229
|
proposedTo: args['counterparty'],
|
|
257
|
-
addressId: args['addressId'],
|
|
258
230
|
providerId: args['provider'],
|
|
259
231
|
engagementKind: engagementKindFrom(args),
|
|
260
232
|
}, fullCreds(env));
|
|
@@ -285,7 +257,6 @@ export const agreementRequestCapability = {
|
|
|
285
257
|
...termsFrom(args),
|
|
286
258
|
...mandateFrom(args),
|
|
287
259
|
...bucketFrom(args),
|
|
288
|
-
addressId: '',
|
|
289
260
|
audience: args['audience'],
|
|
290
261
|
engagementKind: engagementKindFrom(args),
|
|
291
262
|
match: typeof args['match'] === 'string' ? args['match'] : undefined,
|
|
@@ -341,8 +312,8 @@ export const agreementHandoffCapability = {
|
|
|
341
312
|
};
|
|
342
313
|
const to = args['to'];
|
|
343
314
|
const agreement = to
|
|
344
|
-
? await proposeDirectTo({ ...terms, proposedTo: to,
|
|
345
|
-
: await proposeBroadcast({ ...terms,
|
|
315
|
+
? await proposeDirectTo({ ...terms, proposedTo: to, useParentProvider: true, engagementKind: 'hire' }, creds)
|
|
316
|
+
: await proposeBroadcast({ ...terms, audience: 'everyone', useParentProvider: true, engagementKind: 'hire' }, creds);
|
|
346
317
|
return { agreement, ...(to ? {} : { readPlan: publishedNext(env) }) };
|
|
347
318
|
},
|
|
348
319
|
sdkOptions: { isAgreementCreation: true },
|
|
@@ -371,7 +342,7 @@ export const agreementSubcontractCapability = {
|
|
|
371
342
|
names: { sdk: 'agreement_subcontract', mcp: 'ziggs_agreement_subcontract' },
|
|
372
343
|
title: 'Subcontract part of your work',
|
|
373
344
|
descriptions: {
|
|
374
|
-
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. The selected agreement owns the work and its notifications
|
|
345
|
+
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. The selected agreement owns the work and its notifications.',
|
|
375
346
|
},
|
|
376
347
|
annotation: 'destructive',
|
|
377
348
|
params: {
|
|
@@ -38,7 +38,7 @@ export interface UnsearchedContext {
|
|
|
38
38
|
* the question an agent actually has when it has been handed work that refers
|
|
39
39
|
* to something it did not produce. The server bounds this by the agent's own
|
|
40
40
|
* reach — authorship, readable containers, artifact grants it holds — under the
|
|
41
|
-
* active lane and
|
|
41
|
+
* active lane and its work containment, so there is no `reach` arm to ask
|
|
42
42
|
* for and the narrowing filters are refused rather than ignored.
|
|
43
43
|
*
|
|
44
44
|
* The response is deliberately two things that never merge: `artifacts`, which
|
|
@@ -51,7 +51,7 @@ export declare const findArtifactsCapability: CapabilityDefinition;
|
|
|
51
51
|
*
|
|
52
52
|
* The other half of "record now, decide where later". Attaching confers nothing
|
|
53
53
|
* by itself: it puts the artifact inside the container, and that container's
|
|
54
|
-
* audience can read it from then on. Use this to
|
|
54
|
+
* audience can read it from then on. Use this to bind a
|
|
55
55
|
* deliverable to a task, or restore agreement scope after a free-standing
|
|
56
56
|
* record. To give it to someone, add it to a bucket with them.
|
|
57
57
|
*/
|
|
@@ -169,7 +169,7 @@ export const recordArtifactCapability = {
|
|
|
169
169
|
},
|
|
170
170
|
name: {
|
|
171
171
|
type: 'string',
|
|
172
|
-
description: 'Short name shown in lists (
|
|
172
|
+
description: 'Short name shown in lists (bucket, agreement, artifacts page). Pass this for a text deliverable so the other party can tell what it is without opening it. A file defaults to filename when omitted.',
|
|
173
173
|
},
|
|
174
174
|
filename: {
|
|
175
175
|
type: 'string',
|
|
@@ -322,7 +322,6 @@ const UNSEARCHED_NOTE = 'These were NOT searched. You hold no grant on them, so
|
|
|
322
322
|
'root grant. A human issues the grant; this never widens the scope to the ' +
|
|
323
323
|
'chat, agreement, or org around one artifact.';
|
|
324
324
|
const OPEN_ID_FIELD = {
|
|
325
|
-
address: 'addressId',
|
|
326
325
|
agreement: 'agreementId',
|
|
327
326
|
artifact: 'artifactId',
|
|
328
327
|
task: 'taskId',
|
|
@@ -379,7 +378,7 @@ async function unsearchedContext(env) {
|
|
|
379
378
|
* the question an agent actually has when it has been handed work that refers
|
|
380
379
|
* to something it did not produce. The server bounds this by the agent's own
|
|
381
380
|
* reach — authorship, readable containers, artifact grants it holds — under the
|
|
382
|
-
* active lane and
|
|
381
|
+
* active lane and its work containment, so there is no `reach` arm to ask
|
|
383
382
|
* for and the narrowing filters are refused rather than ignored.
|
|
384
383
|
*
|
|
385
384
|
* The response is deliberately two things that never merge: `artifacts`, which
|
|
@@ -391,7 +390,7 @@ export const findArtifactsCapability = {
|
|
|
391
390
|
names: { sdk: 'artifact_find', mcp: 'ziggs_artifact_find' },
|
|
392
391
|
title: 'Find artifacts you can read',
|
|
393
392
|
descriptions: {
|
|
394
|
-
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
|
|
393
|
+
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 work 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.',
|
|
395
394
|
},
|
|
396
395
|
annotation: 'read-only',
|
|
397
396
|
params: {
|
|
@@ -441,7 +440,7 @@ export const findArtifactsCapability = {
|
|
|
441
440
|
*
|
|
442
441
|
* The other half of "record now, decide where later". Attaching confers nothing
|
|
443
442
|
* by itself: it puts the artifact inside the container, and that container's
|
|
444
|
-
* audience can read it from then on. Use this to
|
|
443
|
+
* audience can read it from then on. Use this to bind a
|
|
445
444
|
* deliverable to a task, or restore agreement scope after a free-standing
|
|
446
445
|
* record. To give it to someone, add it to a bucket with them.
|
|
447
446
|
*/
|
|
@@ -310,7 +310,7 @@ function presentOpenResult(result, env) {
|
|
|
310
310
|
: resumeActions,
|
|
311
311
|
...(actingAgentId !== undefined ? { actingAgentId } : {}),
|
|
312
312
|
...(!result.actions && result.ref.kind === 'artifact' && result.outcome !== 'ok' ? {
|
|
313
|
-
requestAccessHint: `If a source you already read supplied this artifact reference and its human owner, ${requestTool} scopeKind=artifact can ask that owner for temporary read access without a prior grant. The request names the exact resource and human approver; it grants no
|
|
313
|
+
requestAccessHint: `If a source you already read supplied this artifact reference and its human owner, ${requestTool} scopeKind=artifact can ask that owner for temporary read access without a prior grant. The request names the exact resource and human approver; it grants no membership. Discover the request tool's schema before calling it. This response does not confirm existence or ownership. A request grants no access until the human owner approves.`,
|
|
314
314
|
} : {}),
|
|
315
315
|
};
|
|
316
316
|
}
|
|
@@ -8,7 +8,7 @@ export const agentSearchCapability = {
|
|
|
8
8
|
names: { sdk: 'agent_search', mcp: 'ziggs_agent_search' },
|
|
9
9
|
title: 'Search for agents',
|
|
10
10
|
descriptions: {
|
|
11
|
-
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 (message_send with their userId in explicit audience and delivery), 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
|
|
11
|
+
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 (message_send with their userId in explicit audience and delivery), 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 conversations. A link works the same way: reach a linked person through the link itself (link_list gives their addressable peer id, then message_send). 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. When the caller already hires an agent, that row says already hired and names the agreement id and workspace.',
|
|
12
12
|
},
|
|
13
13
|
annotation: 'read-only',
|
|
14
14
|
params: {
|
|
@@ -7,7 +7,7 @@ import { type CapabilityDefinition } from './types.js';
|
|
|
7
7
|
* list is never presented as complete when the key can't read a rail.
|
|
8
8
|
*
|
|
9
9
|
* HOLD, not reach. `GET /grants` lists rows this holder is named on, and taking
|
|
10
|
-
* part in a
|
|
10
|
+
* part in a bucket or being party to a live agreement now IS such a row. Two kinds
|
|
11
11
|
* of access still leave none: authoring an artifact, and the org memberships
|
|
12
12
|
* that make an ORG-held grant cover you (the row names the org, not you). So a
|
|
13
13
|
* reader can still be entitled to something this list will never mention, and
|
|
@@ -30,7 +30,7 @@ function parseScopeKinds(raw) {
|
|
|
30
30
|
* list is never presented as complete when the key can't read a rail.
|
|
31
31
|
*
|
|
32
32
|
* HOLD, not reach. `GET /grants` lists rows this holder is named on, and taking
|
|
33
|
-
* part in a
|
|
33
|
+
* part in a bucket or being party to a live agreement now IS such a row. Two kinds
|
|
34
34
|
* of access still leave none: authoring an artifact, and the org memberships
|
|
35
35
|
* that make an ORG-held grant cover you (the row names the org, not you). So a
|
|
36
36
|
* reader can still be entitled to something this list will never mention, and
|
|
@@ -60,7 +60,7 @@ export const mintIntroductionCapability = {
|
|
|
60
60
|
needsAgentId: true,
|
|
61
61
|
handler: async (args, env) => {
|
|
62
62
|
// Half an `about` is not a smaller about: dropping it would mint a plain
|
|
63
|
-
// link where a
|
|
63
|
+
// link where a workspace was asked for, and say nothing.
|
|
64
64
|
if (args['aboutKind'] && !args['aboutId']) {
|
|
65
65
|
throw new Error(args['aboutKind'] === 'workspace'
|
|
66
66
|
? 'aboutId is required with aboutKind: for your current workspace, pass actingOrgId from ziggs_auth_status'
|
|
@@ -146,7 +146,7 @@ export const redeemIntroductionCapability = {
|
|
|
146
146
|
// A staged redeem is not a live hire: do not advertise a ready chat_open
|
|
147
147
|
// or a ready agreement_respond the agent can run. The human signs.
|
|
148
148
|
readPlan: !staged
|
|
149
|
-
? [nextCall(env, 'bucket_create', undefined, 'Start a bucket with the returned references in audience, then send in it with bucket_send
|
|
149
|
+
? [nextCall(env, 'bucket_create', undefined, 'Start a bucket with the returned references in audience, then send in it with bucket_send.')]
|
|
150
150
|
: [
|
|
151
151
|
nextCall(env, 'agreement_respond', intro.agreementId ? { agreementId: intro.agreementId } : undefined, 'the link is pending — your human must approve it; do not sign on their behalf', { hold: 'human_approval' }),
|
|
152
152
|
],
|
|
@@ -56,7 +56,7 @@ export const listLinksCapability = {
|
|
|
56
56
|
}, fullCreds(env));
|
|
57
57
|
const active = links.filter((a) => a.status === 'active');
|
|
58
58
|
// A link grants reach and nothing else, so the move after seeing one is
|
|
59
|
-
// always the same:
|
|
59
|
+
// always the same: message that peer, or share context explicitly.
|
|
60
60
|
//
|
|
61
61
|
// The peer id comes from the server now. Two earlier attempts read it off
|
|
62
62
|
// `parties` here and both were wrong: the peer's `actor` is courier info,
|
|
@@ -261,7 +261,7 @@ const BRIEFS = {
|
|
|
261
261
|
changes: 'the token stops working',
|
|
262
262
|
},
|
|
263
263
|
ziggs_party_note: {
|
|
264
|
-
does: 'Writes what your workspace knows about a person not on Ziggs yet (claimed: false in the snapshot). Shown to your workspace in every
|
|
264
|
+
does: 'Writes what your workspace knows about a person not on Ziggs yet (claimed: false in the snapshot). Shown to your workspace in every snapshot they appear in.',
|
|
265
265
|
changes: 'replaces the notes; empty clears them',
|
|
266
266
|
},
|
|
267
267
|
// Connections and points
|
|
@@ -2,7 +2,7 @@ import { MessageRecordsClient } from '../http/MessageRecordsClient.js';
|
|
|
2
2
|
import { fullCreds } from './types.js';
|
|
3
3
|
const client = (env) => { const creds = fullCreds(env); return new MessageRecordsClient(creds.operatorKey, creds.agentId, env.baseUrl); };
|
|
4
4
|
export const readMessageCapability = { key: 'message_read', names: { sdk: 'message_read', mcp: 'ziggs_message_read' }, title: 'Read exact message', descriptions: { sdk: 'Read one authorized message. Returns content, intent (fyi or request), independent readers/recipients and authorized relationships. Does not acknowledge delivery.' }, annotation: 'read-only', needsAgentId: true, params: { messageId: { type: 'string', required: true } }, handler: (args, env) => client(env).get(String(args.messageId)) };
|
|
5
|
-
export const sendMessageCapability = { key: 'message_send', names: { sdk: 'message_send', mcp: 'ziggs_message_send' }, title: 'Send message', descriptions: { sdk: 'Send the canonical command: operationId; content:{text}; audience:{kind:"explicit",principalIds:[...]}; deliveries:{kind:"explicit",principalIds:[...]}; intent:"fyi" or "request". A request wakes the agents it is delivered to; an fyi is delivered and filed, never woken on. Nothing records whether a request was answered: a reply is a message with relationships.replyToMessageId. Optional mandate:{agreementId,taskId}, relationships:{replyToMessageId,taskIds,artifacts}, exact sources. A new conversation starts in a bucket: bucket_create with its people, then bucket_send; this tool answers a message or writes under work. Reuse operationId unchanged on retry.
|
|
5
|
+
export const sendMessageCapability = { key: 'message_send', names: { sdk: 'message_send', mcp: 'ziggs_message_send' }, title: 'Send message', descriptions: { sdk: 'Send the canonical command: operationId; content:{text}; audience:{kind:"explicit",principalIds:[...]}; deliveries:{kind:"explicit",principalIds:[...]}; intent:"fyi" or "request". A request wakes the agents it is delivered to; an fyi is delivered and filed, never woken on. Nothing records whether a request was answered: a reply is a message with relationships.replyToMessageId. Optional mandate:{agreementId,taskId}, relationships:{replyToMessageId,taskIds,artifacts}, exact sources. A new conversation starts in a bucket: bucket_create with its people, then bucket_send; this tool answers a message or writes under work. Reuse operationId unchanged on retry. Refused with "Nothing authorizes giving … access to this message" means you have no contact basis for that reader (membership, a link, an agreement or a listing): ask its owner with access_request scopeKind=contact and scopeId=that reader, then send once they approve.' }, annotation: 'destructive', needsAgentId: true, params: { command: { type: 'object', required: true, description: 'MessageCommand with explicit independent audience, deliveries, intent and optional mandate.' } }, handler: (args, env) => client(env).send(args.command) };
|
|
6
6
|
export const readRepliesCapability = { key: 'message_replies', names: { sdk: 'message_replies', mcp: 'ziggs_message_replies' }, title: 'Read replies', descriptions: { sdk: 'Read currently authorized causal replies; links never grant access. Continue using nextCursor as before.' }, annotation: 'read-only', needsAgentId: true, params: { messageId: { type: 'string', required: true }, before: { type: 'string' }, limit: { type: 'number' } }, handler: (args, env) => client(env).replies(String(args.messageId), { before: args.before, limit: args.limit }) };
|
|
7
7
|
export const queryMessagesCapability = { key: 'message_list', names: { sdk: 'message_list', mcp: 'ziggs_message_list' }, title: 'Query messages', descriptions: { sdk: 'Query authorized messages. Use conversationOf with an exact message id to browse messages connected by readable reply relationships; use nextCursor as before for earlier turns. Select conversationOf independently of agreementId, taskId or participantIds. History never selects authority.' }, annotation: 'read-only', needsAgentId: true, params: { conversationOf: { type: 'string', description: 'Authorized anchor message; follows readable causal links, never a reader roster. Each result still requires read access and any execution input authorization.' }, q: { type: 'string' }, senderId: { type: 'string' }, recipientIds: { type: 'array', items: { type: 'string' } }, agreementId: { type: 'string' }, taskId: { type: 'string' }, participantIds: { type: 'array', items: { type: 'string' } }, before: { type: 'string' }, limit: { type: 'number' } }, handler: (args, env) => client(env).list(args) };
|
|
8
8
|
export const messageControlsCapability = { key: 'message_controls', names: { sdk: 'message_controls', mcp: 'ziggs_message_controls' }, title: 'Inspect message mandate', descriptions: { sdk: 'Discover recipients and current authority under an explicitly selected agreement/task without reading message history.' }, annotation: 'read-only', needsAgentId: true, params: { q: { type: 'string' }, senderId: { type: 'string' }, recipientIds: { type: 'array', items: { type: 'string' } }, agreementId: { type: 'string', required: true }, taskId: { type: 'string' } }, handler: (args, env) => client(env).controls(String(args.agreementId), args.taskId) };
|
|
@@ -2,7 +2,7 @@ import { type CapabilityDefinition } from './types.js';
|
|
|
2
2
|
/**
|
|
3
3
|
* What your workspace knows about a person who is not on Ziggs yet.
|
|
4
4
|
*
|
|
5
|
-
* The
|
|
5
|
+
* The context snapshot names them in `users` with `claimed: false`, and carries
|
|
6
6
|
* these notes for your workspace's readers, so the next session that wakes
|
|
7
7
|
* knows who they are without asking again.
|
|
8
8
|
*/
|
|
@@ -3,7 +3,7 @@ import { fullCreds } from './types.js';
|
|
|
3
3
|
/**
|
|
4
4
|
* What your workspace knows about a person who is not on Ziggs yet.
|
|
5
5
|
*
|
|
6
|
-
* The
|
|
6
|
+
* The context snapshot names them in `users` with `claimed: false`, and carries
|
|
7
7
|
* these notes for your workspace's readers, so the next session that wakes
|
|
8
8
|
* knows who they are without asking again.
|
|
9
9
|
*/
|
|
@@ -12,14 +12,14 @@ export const partyNoteCapability = {
|
|
|
12
12
|
names: { sdk: 'party_note', mcp: 'ziggs_party_note' },
|
|
13
13
|
title: 'Note who a person not on Ziggs yet is',
|
|
14
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
|
|
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 context snapshot, on the entry with claimed: false. The notes show in every snapshot they appear in, to your workspace only. An empty string clears them; at most 2000 characters. Write what you learned, not what they said verbatim.',
|
|
16
16
|
},
|
|
17
17
|
annotation: 'write',
|
|
18
18
|
params: {
|
|
19
19
|
partyId: {
|
|
20
20
|
type: 'string',
|
|
21
21
|
required: true,
|
|
22
|
-
description: 'The person: their userId in the
|
|
22
|
+
description: 'The person: their userId in the context snapshot, where claimed is false.',
|
|
23
23
|
},
|
|
24
24
|
notes: {
|
|
25
25
|
type: 'string',
|
|
@@ -35,7 +35,7 @@ export const partyNoteCapability = {
|
|
|
35
35
|
return {
|
|
36
36
|
party: saved,
|
|
37
37
|
message: saved.notes
|
|
38
|
-
? 'Saved. It shows in
|
|
38
|
+
? 'Saved. It shows in every snapshot they appear in, to your workspace only.'
|
|
39
39
|
: 'Cleared.',
|
|
40
40
|
};
|
|
41
41
|
},
|
package/dist/decisionWords.d.ts
CHANGED
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
* A person's account id is `username:::email`. The server shows a reader
|
|
20
20
|
* outside that person's org their `psn_` face instead, but an older
|
|
21
21
|
* server, or a row written before that, still hands the raw id over, and the
|
|
22
|
-
* model repeats whatever it is told into the
|
|
22
|
+
* model repeats whatever it is told into the conversation. So an id shaped like a
|
|
23
23
|
* person's account is left out rather than said.
|
|
24
24
|
*/
|
|
25
25
|
export declare function speakableActor(actorId: string | null | undefined): string | null;
|
package/dist/decisionWords.js
CHANGED
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
* A person's account id is `username:::email`. The server shows a reader
|
|
20
20
|
* outside that person's org their `psn_` face instead, but an older
|
|
21
21
|
* server, or a row written before that, still hands the raw id over, and the
|
|
22
|
-
* model repeats whatever it is told into the
|
|
22
|
+
* model repeats whatever it is told into the conversation. So an id shaped like a
|
|
23
23
|
* person's account is left out rather than said.
|
|
24
24
|
*/
|
|
25
25
|
export function speakableActor(actorId) {
|
|
@@ -32,8 +32,6 @@ export interface EngagementGuide {
|
|
|
32
32
|
kind: EngagementGuideKind;
|
|
33
33
|
outcome: EngagementOutcome;
|
|
34
34
|
summary: string;
|
|
35
|
-
/** Room the brief arrived in — never a substitute for agreementId. */
|
|
36
|
-
addressId?: string | null;
|
|
37
35
|
agreementId?: string | null;
|
|
38
36
|
taskId?: string | null;
|
|
39
37
|
waitingOn?: WaitingOn | null;
|
|
@@ -105,12 +103,11 @@ export interface InboxEngagementInput {
|
|
|
105
103
|
tasks?: EngagementTaskHint[];
|
|
106
104
|
continuation?: Pick<SessionContinuation, 'canScheduleWake' | 'kind'>;
|
|
107
105
|
}
|
|
108
|
-
/** Same event twice, or a hire
|
|
106
|
+
/** Same event twice, or a hire brief that already has an open task. */
|
|
109
107
|
export declare function isEchoOrDuplicate(inbox: Pick<InboxEnvelope, 'deliveries' | 'tasksAwaitingMe'>, agentId: string): boolean;
|
|
110
108
|
/**
|
|
111
|
-
* Assigned message under a live hire.
|
|
112
|
-
*
|
|
113
|
-
* An agrn- notification lane is not treated as a chat row.
|
|
109
|
+
* Assigned message under a live hire. It runs after access to that agreement
|
|
110
|
+
* is proven. An agrn- notification lane is not treated as a message row.
|
|
114
111
|
*/
|
|
115
112
|
export declare function isHireWorkOrder(delivery: InboxDeliveryRef, agentId: string, tasksAwaitingMe?: readonly InboxTaskRef[]): boolean;
|
|
116
113
|
export declare function waitingOnFromTask(task: EngagementTaskHint): WaitingOn | null;
|
|
@@ -138,7 +135,7 @@ export declare function marketplaceFormation(env: CapabilityEnv, input: {
|
|
|
138
135
|
*/
|
|
139
136
|
export declare function contactPath(env: CapabilityEnv, input: ContactPathInput): EngagementGuide;
|
|
140
137
|
export declare function hireWorkOrderGuide(env: CapabilityEnv, delivery: InboxDeliveryRef): EngagementGuide;
|
|
141
|
-
export declare function strangerBriefGuide(env: CapabilityEnv
|
|
138
|
+
export declare function strangerBriefGuide(env: CapabilityEnv): EngagementGuide;
|
|
142
139
|
export declare function duplicateGuide(): EngagementGuide;
|
|
143
140
|
/**
|
|
144
141
|
* First engagement that matters on this envelope. Empty mail with no held
|
package/dist/engagementGuide.js
CHANGED
|
@@ -17,7 +17,7 @@ function openTasksForAgreement(tasks, agreementId) {
|
|
|
17
17
|
function assignedToMe(delivery, agentId) {
|
|
18
18
|
return Boolean(agentId) && delivery.assigneeId === agentId;
|
|
19
19
|
}
|
|
20
|
-
/** Same event twice, or a hire
|
|
20
|
+
/** Same event twice, or a hire brief that already has an open task. */
|
|
21
21
|
export function isEchoOrDuplicate(inbox, agentId) {
|
|
22
22
|
const mine = inbox.deliveries.filter((d) => assignedToMe(d, agentId));
|
|
23
23
|
const eventIds = mine.map((d) => d.eventId).filter(Boolean);
|
|
@@ -38,9 +38,8 @@ export function isEchoOrDuplicate(inbox, agentId) {
|
|
|
38
38
|
return false;
|
|
39
39
|
}
|
|
40
40
|
/**
|
|
41
|
-
* Assigned message under a live hire.
|
|
42
|
-
*
|
|
43
|
-
* An agrn- notification lane is not treated as a chat row.
|
|
41
|
+
* Assigned message under a live hire. It runs after access to that agreement
|
|
42
|
+
* is proven. An agrn- notification lane is not treated as a message row.
|
|
44
43
|
*/
|
|
45
44
|
export function isHireWorkOrder(delivery, agentId, tasksAwaitingMe) {
|
|
46
45
|
if (!assignedToMe(delivery, agentId))
|
|
@@ -258,7 +257,6 @@ export function hireWorkOrderGuide(env, delivery) {
|
|
|
258
257
|
return {
|
|
259
258
|
kind: 'work_order',
|
|
260
259
|
outcome: 'ok',
|
|
261
|
-
addressId: delivery.addressId,
|
|
262
260
|
agreementId,
|
|
263
261
|
summary: 'A brief from the principal in this hire is a work order. Create a task on yourself under that agreement. Fill the description from the brief after you read it. When you need helpers, declare a graph — do not invent worker_next.',
|
|
264
262
|
next: nextCall(env, 'task_create', {
|
|
@@ -267,11 +265,10 @@ export function hireWorkOrderGuide(env, delivery) {
|
|
|
267
265
|
}, 'create the work order on yourself under this hire'),
|
|
268
266
|
};
|
|
269
267
|
}
|
|
270
|
-
export function strangerBriefGuide(env
|
|
268
|
+
export function strangerBriefGuide(env) {
|
|
271
269
|
return {
|
|
272
270
|
kind: 'stranger_brief',
|
|
273
271
|
outcome: 'pending',
|
|
274
|
-
addressId,
|
|
275
272
|
summary: "A stranger's brief is not a work order. They hire you through your store listing, or through an agreement you draft when you have none; do not create a task under a hire you do not have.",
|
|
276
273
|
next: nextCall(env, 'agreement_request', undefined, 'draft the agreement this brief would ride', { definition: agreementRequestCapability }),
|
|
277
274
|
};
|
|
@@ -311,7 +308,7 @@ export function inboxEngagement(input) {
|
|
|
311
308
|
}
|
|
312
309
|
const stranger = mine.find((d) => d.kind === 'message' && !d.agreementId);
|
|
313
310
|
if (stranger) {
|
|
314
|
-
return strangerBriefGuide(env
|
|
311
|
+
return strangerBriefGuide(env);
|
|
315
312
|
}
|
|
316
313
|
const held = tasks.find((t) => t.heldByDeps);
|
|
317
314
|
if (held) {
|
package/dist/handles.d.ts
CHANGED
|
@@ -1,18 +1,24 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Short handles: the id of a task (T…), agreement (A…)
|
|
3
|
-
*
|
|
4
|
-
*
|
|
2
|
+
* Short handles: the id of a task (T…), agreement (A…) or artifact (F…).
|
|
3
|
+
* A kind letter, five to eight letters from 0-9 A-Z without I, L, O and U,
|
|
4
|
+
* and a check letter. Read in any case; written upper case.
|
|
5
5
|
*
|
|
6
6
|
* Mirrors the server's rule so a mistyped handle is refused here, before any
|
|
7
7
|
* call. The server stays the judge of what the handle opens.
|
|
8
8
|
*/
|
|
9
9
|
export declare const HANDLE_ALPHABET = "0123456789ABCDEFGHJKMNPQRSTVWXYZ";
|
|
10
|
-
export type HandleKind = 'task' | 'agreement' | '
|
|
10
|
+
export type HandleKind = 'task' | 'agreement' | 'artifact';
|
|
11
11
|
/** The handle's kind and its upper-case form, or null when it is not one. */
|
|
12
12
|
export declare function parseHandle(raw: string): {
|
|
13
13
|
kind: HandleKind;
|
|
14
14
|
id: string;
|
|
15
15
|
} | null;
|
|
16
|
+
/**
|
|
17
|
+
* A reference to a room: a chat handle (C…), the 24-letter room id, or an
|
|
18
|
+
* `address:` / `chat:` ref, alone or inside a Ziggs URL. Rooms are gone, so
|
|
19
|
+
* these are refused with a clear word instead of being sent to the server.
|
|
20
|
+
*/
|
|
21
|
+
export declare function isRetiredRoomRef(raw: string): boolean;
|
|
16
22
|
/** The shape of a handle, whether or not its check letter holds. */
|
|
17
23
|
export declare function looksLikeHandle(raw: string): boolean;
|
|
18
24
|
/**
|
package/dist/handles.js
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Short handles: the id of a task (T…), agreement (A…)
|
|
3
|
-
*
|
|
4
|
-
*
|
|
2
|
+
* Short handles: the id of a task (T…), agreement (A…) or artifact (F…).
|
|
3
|
+
* A kind letter, five to eight letters from 0-9 A-Z without I, L, O and U,
|
|
4
|
+
* and a check letter. Read in any case; written upper case.
|
|
5
5
|
*
|
|
6
6
|
* Mirrors the server's rule so a mistyped handle is refused here, before any
|
|
7
7
|
* call. The server stays the judge of what the handle opens.
|
|
8
8
|
*/
|
|
9
9
|
export const HANDLE_ALPHABET = '0123456789ABCDEFGHJKMNPQRSTVWXYZ';
|
|
10
|
-
const LETTER_KIND = { T: 'task', A: 'agreement',
|
|
10
|
+
const LETTER_KIND = { T: 'task', A: 'agreement', F: 'artifact' };
|
|
11
11
|
const N = HANDLE_ALPHABET.length;
|
|
12
12
|
function checkHolds(handle) {
|
|
13
13
|
let factor = 1;
|
|
@@ -36,11 +36,21 @@ const OLD_SHAPES = [
|
|
|
36
36
|
[/^task_[0-9a-f-]{36}$/, 'task'],
|
|
37
37
|
[/^agr_[A-Za-z0-9_]+$/, 'agreement'],
|
|
38
38
|
[/^(art_|org-state-)[A-Za-z0-9_-]+$/, 'artifact'],
|
|
39
|
-
[/^[a-z]{24}$/, 'address'],
|
|
40
39
|
];
|
|
40
|
+
/**
|
|
41
|
+
* A reference to a room: a chat handle (C…), the 24-letter room id, or an
|
|
42
|
+
* `address:` / `chat:` ref, alone or inside a Ziggs URL. Rooms are gone, so
|
|
43
|
+
* these are refused with a clear word instead of being sent to the server.
|
|
44
|
+
*/
|
|
45
|
+
export function isRetiredRoomRef(raw) {
|
|
46
|
+
const value = raw.trim();
|
|
47
|
+
if (/^(?:address|chat):/i.test(value))
|
|
48
|
+
return true;
|
|
49
|
+
return [value, ...value.split(/[/?#&=]/)].some((part) => /^[a-z]{24}$/.test(part) || (/^C[0-9A-Z]{6,9}$/i.test(part) && checkHolds(part.toUpperCase())));
|
|
50
|
+
}
|
|
41
51
|
/** The shape of a handle, whether or not its check letter holds. */
|
|
42
52
|
export function looksLikeHandle(raw) {
|
|
43
|
-
return /^[
|
|
53
|
+
return /^[TAF][0-9A-Z]{6,9}$/i.test(raw.trim());
|
|
44
54
|
}
|
|
45
55
|
function parseOne(token) {
|
|
46
56
|
const trimmed = token.trim();
|
|
@@ -43,8 +43,6 @@ export interface ProposeTerms {
|
|
|
43
43
|
/** 1:1 proposal to a specific user or agent (`proposedTo` = their id). */
|
|
44
44
|
export interface ProposeDirectInput extends ProposeTerms {
|
|
45
45
|
proposedTo: string;
|
|
46
|
-
/** Optional display-reference context for resolving a masked party; does not publish or share. */
|
|
47
|
-
addressId?: string;
|
|
48
46
|
/**
|
|
49
47
|
* The bucket the agreement goes into, one you are in. Left out: the bucket
|
|
50
48
|
* your run works in, else a new one. The other side comes in when it starts.
|
|
@@ -155,7 +155,7 @@ export declare class ArtifactsClient {
|
|
|
155
155
|
/**
|
|
156
156
|
* `GET /artifacts/find` — lexical search over the artifacts this agent can
|
|
157
157
|
* already reach: what it authored, what its readable containers hold, and
|
|
158
|
-
* what artifact grants it holds. Bounded by the active lane and
|
|
158
|
+
* what artifact grants it holds. Bounded by the active lane and its work
|
|
159
159
|
* containment, exactly as a point read is.
|
|
160
160
|
*
|
|
161
161
|
* This is not `list()` with a query string. `list()` answers "what is in this
|
|
@@ -80,7 +80,7 @@ export class ArtifactsClient {
|
|
|
80
80
|
/**
|
|
81
81
|
* `GET /artifacts/find` — lexical search over the artifacts this agent can
|
|
82
82
|
* already reach: what it authored, what its readable containers hold, and
|
|
83
|
-
* what artifact grants it holds. Bounded by the active lane and
|
|
83
|
+
* what artifact grants it holds. Bounded by the active lane and its work
|
|
84
84
|
* containment, exactly as a point read is.
|
|
85
85
|
*
|
|
86
86
|
* This is not `list()` with a query string. `list()` answers "what is in this
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { looksLikeHandle, parseRef } from '../handles.js';
|
|
1
|
+
import { isRetiredRoomRef, looksLikeHandle, parseRef } from '../handles.js';
|
|
2
2
|
import { getBackendUrl } from '../utils/urlUtils.js';
|
|
3
3
|
import { pollSurfaceError } from '../shared/rateLimit.js';
|
|
4
4
|
import { buildOperatorHeaders } from './operatorHeaders.js';
|
|
@@ -63,7 +63,7 @@ export function normalizeContextOpenBody(args) {
|
|
|
63
63
|
if (!raw)
|
|
64
64
|
throw invalid(`${key} must be a non-empty resource reference`);
|
|
65
65
|
const ref = parseRef(raw);
|
|
66
|
-
if (
|
|
66
|
+
if (isRetiredRoomRef(raw))
|
|
67
67
|
throw invalid('Room references are retired; select an exact artifact, task or agreement');
|
|
68
68
|
if (!ref && looksLikeHandle(raw))
|
|
69
69
|
throw invalid(`${raw} is not a handle: its check letter does not match. Check it for a typo`);
|
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
export declare const CONTEXT_READ_TYPES: readonly ["artifacts", "agreements", "tasks"];
|
|
2
2
|
export type ContextReadType = (typeof CONTEXT_READ_TYPES)[number];
|
|
3
3
|
/**
|
|
4
|
-
*
|
|
5
|
-
* The server still accepts legacy room entries until coordinated removal;
|
|
6
|
-
* new callers use only the domain resources below.
|
|
4
|
+
* Resource entry points for context reads and snapshots.
|
|
7
5
|
*/
|
|
8
6
|
export declare const VIA_KINDS: readonly ["agreement", "task", "artifact", "message"];
|
|
9
7
|
export type ViaKind = (typeof VIA_KINDS)[number];
|
|
@@ -57,7 +55,7 @@ export interface ContextSnapshotParticipant {
|
|
|
57
55
|
[key: string]: unknown;
|
|
58
56
|
}
|
|
59
57
|
export interface ContextSnapshotQuery {
|
|
60
|
-
/** Exact message, task, agreement, or artifact entry
|
|
58
|
+
/** Exact message, task, agreement, or artifact entry. */
|
|
61
59
|
via: string;
|
|
62
60
|
agreementId?: string;
|
|
63
61
|
artifactId?: string;
|
|
@@ -7,9 +7,7 @@ export const CONTEXT_READ_TYPES = [
|
|
|
7
7
|
'tasks',
|
|
8
8
|
];
|
|
9
9
|
/**
|
|
10
|
-
*
|
|
11
|
-
* The server still accepts legacy room entries until coordinated removal;
|
|
12
|
-
* new callers use only the domain resources below.
|
|
10
|
+
* Resource entry points for context reads and snapshots.
|
|
13
11
|
*/
|
|
14
12
|
export const VIA_KINDS = [
|
|
15
13
|
'agreement',
|
|
@@ -12,8 +12,6 @@ import { type Agreement, type Creds, type EngagementKind } from '../types.js';
|
|
|
12
12
|
*/
|
|
13
13
|
export interface UnifiedProposeInput extends ProposeTerms {
|
|
14
14
|
proposedTo: string;
|
|
15
|
-
/** Required on direct proposals; optional on broadcasts/links. */
|
|
16
|
-
addressId?: string;
|
|
17
15
|
engagementKind?: EngagementKind;
|
|
18
16
|
}
|
|
19
17
|
export type ProposeShape = 'direct' | 'request' | 'offer';
|
|
@@ -2,7 +2,7 @@ import { claimAgreement, proposeBroadcast, proposeDirectTo, } from './AgreementC
|
|
|
2
2
|
import { publishOffer } from './MarketplaceClient.js';
|
|
3
3
|
import { isBroadcastTarget, } from '../types.js';
|
|
4
4
|
export async function proposeUnified(input, creds) {
|
|
5
|
-
const { proposedTo,
|
|
5
|
+
const { proposedTo, engagementKind, providerId, ...terms } = input;
|
|
6
6
|
if (!proposedTo)
|
|
7
7
|
throw new Error('proposedTo is required (a user/agent id, or "everyone"/"org"/"company" to broadcast)');
|
|
8
8
|
// The 'link' arm is gone. A link is not a proposal shape: it has no
|
|
@@ -34,24 +34,16 @@ export async function proposeUnified(input, creds) {
|
|
|
34
34
|
// Buyer-broadcast: the claimer works, your side pays — an open request.
|
|
35
35
|
const agreement = await proposeBroadcast({
|
|
36
36
|
...terms,
|
|
37
|
-
addressId: addressId ?? '',
|
|
38
37
|
engagementKind: engagementKind ?? 'service',
|
|
39
38
|
audience,
|
|
40
39
|
}, creds);
|
|
41
40
|
return { agreement, shape: 'request' };
|
|
42
41
|
}
|
|
43
|
-
//
|
|
44
|
-
//
|
|
45
|
-
// depend on which client you used: an agreement between parties who have no
|
|
46
|
-
// conversation had to invent a chat id to be created. Delivery does not go
|
|
47
|
-
// through the room — the create-time event targets the party slots — so the
|
|
48
|
-
// counterparty is told either way.
|
|
42
|
+
// A direct proposal is delivered to the party slots, so the counterparty is
|
|
43
|
+
// told whether or not the parties have talked before.
|
|
49
44
|
const agreement = await proposeDirectTo({
|
|
50
45
|
...terms,
|
|
51
46
|
proposedTo,
|
|
52
|
-
// Omitted rather than sent empty: an absent field says "no room", and an
|
|
53
|
-
// empty string is one more fiction for the server to interpret.
|
|
54
|
-
...(addressId ? { addressId } : {}),
|
|
55
47
|
providerId: providerId?.trim() || proposedTo,
|
|
56
48
|
engagementKind: engagementKind ?? 'service',
|
|
57
49
|
}, creds);
|
package/dist/index.d.ts
CHANGED
|
@@ -13,7 +13,7 @@ export type { DelegateEnv, ResolvedDelegateCreds, } from './shared/delegateCreds
|
|
|
13
13
|
export { RateLimitedError, isRateLimited, parseRetryAfterMs, pollSurfaceError, } from './shared/rateLimit.js';
|
|
14
14
|
export { parseErrorMessage, parseErrorCode, throwApiError, } from './shared/apiError.js';
|
|
15
15
|
export { ApiError } from './types.js';
|
|
16
|
-
export type { Creds, Task, TaskState, PlanStep, PlanStepStatus, Agreement, AgreementParties, AgreementPartySide, EngagementKind, BroadcastAudience, EntryType, ContentType, InboxDeliveryKind, InboxDeliveryRef,
|
|
16
|
+
export type { Creds, Task, TaskState, PlanStep, PlanStepStatus, Agreement, AgreementParties, AgreementPartySide, EngagementKind, BroadcastAudience, EntryType, ContentType, InboxDeliveryKind, InboxDeliveryRef, InboxProposalRef, InboxTaskRef, InboxRequestRef, InboxPlanAckRef, InboxConnectionRequestRef, InboxHumanAttention, InboxEnvelope, InboxAckResult, InboxPeek, InboxReadOptions, } from './types.js';
|
|
17
17
|
export type { ProposeTerms, ProposeDirectInput, ProposeBroadcastInput, ProposeAgreementData, ClaimOptions, } from './http/AgreementClient.js';
|
|
18
18
|
export { decisionWords, speakableActor } from './decisionWords.js';
|
|
19
19
|
export type { DecisionOutcome, DecisionWords, DecisionWordsInput, } from './decisionWords.js';
|
|
@@ -11,7 +11,7 @@ const SCOPE_DENIED_HINT = 'For missing access to a returned artifact, chat, agre
|
|
|
11
11
|
'a pending access approval agreement; it grants no access. After approval, ' +
|
|
12
12
|
'ziggs_open the same resource using the same agent identity. For earlier chat ' +
|
|
13
13
|
'messages request temporal=from-start; replying also requires permission=reply. ' +
|
|
14
|
-
'Do not issue yourself a grant. A new
|
|
14
|
+
'Do not issue yourself a grant. A new bucket does not show another conversation\'s history.';
|
|
15
15
|
// a human-authority denial is not "try again with more scope": no
|
|
16
16
|
// retry by this caller can ever pass it, because the guard refuses on being an
|
|
17
17
|
// agent at all, before it looks at what was asked. Without a next action the
|
package/dist/types.d.ts
CHANGED
|
@@ -319,12 +319,6 @@ export interface InboxSourceRef {
|
|
|
319
319
|
}
|
|
320
320
|
/** One delivery in a mailbox, as the wire carries it. */
|
|
321
321
|
export type { InboxDeliveryRef };
|
|
322
|
-
/** Message/artifact deliveries folded by chat, so you can open chats directly. */
|
|
323
|
-
export interface InboxChatNews {
|
|
324
|
-
addressId: string;
|
|
325
|
-
count: number;
|
|
326
|
-
latestAt: string;
|
|
327
|
-
}
|
|
328
322
|
export interface InboxProposalRef {
|
|
329
323
|
executionContext?: import('@ziggs-ai/contracts').WorkExecutionContext;
|
|
330
324
|
executionBlocked?: import('@ziggs-ai/contracts').ExecutionBlock;
|
|
@@ -456,8 +450,6 @@ export interface InboxEnvelope extends InboxRequestChannel, Partial<InboxPlanAck
|
|
|
456
450
|
/** The last row IN this window; everything after it is the backlog. */
|
|
457
451
|
windowEndsAt: string;
|
|
458
452
|
} | null;
|
|
459
|
-
/** This agent's ASSIGNED chat mail, folded by chat. */
|
|
460
|
-
chats: InboxChatNews[];
|
|
461
453
|
/**
|
|
462
454
|
* Opaque watermark bundle. Pass to `ack(upTo, { handledDeliveryIds })`
|
|
463
455
|
* VERBATIM after acting — never construct or parse one; the per-mailbox
|
|
@@ -519,7 +511,7 @@ export interface InboxChangesResult {
|
|
|
519
511
|
cursor: string;
|
|
520
512
|
expiresAt: string;
|
|
521
513
|
hasMore: boolean;
|
|
522
|
-
deliveries: Array<Pick<InboxDeliveryRef, 'eventId' | 'kind' | 'resourceId' | '
|
|
514
|
+
deliveries: Array<Pick<InboxDeliveryRef, 'eventId' | 'kind' | 'resourceId' | 'taskId' | 'agreementId' | 'assigneeId' | 'needsHuman' | 'ts'> & {
|
|
523
515
|
orgId?: string | null;
|
|
524
516
|
}>;
|
|
525
517
|
}
|