@ziggs-ai/api-client 0.37.20 → 0.37.22
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +9 -0
- package/dist/capabilities/activeHire.d.ts +19 -0
- package/dist/capabilities/activeHire.js +31 -0
- package/dist/capabilities/discovery.js +36 -3
- package/dist/capabilities/mcpBriefs.js +3 -4
- package/dist/http/index.d.ts +1 -1
- package/dist/http/index.js +1 -1
- package/dist/http/operatorHeaders.d.ts +16 -2
- package/dist/http/operatorHeaders.js +29 -3
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,15 @@
|
|
|
2
2
|
|
|
3
3
|
## Unreleased
|
|
4
4
|
|
|
5
|
+
## 0.37.22
|
|
6
|
+
|
|
7
|
+
- A full inbox read says it takes or renews this host's lease and that waitSeconds long-polls. The read stays read-only. Acknowledgement stays on its own call.
|
|
8
|
+
|
|
9
|
+
## 0.37.21
|
|
10
|
+
|
|
11
|
+
- A room lane can name the agreement the wake works under: `laneUnderAgreement(chatId, agreementId)` builds it, and the lane header sends it as `X-Ziggs-Agreement` beside `X-Ziggs-Lane`. The backend takes it only for an agreement the agent has mail under in that room.
|
|
12
|
+
- A search row names an active hire of that agent: it says already hired and carries the agreement id and the workspace the payer bought it in. An agent with no such hire has no such field.
|
|
13
|
+
|
|
5
14
|
## 0.37.20
|
|
6
15
|
|
|
7
16
|
- Shorter parameter text on the agreement verbs and the artifact record capability. Every rule stays.
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { type Agreement } from '../types.js';
|
|
2
|
+
/** One live hire of an agent, as a search row names it. */
|
|
3
|
+
export interface ActiveHire {
|
|
4
|
+
agreementId: string;
|
|
5
|
+
/** The workspace the payer bought it in. Null when the row records none. */
|
|
6
|
+
workspace: string | null;
|
|
7
|
+
}
|
|
8
|
+
type HireRow = Agreement & {
|
|
9
|
+
payerLane?: string | null;
|
|
10
|
+
};
|
|
11
|
+
/**
|
|
12
|
+
* Active hires whose provider is this agent.
|
|
13
|
+
*
|
|
14
|
+
* A listing is not a hire: its payer is still a broadcast. A link and a
|
|
15
|
+
* membership are not hires either. `service` stays, because older hires
|
|
16
|
+
* were written as services with a named payer.
|
|
17
|
+
*/
|
|
18
|
+
export declare function activeHiresForAgent(agentId: string, agreements: readonly HireRow[]): ActiveHire[];
|
|
19
|
+
export {};
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { AGREEMENT_ENGAGEMENT_KIND, isBroadcastTarget, } from '../types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Active hires whose provider is this agent.
|
|
4
|
+
*
|
|
5
|
+
* A listing is not a hire: its payer is still a broadcast. A link and a
|
|
6
|
+
* membership are not hires either. `service` stays, because older hires
|
|
7
|
+
* were written as services with a named payer.
|
|
8
|
+
*/
|
|
9
|
+
export function activeHiresForAgent(agentId, agreements) {
|
|
10
|
+
if (!agentId)
|
|
11
|
+
return [];
|
|
12
|
+
const hires = [];
|
|
13
|
+
for (const row of agreements) {
|
|
14
|
+
if (row.status !== 'active')
|
|
15
|
+
continue;
|
|
16
|
+
if (row.engagementKind !== AGREEMENT_ENGAGEMENT_KIND.HIRE &&
|
|
17
|
+
row.engagementKind !== AGREEMENT_ENGAGEMENT_KIND.SERVICE) {
|
|
18
|
+
continue;
|
|
19
|
+
}
|
|
20
|
+
if (row.parties?.provider?.actor !== agentId)
|
|
21
|
+
continue;
|
|
22
|
+
const payer = row.parties?.payer?.principal;
|
|
23
|
+
if (typeof payer === 'string' && isBroadcastTarget(payer))
|
|
24
|
+
continue;
|
|
25
|
+
hires.push({
|
|
26
|
+
agreementId: row.agreementId,
|
|
27
|
+
workspace: row.payerLane ?? null,
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
return hires;
|
|
31
|
+
}
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import { AgentSearchClient } from '../http/AgentSearchClient.js';
|
|
2
|
+
import { getMyAgreements } from '../http/AgreementClient.js';
|
|
3
|
+
import { activeHiresForAgent } from './activeHire.js';
|
|
2
4
|
import { RESOURCE_HIDDEN_MESSAGE } from './context.js';
|
|
3
5
|
import { fullCreds } from './types.js';
|
|
4
6
|
export const agentSearchCapability = {
|
|
@@ -6,7 +8,7 @@ export const agentSearchCapability = {
|
|
|
6
8
|
names: { sdk: 'agent_search', mcp: 'ziggs_agent_search' },
|
|
7
9
|
title: 'Search for agents',
|
|
8
10
|
descriptions: {
|
|
9
|
-
sdk: 'Search for agents by capability, name, or description. Returns ranked results with relevance scores. A keyword/natural-language query searches the published store, your org\'s own agents and your own agents, and it matches your teammates by name: a teammate comes back under `people` as a person to message (chat_open with their userId), never as a list of their agents. Someone else\'s agent is reached through the person it answers for, inside your org and outside it: you message the person, which of their agents answers is theirs to decide, and their agents become known to you by turning up in rooms. A link works the same way: reach a linked person through the link itself (link_list gives their addressable peer id, then chat_open). Passing an EXACT agent id resolves that one agent when you can reach it. Each row carries `doors` — its engagement doors: doors.listingAgreementId is a live listing to CLAIM (agreement_claim — the default, one hop from here) and doors.acceptsProposals says whether a direct proposal would even be accepted (most published agents are claim-only). Use returned agentId in grant/issue tools — do not guess ids.',
|
|
11
|
+
sdk: 'Search for agents by capability, name, or description. Returns ranked results with relevance scores. A keyword/natural-language query searches the published store, your org\'s own agents and your own agents, and it matches your teammates by name: a teammate comes back under `people` as a person to message (chat_open with their userId), never as a list of their agents. Someone else\'s agent is reached through the person it answers for, inside your org and outside it: you message the person, which of their agents answers is theirs to decide, and their agents become known to you by turning up in rooms. A link works the same way: reach a linked person through the link itself (link_list gives their addressable peer id, then chat_open). Passing an EXACT agent id resolves that one agent when you can reach it. Each row carries `doors` — its engagement doors: doors.listingAgreementId is a live listing to CLAIM (agreement_claim — the default, one hop from here) and doors.acceptsProposals says whether a direct proposal would even be accepted (most published agents are claim-only). Use returned agentId in grant/issue tools — do not guess ids. When the caller already hires an agent, that row says already hired and names the agreement id and workspace.',
|
|
10
12
|
},
|
|
11
13
|
annotation: 'read-only',
|
|
12
14
|
params: {
|
|
@@ -42,7 +44,9 @@ export const agentSearchCapability = {
|
|
|
42
44
|
peopleNote: `These are teammates whose name matched. Message the person with ${chatOpen} participantId=<userId>; which of their agents answers is theirs to decide.`,
|
|
43
45
|
}
|
|
44
46
|
: {};
|
|
45
|
-
|
|
47
|
+
const hired = await hireNotes(result.agents ?? [], env);
|
|
48
|
+
const agents = (result.agents ?? []).map((agent) => withHire(agent, hired));
|
|
49
|
+
if (!agents.length) {
|
|
46
50
|
// a bare {count: 0} reads as "discovery is down" to LLM
|
|
47
51
|
// callers — say what was searched and how to recover instead.
|
|
48
52
|
return {
|
|
@@ -67,7 +71,12 @@ export const agentSearchCapability = {
|
|
|
67
71
|
`not their agents. Take their peer id from ${linkList} and open a chat with the person instead.`,
|
|
68
72
|
};
|
|
69
73
|
}
|
|
70
|
-
return {
|
|
74
|
+
return {
|
|
75
|
+
count: agents.length,
|
|
76
|
+
agents,
|
|
77
|
+
...(hired.checked ? {} : { hireCheck: 'unavailable' }),
|
|
78
|
+
...messageThem,
|
|
79
|
+
};
|
|
71
80
|
},
|
|
72
81
|
sdkOptions: { isGenericFallback: true },
|
|
73
82
|
};
|
|
@@ -106,3 +115,27 @@ export const DISCOVERY_CAPABILITIES = [
|
|
|
106
115
|
agentSearchCapability,
|
|
107
116
|
agentGetCapability,
|
|
108
117
|
];
|
|
118
|
+
function withHire(agent, hired) {
|
|
119
|
+
const hires = hired.byAgent.get(agent.agentId);
|
|
120
|
+
if (!hires?.length)
|
|
121
|
+
return agent;
|
|
122
|
+
return { ...agent, alreadyHired: 'already hired', hires };
|
|
123
|
+
}
|
|
124
|
+
/** One reachable-agreement read for the whole result. A failure is said, so a row with no hire field was checked. */
|
|
125
|
+
async function hireNotes(agents, env) {
|
|
126
|
+
const byAgent = new Map();
|
|
127
|
+
if (agents.length === 0)
|
|
128
|
+
return { checked: true, byAgent };
|
|
129
|
+
try {
|
|
130
|
+
const agreements = await getMyAgreements({}, fullCreds(env));
|
|
131
|
+
for (const agent of agents) {
|
|
132
|
+
const hires = activeHiresForAgent(agent.agentId, agreements);
|
|
133
|
+
if (hires.length)
|
|
134
|
+
byAgent.set(agent.agentId, hires);
|
|
135
|
+
}
|
|
136
|
+
return { checked: true, byAgent };
|
|
137
|
+
}
|
|
138
|
+
catch {
|
|
139
|
+
return { checked: false, byAgent };
|
|
140
|
+
}
|
|
141
|
+
}
|
|
@@ -35,8 +35,7 @@ const BRIEFS = {
|
|
|
35
35
|
returns: 'a readPlan of next calls; backlog if more is unread',
|
|
36
36
|
next: 'ziggs_inbox_claim to handle them',
|
|
37
37
|
compact: {
|
|
38
|
-
does: 'Reads your inbox: deliveries by recipient, tasks, decisions, sessionChatCard; waitSeconds
|
|
39
|
-
changes: 'takes or renews this host’s lease',
|
|
38
|
+
does: 'Reads your inbox: deliveries by recipient, tasks, decisions, sessionChatCard; waitSeconds long-polls. It takes or renews this host’s lease.',
|
|
40
39
|
next: 'ziggs_inbox_ack after handling',
|
|
41
40
|
},
|
|
42
41
|
},
|
|
@@ -59,7 +58,7 @@ const BRIEFS = {
|
|
|
59
58
|
},
|
|
60
59
|
// Agreements
|
|
61
60
|
ziggs_agreement_list: {
|
|
62
|
-
does: 'Lists agreements you
|
|
61
|
+
does: 'Lists the agreements you can reach, including hires. scope mine keeps only agreements you are a party to.',
|
|
63
62
|
},
|
|
64
63
|
ziggs_agreement_get: {
|
|
65
64
|
does: 'Reads one agreement: parties, terms, status, and approvalAction (who may decide a pending slot).',
|
|
@@ -223,7 +222,7 @@ const BRIEFS = {
|
|
|
223
222
|
},
|
|
224
223
|
// Agents, links and introductions
|
|
225
224
|
ziggs_agent_search: {
|
|
226
|
-
does: 'Finds agents in the store, your workspaces and your own;
|
|
225
|
+
does: 'Finds agents in the store, your workspaces and your own; teammates come back as people. A row you already hire says already hired and names that agreement and workspace.',
|
|
227
226
|
},
|
|
228
227
|
ziggs_agent_get: {
|
|
229
228
|
does: 'Reads one agent’s profile by exact id, with how to hire it: listingAgreementId to claim, acceptsProposals for a direct proposal.',
|
package/dist/http/index.d.ts
CHANGED
|
@@ -33,5 +33,5 @@ export { TelemetryClient } from './TelemetryClient.js';
|
|
|
33
33
|
export { InboxClient } from './InboxClient.js';
|
|
34
34
|
export { planInboxAck, planPartialInboxAck, inboxAckAllowed, inboxAckHandledIds, } from '../inboxAck.js';
|
|
35
35
|
export type { InboxAckDecision, InboxAckStep, InboxAckEnvelope, PlanInboxAckOptions, } from '../inboxAck.js';
|
|
36
|
-
export { WAKE_LANE_HEADER, laneHeader, buildOperatorHeaders, buildCredsHeaders, } from './operatorHeaders.js';
|
|
36
|
+
export { WAKE_LANE_HEADER, WAKE_AGREEMENT_HEADER, laneHeader, laneUnderAgreement, buildOperatorHeaders, buildCredsHeaders, } from './operatorHeaders.js';
|
|
37
37
|
export { backendToolPick, type ToolPickOption, type ToolPickAnswer, type PickTool } from './ToolPickClient.js';
|
package/dist/http/index.js
CHANGED
|
@@ -25,5 +25,5 @@ export { planInboxAck, planPartialInboxAck, inboxAckAllowed, inboxAckHandledIds,
|
|
|
25
25
|
// The lane header, built in one place — see operatorHeaders.ts. Exported
|
|
26
26
|
// because the MCP transports in agent-sdk and ziggs-mcp send it too, and a
|
|
27
27
|
// copy of a header nobody notices missing goes stale unseen.
|
|
28
|
-
export { WAKE_LANE_HEADER, laneHeader, buildOperatorHeaders, buildCredsHeaders, } from './operatorHeaders.js';
|
|
28
|
+
export { WAKE_LANE_HEADER, WAKE_AGREEMENT_HEADER, laneHeader, laneUnderAgreement, buildOperatorHeaders, buildCredsHeaders, } from './operatorHeaders.js';
|
|
29
29
|
export { backendToolPick } from './ToolPickClient.js';
|
|
@@ -24,8 +24,22 @@ export declare function assistantRequestHeaders(): Record<string, string>;
|
|
|
24
24
|
/** The header the backend's wake fence reads (`access/wake-fence.ts`). */
|
|
25
25
|
export declare const WAKE_LANE_HEADER = "X-Ziggs-Lane";
|
|
26
26
|
/**
|
|
27
|
-
* The
|
|
28
|
-
* for
|
|
27
|
+
* The header naming the agreement a room wake works under. The backend takes
|
|
28
|
+
* it only for an agreement the agent has mail under in that room, and reads
|
|
29
|
+
* it off that mail when it is absent.
|
|
30
|
+
*/
|
|
31
|
+
export declare const WAKE_AGREEMENT_HEADER = "X-Ziggs-Agreement";
|
|
32
|
+
/**
|
|
33
|
+
* A room lane that also names the agreement the wake works under:
|
|
34
|
+
* `<chatId>@<agreementId>`. Every client already carries the lane to
|
|
35
|
+
* {@link laneHeader}, so the agreement travels with it without a second
|
|
36
|
+
* parameter on each of them. An `agrn-` lane already is its agreement.
|
|
37
|
+
*/
|
|
38
|
+
export declare function laneUnderAgreement(laneId: string, agreementId?: string | null): string;
|
|
39
|
+
/**
|
|
40
|
+
* The lane headers, or nothing. `laneId` is a chat id, `agrn-<agreementId>`
|
|
41
|
+
* for a task with no origin chat, or a chat id with the agreement the wake
|
|
42
|
+
* works under (`<chatId>@<agreementId>`, see {@link laneUnderAgreement}).
|
|
29
43
|
*/
|
|
30
44
|
export declare function laneHeader(laneId?: string): Record<string, string>;
|
|
31
45
|
export declare function buildOperatorHeaders(operatorKey: string, agentId?: string, extra?: Record<string, string>,
|
|
@@ -37,11 +37,37 @@ export function assistantRequestHeaders() {
|
|
|
37
37
|
/** The header the backend's wake fence reads (`access/wake-fence.ts`). */
|
|
38
38
|
export const WAKE_LANE_HEADER = 'X-Ziggs-Lane';
|
|
39
39
|
/**
|
|
40
|
-
* The
|
|
41
|
-
* for
|
|
40
|
+
* The header naming the agreement a room wake works under. The backend takes
|
|
41
|
+
* it only for an agreement the agent has mail under in that room, and reads
|
|
42
|
+
* it off that mail when it is absent.
|
|
43
|
+
*/
|
|
44
|
+
export const WAKE_AGREEMENT_HEADER = 'X-Ziggs-Agreement';
|
|
45
|
+
/**
|
|
46
|
+
* A room lane that also names the agreement the wake works under:
|
|
47
|
+
* `<chatId>@<agreementId>`. Every client already carries the lane to
|
|
48
|
+
* {@link laneHeader}, so the agreement travels with it without a second
|
|
49
|
+
* parameter on each of them. An `agrn-` lane already is its agreement.
|
|
50
|
+
*/
|
|
51
|
+
export function laneUnderAgreement(laneId, agreementId) {
|
|
52
|
+
if (!agreementId || laneId.startsWith('agrn-') || laneId.includes('@'))
|
|
53
|
+
return laneId;
|
|
54
|
+
return `${laneId}@${agreementId}`;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* The lane headers, or nothing. `laneId` is a chat id, `agrn-<agreementId>`
|
|
58
|
+
* for a task with no origin chat, or a chat id with the agreement the wake
|
|
59
|
+
* works under (`<chatId>@<agreementId>`, see {@link laneUnderAgreement}).
|
|
42
60
|
*/
|
|
43
61
|
export function laneHeader(laneId) {
|
|
44
|
-
|
|
62
|
+
if (!laneId)
|
|
63
|
+
return {};
|
|
64
|
+
const at = laneId.indexOf('@');
|
|
65
|
+
if (at <= 0)
|
|
66
|
+
return { [WAKE_LANE_HEADER]: laneId };
|
|
67
|
+
return {
|
|
68
|
+
[WAKE_LANE_HEADER]: laneId.slice(0, at),
|
|
69
|
+
[WAKE_AGREEMENT_HEADER]: laneId.slice(at + 1),
|
|
70
|
+
};
|
|
45
71
|
}
|
|
46
72
|
export function buildOperatorHeaders(operatorKey, agentId, extra,
|
|
47
73
|
/**
|