@ziggs-ai/api-client 0.9.1 → 0.9.3
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/ConnectionManager.d.ts +2 -2
- package/dist/ConnectionManager.js +3 -3
- package/dist/capabilities/chat.js +13 -3
- package/dist/capabilities/grants.js +17 -2
- package/dist/capabilities/payments.js +5 -0
- package/dist/config.d.ts +33 -0
- package/dist/config.js +42 -0
- package/dist/http/AgentSearchClient.d.ts +0 -1
- package/dist/http/AgentSearchClient.js +0 -1
- package/dist/http/AgreementClient.d.ts +0 -1
- package/dist/http/AgreementClient.js +3 -4
- package/dist/http/ArtifactsClient.d.ts +0 -1
- package/dist/http/ArtifactsClient.js +0 -1
- package/dist/http/ChatClient.d.ts +6 -3
- package/dist/http/ChatClient.js +5 -4
- package/dist/http/ConnectionsClient.d.ts +0 -1
- package/dist/http/ConnectionsClient.js +0 -1
- package/dist/http/ContextDiscoveryClient.d.ts +0 -1
- package/dist/http/ContextDiscoveryClient.js +0 -1
- package/dist/http/ContextGrantsClient.d.ts +0 -1
- package/dist/http/ContextGrantsClient.js +0 -1
- package/dist/http/ContextReadClient.d.ts +0 -1
- package/dist/http/ContextReadClient.js +0 -1
- package/dist/http/GrantsClient.d.ts +9 -1
- package/dist/http/GrantsClient.js +4 -1
- package/dist/http/InboxClient.d.ts +1 -130
- package/dist/http/InboxClient.js +0 -1
- package/dist/http/MarketplaceClient.d.ts +0 -1
- package/dist/http/MarketplaceClient.js +0 -1
- package/dist/http/MessagesClient.d.ts +0 -1
- package/dist/http/MessagesClient.js +0 -1
- package/dist/http/OrgsClient.d.ts +0 -1
- package/dist/http/OrgsClient.js +0 -1
- package/dist/http/PaymentsClient.d.ts +4 -2
- package/dist/http/PaymentsClient.js +24 -2
- package/dist/http/TaskClient.d.ts +0 -1
- package/dist/http/TaskClient.js +0 -1
- package/dist/http/TelemetryClient.d.ts +0 -1
- package/dist/http/TelemetryClient.js +0 -1
- package/dist/http/index.d.ts +0 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.js +2 -0
- package/dist/shared/runtimeLog.d.ts +0 -6
- package/dist/shared/runtimeLog.js +10 -7
- package/dist/types.d.ts +152 -0
- package/dist/utils/urlUtils.js +3 -2
- package/package.json +1 -2
|
@@ -40,8 +40,8 @@ export declare class ConnectionManager {
|
|
|
40
40
|
*/
|
|
41
41
|
connectAll(): Promise<void>;
|
|
42
42
|
startAgent(id: string): Promise<unknown>;
|
|
43
|
-
|
|
44
|
-
|
|
43
|
+
stopAgent(id: string): Promise<void>;
|
|
44
|
+
stopAll(): Promise<void>;
|
|
45
45
|
list(): string[];
|
|
46
46
|
listActive(): string[];
|
|
47
47
|
get size(): number;
|
|
@@ -73,7 +73,7 @@ export class ConnectionManager {
|
|
|
73
73
|
this._starting.set(id, startPromise);
|
|
74
74
|
return startPromise;
|
|
75
75
|
}
|
|
76
|
-
async
|
|
76
|
+
async stopAgent(id) {
|
|
77
77
|
if (!this._active.has(id))
|
|
78
78
|
return;
|
|
79
79
|
const handle = this._active.get(id);
|
|
@@ -82,8 +82,8 @@ export class ConnectionManager {
|
|
|
82
82
|
if (reg)
|
|
83
83
|
await reg.closeFn(handle);
|
|
84
84
|
}
|
|
85
|
-
async
|
|
86
|
-
await Promise.all([...this._active.keys()].map(id => this.
|
|
85
|
+
async stopAll() {
|
|
86
|
+
await Promise.all([...this._active.keys()].map(id => this.stopAgent(id)));
|
|
87
87
|
}
|
|
88
88
|
list() { return [...this._entries.keys()]; }
|
|
89
89
|
listActive() { return [...this._active.keys()]; }
|
|
@@ -12,8 +12,8 @@ export const openConversationCapability = {
|
|
|
12
12
|
key: 'chat_open',
|
|
13
13
|
names: { sdk: 'chat_open', mcp: 'ziggs_chat_open' },
|
|
14
14
|
descriptions: {
|
|
15
|
-
sdk: 'Open or reuse a chat with a user or agent participant. To reach an agent in ANOTHER org, establish a link first — agreement_propose with engagementKind "link" (if you have its agent id) or link_create_invite (if you do not), approved/claimed — otherwise this fails with AGENT_NOT_PUBLISHED. To list chats you can already read, use grant_list scopeKind=chat.',
|
|
16
|
-
mcp: 'Open or reuse a chat with a user or agent participant. To reach an agent in ANOTHER org, an unpublished delegate must establish a link first — ziggs_agreement_propose with engagementKind "link" (if you have its agent id) or ziggs_link_create_invite (if you do not), approved/claimed — otherwise this fails with AGENT_NOT_PUBLISHED.',
|
|
15
|
+
sdk: 'Open or reuse a chat with a user or agent participant. Calling it again for the same participant returns the SAME chat, so it is how you find the conversation you already have with someone — pass newChat only when this really is a separate subject. To reach an agent in ANOTHER org, establish a link first — agreement_propose with engagementKind "link" (if you have its agent id) or link_create_invite (if you do not), approved/claimed — otherwise this fails with AGENT_NOT_PUBLISHED. To list chats you can already read, use grant_list scopeKind=chat.',
|
|
16
|
+
mcp: 'Open or reuse a chat with a user or agent participant. Calling it again for the same participant returns the SAME chat; pass newChat only when this really is a separate subject. To reach an agent in ANOTHER org, an unpublished delegate must establish a link first — ziggs_agreement_propose with engagementKind "link" (if you have its agent id) or ziggs_link_create_invite (if you do not), approved/claimed — otherwise this fails with AGENT_NOT_PUBLISHED.',
|
|
17
17
|
},
|
|
18
18
|
annotation: 'write',
|
|
19
19
|
params: {
|
|
@@ -22,12 +22,22 @@ export const openConversationCapability = {
|
|
|
22
22
|
required: true,
|
|
23
23
|
description: 'User or agent id to converse with (from agent search — do not guess ids)',
|
|
24
24
|
},
|
|
25
|
+
newChat: {
|
|
26
|
+
type: 'boolean',
|
|
27
|
+
description: 'Open a separate chat even though one is already open with this participant. ' +
|
|
28
|
+
'For when the conversation is genuinely its own subject and would confuse an ' +
|
|
29
|
+
'existing thread. The separate chat does not become the main one, so a later ' +
|
|
30
|
+
'call without this still returns the original. Leave unset to continue where ' +
|
|
31
|
+
'you left off.',
|
|
32
|
+
},
|
|
25
33
|
},
|
|
26
34
|
needsAgentId: true,
|
|
27
35
|
handler: async (args, env) => {
|
|
28
36
|
if (!args['participantId'])
|
|
29
37
|
throw new Error('participantId is required');
|
|
30
|
-
const { chatId } = await openConversation(args['participantId'], fullCreds(env)
|
|
38
|
+
const { chatId } = await openConversation(args['participantId'], fullCreds(env), {
|
|
39
|
+
newChat: args['newChat'] === true,
|
|
40
|
+
});
|
|
31
41
|
const lister = env.surface === 'mcp' ? 'ziggs_grant_list' : 'grant_list';
|
|
32
42
|
return {
|
|
33
43
|
chatId,
|
|
@@ -38,16 +38,25 @@ export const listGrantsCapability = {
|
|
|
38
38
|
key: 'grant_list',
|
|
39
39
|
names: { sdk: 'grant_list', mcp: 'ziggs_grant_list' },
|
|
40
40
|
descriptions: {
|
|
41
|
-
sdk: 'List
|
|
42
|
-
mcp: 'List
|
|
41
|
+
sdk: 'List grants this agent holds — or, with role=issuer, grants this agent caused (author-shares and delegate children). Context (chat/agreement/org/artifact), connection, and wallet — canonical grants (grantId, scope, caveats, expiresAt, health; no content or credentials). Default role=holder answers "what grants do I HOLD?", which is narrower than "what can I reach?": authorship, chat membership, agreement party, and org membership leave no grant row — an empty holder list means "no grants", never "no access". role=issuer answers "who did I share with / what did I mint?" after artifact_share. Filter by scopeKind, scopeId, and health (defaults to active). Rails you lack the operator-key read scope for are named in unreadableRails. Cursor-paginated.',
|
|
42
|
+
mcp: 'List grants this delegate holds — or, with role=issuer, grants this delegate caused (author-shares and delegate children). Context (chat/agreement/org/artifact), connection, and wallet — canonical grants (grantId, scope, caveats, expiresAt, health; no content or credentials). Default role=holder answers "what grants do I HOLD?", which is narrower than "what can I reach?": authorship, chat membership, agreement party, and org membership leave no grant row — an empty holder list means "no grants", never "no access". After ziggs_artifact_share, pass role=issuer (and usually scopeKind=["artifact"]) to recover grantIds and revoke with ziggs_context_revoke_grant. Filter by scopeKind, scopeId, and health (defaults to active). Rails you lack the operator-key read scope for are named in unreadableRails. Cursor-paginated.',
|
|
43
43
|
},
|
|
44
44
|
annotation: 'read-only',
|
|
45
45
|
params: {
|
|
46
|
+
role: {
|
|
47
|
+
type: 'string',
|
|
48
|
+
enum: ['holder', 'issuer'],
|
|
49
|
+
description: 'holder (default): grants you hold. issuer: grants you caused — author-shares you made and delegate children you minted (not your human owner\'s full issuer view).',
|
|
50
|
+
},
|
|
46
51
|
scopeKind: {
|
|
47
52
|
type: 'array',
|
|
48
53
|
items: { type: 'string', enum: SCOPE_KINDS },
|
|
49
54
|
description: 'Rail filter (repeatable): chat | agreement | org | artifact (context) | connection | wallet. Omit for every rail you can read.',
|
|
50
55
|
},
|
|
56
|
+
scopeId: {
|
|
57
|
+
type: 'string',
|
|
58
|
+
description: 'Narrow to one resource id (e.g. one artifactId) within the rails above.',
|
|
59
|
+
},
|
|
51
60
|
health: {
|
|
52
61
|
type: 'string',
|
|
53
62
|
enum: HEALTHS,
|
|
@@ -64,8 +73,14 @@ export const listGrantsCapability = {
|
|
|
64
73
|
if (healthArg !== undefined && !HEALTHS.includes(healthArg)) {
|
|
65
74
|
throw new Error(`health must be one of ${HEALTHS.join(', ')}`);
|
|
66
75
|
}
|
|
76
|
+
const roleArg = args['role'];
|
|
77
|
+
if (roleArg !== undefined && roleArg !== 'holder' && roleArg !== 'issuer') {
|
|
78
|
+
throw new Error('role must be holder or issuer');
|
|
79
|
+
}
|
|
67
80
|
const { items, nextCursor, unreadableRails } = await new GrantsClient(creds.operatorKey, creds.agentId, env.baseUrl).listGrants({
|
|
68
81
|
scopeKind,
|
|
82
|
+
scopeId: typeof args['scopeId'] === 'string' ? args['scopeId'] : undefined,
|
|
83
|
+
role: roleArg,
|
|
69
84
|
// Reach = live grants only by default; pass health to see expired/revoked.
|
|
70
85
|
health: healthArg ?? 'active',
|
|
71
86
|
cursor: args['cursor'],
|
|
@@ -216,6 +216,10 @@ export const paymentHoldCapability = {
|
|
|
216
216
|
amount: { type: 'number', required: true, description: 'Amount in integer cents, > 0' },
|
|
217
217
|
description: { type: 'string', description: 'Human-readable hold memo' },
|
|
218
218
|
idempotencyKey: { type: 'string', description: 'Client-supplied retry-safety key' },
|
|
219
|
+
paymentGrantId: {
|
|
220
|
+
type: 'string',
|
|
221
|
+
description: 'Payment grant authorizing this hold (required for agent actors; auto-picks an active wallet grant when omitted)',
|
|
222
|
+
},
|
|
219
223
|
},
|
|
220
224
|
handler: async (args, env) => {
|
|
221
225
|
const amount = args['amount'];
|
|
@@ -226,6 +230,7 @@ export const paymentHoldCapability = {
|
|
|
226
230
|
amount: Math.round(amount),
|
|
227
231
|
description: args['description'] || 'Agent escrow hold',
|
|
228
232
|
idempotencyKey: args['idempotencyKey'],
|
|
233
|
+
paymentGrantId: args['paymentGrantId'],
|
|
229
234
|
});
|
|
230
235
|
return {
|
|
231
236
|
status: 'held',
|
package/dist/config.d.ts
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Runtime configuration for this package, injected by whoever owns the process.
|
|
3
|
+
*
|
|
4
|
+
* This package used to read `process.env` directly, which is why every http
|
|
5
|
+
* client began with `import 'dotenv/config'`. Metro (React Native's bundler)
|
|
6
|
+
* cannot resolve dotenv, so a mobile consumer could not import api-client at
|
|
7
|
+
* all. The environment is now read by the host — `env-init.ts` in this repo,
|
|
8
|
+
* the MCP server's config loader, a mobile app's bootstrap — and handed here.
|
|
9
|
+
*
|
|
10
|
+
* Configure before constructing clients: `getBackendUrl()` is called in their
|
|
11
|
+
* constructors, so a client built first keeps the URL that was current then.
|
|
12
|
+
*/
|
|
13
|
+
/** Threshold names accepted by {@link ApiClientConfig.logLevel}. */
|
|
14
|
+
export type ApiClientLogLevel = 'debug' | 'trace' | 'info' | 'warn' | 'error' | 'silent' | 'none';
|
|
15
|
+
export interface ApiClientConfig {
|
|
16
|
+
/** Backend base URL. Falls back to production when nothing sets it. */
|
|
17
|
+
httpUrl?: string;
|
|
18
|
+
/** WebSocket base URL. Falls back to production when nothing sets it. */
|
|
19
|
+
wsUrl?: string;
|
|
20
|
+
/** `runtimeLog` threshold. Falls back to `info`. */
|
|
21
|
+
logLevel?: ApiClientLogLevel;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Merge settings into the package config. Partial: passing only `logLevel`
|
|
25
|
+
* leaves a previously configured `httpUrl` alone. Explicit `undefined` is
|
|
26
|
+
* ignored rather than treated as a clear, so a host can spread a half-filled
|
|
27
|
+
* options object without wiping what it already set.
|
|
28
|
+
*/
|
|
29
|
+
export declare function configureApiClient(next: ApiClientConfig): void;
|
|
30
|
+
/** Current config. Read-only — mutate through {@link configureApiClient}. */
|
|
31
|
+
export declare function apiClientConfig(): Readonly<ApiClientConfig>;
|
|
32
|
+
/** Generation counter for cache invalidation. */
|
|
33
|
+
export declare function apiClientConfigVersion(): number;
|
package/dist/config.js
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Runtime configuration for this package, injected by whoever owns the process.
|
|
3
|
+
*
|
|
4
|
+
* This package used to read `process.env` directly, which is why every http
|
|
5
|
+
* client began with `import 'dotenv/config'`. Metro (React Native's bundler)
|
|
6
|
+
* cannot resolve dotenv, so a mobile consumer could not import api-client at
|
|
7
|
+
* all. The environment is now read by the host — `env-init.ts` in this repo,
|
|
8
|
+
* the MCP server's config loader, a mobile app's bootstrap — and handed here.
|
|
9
|
+
*
|
|
10
|
+
* Configure before constructing clients: `getBackendUrl()` is called in their
|
|
11
|
+
* constructors, so a client built first keeps the URL that was current then.
|
|
12
|
+
*/
|
|
13
|
+
const config = {};
|
|
14
|
+
/**
|
|
15
|
+
* Bumped on every configure so derived caches (the log threshold) know to
|
|
16
|
+
* recompute. A version counter rather than a reset callback because
|
|
17
|
+
* `runtimeLog` reads config — a callback the other way would be a cycle.
|
|
18
|
+
*/
|
|
19
|
+
let version = 0;
|
|
20
|
+
/**
|
|
21
|
+
* Merge settings into the package config. Partial: passing only `logLevel`
|
|
22
|
+
* leaves a previously configured `httpUrl` alone. Explicit `undefined` is
|
|
23
|
+
* ignored rather than treated as a clear, so a host can spread a half-filled
|
|
24
|
+
* options object without wiping what it already set.
|
|
25
|
+
*/
|
|
26
|
+
export function configureApiClient(next) {
|
|
27
|
+
if (next.httpUrl !== undefined)
|
|
28
|
+
config.httpUrl = next.httpUrl;
|
|
29
|
+
if (next.wsUrl !== undefined)
|
|
30
|
+
config.wsUrl = next.wsUrl;
|
|
31
|
+
if (next.logLevel !== undefined)
|
|
32
|
+
config.logLevel = next.logLevel;
|
|
33
|
+
version += 1;
|
|
34
|
+
}
|
|
35
|
+
/** Current config. Read-only — mutate through {@link configureApiClient}. */
|
|
36
|
+
export function apiClientConfig() {
|
|
37
|
+
return config;
|
|
38
|
+
}
|
|
39
|
+
/** Generation counter for cache invalidation. */
|
|
40
|
+
export function apiClientConfigVersion() {
|
|
41
|
+
return version;
|
|
42
|
+
}
|
|
@@ -1,11 +1,10 @@
|
|
|
1
|
-
import 'dotenv/config';
|
|
2
1
|
import { runtimeLog } from '../shared/runtimeLog.js';
|
|
3
2
|
import { getBackendUrl } from '../utils/urlUtils.js';
|
|
4
3
|
import { OPEN_AGREEMENT_TARGET, ORG_AGREEMENT_TARGET, isBroadcastTarget } from '../types.js';
|
|
5
4
|
import { throwApiError } from '../shared/apiError.js';
|
|
6
|
-
// Lazy: read at call time so
|
|
7
|
-
// still takes effect. Baking it at module-load time would
|
|
8
|
-
// before the
|
|
5
|
+
// Lazy: read at call time so a `configureApiClient` call that lands after this
|
|
6
|
+
// module is imported still takes effect. Baking it at module-load time would
|
|
7
|
+
// freeze the URL before the host has configured one.
|
|
9
8
|
function getAgreementBaseUrl() {
|
|
10
9
|
return `${getBackendUrl()}/agreements`;
|
|
11
10
|
}
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import 'dotenv/config';
|
|
2
1
|
import { type Creds } from '../types.js';
|
|
3
2
|
/** Shape of GET /chats/mine items — the backend's ChatReadDto (ZIG-665). */
|
|
4
3
|
export interface ChatSummary {
|
|
@@ -10,7 +9,9 @@ export interface ChatSummary {
|
|
|
10
9
|
orgId: string | null;
|
|
11
10
|
isOrgChat: boolean;
|
|
12
11
|
}
|
|
13
|
-
export declare function openConversation(participantId: string, creds: Creds
|
|
12
|
+
export declare function openConversation(participantId: string, creds: Creds, { newChat }?: {
|
|
13
|
+
newChat?: boolean;
|
|
14
|
+
}): Promise<{
|
|
14
15
|
chatId: string;
|
|
15
16
|
}>;
|
|
16
17
|
export interface SendChatMessageInput {
|
|
@@ -75,7 +76,9 @@ export declare class ChatClient {
|
|
|
75
76
|
* @param agentId Required for fleet keys (sent as X-Agent-Id). Omit for agent-scoped keys.
|
|
76
77
|
*/
|
|
77
78
|
constructor(operatorKey: string, agentId?: string);
|
|
78
|
-
open(participantId: string
|
|
79
|
+
open(participantId: string, opts?: {
|
|
80
|
+
newChat?: boolean;
|
|
81
|
+
}): Promise<{
|
|
79
82
|
chatId: string;
|
|
80
83
|
}>;
|
|
81
84
|
addMember(input: AddChatMemberInput): Promise<AddChatMemberResult>;
|
package/dist/http/ChatClient.js
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import 'dotenv/config';
|
|
2
1
|
import { runtimeLog } from '../shared/runtimeLog.js';
|
|
3
2
|
import { getBackendUrl } from '../utils/urlUtils.js';
|
|
4
3
|
import { throwApiError } from '../shared/apiError.js';
|
|
@@ -18,14 +17,16 @@ function assertCreds(creds, op) {
|
|
|
18
17
|
if (!creds?.agentId)
|
|
19
18
|
throw new Error(`agentId is required for ${op}`);
|
|
20
19
|
}
|
|
21
|
-
export async function openConversation(participantId, creds) {
|
|
20
|
+
export async function openConversation(participantId, creds, { newChat = false } = {}) {
|
|
22
21
|
if (!participantId)
|
|
23
22
|
throw new Error('participantId is required for openConversation');
|
|
24
23
|
assertCreds(creds, 'open conversation');
|
|
25
24
|
const res = await fetch(`${getBackendUrl()}/chats`, {
|
|
26
25
|
method: 'POST',
|
|
27
26
|
headers: buildHeaders(creds),
|
|
28
|
-
|
|
27
|
+
// Only sent when asked for: an older backend ignores the field, so a
|
|
28
|
+
// caller that never wants a separate room behaves identically either way.
|
|
29
|
+
body: JSON.stringify({ participantId, ...(newChat ? { newChat: true } : {}) }),
|
|
29
30
|
});
|
|
30
31
|
if (!res.ok) {
|
|
31
32
|
const body = await res.text().catch(() => '');
|
|
@@ -137,7 +138,7 @@ export class ChatClient {
|
|
|
137
138
|
// standalone functions still assert it per call.
|
|
138
139
|
this.creds = { operatorKey, agentId };
|
|
139
140
|
}
|
|
140
|
-
open(participantId) { return openConversation(participantId, this.creds); }
|
|
141
|
+
open(participantId, opts) { return openConversation(participantId, this.creds, opts); }
|
|
141
142
|
addMember(input) { return addChatMember(input, this.creds); }
|
|
142
143
|
sendMessage(input) { return sendChatMessage(input, this.creds); }
|
|
143
144
|
listMine() { return listMyChats(this.creds); }
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import 'dotenv/config';
|
|
2
1
|
import type { GrantView, GrantScopeKind, GrantHealth } from './grants.js';
|
|
3
2
|
export interface ListGrantsQuery {
|
|
4
3
|
/**
|
|
@@ -11,6 +10,15 @@ export interface ListGrantsQuery {
|
|
|
11
10
|
* kinds: chat, agreement, org). Absent = every rail.
|
|
12
11
|
*/
|
|
13
12
|
scopeKind?: GrantScopeKind | GrantScopeKind[];
|
|
13
|
+
/**
|
|
14
|
+
* Narrow to one resource id (e.g. one artifact). Server-side page filter.
|
|
15
|
+
*/
|
|
16
|
+
scopeId?: string;
|
|
17
|
+
/**
|
|
18
|
+
* `'holder'` (default) = grants you hold. `'issuer'` = grants you caused
|
|
19
|
+
* (ZIG-1217 for agents: author-shares + delegate children).
|
|
20
|
+
*/
|
|
21
|
+
role?: 'holder' | 'issuer';
|
|
14
22
|
/** Filter to grants of one health. */
|
|
15
23
|
health?: GrantHealth;
|
|
16
24
|
cursor?: string;
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import 'dotenv/config';
|
|
2
1
|
import { getBackendUrl } from '../utils/urlUtils.js';
|
|
3
2
|
import { throwApiError } from '../shared/apiError.js';
|
|
4
3
|
import { buildOperatorHeaders } from './operatorHeaders.js';
|
|
@@ -31,6 +30,10 @@ export class GrantsClient {
|
|
|
31
30
|
for (const k of kinds)
|
|
32
31
|
url.searchParams.append('scopeKind', k);
|
|
33
32
|
}
|
|
33
|
+
if (query.scopeId)
|
|
34
|
+
url.searchParams.set('scopeId', query.scopeId);
|
|
35
|
+
if (query.role)
|
|
36
|
+
url.searchParams.set('role', query.role);
|
|
34
37
|
if (query.health)
|
|
35
38
|
url.searchParams.set('health', query.health);
|
|
36
39
|
if (query.cursor)
|
|
@@ -1,133 +1,4 @@
|
|
|
1
|
-
import '
|
|
2
|
-
/**
|
|
3
|
-
* What a delivery can be about. A closed union, not a comment: a consumer that
|
|
4
|
-
* dispatches on `kind` (the MCP read plan) is only safe if the compiler can tell
|
|
5
|
-
* it a case is missing. The task-only deliverable that was acked unread got
|
|
6
|
-
* through precisely because this was `string`.
|
|
7
|
-
*
|
|
8
|
-
* A type and not a value list, unlike the backend's `RESOURCE_KINDS` — nothing
|
|
9
|
-
* on this side validates a delivery kind at runtime (the server does that on the
|
|
10
|
-
* way in), and exhaustiveness checking is purely type-level.
|
|
11
|
-
*/
|
|
12
|
-
export type InboxDeliveryKind = 'message' | 'artifact' | 'task-state' | 'agreement';
|
|
13
|
-
/**
|
|
14
|
-
* One thing addressed to this agent. A reference, never content — following it
|
|
15
|
-
* (a chat read, a task read) is where this agent's grants are enforced.
|
|
16
|
-
*/
|
|
17
|
-
export interface InboxDeliveryRef {
|
|
18
|
-
kind: InboxDeliveryKind;
|
|
19
|
-
resourceId: string;
|
|
20
|
-
chatId: string | null;
|
|
21
|
-
agreementId: string | null;
|
|
22
|
-
taskId: string | null;
|
|
23
|
-
/** Who wrote it. Never this agent — you are not woken by your own writes. */
|
|
24
|
-
actorId: string | null;
|
|
25
|
-
ts: string;
|
|
26
|
-
}
|
|
27
|
-
/** Message/artifact deliveries folded by chat, so you can open chats directly. */
|
|
28
|
-
export interface InboxChatNews {
|
|
29
|
-
chatId: string;
|
|
30
|
-
count: number;
|
|
31
|
-
latestAt: string;
|
|
32
|
-
}
|
|
33
|
-
export interface InboxProposalRef {
|
|
34
|
-
agreementId: string;
|
|
35
|
-
title: string;
|
|
36
|
-
proposedAt: string | null;
|
|
37
|
-
/**
|
|
38
|
-
* ZIG-1087 — party ids still owing a decision, and the named responder slot.
|
|
39
|
-
* The inbox lists proposals awaiting the agent OR its human, and only the
|
|
40
|
-
* agent's own slot is one it can submit; these say which is which.
|
|
41
|
-
*
|
|
42
|
-
* Optional because a backend deployed before ZIG-1087 omits them, and this
|
|
43
|
-
* client is installed independently of the server it talks to. Absent reads
|
|
44
|
-
* as "no slot of mine", which routes the decision to the human — the safe
|
|
45
|
-
* direction: it withholds a call, it never invents authority.
|
|
46
|
-
*/
|
|
47
|
-
pendingApprovalPartyIds?: string[];
|
|
48
|
-
proposedTo?: string | null;
|
|
49
|
-
}
|
|
50
|
-
export interface InboxConnectionRequestRef {
|
|
51
|
-
requestId: string;
|
|
52
|
-
/**
|
|
53
|
-
* Non-addressable persona reference for the requester (`psn_*`).
|
|
54
|
-
* Never use as an account id for lookup / wake / pay (ZIG-1137).
|
|
55
|
-
*/
|
|
56
|
-
requesterRef: string;
|
|
57
|
-
/** ZIG-1039 — human-readable name for consent cards. */
|
|
58
|
-
requesterDisplayName?: string | null;
|
|
59
|
-
/** ZIG-1039 — org label for consent cards. */
|
|
60
|
-
requesterOrgName?: string | null;
|
|
61
|
-
message: string | null;
|
|
62
|
-
requestedAt: string | null;
|
|
63
|
-
/** ZIG-1087 — see InboxProposalRef; a link request uses the same gate. */
|
|
64
|
-
pendingApprovalPartyIds?: string[];
|
|
65
|
-
proposedTo?: string | null;
|
|
66
|
-
}
|
|
67
|
-
/** Pull-only MCP: prompt the human when proposals need a decision (ZIG-482 / ZIG-481). */
|
|
68
|
-
export interface InboxHumanAttention {
|
|
69
|
-
required: true;
|
|
70
|
-
reason: 'proposals_awaiting_me' | 'connection_requests_awaiting_me' | 'multiple';
|
|
71
|
-
proposalCount: number;
|
|
72
|
-
truncatedProposals: number;
|
|
73
|
-
connectionRequestCount: number;
|
|
74
|
-
truncatedConnectionRequests: number;
|
|
75
|
-
promptUser: string;
|
|
76
|
-
}
|
|
77
|
-
/**
|
|
78
|
-
* An open task assigned to this agent (ZIG-973). References only — read the
|
|
79
|
-
* task for its description/plan/inputs.
|
|
80
|
-
*
|
|
81
|
-
* Tasks ride their own channel because assignment IS their delivery: before
|
|
82
|
-
* this, a task wake was a synthetic chat row, so work under a chat-less
|
|
83
|
-
* agreement (or self-assigned) reached nobody.
|
|
84
|
-
*/
|
|
85
|
-
export interface InboxTaskRef {
|
|
86
|
-
taskId: string;
|
|
87
|
-
agreementId: string | null;
|
|
88
|
-
title: string;
|
|
89
|
-
state: string;
|
|
90
|
-
updatedAt: string | null;
|
|
91
|
-
}
|
|
92
|
-
export interface InboxEnvelope {
|
|
93
|
-
asOf: string;
|
|
94
|
-
/**
|
|
95
|
-
* Unacked deliveries addressed to this agent, newest first. This IS the
|
|
96
|
-
* inbox — read straight out of the delivery log, not derived from grants.
|
|
97
|
-
*/
|
|
98
|
-
deliveries: InboxDeliveryRef[];
|
|
99
|
-
/** True when there was more than one envelope's worth; the rest stay unacked. */
|
|
100
|
-
deliveriesCapped: boolean;
|
|
101
|
-
/** The chat-bearing deliveries above, folded by chat. */
|
|
102
|
-
chats: InboxChatNews[];
|
|
103
|
-
/**
|
|
104
|
-
* Pass to `ack()` after acting. Null when there is nothing to ack. Ack after
|
|
105
|
-
* acting, not after reading: a crash in between redelivers.
|
|
106
|
-
*/
|
|
107
|
-
ackTo: string | null;
|
|
108
|
-
/** Open tasks assigned to this agent — the work channel (ZIG-973). */
|
|
109
|
-
tasksAwaitingMe: InboxTaskRef[];
|
|
110
|
-
truncatedTasks: number;
|
|
111
|
-
proposalsAwaitingMe: InboxProposalRef[];
|
|
112
|
-
truncatedProposals: number;
|
|
113
|
-
connectionRequestsAwaitingMe: InboxConnectionRequestRef[];
|
|
114
|
-
truncatedConnectionRequests: number;
|
|
115
|
-
humanAttention?: InboxHumanAttention;
|
|
116
|
-
}
|
|
117
|
-
export interface InboxAckResult {
|
|
118
|
-
/** Where the watermark now sits. Monotonic — a rewind is a no-op, not an error. */
|
|
119
|
-
ackedUpTo: string | null;
|
|
120
|
-
}
|
|
121
|
-
/**
|
|
122
|
-
* Long-poll option shared by the inbox reads. The server holds the request up
|
|
123
|
-
* to this many seconds (server-clamped, ~25s ceiling) and returns as soon as
|
|
124
|
-
* anything actionable exists. Omit for an immediate snapshot — the response
|
|
125
|
-
* shape is identical either way, so `wait` only changes how long an EMPTY
|
|
126
|
-
* answer is withheld.
|
|
127
|
-
*/
|
|
128
|
-
export interface InboxReadOptions {
|
|
129
|
-
waitSeconds?: number;
|
|
130
|
-
}
|
|
1
|
+
import type { InboxAckResult, InboxEnvelope, InboxReadOptions } from '../types.js';
|
|
131
2
|
/**
|
|
132
3
|
* The doorbell, not the door (ZIG-434): references addressed to this agent
|
|
133
4
|
* since its last ack — never content. Flow: inbox → read → act → ack
|
package/dist/http/InboxClient.js
CHANGED
package/dist/http/OrgsClient.js
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import 'dotenv/config';
|
|
2
1
|
import type { GrantView } from './grants.js';
|
|
3
2
|
/** Thrown by PaymentsClient with the HTTP status and raw body attached. */
|
|
4
3
|
export interface PaymentsError extends Error {
|
|
@@ -101,11 +100,14 @@ export declare class PaymentsClient {
|
|
|
101
100
|
description?: string;
|
|
102
101
|
paymentGrantId?: string;
|
|
103
102
|
}): Promise<TransferResult>;
|
|
104
|
-
hold({ amount, idempotencyKey, description, }: {
|
|
103
|
+
hold({ amount, idempotencyKey, description, paymentGrantId, }: {
|
|
105
104
|
amount: number;
|
|
106
105
|
idempotencyKey?: string;
|
|
107
106
|
description?: string;
|
|
107
|
+
paymentGrantId?: string;
|
|
108
108
|
}): Promise<HoldResult>;
|
|
109
|
+
/** Prefer a single active wallet grant the agent already holds (ZIG-1182). */
|
|
110
|
+
private resolveAgentPaymentGrantId;
|
|
109
111
|
release({ holdId, action, toWalletId, idempotencyKey, }: {
|
|
110
112
|
holdId: string;
|
|
111
113
|
action?: string;
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import 'dotenv/config';
|
|
2
1
|
import { getBackendUrl } from '../utils/urlUtils.js';
|
|
3
2
|
import { buildOperatorHeaders } from './operatorHeaders.js';
|
|
4
3
|
import { GrantsClient } from './GrantsClient.js';
|
|
@@ -51,6 +50,11 @@ export class PaymentsClient {
|
|
|
51
50
|
throw new Error('transfer: `to` is required');
|
|
52
51
|
if (!(Number.isInteger(amount) && amount > 0))
|
|
53
52
|
throw new Error('transfer: `amount` must be a positive integer (cents)');
|
|
53
|
+
// ZIG-1182 — resolve a standing/active grant when the caller omitted one
|
|
54
|
+
// (Claude/MCP ensureForUser mints it). Explicit id still wins.
|
|
55
|
+
if (this.agentId && !paymentGrantId) {
|
|
56
|
+
paymentGrantId = (await this.resolveAgentPaymentGrantId()) ?? undefined;
|
|
57
|
+
}
|
|
54
58
|
if (this.agentId && !paymentGrantId)
|
|
55
59
|
throw new Error('transfer: paymentGrantId is required for agent-impersonated transfers. The wallet owner must have issued a payment grant to this agentId.');
|
|
56
60
|
let toWalletId = to;
|
|
@@ -86,15 +90,33 @@ export class PaymentsClient {
|
|
|
86
90
|
amount,
|
|
87
91
|
};
|
|
88
92
|
}
|
|
89
|
-
async hold({ amount, idempotencyKey, description, }) {
|
|
93
|
+
async hold({ amount, idempotencyKey, description, paymentGrantId, }) {
|
|
90
94
|
if (!(Number.isInteger(amount) && amount > 0))
|
|
91
95
|
throw new Error('hold: `amount` must be a positive integer (cents)');
|
|
96
|
+
// ZIG-1182 — agent holds reserve the owner's wallet; require a grant.
|
|
97
|
+
if (this.agentId && !paymentGrantId) {
|
|
98
|
+
paymentGrantId = (await this.resolveAgentPaymentGrantId()) ?? undefined;
|
|
99
|
+
}
|
|
100
|
+
if (this.agentId && !paymentGrantId)
|
|
101
|
+
throw new Error('hold: paymentGrantId is required for agent-impersonated holds. The wallet owner must have issued a payment grant to this agentId.');
|
|
92
102
|
return (await this._post('/payments/hold', {
|
|
93
103
|
amount,
|
|
94
104
|
idempotencyKey: idempotencyKey || randomIdempotencyKey('hold'),
|
|
95
105
|
description,
|
|
106
|
+
paymentGrantId,
|
|
96
107
|
}));
|
|
97
108
|
}
|
|
109
|
+
/** Prefer a single active wallet grant the agent already holds (ZIG-1182). */
|
|
110
|
+
async resolveAgentPaymentGrantId() {
|
|
111
|
+
try {
|
|
112
|
+
const grants = await this.listGrants();
|
|
113
|
+
const id = grants[0]?.grantId;
|
|
114
|
+
return typeof id === 'string' && id.length > 0 ? id : null;
|
|
115
|
+
}
|
|
116
|
+
catch {
|
|
117
|
+
return null;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
98
120
|
async release({ holdId, action = 'complete', toWalletId, idempotencyKey, }) {
|
|
99
121
|
return (await this._post(`/payments/release/${holdId}`, {
|
|
100
122
|
idempotencyKey: idempotencyKey || randomIdempotencyKey('rel'),
|
package/dist/http/TaskClient.js
CHANGED
package/dist/http/index.d.ts
CHANGED
|
@@ -26,4 +26,3 @@ export type { MyOrg, OrgResolution } from './OrgsClient.js';
|
|
|
26
26
|
export { AgentSearchClient } from './AgentSearchClient.js';
|
|
27
27
|
export { TelemetryClient } from './TelemetryClient.js';
|
|
28
28
|
export { InboxClient } from './InboxClient.js';
|
|
29
|
-
export type { InboxDeliveryKind, InboxDeliveryRef, InboxChatNews, InboxProposalRef, InboxTaskRef, InboxConnectionRequestRef, InboxHumanAttention, InboxEnvelope, InboxAckResult, } from './InboxClient.js';
|
package/dist/index.d.ts
CHANGED
|
@@ -5,9 +5,11 @@ export { ConnectionManager } from './ConnectionManager.js';
|
|
|
5
5
|
export { EntryTypes, ContentTypes, OPEN_AGREEMENT_TARGET, ORG_AGREEMENT_TARGET, BROADCAST_TARGETS, isBroadcastTarget, isPersonaRef, isRoomPresentationRef, isOpaquePresentationRef, AGREEMENT_ENGAGEMENT_KIND, isValidContentType, } from './types.js';
|
|
6
6
|
export type { PrincipalPresentation } from './types.js';
|
|
7
7
|
export { getBackendUrl, getWebSocketUrl } from './utils/urlUtils.js';
|
|
8
|
+
export { configureApiClient, apiClientConfig } from './config.js';
|
|
9
|
+
export type { ApiClientConfig, ApiClientLogLevel } from './config.js';
|
|
8
10
|
export { runtimeLog, resetRuntimeLogLevelCache } from './shared/runtimeLog.js';
|
|
9
11
|
export { RateLimitedError, isRateLimited, parseRetryAfterMs, pollSurfaceError, } from './shared/rateLimit.js';
|
|
10
12
|
export { parseErrorMessage, parseErrorCode, throwApiError, } from './shared/apiError.js';
|
|
11
13
|
export { ApiError } from './types.js';
|
|
12
|
-
export type { Creds, Task, TaskState, PlanStep, PlanStepStatus, Agreement, EngagementKind, BroadcastAudience, EntryType, ContentType, MessageMetadata, MessageHandler, } from './types.js';
|
|
14
|
+
export type { Creds, Task, TaskState, PlanStep, PlanStepStatus, Agreement, EngagementKind, BroadcastAudience, EntryType, ContentType, MessageMetadata, MessageHandler, InboxDeliveryKind, InboxDeliveryRef, InboxChatNews, InboxProposalRef, InboxTaskRef, InboxQuestRef, InboxConnectionRequestRef, InboxHumanAttention, InboxEnvelope, InboxAckResult, InboxReadOptions, } from './types.js';
|
|
13
15
|
export type { ProposeTerms, ProposeDirectInput, ProposeBroadcastInput, ProposeAgreementData, } from './http/AgreementClient.js';
|
package/dist/index.js
CHANGED
|
@@ -4,6 +4,8 @@ export * from './relay/provisionRelayWorkers.js';
|
|
|
4
4
|
export { ConnectionManager } from './ConnectionManager.js';
|
|
5
5
|
export { EntryTypes, ContentTypes, OPEN_AGREEMENT_TARGET, ORG_AGREEMENT_TARGET, BROADCAST_TARGETS, isBroadcastTarget, isPersonaRef, isRoomPresentationRef, isOpaquePresentationRef, AGREEMENT_ENGAGEMENT_KIND, isValidContentType, } from './types.js';
|
|
6
6
|
export { getBackendUrl, getWebSocketUrl } from './utils/urlUtils.js';
|
|
7
|
+
// ZIG-652: the host injects the environment; this package never reads it.
|
|
8
|
+
export { configureApiClient, apiClientConfig } from './config.js';
|
|
7
9
|
export { runtimeLog, resetRuntimeLogLevelCache } from './shared/runtimeLog.js';
|
|
8
10
|
// ZIG-1019 / ZIG-1124: one ApiError shape; 429s carry the server's wait.
|
|
9
11
|
export { RateLimitedError, isRateLimited, parseRetryAfterMs, pollSurfaceError, } from './shared/rateLimit.js';
|
|
@@ -1,9 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Same semantics as `@ziggs-ai/agent-sdk` `shared/runtimeLog.ts` (duplicated
|
|
3
|
-
* here so this package stays dependency-free).
|
|
4
|
-
*
|
|
5
|
-
* @see agent-sdk/src/shared/runtimeLog.ts
|
|
6
|
-
*/
|
|
7
1
|
export type RuntimeLogLevel = 'debug' | 'info' | 'warn' | 'error';
|
|
8
2
|
export declare function resetRuntimeLogLevelCache(): void;
|
|
9
3
|
export declare const runtimeLog: {
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
*
|
|
5
5
|
* @see agent-sdk/src/shared/runtimeLog.ts
|
|
6
6
|
*/
|
|
7
|
+
import { apiClientConfig, apiClientConfigVersion } from '../config.js';
|
|
7
8
|
const SEVERITY = {
|
|
8
9
|
debug: 0,
|
|
9
10
|
info: 1,
|
|
@@ -11,12 +12,7 @@ const SEVERITY = {
|
|
|
11
12
|
error: 3,
|
|
12
13
|
};
|
|
13
14
|
function parseThreshold() {
|
|
14
|
-
|
|
15
|
-
return SEVERITY.debug;
|
|
16
|
-
}
|
|
17
|
-
const raw = (process.env.LOG_LEVEL ||
|
|
18
|
-
process.env.AGENTPLUS_LOG_LEVEL ||
|
|
19
|
-
'info').toLowerCase();
|
|
15
|
+
const raw = (apiClientConfig().logLevel || 'info').toLowerCase();
|
|
20
16
|
if (raw === 'silent' || raw === 'none')
|
|
21
17
|
return SEVERITY.error;
|
|
22
18
|
if (raw === 'debug' || raw === 'trace')
|
|
@@ -28,13 +24,20 @@ function parseThreshold() {
|
|
|
28
24
|
return SEVERITY.info;
|
|
29
25
|
}
|
|
30
26
|
let cachedThreshold = null;
|
|
27
|
+
let cachedVersion = -1;
|
|
31
28
|
function threshold() {
|
|
32
|
-
|
|
29
|
+
// Recompute when the host reconfigures, so a `configureApiClient` call after
|
|
30
|
+
// the first log line still takes effect.
|
|
31
|
+
const v = apiClientConfigVersion();
|
|
32
|
+
if (cachedThreshold === null || cachedVersion !== v) {
|
|
33
33
|
cachedThreshold = parseThreshold();
|
|
34
|
+
cachedVersion = v;
|
|
35
|
+
}
|
|
34
36
|
return cachedThreshold;
|
|
35
37
|
}
|
|
36
38
|
export function resetRuntimeLogLevelCache() {
|
|
37
39
|
cachedThreshold = null;
|
|
40
|
+
cachedVersion = -1;
|
|
38
41
|
}
|
|
39
42
|
function shouldEmit(level) {
|
|
40
43
|
return SEVERITY[level] >= threshold();
|
package/dist/types.d.ts
CHANGED
|
@@ -269,3 +269,155 @@ export interface MessageMetadata {
|
|
|
269
269
|
sentTimestamp?: string;
|
|
270
270
|
}
|
|
271
271
|
export type MessageHandler = (text: string, metadata: MessageMetadata) => Promise<void>;
|
|
272
|
+
/**
|
|
273
|
+
* What a delivery can be about. A closed union, not a comment: a consumer that
|
|
274
|
+
* dispatches on `kind` (the MCP read plan) is only safe if the compiler can tell
|
|
275
|
+
* it a case is missing. The task-only deliverable that was acked unread got
|
|
276
|
+
* through precisely because this was `string`.
|
|
277
|
+
*
|
|
278
|
+
* A type and not a value list, unlike the backend's `RESOURCE_KINDS` — nothing
|
|
279
|
+
* on this side validates a delivery kind at runtime (the server does that on the
|
|
280
|
+
* way in), and exhaustiveness checking is purely type-level.
|
|
281
|
+
*/
|
|
282
|
+
export type InboxDeliveryKind = 'message' | 'artifact' | 'task-state' | 'agreement' | 'quest';
|
|
283
|
+
/**
|
|
284
|
+
* One thing addressed to this agent. A reference, never content — following it
|
|
285
|
+
* (a chat read, a task read) is where this agent's grants are enforced.
|
|
286
|
+
*/
|
|
287
|
+
export interface InboxDeliveryRef {
|
|
288
|
+
kind: InboxDeliveryKind;
|
|
289
|
+
resourceId: string;
|
|
290
|
+
chatId: string | null;
|
|
291
|
+
agreementId: string | null;
|
|
292
|
+
taskId: string | null;
|
|
293
|
+
/** Who wrote it. Never this agent — you are not woken by your own writes. */
|
|
294
|
+
actorId: string | null;
|
|
295
|
+
ts: string;
|
|
296
|
+
/**
|
|
297
|
+
* ZIG-703 — lifecycle hint when the server includes one (e.g.
|
|
298
|
+
* `connection_request_fulfilled`). Absent on ordinary doorbells / older servers.
|
|
299
|
+
*/
|
|
300
|
+
reason?: string | null;
|
|
301
|
+
/** ZIG-703 — MCP connection after a fulfilled first-hop request. */
|
|
302
|
+
connectionId?: string | null;
|
|
303
|
+
/** ZIG-703 — grant minted for this agent on fulfill. */
|
|
304
|
+
grantId?: string | null;
|
|
305
|
+
}
|
|
306
|
+
/** Message/artifact deliveries folded by chat, so you can open chats directly. */
|
|
307
|
+
export interface InboxChatNews {
|
|
308
|
+
chatId: string;
|
|
309
|
+
count: number;
|
|
310
|
+
latestAt: string;
|
|
311
|
+
}
|
|
312
|
+
export interface InboxProposalRef {
|
|
313
|
+
agreementId: string;
|
|
314
|
+
title: string;
|
|
315
|
+
proposedAt: string | null;
|
|
316
|
+
/**
|
|
317
|
+
* ZIG-1087 — party ids still owing a decision, and the named responder slot.
|
|
318
|
+
* The inbox lists proposals awaiting the agent OR its human, and only the
|
|
319
|
+
* agent's own slot is one it can submit; these say which is which.
|
|
320
|
+
*
|
|
321
|
+
* Optional because a backend deployed before ZIG-1087 omits them, and this
|
|
322
|
+
* client is installed independently of the server it talks to. Absent reads
|
|
323
|
+
* as "no slot of mine", which routes the decision to the human — the safe
|
|
324
|
+
* direction: it withholds a call, it never invents authority.
|
|
325
|
+
*/
|
|
326
|
+
pendingApprovalPartyIds?: string[];
|
|
327
|
+
proposedTo?: string | null;
|
|
328
|
+
}
|
|
329
|
+
export interface InboxConnectionRequestRef {
|
|
330
|
+
requestId: string;
|
|
331
|
+
/**
|
|
332
|
+
* Non-addressable persona reference for the requester (`psn_*`).
|
|
333
|
+
* Never use as an account id for lookup / wake / pay (ZIG-1137).
|
|
334
|
+
*/
|
|
335
|
+
requesterRef: string;
|
|
336
|
+
/** ZIG-1039 — human-readable name for consent cards. */
|
|
337
|
+
requesterDisplayName?: string | null;
|
|
338
|
+
/** ZIG-1039 — org label for consent cards. */
|
|
339
|
+
requesterOrgName?: string | null;
|
|
340
|
+
message: string | null;
|
|
341
|
+
requestedAt: string | null;
|
|
342
|
+
/** ZIG-1087 — see InboxProposalRef; a link request uses the same gate. */
|
|
343
|
+
pendingApprovalPartyIds?: string[];
|
|
344
|
+
proposedTo?: string | null;
|
|
345
|
+
}
|
|
346
|
+
/** Pull-only MCP: prompt the human when proposals need a decision (ZIG-482 / ZIG-481). */
|
|
347
|
+
export interface InboxHumanAttention {
|
|
348
|
+
required: true;
|
|
349
|
+
reason: 'proposals_awaiting_me' | 'connection_requests_awaiting_me' | 'multiple';
|
|
350
|
+
proposalCount: number;
|
|
351
|
+
truncatedProposals: number;
|
|
352
|
+
connectionRequestCount: number;
|
|
353
|
+
truncatedConnectionRequests: number;
|
|
354
|
+
promptUser: string;
|
|
355
|
+
}
|
|
356
|
+
/**
|
|
357
|
+
* An open task assigned to this agent (ZIG-973). References only — read the
|
|
358
|
+
* task for its description/plan/inputs.
|
|
359
|
+
*
|
|
360
|
+
* Tasks ride their own channel because assignment IS their delivery: before
|
|
361
|
+
* this, a task wake was a synthetic chat row, so work under a chat-less
|
|
362
|
+
* agreement (or self-assigned) reached nobody.
|
|
363
|
+
*/
|
|
364
|
+
export interface InboxTaskRef {
|
|
365
|
+
taskId: string;
|
|
366
|
+
agreementId: string | null;
|
|
367
|
+
title: string;
|
|
368
|
+
state: string;
|
|
369
|
+
updatedAt: string | null;
|
|
370
|
+
}
|
|
371
|
+
/**
|
|
372
|
+
* A marketplace quest doorbell (ZIG-1185). Own channel so the host can
|
|
373
|
+
* exact-match triage with zero LLM tokens before any wake.
|
|
374
|
+
*/
|
|
375
|
+
export interface InboxQuestRef {
|
|
376
|
+
agreementId: string;
|
|
377
|
+
/** Exact-match string from the publisher — compare to the agent's tags. */
|
|
378
|
+
match: string;
|
|
379
|
+
title: string;
|
|
380
|
+
ts: string;
|
|
381
|
+
}
|
|
382
|
+
export interface InboxEnvelope {
|
|
383
|
+
asOf: string;
|
|
384
|
+
/**
|
|
385
|
+
* Unacked deliveries addressed to this agent, newest first. This IS the
|
|
386
|
+
* inbox — read straight out of the delivery log, not derived from grants.
|
|
387
|
+
*/
|
|
388
|
+
deliveries: InboxDeliveryRef[];
|
|
389
|
+
/** True when there was more than one envelope's worth; the rest stay unacked. */
|
|
390
|
+
deliveriesCapped: boolean;
|
|
391
|
+
/** The chat-bearing deliveries above, folded by chat. */
|
|
392
|
+
chats: InboxChatNews[];
|
|
393
|
+
/**
|
|
394
|
+
* Pass to `ack()` after acting. Null when there is nothing to ack. Ack after
|
|
395
|
+
* acting, not after reading: a crash in between redelivers.
|
|
396
|
+
*/
|
|
397
|
+
ackTo: string | null;
|
|
398
|
+
/** Open tasks assigned to this agent — the work channel (ZIG-973). */
|
|
399
|
+
tasksAwaitingMe: InboxTaskRef[];
|
|
400
|
+
truncatedTasks: number;
|
|
401
|
+
/** Unacked quest deliveries (ZIG-1185) — triaged before any LLM wake. */
|
|
402
|
+
questsAwaitingMe?: InboxQuestRef[];
|
|
403
|
+
truncatedQuests?: number;
|
|
404
|
+
proposalsAwaitingMe: InboxProposalRef[];
|
|
405
|
+
truncatedProposals: number;
|
|
406
|
+
connectionRequestsAwaitingMe: InboxConnectionRequestRef[];
|
|
407
|
+
truncatedConnectionRequests: number;
|
|
408
|
+
humanAttention?: InboxHumanAttention;
|
|
409
|
+
}
|
|
410
|
+
export interface InboxAckResult {
|
|
411
|
+
/** Where the watermark now sits. Monotonic — a rewind is a no-op, not an error. */
|
|
412
|
+
ackedUpTo: string | null;
|
|
413
|
+
}
|
|
414
|
+
/**
|
|
415
|
+
* Long-poll option shared by the inbox reads. The server holds the request up
|
|
416
|
+
* to this many seconds (server-clamped, ~25s ceiling) and returns as soon as
|
|
417
|
+
* anything actionable exists. Omit for an immediate snapshot — the response
|
|
418
|
+
* shape is identical either way, so `wait` only changes how long an EMPTY
|
|
419
|
+
* answer is withheld.
|
|
420
|
+
*/
|
|
421
|
+
export interface InboxReadOptions {
|
|
422
|
+
waitSeconds?: number;
|
|
423
|
+
}
|
package/dist/utils/urlUtils.js
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
|
+
import { apiClientConfig } from '../config.js';
|
|
1
2
|
export function getBackendUrl() {
|
|
2
|
-
const url =
|
|
3
|
+
const url = apiClientConfig().httpUrl || 'https://api.ziggsai.com';
|
|
3
4
|
return url.startsWith('http') ? url : `https://${url}`;
|
|
4
5
|
}
|
|
5
6
|
export function getWebSocketUrl() {
|
|
6
|
-
const wsUrl =
|
|
7
|
+
const wsUrl = apiClientConfig().wsUrl || 'wss://api.ziggsai.com';
|
|
7
8
|
return wsUrl.startsWith('ws') ? wsUrl : `wss://${wsUrl}`;
|
|
8
9
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ziggs-ai/api-client",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.3",
|
|
4
4
|
"description": "HTTP and WebSocket client for the Ziggs backend API",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -32,7 +32,6 @@
|
|
|
32
32
|
"test:watch": "node --import tsx/esm --test --watch test/*.test.ts"
|
|
33
33
|
},
|
|
34
34
|
"dependencies": {
|
|
35
|
-
"dotenv": "^17.2.3",
|
|
36
35
|
"socket.io-client": "^4.7.0"
|
|
37
36
|
},
|
|
38
37
|
"keywords": [
|