@ziggs-ai/api-client 0.10.4 → 0.12.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/capabilities/agreementVerbs.d.ts +9 -2
- package/dist/capabilities/agreementVerbs.js +61 -21
- package/dist/capabilities/agreements.d.ts +1 -1
- package/dist/capabilities/agreements.js +18 -6
- package/dist/capabilities/artifacts.d.ts +4 -2
- package/dist/capabilities/artifacts.js +168 -33
- package/dist/capabilities/chat.d.ts +2 -3
- package/dist/capabilities/chat.js +5 -6
- package/dist/capabilities/connections.js +1 -1
- package/dist/capabilities/context.js +3 -0
- package/dist/capabilities/grants.d.ts +7 -6
- package/dist/capabilities/grants.js +9 -8
- package/dist/capabilities/index.d.ts +4 -4
- package/dist/capabilities/index.js +4 -4
- package/dist/capabilities/links.d.ts +17 -6
- package/dist/capabilities/links.js +71 -86
- package/dist/capabilities/marketplace.js +23 -17
- package/dist/capabilities/nextCall.d.ts +36 -5
- package/dist/capabilities/nextCall.js +53 -7
- package/dist/capabilities/payments.d.ts +24 -8
- package/dist/capabilities/payments.js +28 -392
- package/dist/capabilities/proposeProviderId.d.ts +1 -1
- package/dist/capabilities/proposeProviderId.js +1 -1
- package/dist/http/AgreementClient.d.ts +63 -27
- package/dist/http/AgreementClient.js +51 -39
- package/dist/http/ChatClient.d.ts +1 -0
- package/dist/http/ChatClient.js +4 -1
- package/dist/http/ConnectionsClient.js +12 -1
- package/dist/http/ContextGrantsClient.d.ts +15 -1
- package/dist/http/ContextGrantsClient.js +2 -0
- package/dist/http/ContextReadClient.d.ts +14 -5
- package/dist/http/GrantsClient.d.ts +14 -0
- package/dist/http/GrantsClient.js +18 -2
- package/dist/http/InboxClient.js +4 -0
- package/dist/http/MarketplaceClient.d.ts +6 -8
- package/dist/http/MarketplaceClient.js +11 -30
- package/dist/http/TaskClient.d.ts +5 -0
- package/dist/http/TaskClient.js +4 -7
- package/dist/http/agreementFlows.d.ts +6 -7
- package/dist/http/agreementFlows.js +14 -20
- package/dist/http/grants.d.ts +28 -0
- package/dist/http/index.d.ts +2 -2
- package/dist/index.d.ts +3 -3
- package/dist/index.js +1 -1
- package/dist/instanceIdentity.d.ts +4 -0
- package/dist/instanceIdentity.js +44 -0
- package/dist/relay/provisionRelayWorkers.d.ts +2 -2
- package/dist/relay/provisionRelayWorkers.js +5 -5
- package/dist/types.d.ts +80 -31
- package/dist/types.js +18 -0
- package/package.json +1 -1
package/dist/http/TaskClient.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { getBackendUrl } from '../utils/urlUtils.js';
|
|
2
|
+
import { partyActorIds } from '../types.js';
|
|
2
3
|
import { throwApiError } from '../shared/apiError.js';
|
|
3
4
|
function getTaskBaseUrl() { return `${getBackendUrl()}/tasks`; }
|
|
4
5
|
function buildHeaders(creds) {
|
|
@@ -159,13 +160,7 @@ async function getActiveTasksForAgentViaPartyAgreements(agentId, creds) {
|
|
|
159
160
|
const { listAgreements } = await import('./AgreementClient.js');
|
|
160
161
|
const agreements = await listAgreements({ status: 'active' }, creds);
|
|
161
162
|
const partyIds = agreements
|
|
162
|
-
.filter((a) =>
|
|
163
|
-
const p = a.parties ?? {};
|
|
164
|
-
return (p.provider === agentId ||
|
|
165
|
-
p.providerAgent === agentId ||
|
|
166
|
-
p.creator === agentId ||
|
|
167
|
-
p.payer === agentId);
|
|
168
|
-
})
|
|
163
|
+
.filter((a) => partyActorIds(a.parties).includes(agentId))
|
|
169
164
|
.map((a) => a.agreementId)
|
|
170
165
|
.filter(Boolean);
|
|
171
166
|
if (partyIds.length === 0)
|
|
@@ -345,6 +340,8 @@ export async function listTasks(options = {}, creds) {
|
|
|
345
340
|
url.searchParams.set('limit', String(options.limit));
|
|
346
341
|
if (options.assignedTo)
|
|
347
342
|
url.searchParams.set('assignedTo', options.assignedTo);
|
|
343
|
+
if (options.createdBy)
|
|
344
|
+
url.searchParams.set('createdBy', options.createdBy);
|
|
348
345
|
const res = await fetch(url.toString(), {
|
|
349
346
|
method: 'GET',
|
|
350
347
|
headers: buildHeaders(creds),
|
|
@@ -1,14 +1,13 @@
|
|
|
1
|
-
import { type ClaimedKind, type ProposeTerms } from './AgreementClient.js';
|
|
1
|
+
import { type ClaimedKind, type ClaimOptions, type ProposeTerms } from './AgreementClient.js';
|
|
2
2
|
import { type Agreement, type Creds, type EngagementKind } from '../types.js';
|
|
3
3
|
/**
|
|
4
|
-
* one propose grammar. Direct, broadcast (
|
|
4
|
+
* one propose grammar. Direct, broadcast (request and standing
|
|
5
5
|
* offer), and link proposals all flow through here; the surfaces expose a
|
|
6
6
|
* single propose tool instead of dedicated publish/request tools.
|
|
7
7
|
*
|
|
8
8
|
* Routing:
|
|
9
|
-
* - engagementKind 'link' → POST /agreements (link proposal / open invite)
|
|
10
9
|
* - proposedTo 'everyone' | 'org', providerId = self → seller-broadcast standing offer
|
|
11
|
-
* - proposedTo 'everyone' | 'org', no providerId → buyer-broadcast
|
|
10
|
+
* - proposedTo 'everyone' | 'org', no providerId → buyer-broadcast request
|
|
12
11
|
* - anything else → direct proposal
|
|
13
12
|
*/
|
|
14
13
|
export interface UnifiedProposeInput extends ProposeTerms {
|
|
@@ -17,13 +16,13 @@ export interface UnifiedProposeInput extends ProposeTerms {
|
|
|
17
16
|
chatId?: string;
|
|
18
17
|
engagementKind?: EngagementKind;
|
|
19
18
|
}
|
|
20
|
-
export type ProposeShape = 'direct' | '
|
|
19
|
+
export type ProposeShape = 'direct' | 'request' | 'offer';
|
|
21
20
|
export declare function proposeUnified(input: UnifiedProposeInput, creds: Creds): Promise<{
|
|
22
21
|
agreement: Agreement;
|
|
23
22
|
shape: ProposeShape;
|
|
24
23
|
}>;
|
|
25
24
|
/**
|
|
26
|
-
* one claim verb for any open broadcast: link invite,
|
|
25
|
+
* one claim verb for any open broadcast: link invite, request,
|
|
27
26
|
* hand-off, or standing offer.
|
|
28
27
|
*
|
|
29
28
|
* One request. This used to read the agreement first to decide which endpoint to
|
|
@@ -36,7 +35,7 @@ export declare function proposeUnified(input: UnifiedProposeInput, creds: Creds)
|
|
|
36
35
|
* `kind` arrives on the claim response — the route that did the routing reports
|
|
37
36
|
* which broadcast kind this turned out to be.
|
|
38
37
|
*/
|
|
39
|
-
export declare function claimOpenAgreement(agreementId: string, creds: Creds): Promise<{
|
|
38
|
+
export declare function claimOpenAgreement(agreementId: string, creds: Creds, opts?: ClaimOptions): Promise<{
|
|
40
39
|
agreement: Agreement;
|
|
41
40
|
kind: ClaimedKind;
|
|
42
41
|
}>;
|
|
@@ -1,21 +1,15 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { claimAgreement, proposeBroadcast, proposeDirectTo, } from './AgreementClient.js';
|
|
2
2
|
import { publishOffer } from './MarketplaceClient.js';
|
|
3
3
|
import { isBroadcastTarget, } from '../types.js';
|
|
4
4
|
export async function proposeUnified(input, creds) {
|
|
5
5
|
const { proposedTo, chatId, engagementKind, providerId, ...terms } = input;
|
|
6
6
|
if (!proposedTo)
|
|
7
7
|
throw new Error('proposedTo is required (a user/agent id, or "everyone"/"org" to broadcast)');
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
engagementKind: 'link',
|
|
14
|
-
...(target ? { providerId: target } : {}),
|
|
15
|
-
...(terms.description ? { description: terms.description } : {}),
|
|
16
|
-
}, creds);
|
|
17
|
-
return { agreement, shape: 'link' };
|
|
18
|
-
}
|
|
8
|
+
// The 'link' arm is gone. A link is not a proposal shape: it has no
|
|
9
|
+
// price, no chat and no work, and it is formed by `link_propose`, which takes
|
|
10
|
+
// an email or an agent id and answers the same either way. Keeping a second
|
|
11
|
+
// door here would have meant a caller reaching a link through the propose
|
|
12
|
+
// grammar, where the constant answer and the org-root refusal do not apply.
|
|
19
13
|
if (isBroadcastTarget(proposedTo)) {
|
|
20
14
|
const audience = proposedTo;
|
|
21
15
|
if (providerId && creds.agentId && providerId === creds.agentId) {
|
|
@@ -33,16 +27,16 @@ export async function proposeUnified(input, creds) {
|
|
|
33
27
|
return { agreement, shape: 'offer' };
|
|
34
28
|
}
|
|
35
29
|
if (providerId) {
|
|
36
|
-
throw new Error('On a broadcast, providerId must be your own agent id (a standing offer: you work, the claimer pays) or omitted (a
|
|
30
|
+
throw new Error('On a broadcast, providerId must be your own agent id (a standing offer: you work, the claimer pays) or omitted (a request: the claimer works, you pay). A third-party providerId is not broadcastable.');
|
|
37
31
|
}
|
|
38
|
-
// Buyer-broadcast: the claimer works, your side pays — an open
|
|
32
|
+
// Buyer-broadcast: the claimer works, your side pays — an open request.
|
|
39
33
|
const agreement = await proposeBroadcast({
|
|
40
34
|
...terms,
|
|
41
35
|
chatId: chatId ?? '',
|
|
42
36
|
engagementKind: engagementKind ?? 'service',
|
|
43
37
|
audience,
|
|
44
38
|
}, creds);
|
|
45
|
-
return { agreement, shape: '
|
|
39
|
+
return { agreement, shape: 'request' };
|
|
46
40
|
}
|
|
47
41
|
if (!chatId)
|
|
48
42
|
throw new Error('chatId is required on a direct proposal');
|
|
@@ -56,7 +50,7 @@ export async function proposeUnified(input, creds) {
|
|
|
56
50
|
return { agreement, shape: 'direct' };
|
|
57
51
|
}
|
|
58
52
|
/**
|
|
59
|
-
* one claim verb for any open broadcast: link invite,
|
|
53
|
+
* one claim verb for any open broadcast: link invite, request,
|
|
60
54
|
* hand-off, or standing offer.
|
|
61
55
|
*
|
|
62
56
|
* One request. This used to read the agreement first to decide which endpoint to
|
|
@@ -69,11 +63,11 @@ export async function proposeUnified(input, creds) {
|
|
|
69
63
|
* `kind` arrives on the claim response — the route that did the routing reports
|
|
70
64
|
* which broadcast kind this turned out to be.
|
|
71
65
|
*/
|
|
72
|
-
export async function claimOpenAgreement(agreementId, creds) {
|
|
66
|
+
export async function claimOpenAgreement(agreementId, creds, opts = {}) {
|
|
73
67
|
if (!agreementId)
|
|
74
68
|
throw new Error('agreementId is required');
|
|
75
|
-
const { agreement, kind } = await claimAgreement(agreementId, creds);
|
|
69
|
+
const { agreement, kind } = await claimAgreement(agreementId, creds, opts);
|
|
76
70
|
// A server that has not shipped the `kind` field yet still claims correctly;
|
|
77
|
-
// '
|
|
78
|
-
return { agreement, kind: kind ?? '
|
|
71
|
+
// 'request' is the shape the route has always handled.
|
|
72
|
+
return { agreement, kind: kind ?? 'request' };
|
|
79
73
|
}
|
package/dist/http/grants.d.ts
CHANGED
|
@@ -11,6 +11,23 @@
|
|
|
11
11
|
* watermark are presented as `temporal` / `watermark_at` caveats.
|
|
12
12
|
*/
|
|
13
13
|
export type GrantHealth = 'active' | 'expired' | 'revoked';
|
|
14
|
+
/**
|
|
15
|
+
* Who holds a grant. Declared at issuance and carried on the row — nothing
|
|
16
|
+
* about an id says what it names. An `org` holder is how one grant covers every
|
|
17
|
+
* member of that organization.
|
|
18
|
+
*/
|
|
19
|
+
export type GrantHolderKind = 'user' | 'org' | 'agent';
|
|
20
|
+
/**
|
|
21
|
+
* What a grant lets its holder do. `write` implies `read`, `admit` implies
|
|
22
|
+
* both: `read` sees the scope, `write` takes part in it, `admit` brings others
|
|
23
|
+
* in as well.
|
|
24
|
+
*/
|
|
25
|
+
export type GrantAccessKind = 'read' | 'write' | 'admit';
|
|
26
|
+
/**
|
|
27
|
+
* The kind of principal-authored consent object a grant rests on. Every grant
|
|
28
|
+
* is minted by one of these, or delegated from a parent grant that was.
|
|
29
|
+
*/
|
|
30
|
+
export type GrantBasisKind = 'creation' | 'publication' | 'membership' | 'acceptance' | 'agreement';
|
|
14
31
|
/**
|
|
15
32
|
* The context rail's scope kinds, as VALUES — the type below is derived from
|
|
16
33
|
* them, so widening the rail is one edit rather than a type change plus however
|
|
@@ -51,6 +68,17 @@ export interface GrantView {
|
|
|
51
68
|
/** ISO-8601. */
|
|
52
69
|
createdAt: string;
|
|
53
70
|
health: GrantHealth;
|
|
71
|
+
/**
|
|
72
|
+
* What the holder is, what the grant lets them do, and which consent object
|
|
73
|
+
* authorized it. Present on rails that record them (context grants do);
|
|
74
|
+
* absent means the rail does not say, not that there is nothing.
|
|
75
|
+
*/
|
|
76
|
+
holderKind?: GrantHolderKind;
|
|
77
|
+
access?: GrantAccessKind;
|
|
78
|
+
basis?: {
|
|
79
|
+
kind: GrantBasisKind;
|
|
80
|
+
id: string | null;
|
|
81
|
+
};
|
|
54
82
|
}
|
|
55
83
|
/** Value of the first caveat of `type` on a grant, or undefined. */
|
|
56
84
|
export declare function grantCaveat(grant: GrantView, type: string): unknown | undefined;
|
package/dist/http/index.d.ts
CHANGED
|
@@ -8,7 +8,7 @@ export type { ListMessagesOptions, ListMessagesResult } from './MessagesClient.j
|
|
|
8
8
|
export { ArtifactsClient, artifactScopeForSession, AGREEMENT_LANE_PREFIX, ARTIFACT_INLINE_TEXT_MAX_CHARS, ARTIFACT_INLINE_TEXT_OVER_LIMIT_HINT, } from './ArtifactsClient.js';
|
|
9
9
|
export type { ArtifactVisibility, ListArtifactsOptions, ListArtifactsQuery, ListArtifactsResult, WriteArtifactInput, } from './ArtifactsClient.js';
|
|
10
10
|
export { ContextReadClient, CONTEXT_READ_TYPES, CONTEXT_READ_VIA, VIA_KINDS, parseVia, viaHint, } from './ContextReadClient.js';
|
|
11
|
-
export type { ContextReadType, ContextReadQuery, ContextReadEnvelope, ContextSnapshotResult, ViaKind, } from './ContextReadClient.js';
|
|
11
|
+
export type { ContextReadType, ContextReadQuery, ContextReadEnvelope, ContextSnapshotResult, ContextSnapshotParticipant, ViaKind, } from './ContextReadClient.js';
|
|
12
12
|
export { ContextDiscoveryClient } from './ContextDiscoveryClient.js';
|
|
13
13
|
export type { DiscoverableItem } from './ContextDiscoveryClient.js';
|
|
14
14
|
export { GrantsClient } from './GrantsClient.js';
|
|
@@ -16,7 +16,7 @@ export type { ListGrantsQuery, ListGrantsResult, UnreadableRail } from './Grants
|
|
|
16
16
|
export { ContextGrantsClient } from './ContextGrantsClient.js';
|
|
17
17
|
export type { ContextGrantRecord, ContextGrantScope, ContextGrantScopeKind, ContextTemporal, IssueContextGrantInput, DelegateContextGrantInput, DelegateContextGrantResult, ReachEntry, GrantReachResult, } from './ContextGrantsClient.js';
|
|
18
18
|
export { grantCaveat, CONTEXT_GRANT_SCOPE_KINDS, GRANT_SCOPE_KINDS, } from './grants.js';
|
|
19
|
-
export type { GrantView, GrantScopeKind, GrantScopeView, GrantCaveatView, GrantHealth, } from './grants.js';
|
|
19
|
+
export type { GrantView, GrantScopeKind, GrantScopeView, GrantCaveatView, GrantHealth, GrantHolderKind, GrantAccessKind, GrantBasisKind, } from './grants.js';
|
|
20
20
|
export { PaymentsClient } from './PaymentsClient.js';
|
|
21
21
|
export type { PaymentsError, WalletBalance, WalletRef, PaymentTransactionView, TransferResult, HoldResult, ReleaseResult, PaymentGrantView, PaymentGrantEnvelope, RevokeGrantResult, PaymentApproval, WaitForApprovalResult, } from './PaymentsClient.js';
|
|
22
22
|
export { ConnectionsClient, assertNoLeakedConnectionSecret, } from './ConnectionsClient.js';
|
package/dist/index.d.ts
CHANGED
|
@@ -2,7 +2,7 @@ export * from './http/index.js';
|
|
|
2
2
|
export * from './capabilities/index.js';
|
|
3
3
|
export * from './relay/provisionRelayWorkers.js';
|
|
4
4
|
export { ConnectionManager } from './ConnectionManager.js';
|
|
5
|
-
export { EntryTypes, ContentTypes, OPEN_AGREEMENT_TARGET, ORG_AGREEMENT_TARGET, BROADCAST_TARGETS, isBroadcastTarget, isPersonaRef, isRoomPresentationRef, isOpaquePresentationRef, AGREEMENT_ENGAGEMENT_KIND, isValidContentType, } from './types.js';
|
|
5
|
+
export { EntryTypes, ContentTypes, OPEN_AGREEMENT_TARGET, ORG_AGREEMENT_TARGET, BROADCAST_TARGETS, isBroadcastTarget, isPersonaRef, isRoomPresentationRef, isOpaquePresentationRef, AGREEMENT_ENGAGEMENT_KIND, isValidContentType, partySideIds, partyActorIds, } from './types.js';
|
|
6
6
|
export type { PrincipalPresentation } from './types.js';
|
|
7
7
|
export { getBackendUrl } from './utils/urlUtils.js';
|
|
8
8
|
export { configureApiClient, apiClientConfig } from './config.js';
|
|
@@ -11,5 +11,5 @@ export { runtimeLog, resetRuntimeLogLevelCache } from './shared/runtimeLog.js';
|
|
|
11
11
|
export { RateLimitedError, isRateLimited, parseRetryAfterMs, pollSurfaceError, } from './shared/rateLimit.js';
|
|
12
12
|
export { parseErrorMessage, parseErrorCode, throwApiError, } from './shared/apiError.js';
|
|
13
13
|
export { ApiError } from './types.js';
|
|
14
|
-
export type { Creds, Task, TaskState, PlanStep, PlanStepStatus, Agreement, EngagementKind, BroadcastAudience, EntryType, ContentType, MessageMetadata, MessageHandler, InboxDeliveryKind, InboxDeliveryRef, InboxChatNews, InboxProposalRef, InboxTaskRef,
|
|
15
|
-
export type { ProposeTerms, ProposeDirectInput, ProposeBroadcastInput, ProposeAgreementData, } from './http/AgreementClient.js';
|
|
14
|
+
export type { Creds, Task, TaskState, PlanStep, PlanStepStatus, Agreement, AgreementParties, AgreementPartySide, EngagementKind, BroadcastAudience, EntryType, ContentType, MessageMetadata, MessageHandler, InboxDeliveryKind, InboxDeliveryRef, InboxChatNews, InboxProposalRef, InboxTaskRef, InboxRequestRef, InboxConnectionRequestRef, InboxHumanAttention, InboxEnvelope, InboxAckResult, InboxReadOptions, } from './types.js';
|
|
15
|
+
export type { ProposeTerms, ProposeDirectInput, ProposeBroadcastInput, ProposeAgreementData, ClaimOptions, } from './http/AgreementClient.js';
|
package/dist/index.js
CHANGED
|
@@ -2,7 +2,7 @@ export * from './http/index.js';
|
|
|
2
2
|
export * from './capabilities/index.js';
|
|
3
3
|
export * from './relay/provisionRelayWorkers.js';
|
|
4
4
|
export { ConnectionManager } from './ConnectionManager.js';
|
|
5
|
-
export { EntryTypes, ContentTypes, OPEN_AGREEMENT_TARGET, ORG_AGREEMENT_TARGET, BROADCAST_TARGETS, isBroadcastTarget, isPersonaRef, isRoomPresentationRef, isOpaquePresentationRef, AGREEMENT_ENGAGEMENT_KIND, isValidContentType, } from './types.js';
|
|
5
|
+
export { EntryTypes, ContentTypes, OPEN_AGREEMENT_TARGET, ORG_AGREEMENT_TARGET, BROADCAST_TARGETS, isBroadcastTarget, isPersonaRef, isRoomPresentationRef, isOpaquePresentationRef, AGREEMENT_ENGAGEMENT_KIND, isValidContentType, partySideIds, partyActorIds, } from './types.js';
|
|
6
6
|
export { getBackendUrl } from './utils/urlUtils.js';
|
|
7
7
|
// the host injects the environment; this package never reads it.
|
|
8
8
|
export { configureApiClient, apiClientConfig } from './config.js';
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { hostname } from 'node:os';
|
|
2
|
+
/**
|
|
3
|
+
* Which process is calling GET /inbox.
|
|
4
|
+
*
|
|
5
|
+
* The exclusive-read claimant must be the *host* (this fleet task, a
|
|
6
|
+
* laptop fleet, an MCP process), not the API process. Two fleets share
|
|
7
|
+
* one backend task, so stamping the API's identity would let both wake.
|
|
8
|
+
*
|
|
9
|
+
* `ecs:<id>` on Fargate, `local:<host>:<pid>` otherwise. Env-derived
|
|
10
|
+
* and memoized.
|
|
11
|
+
*/
|
|
12
|
+
let cached = null;
|
|
13
|
+
const MAX_LENGTH = 64;
|
|
14
|
+
export const INBOX_HOST_CLAIMANT_HEADER = 'X-Ziggs-Instance';
|
|
15
|
+
export function instanceIdentity() {
|
|
16
|
+
if (cached)
|
|
17
|
+
return cached;
|
|
18
|
+
cached = resolve().slice(0, MAX_LENGTH);
|
|
19
|
+
return cached;
|
|
20
|
+
}
|
|
21
|
+
/** Test seam: forget the memoized value so a case can set different env. */
|
|
22
|
+
export function resetInstanceIdentityForTests() {
|
|
23
|
+
cached = null;
|
|
24
|
+
}
|
|
25
|
+
function resolve() {
|
|
26
|
+
const metadataUri = process.env.ECS_CONTAINER_METADATA_URI_V4 ??
|
|
27
|
+
process.env.ECS_CONTAINER_METADATA_URI;
|
|
28
|
+
if (metadataUri) {
|
|
29
|
+
const id = metadataUri.split('/').filter(Boolean).pop() ?? '';
|
|
30
|
+
const short = id.replace(/[^A-Za-z0-9]/g, '').slice(0, 12);
|
|
31
|
+
if (short.length >= 8)
|
|
32
|
+
return `ecs:${short}`;
|
|
33
|
+
}
|
|
34
|
+
const host = process.env.HOSTNAME || safeHostname();
|
|
35
|
+
return `local:${host}:${process.pid}`;
|
|
36
|
+
}
|
|
37
|
+
function safeHostname() {
|
|
38
|
+
try {
|
|
39
|
+
return hostname() || 'unknown-host';
|
|
40
|
+
}
|
|
41
|
+
catch {
|
|
42
|
+
return 'unknown-host';
|
|
43
|
+
}
|
|
44
|
+
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { Agreement, Creds } from '../types.js';
|
|
2
|
-
import {
|
|
2
|
+
import { claimOpenAgreement, delegateAgreement, getMyAgreements, pullOffers } from '../http/index.js';
|
|
3
3
|
/** Minimal relay step shape — keep field names aligned with agents/coordinators/relayTypes.ts */
|
|
4
4
|
export interface RelayStepInput {
|
|
5
5
|
stepId: string;
|
|
@@ -28,7 +28,7 @@ export type ProvisionedRelayStep = RelayPayloadShape['steps'][number] & {
|
|
|
28
28
|
export interface RelayProvisionDeps {
|
|
29
29
|
getMyAgreements: typeof getMyAgreements;
|
|
30
30
|
pullOffers: typeof pullOffers;
|
|
31
|
-
|
|
31
|
+
claimOpenAgreement: typeof claimOpenAgreement;
|
|
32
32
|
delegateAgreement: typeof delegateAgreement;
|
|
33
33
|
}
|
|
34
34
|
export interface ProvisionRelayWorkersInput {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { claimOpenAgreement, delegateAgreement, getMyAgreements, pullOffers, } from '../http/index.js';
|
|
2
2
|
function providerAgentId(agreement) {
|
|
3
|
-
return agreement.parties?.
|
|
3
|
+
return agreement.parties?.provider?.actor ?? null;
|
|
4
4
|
}
|
|
5
5
|
function isActiveAgreement(agreement) {
|
|
6
6
|
return agreement.status === 'active';
|
|
@@ -30,7 +30,7 @@ export function findOpenOfferForAgent(assigneeId, offers) {
|
|
|
30
30
|
export async function provisionRelayWorkers(input, deps = {
|
|
31
31
|
getMyAgreements,
|
|
32
32
|
pullOffers,
|
|
33
|
-
|
|
33
|
+
claimOpenAgreement,
|
|
34
34
|
delegateAgreement,
|
|
35
35
|
}) {
|
|
36
36
|
const { creds, hireAgreementId, chatId, steps, inputArtifactIds } = input;
|
|
@@ -55,7 +55,7 @@ export async function provisionRelayWorkers(input, deps = {
|
|
|
55
55
|
continue;
|
|
56
56
|
}
|
|
57
57
|
if (step.offerAgreementId) {
|
|
58
|
-
const claimed = await deps.
|
|
58
|
+
const { agreement: claimed } = await deps.claimOpenAgreement(step.offerAgreementId, creds);
|
|
59
59
|
const agreementId = claimed.agreementId;
|
|
60
60
|
const status = isActiveAgreement(claimed)
|
|
61
61
|
? 'active'
|
|
@@ -78,7 +78,7 @@ export async function provisionRelayWorkers(input, deps = {
|
|
|
78
78
|
}
|
|
79
79
|
const openOffer = findOpenOfferForAgent(step.assigneeId, offersCache);
|
|
80
80
|
if (openOffer?.agreementId) {
|
|
81
|
-
const claimed = await deps.
|
|
81
|
+
const { agreement: claimed } = await deps.claimOpenAgreement(openOffer.agreementId, creds);
|
|
82
82
|
const agreementId = claimed.agreementId;
|
|
83
83
|
const status = isActiveAgreement(claimed)
|
|
84
84
|
? 'active'
|
package/dist/types.d.ts
CHANGED
|
@@ -91,19 +91,46 @@ export declare const AGREEMENT_ENGAGEMENT_KIND: {
|
|
|
91
91
|
readonly LINK: "link";
|
|
92
92
|
};
|
|
93
93
|
export type EngagementKind = (typeof AGREEMENT_ENGAGEMENT_KIND)[keyof typeof AGREEMENT_ENGAGEMENT_KIND];
|
|
94
|
+
/**
|
|
95
|
+
* One side of an agreement.
|
|
96
|
+
*
|
|
97
|
+
* An agent id occupies `actor` and nowhere else, so "is this agent on this
|
|
98
|
+
* side?" is a structural read rather than a lookup against the Agent
|
|
99
|
+
* collection. Asking `principal` about an agent id is always the wrong
|
|
100
|
+
* question — it would match that agent's estate instead.
|
|
101
|
+
*/
|
|
102
|
+
export interface AgreementPartySide {
|
|
103
|
+
/**
|
|
104
|
+
* The accountable person or org — never an agent. On `payer` and `proposedTo`
|
|
105
|
+
* this may instead hold a broadcast sentinel ({@link isBroadcastTarget}), in
|
|
106
|
+
* which case nobody has taken the side up yet.
|
|
107
|
+
*/
|
|
108
|
+
principal?: string | null;
|
|
109
|
+
/** The agent that performed on this side. Null when the principal acted itself. */
|
|
110
|
+
actor?: string | null;
|
|
111
|
+
}
|
|
112
|
+
/** The four sides of an agreement, each {@link AgreementPartySide}. */
|
|
113
|
+
export interface AgreementParties {
|
|
114
|
+
payer?: AgreementPartySide;
|
|
115
|
+
provider?: AgreementPartySide;
|
|
116
|
+
proposedTo?: AgreementPartySide;
|
|
117
|
+
creator?: AgreementPartySide;
|
|
118
|
+
}
|
|
119
|
+
/** Both ids on one side, principal first, absent ones dropped. */
|
|
120
|
+
export declare function partySideIds(side: AgreementPartySide | null | undefined): string[];
|
|
121
|
+
/**
|
|
122
|
+
* Every agent that acted on this agreement, deduped.
|
|
123
|
+
*
|
|
124
|
+
* The read for "is this agent a party?" — an agent id lives in `actor` alone,
|
|
125
|
+
* so widening the match to `principal` would hit an unrelated estate.
|
|
126
|
+
*/
|
|
127
|
+
export declare function partyActorIds(parties: AgreementParties | null | undefined): string[];
|
|
94
128
|
/** Compact agreement reference carried by task reads. */
|
|
95
129
|
export interface AgreementSummary {
|
|
96
130
|
agreementId: string;
|
|
97
131
|
description: string;
|
|
98
132
|
status: AgreementStatus;
|
|
99
|
-
parties?:
|
|
100
|
-
proposedTo?: string | null;
|
|
101
|
-
provider?: string | null;
|
|
102
|
-
payer?: string | null;
|
|
103
|
-
creator?: string | null;
|
|
104
|
-
creatorAgent?: string | null;
|
|
105
|
-
providerAgent?: string | null;
|
|
106
|
-
};
|
|
133
|
+
parties?: AgreementParties;
|
|
107
134
|
/** The opposite party relative to the requesting agent; null for observers,
|
|
108
135
|
* broadcast sentinels, and self-agreements. */
|
|
109
136
|
counterparty: string | null;
|
|
@@ -120,14 +147,7 @@ export interface Agreement {
|
|
|
120
147
|
status?: AgreementStatus;
|
|
121
148
|
engagementKind?: EngagementKind;
|
|
122
149
|
proposalStatus?: ProposalStatus;
|
|
123
|
-
parties?:
|
|
124
|
-
proposedTo?: string;
|
|
125
|
-
provider?: string;
|
|
126
|
-
payer?: string;
|
|
127
|
-
creator?: string;
|
|
128
|
-
creatorAgent?: string;
|
|
129
|
-
providerAgent?: string;
|
|
130
|
-
};
|
|
150
|
+
parties?: AgreementParties;
|
|
131
151
|
approvals?: AgreementApprovalEntry[];
|
|
132
152
|
/** Legacy root-level price — always null in practice. Use money.price instead. */
|
|
133
153
|
price?: number | null;
|
|
@@ -287,14 +307,34 @@ export type MessageHandler = (text: string, metadata: MessageMetadata) => Promis
|
|
|
287
307
|
* on this side validates a delivery kind at runtime (the server does that on the
|
|
288
308
|
* way in), and exhaustiveness checking is purely type-level.
|
|
289
309
|
*/
|
|
290
|
-
export type InboxDeliveryKind = 'message' | 'artifact' | 'task-state' | 'agreement' | '
|
|
310
|
+
export type InboxDeliveryKind = 'message' | 'artifact' | 'task-state' | 'agreement' | 'request';
|
|
311
|
+
/** The two mailbox owners. Agents own no mailbox — they read through grants. */
|
|
312
|
+
export type InboxPartyKind = 'human' | 'org';
|
|
313
|
+
/** One mailbox this reader's merged view includes. */
|
|
314
|
+
export interface InboxSourceRef {
|
|
315
|
+
partyId: string;
|
|
316
|
+
partyKind: InboxPartyKind;
|
|
317
|
+
}
|
|
291
318
|
/**
|
|
292
|
-
* One
|
|
293
|
-
* (a chat read, a task read) is where this agent's grants are enforced.
|
|
319
|
+
* One row in this reader's merged view. A reference, never content — following
|
|
320
|
+
* it (a chat read, a task read) is where this agent's grants are enforced.
|
|
321
|
+
*
|
|
322
|
+
* "Mine to act on" is `assigneeId === my agent id`, nothing else. A row
|
|
323
|
+
* without my stamp is context I may read, never a wake and never mine to ack
|
|
324
|
+
* as handled.
|
|
294
325
|
*/
|
|
295
326
|
export interface InboxDeliveryRef {
|
|
296
327
|
kind: InboxDeliveryKind;
|
|
297
328
|
resourceId: string;
|
|
329
|
+
/** One emit, one id — copies of the same event collapse on this. */
|
|
330
|
+
eventId: string;
|
|
331
|
+
/** The mailbox this copy lives in. */
|
|
332
|
+
partyId: string;
|
|
333
|
+
partyKind: InboxPartyKind;
|
|
334
|
+
/** The ONE agent stamped to act; null when nothing has to. */
|
|
335
|
+
assigneeId: string | null;
|
|
336
|
+
/** The owner's human should see this. */
|
|
337
|
+
needsHuman: boolean;
|
|
298
338
|
chatId: string | null;
|
|
299
339
|
agreementId: string | null;
|
|
300
340
|
taskId: string | null;
|
|
@@ -377,10 +417,10 @@ export interface InboxTaskRef {
|
|
|
377
417
|
updatedAt: string | null;
|
|
378
418
|
}
|
|
379
419
|
/**
|
|
380
|
-
* A marketplace
|
|
420
|
+
* A marketplace request doorbell. Own channel so the host can
|
|
381
421
|
* exact-match triage with zero LLM tokens before any wake.
|
|
382
422
|
*/
|
|
383
|
-
export interface
|
|
423
|
+
export interface InboxRequestRef {
|
|
384
424
|
agreementId: string;
|
|
385
425
|
/** Exact-match string from the publisher — compare to the agent's tags. */
|
|
386
426
|
match: string;
|
|
@@ -390,27 +430,36 @@ export interface InboxQuestRef {
|
|
|
390
430
|
export interface InboxEnvelope {
|
|
391
431
|
asOf: string;
|
|
392
432
|
/**
|
|
393
|
-
*
|
|
394
|
-
* inbox
|
|
433
|
+
* The mailboxes this reader's view merges — its owner's, plus whatever
|
|
434
|
+
* inbox grants add. Absent on older servers.
|
|
435
|
+
*/
|
|
436
|
+
sources?: InboxSourceRef[];
|
|
437
|
+
/**
|
|
438
|
+
* Unacked rows across every source, newest first, copies of one event
|
|
439
|
+
* collapsed. This IS the inbox — read straight out of the party delivery
|
|
440
|
+
* logs, not derived from grants. Rows with `assigneeId === me` are mine to
|
|
441
|
+
* act on; the rest are readable context.
|
|
395
442
|
*/
|
|
396
443
|
deliveries: InboxDeliveryRef[];
|
|
397
444
|
/** True when there was more than one envelope's worth; the rest stay unacked. */
|
|
398
445
|
deliveriesCapped: boolean;
|
|
399
|
-
/**
|
|
446
|
+
/** This agent's ASSIGNED chat mail, folded by chat. */
|
|
400
447
|
chats: InboxChatNews[];
|
|
401
448
|
/**
|
|
402
|
-
* Pass to `ack(upTo, { handledResourceIds })`
|
|
403
|
-
*
|
|
404
|
-
*
|
|
405
|
-
*
|
|
449
|
+
* Opaque watermark bundle. Pass to `ack(upTo, { handledResourceIds })`
|
|
450
|
+
* VERBATIM after acting — never construct or parse one; the per-mailbox
|
|
451
|
+
* positions live inside the value. Null when there is nothing to ack. Ack
|
|
452
|
+
* after acting, not after reading: a crash in between redelivers. Listing
|
|
453
|
+
* every ASSIGNED resourceId is what stops a partial triage from burying
|
|
454
|
+
* work.
|
|
406
455
|
*/
|
|
407
456
|
ackTo: string | null;
|
|
408
457
|
/** Open tasks assigned to this agent — the work channel. */
|
|
409
458
|
tasksAwaitingMe: InboxTaskRef[];
|
|
410
459
|
truncatedTasks: number;
|
|
411
|
-
/** Unacked
|
|
412
|
-
|
|
413
|
-
|
|
460
|
+
/** Unacked request deliveries — triaged before any LLM wake. */
|
|
461
|
+
requestsAwaitingMe?: InboxRequestRef[];
|
|
462
|
+
truncatedRequests?: number;
|
|
414
463
|
proposalsAwaitingMe: InboxProposalRef[];
|
|
415
464
|
truncatedProposals: number;
|
|
416
465
|
connectionRequestsAwaitingMe: InboxConnectionRequestRef[];
|
package/dist/types.js
CHANGED
|
@@ -34,6 +34,24 @@ export const AGREEMENT_ENGAGEMENT_KIND = {
|
|
|
34
34
|
/** a bilateral reach link between two agents (no money, no work). */
|
|
35
35
|
LINK: 'link',
|
|
36
36
|
};
|
|
37
|
+
/** The four sides, in the order every fan-out walks them. */
|
|
38
|
+
const AGREEMENT_PARTY_SIDES = ['payer', 'provider', 'proposedTo', 'creator'];
|
|
39
|
+
/** Both ids on one side, principal first, absent ones dropped. */
|
|
40
|
+
export function partySideIds(side) {
|
|
41
|
+
return [side?.principal, side?.actor].filter((id) => typeof id === 'string' && id.length > 0);
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Every agent that acted on this agreement, deduped.
|
|
45
|
+
*
|
|
46
|
+
* The read for "is this agent a party?" — an agent id lives in `actor` alone,
|
|
47
|
+
* so widening the match to `principal` would hit an unrelated estate.
|
|
48
|
+
*/
|
|
49
|
+
export function partyActorIds(parties) {
|
|
50
|
+
const p = parties ?? {};
|
|
51
|
+
return [
|
|
52
|
+
...new Set(AGREEMENT_PARTY_SIDES.map((name) => p[name]?.actor).filter((id) => typeof id === 'string' && id.length > 0)),
|
|
53
|
+
];
|
|
54
|
+
}
|
|
37
55
|
/** ⚠️ Mirrors the server's entry-type constant; the server is authoritative. */
|
|
38
56
|
export const EntryTypes = {
|
|
39
57
|
MESSAGE: 'message',
|