@ziggs-ai/api-client 0.13.0 → 0.14.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/capabilities/agreements.js +33 -3
- package/dist/capabilities/artifacts.d.ts +4 -3
- package/dist/capabilities/artifacts.js +39 -16
- package/dist/capabilities/index.d.ts +1 -0
- package/dist/capabilities/index.js +1 -0
- package/dist/capabilities/introductions.d.ts +6 -0
- package/dist/capabilities/introductions.js +172 -0
- package/dist/capabilities/links.d.ts +1 -0
- package/dist/capabilities/links.js +1 -1
- package/dist/http/ArtifactsClient.d.ts +7 -6
- package/dist/http/ArtifactsClient.js +7 -6
- package/dist/http/ChatClient.d.ts +13 -2
- package/dist/http/ChatClient.js +14 -4
- package/dist/http/ContextGrantsClient.js +20 -24
- package/dist/http/IntroductionsClient.d.ts +71 -0
- package/dist/http/IntroductionsClient.js +54 -0
- package/dist/http/TaskClient.d.ts +25 -0
- package/dist/http/TaskClient.js +51 -2
- package/dist/http/index.d.ts +2 -0
- package/dist/http/index.js +1 -0
- package/dist/index.d.ts +0 -1
- package/dist/index.js +0 -1
- package/dist/types.d.ts +23 -0
- package/package.json +1 -1
- package/dist/relay/provisionRelayWorkers.d.ts +0 -119
- package/dist/relay/provisionRelayWorkers.js +0 -267
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/** What became of one hello. `expired` is derived by the server, not stored. */
|
|
2
|
+
export type IntroductionStatus = 'open' | 'redeemed' | 'declined' | 'revoked' | 'expired';
|
|
3
|
+
export type IntroductionOutcome = 'link_pending' | 'already_teammates' | 'already_linked';
|
|
4
|
+
export interface IntroductionFrom {
|
|
5
|
+
orgId: string;
|
|
6
|
+
agentId: string | null;
|
|
7
|
+
agentCreatedAt?: string | null;
|
|
8
|
+
claimedLabel?: {
|
|
9
|
+
text: string;
|
|
10
|
+
selfChosen: boolean;
|
|
11
|
+
verified: boolean;
|
|
12
|
+
};
|
|
13
|
+
/**
|
|
14
|
+
* Same text as claimedLabel.text. Not identity — anyone can pick it.
|
|
15
|
+
*/
|
|
16
|
+
label: string;
|
|
17
|
+
}
|
|
18
|
+
export interface IntroductionView {
|
|
19
|
+
token: string;
|
|
20
|
+
status: IntroductionStatus;
|
|
21
|
+
outcome: IntroductionOutcome | null;
|
|
22
|
+
notice?: string;
|
|
23
|
+
from: IntroductionFrom;
|
|
24
|
+
venue: string | null;
|
|
25
|
+
venueRef: string | null;
|
|
26
|
+
note: string | null;
|
|
27
|
+
agreementId: string | null;
|
|
28
|
+
redeemedBy: {
|
|
29
|
+
agentId: string | null;
|
|
30
|
+
orgId: string | null;
|
|
31
|
+
} | null;
|
|
32
|
+
expiresAt: string;
|
|
33
|
+
/** The public page the string points at. This is what you hand over. */
|
|
34
|
+
url: string;
|
|
35
|
+
/**
|
|
36
|
+
* Returned to a redeemer only: the two ids the meeting is now worth, and what
|
|
37
|
+
* each is for. `agentId` is where messages go; `principal` is who can be a
|
|
38
|
+
* party to an agreement. Passing one where the other belongs is refused as if
|
|
39
|
+
* the agent did not exist, which is the wall this field exists to remove.
|
|
40
|
+
*/
|
|
41
|
+
counterparty?: {
|
|
42
|
+
principal: string;
|
|
43
|
+
agentId: string | null;
|
|
44
|
+
label: string;
|
|
45
|
+
nextStep: string;
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
export interface MintIntroductionInput {
|
|
49
|
+
venue?: string;
|
|
50
|
+
venueRef?: string;
|
|
51
|
+
note?: string;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Introduction tokens — the one object to exchange when you meet an
|
|
55
|
+
* agent somewhere Ziggs does not own.
|
|
56
|
+
*
|
|
57
|
+
* The token carries no authority, which is why minting one is free: it widens
|
|
58
|
+
* nobody's reach. Redeeming one stages a link proposal the two humans sign.
|
|
59
|
+
*/
|
|
60
|
+
export declare class IntroductionsClient {
|
|
61
|
+
private readonly operatorKey;
|
|
62
|
+
private readonly agentId?;
|
|
63
|
+
private readonly baseUrl;
|
|
64
|
+
constructor(operatorKey: string, agentId?: string, baseUrl?: string);
|
|
65
|
+
mint(input?: MintIntroductionInput): Promise<IntroductionView>;
|
|
66
|
+
redeem(token: string): Promise<IntroductionView>;
|
|
67
|
+
decline(token: string): Promise<IntroductionView>;
|
|
68
|
+
revoke(token: string): Promise<IntroductionView>;
|
|
69
|
+
listMine(limit?: number): Promise<IntroductionView[]>;
|
|
70
|
+
private call;
|
|
71
|
+
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { getBackendUrl } from '../utils/urlUtils.js';
|
|
2
|
+
import { throwApiError } from '../shared/apiError.js';
|
|
3
|
+
import { buildOperatorHeaders } from './operatorHeaders.js';
|
|
4
|
+
/**
|
|
5
|
+
* Introduction tokens — the one object to exchange when you meet an
|
|
6
|
+
* agent somewhere Ziggs does not own.
|
|
7
|
+
*
|
|
8
|
+
* The token carries no authority, which is why minting one is free: it widens
|
|
9
|
+
* nobody's reach. Redeeming one stages a link proposal the two humans sign.
|
|
10
|
+
*/
|
|
11
|
+
export class IntroductionsClient {
|
|
12
|
+
operatorKey;
|
|
13
|
+
agentId;
|
|
14
|
+
baseUrl;
|
|
15
|
+
constructor(operatorKey, agentId, baseUrl) {
|
|
16
|
+
if (!operatorKey) {
|
|
17
|
+
throw new Error('IntroductionsClient: operatorKey is required');
|
|
18
|
+
}
|
|
19
|
+
this.operatorKey = operatorKey;
|
|
20
|
+
this.agentId = agentId;
|
|
21
|
+
this.baseUrl = baseUrl || getBackendUrl();
|
|
22
|
+
}
|
|
23
|
+
async mint(input = {}) {
|
|
24
|
+
return this.call('POST', '/introductions', input, 'mint');
|
|
25
|
+
}
|
|
26
|
+
async redeem(token) {
|
|
27
|
+
return this.call('POST', `/introductions/${encodeURIComponent(token)}/redeem`, {}, 'redeem');
|
|
28
|
+
}
|
|
29
|
+
async decline(token) {
|
|
30
|
+
return this.call('POST', `/introductions/${encodeURIComponent(token)}/decline`, {}, 'decline');
|
|
31
|
+
}
|
|
32
|
+
async revoke(token) {
|
|
33
|
+
return this.call('DELETE', `/introductions/${encodeURIComponent(token)}`, undefined, 'revoke');
|
|
34
|
+
}
|
|
35
|
+
async listMine(limit) {
|
|
36
|
+
const query = limit != null ? `?limit=${encodeURIComponent(String(limit))}` : '';
|
|
37
|
+
return this.call('GET', `/introductions${query}`, undefined, 'listMine');
|
|
38
|
+
}
|
|
39
|
+
async call(method, path, body, label) {
|
|
40
|
+
const res = await fetch(`${this.baseUrl}${path}`, {
|
|
41
|
+
method,
|
|
42
|
+
headers: {
|
|
43
|
+
...buildOperatorHeaders(this.operatorKey, this.agentId),
|
|
44
|
+
...(body === undefined ? {} : { 'Content-Type': 'application/json' }),
|
|
45
|
+
},
|
|
46
|
+
...(body === undefined ? {} : { body: JSON.stringify(body) }),
|
|
47
|
+
});
|
|
48
|
+
const text = await res.text().catch(() => '');
|
|
49
|
+
if (!res.ok) {
|
|
50
|
+
throwApiError(res, text, `IntroductionsClient.${label} failed: ${res.status}`);
|
|
51
|
+
}
|
|
52
|
+
return JSON.parse(text);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
@@ -13,6 +13,7 @@ export interface TaskWriteConfirm {
|
|
|
13
13
|
structureChanged?: boolean;
|
|
14
14
|
stepId?: string;
|
|
15
15
|
stepStatus?: string;
|
|
16
|
+
patchedCount?: number;
|
|
16
17
|
resultRecorded?: boolean;
|
|
17
18
|
terminalState?: string;
|
|
18
19
|
[key: string]: unknown;
|
|
@@ -23,6 +24,20 @@ export interface TaskWriteConfirm {
|
|
|
23
24
|
* subcontract inputs rather than teaching those routes to keep one.
|
|
24
25
|
*/
|
|
25
26
|
export type PlanReviewTiming = 'with_proposal' | 'before_execution';
|
|
27
|
+
export interface CreateTaskGraphNodeData {
|
|
28
|
+
nodeId: string;
|
|
29
|
+
agreementId: string;
|
|
30
|
+
description: string;
|
|
31
|
+
title?: string;
|
|
32
|
+
assigneeId?: string;
|
|
33
|
+
waitsOn?: string[];
|
|
34
|
+
joinKind?: 'all' | 'any';
|
|
35
|
+
}
|
|
36
|
+
export interface CreateTaskGraphData {
|
|
37
|
+
nodes: CreateTaskGraphNodeData[];
|
|
38
|
+
inputArtifactIds?: string[];
|
|
39
|
+
review?: 'before_execution';
|
|
40
|
+
}
|
|
26
41
|
export interface CreateTaskData {
|
|
27
42
|
description: string;
|
|
28
43
|
/**
|
|
@@ -55,6 +70,8 @@ export interface CreateTaskData {
|
|
|
55
70
|
* the shape in its own control flow where nothing else can see it.
|
|
56
71
|
*/
|
|
57
72
|
waitsOn?: string[];
|
|
73
|
+
/** Atomically declare a native work graph beneath the returned root task. */
|
|
74
|
+
graph?: CreateTaskGraphData;
|
|
58
75
|
}
|
|
59
76
|
export declare function createTask(taskData: CreateTaskData, creds: Creds): Promise<Task>;
|
|
60
77
|
export declare function getTask(taskId: string, creds: Creds): Promise<Task>;
|
|
@@ -91,6 +108,13 @@ export interface PlanReplaceStep {
|
|
|
91
108
|
result?: unknown;
|
|
92
109
|
}
|
|
93
110
|
export declare function replaceTaskPlan(taskId: string, steps: PlanReplaceStep[], creds: Creds): Promise<TaskWriteConfirm>;
|
|
111
|
+
/** Named-step progress — only the listed steps change. */
|
|
112
|
+
export type PlanStepPatch = {
|
|
113
|
+
stepId: string;
|
|
114
|
+
status: 'pending' | 'in_progress' | 'completed' | 'skipped';
|
|
115
|
+
result?: unknown;
|
|
116
|
+
};
|
|
117
|
+
export declare function updateTaskPlanSteps(taskId: string, patches: PlanStepPatch[], creds: Creds): Promise<TaskWriteConfirm>;
|
|
94
118
|
export declare function updateTaskPlanStep(taskId: string, stepId: string, status: string, result: unknown, creds: Creds): Promise<TaskWriteConfirm>;
|
|
95
119
|
export declare function reportTask(taskId: string, message: string | undefined, creds: Creds): Promise<TaskWriteConfirm>;
|
|
96
120
|
export declare function setTaskSatisfaction(taskId: string, satisfaction: 'positive' | 'negative', creds: Creds): Promise<TaskWriteConfirm>;
|
|
@@ -135,6 +159,7 @@ export declare class TaskClient {
|
|
|
135
159
|
getSubtasks(parentTaskId: string): Promise<Task[]>;
|
|
136
160
|
replaceTaskPlan(taskId: string, steps: PlanReplaceStep[]): Promise<TaskWriteConfirm>;
|
|
137
161
|
updateTaskPlanStep(taskId: string, stepId: string, status: string, result?: unknown): Promise<TaskWriteConfirm>;
|
|
162
|
+
updateTaskPlanSteps(taskId: string, patches: PlanStepPatch[]): Promise<TaskWriteConfirm>;
|
|
138
163
|
reportTask(taskId: string, message?: string): Promise<TaskWriteConfirm>;
|
|
139
164
|
setTaskSatisfaction(taskId: string, satisfaction: 'positive' | 'negative'): Promise<TaskWriteConfirm>;
|
|
140
165
|
listTasks(options?: ListTasksOptions): Promise<ListTasksResult>;
|
package/dist/http/TaskClient.js
CHANGED
|
@@ -55,6 +55,7 @@ function extractWriteConfirm(data) {
|
|
|
55
55
|
: {}),
|
|
56
56
|
...(typeof d['stepId'] === 'string' ? { stepId: d['stepId'] } : {}),
|
|
57
57
|
...(typeof d['stepStatus'] === 'string' ? { stepStatus: d['stepStatus'] } : {}),
|
|
58
|
+
...(typeof d['patchedCount'] === 'number' ? { patchedCount: d['patchedCount'] } : {}),
|
|
58
59
|
...(d['resultRecorded'] === true ? { resultRecorded: true } : {}),
|
|
59
60
|
...(typeof d['terminalState'] === 'string'
|
|
60
61
|
? { terminalState: d['terminalState'] }
|
|
@@ -152,10 +153,29 @@ export async function getActiveTasksForAgent(agentId, creds) {
|
|
|
152
153
|
const data = await res.json().catch(() => null);
|
|
153
154
|
const fromAgent = Array.isArray(data?.['tasks']) ? data['tasks'] : [];
|
|
154
155
|
if (fromAgent.length > 0)
|
|
155
|
-
return fromAgent;
|
|
156
|
+
return workable(fromAgent);
|
|
156
157
|
// Fallback when /agents/:id/tasks is empty but party-agreement tasks exist.
|
|
157
158
|
return getActiveTasksForAgentViaPartyAgreements(agentId, creds);
|
|
158
159
|
}
|
|
160
|
+
/**
|
|
161
|
+
* Drop the tasks the platform created but deliberately did not deliver.
|
|
162
|
+
*
|
|
163
|
+
* `heldByDeps` is a DELIVERY condition, not a task state: a task waiting on its
|
|
164
|
+
* `waitsOn` edges is genuinely `active`, so `?state=active` returns it and the
|
|
165
|
+
* assignee's own work list hands over a task nobody woke it for. Every caller of
|
|
166
|
+
* this function is asking "what can I act on now", and for a withheld row the
|
|
167
|
+
* answer is nothing — `updateTaskState` refuses it with `dependencies_unmet`.
|
|
168
|
+
* Two of AgentHost's three callers do worse than waste a wake: the needs gate
|
|
169
|
+
* and the unmet-access sweep both FAIL the tasks they find, so a withheld node
|
|
170
|
+
* was one missing grant away from being failed before its turn came.
|
|
171
|
+
*
|
|
172
|
+
* Filtered here rather than at `/agents/:id/tasks`, which is also the route the
|
|
173
|
+
* UI lists an agent's work with — a person looking at the graph should see the
|
|
174
|
+
* withheld node sitting there waiting, which is the whole point of a join.
|
|
175
|
+
*/
|
|
176
|
+
function workable(tasks) {
|
|
177
|
+
return tasks.filter((t) => t.heldByDeps !== true);
|
|
178
|
+
}
|
|
159
179
|
async function getActiveTasksForAgentViaPartyAgreements(agentId, creds) {
|
|
160
180
|
const { listAgreements } = await import('./AgreementClient.js');
|
|
161
181
|
const agreements = await listAgreements({ status: 'active' }, creds);
|
|
@@ -175,7 +195,7 @@ async function getActiveTasksForAgentViaPartyAgreements(agentId, creds) {
|
|
|
175
195
|
return Array.isArray(data?.['tasks']) ? data['tasks'] : [];
|
|
176
196
|
}));
|
|
177
197
|
const merged = lists.flat();
|
|
178
|
-
return merged.filter((t) => !t.assigneeId || t.assigneeId === agentId);
|
|
198
|
+
return workable(merged.filter((t) => !t.assigneeId || t.assigneeId === agentId));
|
|
179
199
|
}
|
|
180
200
|
// Backend deliberately has no `/chats/:id/tasks` route — it's composable
|
|
181
201
|
// from links → per-agreement tasks. We do the composition here so callers
|
|
@@ -263,6 +283,34 @@ export async function replaceTaskPlan(taskId, steps, creds) {
|
|
|
263
283
|
throw new Error('Invalid response: task write confirm not found');
|
|
264
284
|
return confirm;
|
|
265
285
|
}
|
|
286
|
+
export async function updateTaskPlanSteps(taskId, patches, creds) {
|
|
287
|
+
if (!taskId)
|
|
288
|
+
throw new Error('updateTaskPlanSteps: taskId is required');
|
|
289
|
+
if (!patches || !Array.isArray(patches) || patches.length === 0) {
|
|
290
|
+
throw new Error('updateTaskPlanSteps: patches must name at least one step');
|
|
291
|
+
}
|
|
292
|
+
for (const patch of patches) {
|
|
293
|
+
if (!patch?.stepId)
|
|
294
|
+
throw new Error('updateTaskPlanSteps: each patch needs a stepId');
|
|
295
|
+
if (!patch?.status)
|
|
296
|
+
throw new Error('updateTaskPlanSteps: each patch needs a status');
|
|
297
|
+
}
|
|
298
|
+
assertCreds(creds, 'plan step patch');
|
|
299
|
+
const res = await fetch(`${getTaskBaseUrl()}/${taskId}/plan`, {
|
|
300
|
+
method: 'PATCH',
|
|
301
|
+
headers: buildHeaders(creds),
|
|
302
|
+
body: JSON.stringify({ patches }),
|
|
303
|
+
});
|
|
304
|
+
if (!res.ok) {
|
|
305
|
+
const responseBody = await res.text().catch(() => '');
|
|
306
|
+
throwApiError(res, responseBody, `Plan step patch failed: ${res.status} ${res.statusText}`);
|
|
307
|
+
}
|
|
308
|
+
const data = await res.json().catch(() => null);
|
|
309
|
+
const confirm = extractWriteConfirm(data);
|
|
310
|
+
if (!confirm)
|
|
311
|
+
throw new Error('Invalid response: task write confirm not found');
|
|
312
|
+
return confirm;
|
|
313
|
+
}
|
|
266
314
|
export async function updateTaskPlanStep(taskId, stepId, status, result, creds) {
|
|
267
315
|
if (!taskId)
|
|
268
316
|
throw new Error('updateTaskPlanStep: taskId is required');
|
|
@@ -406,6 +454,7 @@ export class TaskClient {
|
|
|
406
454
|
getSubtasks(parentTaskId) { return getSubtasks(parentTaskId, this.creds); }
|
|
407
455
|
replaceTaskPlan(taskId, steps) { return replaceTaskPlan(taskId, steps, this.creds); }
|
|
408
456
|
updateTaskPlanStep(taskId, stepId, status, result) { return updateTaskPlanStep(taskId, stepId, status, result, this.creds); }
|
|
457
|
+
updateTaskPlanSteps(taskId, patches) { return updateTaskPlanSteps(taskId, patches, this.creds); }
|
|
409
458
|
reportTask(taskId, message) { return reportTask(taskId, message, this.creds); }
|
|
410
459
|
setTaskSatisfaction(taskId, satisfaction) { return setTaskSatisfaction(taskId, satisfaction, this.creds); }
|
|
411
460
|
listTasks(options) { return listTasks(options ?? {}, this.creds); }
|
package/dist/http/index.d.ts
CHANGED
|
@@ -11,6 +11,8 @@ export { ContextReadClient, CONTEXT_READ_TYPES, CONTEXT_READ_VIA, VIA_KINDS, par
|
|
|
11
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
|
+
export { IntroductionsClient } from './IntroductionsClient.js';
|
|
15
|
+
export type { IntroductionView, IntroductionFrom, IntroductionStatus, IntroductionOutcome, MintIntroductionInput, } from './IntroductionsClient.js';
|
|
14
16
|
export { GrantsClient } from './GrantsClient.js';
|
|
15
17
|
export type { ListGrantsQuery, ListGrantsResult, UnreadableRail } from './GrantsClient.js';
|
|
16
18
|
export { ContextGrantsClient } from './ContextGrantsClient.js';
|
package/dist/http/index.js
CHANGED
|
@@ -9,6 +9,7 @@ export { ArtifactsClient,
|
|
|
9
9
|
artifactScopeForSession, AGREEMENT_LANE_PREFIX, ARTIFACT_INLINE_TEXT_MAX_CHARS, ARTIFACT_INLINE_TEXT_OVER_LIMIT_HINT, } from './ArtifactsClient.js';
|
|
10
10
|
export { ContextReadClient, CONTEXT_READ_TYPES, CONTEXT_READ_VIA, VIA_KINDS, parseVia, viaHint, } from './ContextReadClient.js';
|
|
11
11
|
export { ContextDiscoveryClient } from './ContextDiscoveryClient.js';
|
|
12
|
+
export { IntroductionsClient } from './IntroductionsClient.js';
|
|
12
13
|
export { GrantsClient } from './GrantsClient.js';
|
|
13
14
|
export { ContextGrantsClient } from './ContextGrantsClient.js';
|
|
14
15
|
export { grantCaveat, CONTEXT_GRANT_SCOPE_KINDS, GRANT_SCOPE_KINDS, } from './grants.js';
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
export * from './http/index.js';
|
|
2
2
|
export * from './capabilities/index.js';
|
|
3
|
-
export * from './relay/provisionRelayWorkers.js';
|
|
4
3
|
export { ConnectionManager } from './ConnectionManager.js';
|
|
5
4
|
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
5
|
export type { PrincipalPresentation } from './types.js';
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
export * from './http/index.js';
|
|
2
2
|
export * from './capabilities/index.js';
|
|
3
|
-
export * from './relay/provisionRelayWorkers.js';
|
|
4
3
|
export { ConnectionManager } from './ConnectionManager.js';
|
|
5
4
|
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
5
|
export { getBackendUrl } from './utils/urlUtils.js';
|
package/dist/types.d.ts
CHANGED
|
@@ -79,6 +79,16 @@ export interface Task {
|
|
|
79
79
|
* from "nobody has picked it up" — this one is waiting on purpose.
|
|
80
80
|
*/
|
|
81
81
|
heldByDeps?: boolean;
|
|
82
|
+
joinKind?: 'all' | 'any';
|
|
83
|
+
graph?: {
|
|
84
|
+
nodes: Array<{
|
|
85
|
+
nodeId: string;
|
|
86
|
+
taskId: string;
|
|
87
|
+
}>;
|
|
88
|
+
review?: 'before_execution';
|
|
89
|
+
} | null;
|
|
90
|
+
graphNodeId?: string | null;
|
|
91
|
+
heldByGraphReview?: boolean;
|
|
82
92
|
plan?: {
|
|
83
93
|
steps?: PlanStep[];
|
|
84
94
|
};
|
|
@@ -148,6 +158,8 @@ export interface AgreementApprovalEntry {
|
|
|
148
158
|
role?: string;
|
|
149
159
|
status?: string;
|
|
150
160
|
respondedAt?: string | null;
|
|
161
|
+
/** Why a pending slot is held (e.g. 'formation-gate', 'contact-basis'), when the server said. */
|
|
162
|
+
heldReason?: string | null;
|
|
151
163
|
}
|
|
152
164
|
export interface Agreement {
|
|
153
165
|
agreementId: string;
|
|
@@ -163,6 +175,17 @@ export interface Agreement {
|
|
|
163
175
|
money?: {
|
|
164
176
|
price?: number | null;
|
|
165
177
|
paymentStatus?: string;
|
|
178
|
+
transactionId?: string | null;
|
|
179
|
+
/**
|
|
180
|
+
* Ledger hold for this agreement, or null if paymentStatus says held but
|
|
181
|
+
* no hold row exists. Amount is cents. Never includes a wallet id.
|
|
182
|
+
*/
|
|
183
|
+
held?: {
|
|
184
|
+
amount: number;
|
|
185
|
+
currency: string;
|
|
186
|
+
state: 'held' | 'released' | 'refunded';
|
|
187
|
+
agreementId: string;
|
|
188
|
+
} | null;
|
|
166
189
|
};
|
|
167
190
|
lifecycle?: string;
|
|
168
191
|
expiresAt?: string;
|
package/package.json
CHANGED
|
@@ -1,119 +0,0 @@
|
|
|
1
|
-
import type { Agreement, Creds } from '../types.js';
|
|
2
|
-
import { claimOpenAgreement, delegateAgreement, getMyAgreements, pullOffers, type DelegateContextGrantResult, type GrantView } from '../http/index.js';
|
|
3
|
-
/** Minimal relay step shape — keep field names aligned with agents/coordinators/relayTypes.ts */
|
|
4
|
-
export interface RelayStepInput {
|
|
5
|
-
stepId: string;
|
|
6
|
-
order: number;
|
|
7
|
-
assigneeId: string;
|
|
8
|
-
description: string;
|
|
9
|
-
/** Standing offer agreementId to claim for this worker (optional). */
|
|
10
|
-
offerAgreementId?: string;
|
|
11
|
-
}
|
|
12
|
-
export interface RelayPayloadShape {
|
|
13
|
-
inputArtifactIds?: string[];
|
|
14
|
-
steps: Array<{
|
|
15
|
-
stepId: string;
|
|
16
|
-
order: number;
|
|
17
|
-
agreementId: string;
|
|
18
|
-
assigneeId: string;
|
|
19
|
-
description: string;
|
|
20
|
-
}>;
|
|
21
|
-
}
|
|
22
|
-
export type ProvisionMethod = 'existing' | 'claim' | 'delegate';
|
|
23
|
-
export type StepProvisionStatus = 'active' | 'pending_approval';
|
|
24
|
-
/**
|
|
25
|
-
* What happened to the coordinator's pass on this worker contract.
|
|
26
|
-
*
|
|
27
|
-
* - `granted` — the coordinator may create work citing this contract.
|
|
28
|
-
* - `reused` — it already held one; nothing was minted.
|
|
29
|
-
* - `pending_approval` — the pass needs a person. An agent cannot MINT a root
|
|
30
|
-
* agreement grant at all: `POST /context/grants` requires the `context:grant`
|
|
31
|
-
* operator scope, which a delegate never holds ("no re-mint or grant will
|
|
32
|
-
* satisfy this"). So an initiator agent's only route is delegating the
|
|
33
|
-
* participation grant it holds — and handing a slice to a third party in
|
|
34
|
-
* another org opens a card that owner must approve.
|
|
35
|
-
* - `deferred` — the contract itself is not active yet, so there is no
|
|
36
|
-
* participation grant to delegate from. Provision again after it activates.
|
|
37
|
-
* - `failed` — named so the caller stops rather than kicking off a run whose
|
|
38
|
-
* branches will each be refused one at a time.
|
|
39
|
-
*/
|
|
40
|
-
export type GrantProvisionStatus = 'granted' | 'reused' | 'pending_approval' | 'deferred' | 'failed';
|
|
41
|
-
export interface StepGrantProvision {
|
|
42
|
-
status: GrantProvisionStatus;
|
|
43
|
-
grantId?: string;
|
|
44
|
-
/** The approval card's agreement id, when a person has to say yes. */
|
|
45
|
-
approvalAgreementId?: string;
|
|
46
|
-
error?: string;
|
|
47
|
-
}
|
|
48
|
-
export type ProvisionedRelayStep = RelayPayloadShape['steps'][number] & {
|
|
49
|
-
provisionMethod: ProvisionMethod;
|
|
50
|
-
status: StepProvisionStatus;
|
|
51
|
-
/**
|
|
52
|
-
* The coordinator's pass on this step's contract. Handing over an agreement
|
|
53
|
-
* id is not enough: membership in work is a grant, and the coordinator is not
|
|
54
|
-
* a party to this contract, so nothing about it reaches the coordinator
|
|
55
|
-
* otherwise.
|
|
56
|
-
*/
|
|
57
|
-
grant: StepGrantProvision;
|
|
58
|
-
};
|
|
59
|
-
export interface RelayProvisionDeps {
|
|
60
|
-
getMyAgreements: typeof getMyAgreements;
|
|
61
|
-
pullOffers: typeof pullOffers;
|
|
62
|
-
claimOpenAgreement: typeof claimOpenAgreement;
|
|
63
|
-
delegateAgreement: typeof delegateAgreement;
|
|
64
|
-
/**
|
|
65
|
-
* Grants on one agreement scope. `role` picks which side: `holder` is what
|
|
66
|
-
* this initiator holds (the participation grant to delegate FROM), `issuer` is
|
|
67
|
-
* what it has already caused (so a re-provision reuses rather than re-mints).
|
|
68
|
-
*/
|
|
69
|
-
listAgreementGrants: (args: {
|
|
70
|
-
agreementId: string;
|
|
71
|
-
role: 'holder' | 'issuer';
|
|
72
|
-
}, creds: Creds) => Promise<GrantView[]>;
|
|
73
|
-
delegateAgreementGrant: (args: {
|
|
74
|
-
parentGrantId: string;
|
|
75
|
-
holderId: string;
|
|
76
|
-
agreementId: string;
|
|
77
|
-
}, creds: Creds) => Promise<DelegateContextGrantResult>;
|
|
78
|
-
}
|
|
79
|
-
export interface ProvisionRelayWorkersInput {
|
|
80
|
-
creds: Creds;
|
|
81
|
-
hireAgreementId: string;
|
|
82
|
-
/**
|
|
83
|
-
* The coordinator that will create the work. Required, because provisioning a
|
|
84
|
-
* worker FOR a coordinator is two acts and this names who the second one is
|
|
85
|
-
* for: without an `agreement`-scope grant on each worker contract, the
|
|
86
|
-
* coordinator's very first `task_create` is refused with "holds no grant on
|
|
87
|
-
* agreement …" and every branch of the run fails the same way.
|
|
88
|
-
*/
|
|
89
|
-
coordinatorId: string;
|
|
90
|
-
chatId?: string;
|
|
91
|
-
steps: RelayStepInput[];
|
|
92
|
-
inputArtifactIds?: string[];
|
|
93
|
-
}
|
|
94
|
-
export interface ProvisionRelayWorkersResult {
|
|
95
|
-
payload: RelayPayloadShape;
|
|
96
|
-
steps: ProvisionedRelayStep[];
|
|
97
|
-
/**
|
|
98
|
-
* Everything a person still has to approve before kickoff — agreement
|
|
99
|
-
* activations AND grant hand-overs, in one list. They gate the run
|
|
100
|
-
* identically, so splitting them would just make a caller check two.
|
|
101
|
-
*/
|
|
102
|
-
pendingApprovals: string[];
|
|
103
|
-
readyForKickoff: boolean;
|
|
104
|
-
}
|
|
105
|
-
type AgreementWithParent = Agreement & {
|
|
106
|
-
parentAgreementId?: string;
|
|
107
|
-
};
|
|
108
|
-
export declare function findExistingWorkerDelegation(hireAgreementId: string, assigneeId: string, agreements: AgreementWithParent[]): AgreementWithParent | null;
|
|
109
|
-
export declare function findOpenOfferForAgent(assigneeId: string, offers: Agreement[]): Agreement | null;
|
|
110
|
-
/**
|
|
111
|
-
* The default grant plumbing, built on the two clients that own these routes.
|
|
112
|
-
*
|
|
113
|
-
* A thin function seam rather than the clients themselves, so a test can drive
|
|
114
|
-
* provisioning without a backend — the same reason the agreement calls are
|
|
115
|
-
* injected.
|
|
116
|
-
*/
|
|
117
|
-
export declare function defaultRelayProvisionDeps(): RelayProvisionDeps;
|
|
118
|
-
export declare function provisionRelayWorkers(input: ProvisionRelayWorkersInput, deps?: RelayProvisionDeps): Promise<ProvisionRelayWorkersResult>;
|
|
119
|
-
export {};
|