@ziggs-ai/agent-sdk 0.38.16 → 0.39.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +11 -2
- package/README.md +37 -0
- package/dist/Agent.d.ts +16 -0
- package/dist/Agent.js +74 -4
- package/dist/brain/ClaudeBrain.d.ts +7 -1
- package/dist/brain/ClaudeBrain.js +24 -1
- package/dist/brain/ZiggsBrain.d.ts +9 -0
- package/dist/brain/toolManagerToSdkMcp.js +1 -0
- package/dist/checkout/box/server.d.ts +1 -0
- package/dist/checkout/box/server.js +581 -0
- package/dist/checkout/boxClient.d.ts +86 -0
- package/dist/checkout/boxClient.js +320 -0
- package/dist/checkout/index.d.ts +10 -0
- package/dist/checkout/index.js +12 -0
- package/dist/checkout/intake.d.ts +15 -0
- package/dist/checkout/intake.js +65 -0
- package/dist/checkout/open.d.ts +49 -0
- package/dist/checkout/open.js +190 -0
- package/dist/checkout/tools.d.ts +24 -0
- package/dist/checkout/tools.js +65 -0
- package/dist/checkout/types.d.ts +88 -0
- package/dist/checkout/types.js +12 -0
- package/dist/index.d.ts +3 -1
- package/dist/index.js +2 -0
- package/dist/platform/ZiggsEffectHandler.js +2 -0
- package/dist/tools/needs.d.ts +13 -6
- package/dist/tools/needs.js +18 -1
- package/dist/tools/toolCreds.d.ts +5 -1
- package/dist/tools/toolCreds.js +7 -1
- package/dist/types.d.ts +2 -0
- package/package.json +2 -2
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { type ToolDefinition } from '../tools/defineTool.js';
|
|
2
|
+
import type { CheckoutBoxClient } from './boxClient.js';
|
|
3
|
+
import type { CheckoutTarget } from './types.js';
|
|
4
|
+
/**
|
|
5
|
+
* What one wake holds once its checkout is open: the box, the repository it
|
|
6
|
+
* cloned, the branch its change lands on. Put on the tool context by the host
|
|
7
|
+
* for the wake, taken off it when the box is destroyed.
|
|
8
|
+
*/
|
|
9
|
+
export interface CheckoutSession {
|
|
10
|
+
client: CheckoutBoxClient;
|
|
11
|
+
target: CheckoutTarget;
|
|
12
|
+
/** The base branch actually checked out (the task's, or the default branch). */
|
|
13
|
+
baseBranch: string;
|
|
14
|
+
/** `agent/<task id>`: the only branch the way out pushes to. */
|
|
15
|
+
branch: string;
|
|
16
|
+
taskId: string;
|
|
17
|
+
/** The box's kind, for the pull request body and the cost line. */
|
|
18
|
+
boxKind: string;
|
|
19
|
+
}
|
|
20
|
+
export declare const checkoutReadTool: ToolDefinition;
|
|
21
|
+
export declare const checkoutWriteTool: ToolDefinition;
|
|
22
|
+
export declare const checkoutRunTool: ToolDefinition;
|
|
23
|
+
export declare const checkoutPushTool: ToolDefinition;
|
|
24
|
+
export declare const CHECKOUT_TOOLS: ToolDefinition[];
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { defineTool } from '../tools/defineTool.js';
|
|
2
|
+
function sessionOf(ctx, tool) {
|
|
3
|
+
const session = ctx['checkout'];
|
|
4
|
+
if (!session?.client) {
|
|
5
|
+
throw new Error(`${tool}: no checkout is open on this wake. A checkout opens when a task assigned to you names a repository (owner/name); this wake carries none.`);
|
|
6
|
+
}
|
|
7
|
+
return session;
|
|
8
|
+
}
|
|
9
|
+
const CHECKOUT_LOCATION = 'Paths are relative to the root of the checkout, which is the repository the task named, cloned at its base branch.';
|
|
10
|
+
export const checkoutReadTool = defineTool('checkout_read', {
|
|
11
|
+
path: { type: 'string', required: true, description: 'File to read, relative to the checkout root.' },
|
|
12
|
+
}, async (args, ctx) => {
|
|
13
|
+
const s = sessionOf(ctx, 'checkout_read');
|
|
14
|
+
return s.client.read(String(args.path));
|
|
15
|
+
}, { description: `Read one file from the checkout. ${CHECKOUT_LOCATION} Large files come back truncated with truncated=true; read a narrower file or use checkout_run with sed to read a range.` });
|
|
16
|
+
export const checkoutWriteTool = defineTool('checkout_write', {
|
|
17
|
+
path: { type: 'string', required: true, description: 'File to write, relative to the checkout root. Folders are created as needed.' },
|
|
18
|
+
content: { type: 'string', required: true, description: 'The complete new content of the file.' },
|
|
19
|
+
}, async (args, ctx) => {
|
|
20
|
+
const s = sessionOf(ctx, 'checkout_write');
|
|
21
|
+
return s.client.write(String(args.path), String(args.content));
|
|
22
|
+
}, { description: `Write one whole file in the checkout, creating or replacing it. ${CHECKOUT_LOCATION} Write complete files, never placeholders.` });
|
|
23
|
+
export const checkoutRunTool = defineTool('checkout_run', {
|
|
24
|
+
command: { type: 'string', required: true, description: 'A shell command, run from the checkout root inside the box (e.g. "npm ci", "npm test", "grep -rn Foo src", "git status").' },
|
|
25
|
+
timeoutSeconds: { type: 'number', description: 'Give up after this many seconds (default 600, max 1800).' },
|
|
26
|
+
}, async (args, ctx) => {
|
|
27
|
+
const s = sessionOf(ctx, 'checkout_run');
|
|
28
|
+
return s.client.run(String(args.command), args.timeoutSeconds != null ? Number(args.timeoutSeconds) : undefined);
|
|
29
|
+
}, { description: `Run a shell command in the checkout and get its exit code, stdout and stderr (tails, capped). Use it to search the code, install dependencies, and run the build or tests the repository defines before you push. ${CHECKOUT_LOCATION} The box has no credentials and no network into Ziggs; package registries are reachable.` });
|
|
30
|
+
export const checkoutPushTool = defineTool('checkout_push', {
|
|
31
|
+
message: { type: 'string', required: true, description: 'One-line commit message saying what changed.' },
|
|
32
|
+
}, async (args, ctx) => {
|
|
33
|
+
const s = sessionOf(ctx, 'checkout_push');
|
|
34
|
+
const result = await s.client.push(String(args.message));
|
|
35
|
+
const agreementId = ctx['serviceAgreementId'] ??
|
|
36
|
+
ctx['wakeAgreementId'] ??
|
|
37
|
+
ctx['onBehalfOfAgreementId'] ??
|
|
38
|
+
null;
|
|
39
|
+
const ran = result.ran.length
|
|
40
|
+
? result.ran.map((r) => `\`${r.command}\` (exit ${r.exitCode ?? 'killed'})`).join(', ')
|
|
41
|
+
: 'nothing';
|
|
42
|
+
return {
|
|
43
|
+
...result,
|
|
44
|
+
baseBranch: s.baseBranch,
|
|
45
|
+
repository: s.target.repository,
|
|
46
|
+
pullRequest: {
|
|
47
|
+
head: result.branch,
|
|
48
|
+
base: s.baseBranch,
|
|
49
|
+
draft: true,
|
|
50
|
+
/** Paste these lines into the pull request body, verbatim. */
|
|
51
|
+
bodyLines: [
|
|
52
|
+
`Opened by a Ziggs agent${agreementId ? ` under hire ${agreementId}` : ''}, task ${s.taskId}.`,
|
|
53
|
+
`Ran in the checkout (${s.boxKind} box): ${ran}.`,
|
|
54
|
+
],
|
|
55
|
+
},
|
|
56
|
+
};
|
|
57
|
+
}, {
|
|
58
|
+
description: 'Commit every change in the checkout as one commit and push it to the task\'s branch agent/<task id>. Never the base branch. Returns the branch, the commit, the files changed, what was run, and the lines to put in the pull request body. Call it once, after the build or tests you ran pass or you have decided to say they did not; then open the draft pull request with your GitHub tool.',
|
|
59
|
+
});
|
|
60
|
+
export const CHECKOUT_TOOLS = [
|
|
61
|
+
checkoutReadTool,
|
|
62
|
+
checkoutWriteTool,
|
|
63
|
+
checkoutRunTool,
|
|
64
|
+
checkoutPushTool,
|
|
65
|
+
];
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The checkout need, host side.
|
|
3
|
+
*
|
|
4
|
+
* An agent declares `{ checkout: 'git' }`; whoever hosts it provides a box. A
|
|
5
|
+
* box is a throwaway isolated unit (its own container) that holds a clone of
|
|
6
|
+
* the task's repository and nothing of the host's: no host environment, no
|
|
7
|
+
* credentials, no network into the host's services. The host talks to it over
|
|
8
|
+
* one narrow channel (read a file, write a file, run a command, push the
|
|
9
|
+
* branch) and the box's git traffic comes back over that same channel, so the
|
|
10
|
+
* box never holds a credential at all.
|
|
11
|
+
*/
|
|
12
|
+
/** Where the host finds a box it started. */
|
|
13
|
+
export interface CheckoutBoxEndpoint {
|
|
14
|
+
/** Base URL of the box's channel, e.g. `http://10.0.11.4:7777`. */
|
|
15
|
+
url: string;
|
|
16
|
+
/** Per-box bearer the host minted and passed into the box at start. */
|
|
17
|
+
secret: string;
|
|
18
|
+
}
|
|
19
|
+
export interface CheckoutBoxSpec {
|
|
20
|
+
/** Per-box channel secret, minted by the SDK; the provider passes it in as `BOX_SECRET`. */
|
|
21
|
+
secret: string;
|
|
22
|
+
/** Hard time cap for the box, in seconds; the box exits when it is reached. */
|
|
23
|
+
ttlSeconds: number;
|
|
24
|
+
/** For logs and task tags; never a credential. */
|
|
25
|
+
label: {
|
|
26
|
+
agentId: string;
|
|
27
|
+
taskId: string;
|
|
28
|
+
repository: string;
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
export interface CheckoutBox {
|
|
32
|
+
endpoint: CheckoutBoxEndpoint;
|
|
33
|
+
/** What kind of unit this is, for the cost line (`fargate`, `sandbox`, ...). */
|
|
34
|
+
kind: string;
|
|
35
|
+
/** The box's size, when the provider knows it, for the cost line. */
|
|
36
|
+
resources?: {
|
|
37
|
+
vcpu?: number;
|
|
38
|
+
memoryMb?: number;
|
|
39
|
+
};
|
|
40
|
+
/** Destroy the box. Idempotent; never throws. */
|
|
41
|
+
stop(): Promise<void>;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Whoever hosts the agent implements this: the fleet starts a Fargate task,
|
|
45
|
+
* a lab starts a confined local process, a person's own runner could hand out
|
|
46
|
+
* a container of its own. The SDK never knows which.
|
|
47
|
+
*/
|
|
48
|
+
/** Host-owned private storage, keyed by agent, hire lane, task, repository and base. */
|
|
49
|
+
export interface CheckoutCheckpointStore {
|
|
50
|
+
load(key: string): Promise<Uint8Array | null>;
|
|
51
|
+
save(key: string, data: Uint8Array): Promise<void>;
|
|
52
|
+
}
|
|
53
|
+
export interface CheckoutProvider {
|
|
54
|
+
/** Optional. Without storage, later wakes resume only the pushed task branch. */
|
|
55
|
+
checkpoints?: CheckoutCheckpointStore;
|
|
56
|
+
start(spec: CheckoutBoxSpec): Promise<CheckoutBox>;
|
|
57
|
+
}
|
|
58
|
+
/** What a task has to name for a checkout to exist. */
|
|
59
|
+
export interface CheckoutTarget {
|
|
60
|
+
/** `owner/name` on GitHub. */
|
|
61
|
+
repository: string;
|
|
62
|
+
owner: string;
|
|
63
|
+
name: string;
|
|
64
|
+
/** Named by the task, or null to use the repository's default branch. */
|
|
65
|
+
baseBranch: string | null;
|
|
66
|
+
}
|
|
67
|
+
/** How a command ran in the box. */
|
|
68
|
+
export interface CheckoutRunResult {
|
|
69
|
+
checkpointWarning?: string;
|
|
70
|
+
command: string;
|
|
71
|
+
exitCode: number | null;
|
|
72
|
+
stdout: string;
|
|
73
|
+
stderr: string;
|
|
74
|
+
timedOut: boolean;
|
|
75
|
+
durationMs: number;
|
|
76
|
+
}
|
|
77
|
+
export interface CheckoutPushResult {
|
|
78
|
+
checkpointWarning?: string;
|
|
79
|
+
branch: string;
|
|
80
|
+
commit: string | null;
|
|
81
|
+
filesChanged: string[];
|
|
82
|
+
pushed: boolean;
|
|
83
|
+
/** Every command the brain ran in this box, with its exit code, for the pull request body. */
|
|
84
|
+
ran: Array<{
|
|
85
|
+
command: string;
|
|
86
|
+
exitCode: number | null;
|
|
87
|
+
}>;
|
|
88
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The checkout need, host side.
|
|
3
|
+
*
|
|
4
|
+
* An agent declares `{ checkout: 'git' }`; whoever hosts it provides a box. A
|
|
5
|
+
* box is a throwaway isolated unit (its own container) that holds a clone of
|
|
6
|
+
* the task's repository and nothing of the host's: no host environment, no
|
|
7
|
+
* credentials, no network into the host's services. The host talks to it over
|
|
8
|
+
* one narrow channel (read a file, write a file, run a command, push the
|
|
9
|
+
* branch) and the box's git traffic comes back over that same channel, so the
|
|
10
|
+
* box never holds a credential at all.
|
|
11
|
+
*/
|
|
12
|
+
export {};
|
package/dist/index.d.ts
CHANGED
|
@@ -60,7 +60,9 @@ export { recordReport } from './tools/recordReport.js';
|
|
|
60
60
|
export { credsFromToolContext, laneFromToolContext } from './tools/toolCreds.js';
|
|
61
61
|
export type { RecordReportInput, RecordReportResult, TaskReport } from './tools/recordReport.js';
|
|
62
62
|
export { MCP_PROVIDER, describeNeed, normalizeNeeds, toolsForNeed, toolsForNeeds, unmetNeeds, unmetNeedsMessage, } from './tools/needs.js';
|
|
63
|
-
export type { AgentNeed, ConnectionNeed } from './tools/needs.js';
|
|
63
|
+
export type { AgentNeed, ConnectionNeed, CheckoutNeed } from './tools/needs.js';
|
|
64
|
+
export { isCheckoutNeed } from './tools/needs.js';
|
|
65
|
+
export { CHECKOUT_TOOLS, checkoutReadTool, checkoutWriteTool, checkoutRunTool, checkoutPushTool, CheckoutBoxClient, CheckoutBoxError, checkoutTargetFromText, checkoutTargetFromTask, checkoutBranchForTask, checkoutBoxServerPath, openCheckout, closeCheckout, doorPathFor, doorHeaders, type CheckoutProvider, type CheckoutCheckpointStore, type CheckoutBox, type CheckoutBoxSpec, type CheckoutBoxEndpoint, type CheckoutTarget, type CheckoutSession, type CheckoutRunResult, type CheckoutPushResult, type GitDoorTarget, type OpenCheckout, type OpenCheckoutDeps, } from './checkout/index.js';
|
|
64
66
|
export { OpenAIAdapter } from './adapters/OpenAIAdapter.js';
|
|
65
67
|
export { extractJSON, safeParseJSON } from './utils/jsonExtractor.js';
|
|
66
68
|
export { HistoryFormatter, historyFormatter, AgreementFormatter, agreementFormatter } from './formatters/index.js';
|
package/dist/index.js
CHANGED
|
@@ -61,6 +61,8 @@ export { credsFromToolContext, laneFromToolContext } from './tools/toolCreds.js'
|
|
|
61
61
|
// An agent declares the access it cannot work without, and the declaration
|
|
62
62
|
// produces the tools for it.
|
|
63
63
|
export { MCP_PROVIDER, describeNeed, normalizeNeeds, toolsForNeed, toolsForNeeds, unmetNeeds, unmetNeedsMessage, } from './tools/needs.js';
|
|
64
|
+
export { isCheckoutNeed } from './tools/needs.js';
|
|
65
|
+
export { CHECKOUT_TOOLS, checkoutReadTool, checkoutWriteTool, checkoutRunTool, checkoutPushTool, CheckoutBoxClient, CheckoutBoxError, checkoutTargetFromText, checkoutTargetFromTask, checkoutBranchForTask, checkoutBoxServerPath, openCheckout, closeCheckout, doorPathFor, doorHeaders, } from './checkout/index.js';
|
|
64
66
|
export { OpenAIAdapter } from './adapters/OpenAIAdapter.js';
|
|
65
67
|
export { extractJSON, safeParseJSON } from './utils/jsonExtractor.js';
|
|
66
68
|
export { HistoryFormatter, historyFormatter, AgreementFormatter, agreementFormatter } from './formatters/index.js';
|
|
@@ -169,6 +169,8 @@ export async function executeToolWithSideEffects(deps, eff, effect, roster) {
|
|
|
169
169
|
serviceAgreementId: effect.serviceAgreementId,
|
|
170
170
|
memory: effect.memory,
|
|
171
171
|
writeKeys: effect.writeKeys,
|
|
172
|
+
// The wake's checkout, when the host opened one.
|
|
173
|
+
...(effect.checkout ? { checkout: effect.checkout } : {}),
|
|
172
174
|
// `wake_at` reads this off the tool context.
|
|
173
175
|
wakeScheduler: deps.wakeScheduler,
|
|
174
176
|
reportUsage,
|
package/dist/tools/needs.d.ts
CHANGED
|
@@ -17,16 +17,23 @@ import { type ToolDefinition } from './defineTool.js';
|
|
|
17
17
|
* "Unknown provider: mcp" — the second wall linear-janitor hit.
|
|
18
18
|
*/
|
|
19
19
|
export declare const MCP_PROVIDER = "mcp";
|
|
20
|
-
/**
|
|
21
|
-
* One shape for now, the one we have actually hit. A second kind means a case in
|
|
22
|
-
* {@link toolsForNeed}: a need nothing derives tools from is a need nothing
|
|
23
|
-
* enforces.
|
|
24
|
-
*/
|
|
25
20
|
export interface ConnectionNeed {
|
|
26
21
|
/** Provider, e.g. 'mcp' or a named connector like 'github'. */
|
|
27
22
|
connection: string;
|
|
28
23
|
}
|
|
29
|
-
|
|
24
|
+
/**
|
|
25
|
+
* A checkout of a git repository, provided by whoever hosts the agent. The
|
|
26
|
+
* task names the repository (owner/name) and a base branch; the host clones it
|
|
27
|
+
* into a throwaway box under the hire's GitHub connection grant, the brain works
|
|
28
|
+
* in that box with file and shell tools, and the way out is a branch
|
|
29
|
+
* `agent/<task id>` for a pull request. Without the GitHub grant the task is
|
|
30
|
+
* refused by name, like a connection need.
|
|
31
|
+
*/
|
|
32
|
+
export interface CheckoutNeed {
|
|
33
|
+
checkout: 'git';
|
|
34
|
+
}
|
|
35
|
+
export type AgentNeed = ConnectionNeed | CheckoutNeed;
|
|
36
|
+
export declare function isCheckoutNeed(need: AgentNeed): need is CheckoutNeed;
|
|
30
37
|
/** Reads a manifest's `needs` field defensively — it crosses a package edge. */
|
|
31
38
|
export declare function normalizeNeeds(input: unknown): AgentNeed[];
|
|
32
39
|
/**
|
package/dist/tools/needs.js
CHANGED
|
@@ -13,12 +13,18 @@
|
|
|
13
13
|
import { toolName } from './defineTool.js';
|
|
14
14
|
import { connectionListGrantsTool, connectionProxyTool } from '../platform/tools/tier2/connectionTools.js';
|
|
15
15
|
import { MCP_CONNECTION_TOOLS } from '../platform/tools/tier2/mcpConnectionTools.js';
|
|
16
|
+
import { CHECKOUT_TOOLS } from '../checkout/tools.js';
|
|
16
17
|
/**
|
|
17
18
|
* A remote MCP server is stored as `provider: 'mcp'` and goes through the
|
|
18
19
|
* gateway. `connection_proxy` resolves a NAMED connector and refuses it with
|
|
19
20
|
* "Unknown provider: mcp" — the second wall linear-janitor hit.
|
|
20
21
|
*/
|
|
21
22
|
export const MCP_PROVIDER = 'mcp';
|
|
23
|
+
export function isCheckoutNeed(need) {
|
|
24
|
+
return need.checkout === 'git';
|
|
25
|
+
}
|
|
26
|
+
/** Providers whose connection grant can back a git checkout. */
|
|
27
|
+
const CHECKOUT_PROVIDERS = new Set(['github', MCP_PROVIDER]);
|
|
22
28
|
/** Reads a manifest's `needs` field defensively — it crosses a package edge. */
|
|
23
29
|
export function normalizeNeeds(input) {
|
|
24
30
|
if (!Array.isArray(input))
|
|
@@ -28,6 +34,11 @@ export function normalizeNeeds(input) {
|
|
|
28
34
|
const connection = raw?.connection;
|
|
29
35
|
if (typeof connection === 'string' && connection.trim()) {
|
|
30
36
|
out.push({ connection: connection.trim() });
|
|
37
|
+
continue;
|
|
38
|
+
}
|
|
39
|
+
const checkout = raw?.checkout;
|
|
40
|
+
if (typeof checkout === 'string' && checkout.trim().toLowerCase() === 'git') {
|
|
41
|
+
out.push({ checkout: 'git' });
|
|
31
42
|
}
|
|
32
43
|
}
|
|
33
44
|
return out;
|
|
@@ -38,6 +49,8 @@ export function normalizeNeeds(input) {
|
|
|
38
49
|
* an agent that held a Linear grant and had no way to notice.
|
|
39
50
|
*/
|
|
40
51
|
export function toolsForNeed(need) {
|
|
52
|
+
if (isCheckoutNeed(need))
|
|
53
|
+
return [connectionListGrantsTool, ...CHECKOUT_TOOLS];
|
|
41
54
|
return need.connection === MCP_PROVIDER
|
|
42
55
|
? [connectionListGrantsTool, ...MCP_CONNECTION_TOOLS]
|
|
43
56
|
: [connectionListGrantsTool, connectionProxyTool];
|
|
@@ -56,6 +69,8 @@ export function toolsForNeeds(needs) {
|
|
|
56
69
|
}
|
|
57
70
|
/** One line naming what is missing, for a refusal a human can act on. */
|
|
58
71
|
export function describeNeed(need) {
|
|
72
|
+
if (isCheckoutNeed(need))
|
|
73
|
+
return 'a GitHub connection (for the checkout)';
|
|
59
74
|
return need.connection === MCP_PROVIDER
|
|
60
75
|
? 'a connection to an MCP server'
|
|
61
76
|
: `a ${need.connection} connection`;
|
|
@@ -71,7 +86,9 @@ export function unmetNeeds(needs, providers) {
|
|
|
71
86
|
const held = new Set(providers
|
|
72
87
|
.map((p) => String(p ?? '').split('—')[0].trim().toLowerCase())
|
|
73
88
|
.filter(Boolean));
|
|
74
|
-
return needs.filter((n) =>
|
|
89
|
+
return needs.filter((n) => isCheckoutNeed(n)
|
|
90
|
+
? ![...CHECKOUT_PROVIDERS].some((p) => held.has(p))
|
|
91
|
+
: !held.has(n.connection.toLowerCase()));
|
|
75
92
|
}
|
|
76
93
|
/**
|
|
77
94
|
* The refusal itself. Names the missing access and who can fix it, because the
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
* remember. Omitting the lane can only narrow reach, never widen it, which is
|
|
20
20
|
* why forgetting it never fails loudly.
|
|
21
21
|
*/
|
|
22
|
-
import type
|
|
22
|
+
import { type Creds } from '@ziggs-ai/api-client';
|
|
23
23
|
/** The loose bag `defineTool` hands a handler. */
|
|
24
24
|
type ToolContext = Record<string, unknown> | undefined | null;
|
|
25
25
|
/**
|
|
@@ -27,6 +27,10 @@ type ToolContext = Record<string, unknown> | undefined | null;
|
|
|
27
27
|
* `agrn-<agreementId>` for an agreement lane. Undefined when the tool is
|
|
28
28
|
* running outside any lane (a bootstrap sweep, a test), which the fence reads
|
|
29
29
|
* as "own org only".
|
|
30
|
+
*
|
|
31
|
+
* A room wake that handles mail under an agreement (`wakeAgreementId`, taken
|
|
32
|
+
* from the delivery itself) names it too, so the backend scopes the wake to
|
|
33
|
+
* that agreement rather than inferring it from the room's mail.
|
|
30
34
|
*/
|
|
31
35
|
export declare function laneFromToolContext(ctx: ToolContext): string | undefined;
|
|
32
36
|
/**
|
package/dist/tools/toolCreds.js
CHANGED
|
@@ -19,6 +19,7 @@
|
|
|
19
19
|
* remember. Omitting the lane can only narrow reach, never widen it, which is
|
|
20
20
|
* why forgetting it never fails loudly.
|
|
21
21
|
*/
|
|
22
|
+
import { laneUnderAgreement } from '@ziggs-ai/api-client';
|
|
22
23
|
const str = (ctx, key) => {
|
|
23
24
|
const value = ctx?.[key];
|
|
24
25
|
return typeof value === 'string' && value.trim() ? value : undefined;
|
|
@@ -28,9 +29,14 @@ const str = (ctx, key) => {
|
|
|
28
29
|
* `agrn-<agreementId>` for an agreement lane. Undefined when the tool is
|
|
29
30
|
* running outside any lane (a bootstrap sweep, a test), which the fence reads
|
|
30
31
|
* as "own org only".
|
|
32
|
+
*
|
|
33
|
+
* A room wake that handles mail under an agreement (`wakeAgreementId`, taken
|
|
34
|
+
* from the delivery itself) names it too, so the backend scopes the wake to
|
|
35
|
+
* that agreement rather than inferring it from the room's mail.
|
|
31
36
|
*/
|
|
32
37
|
export function laneFromToolContext(ctx) {
|
|
33
|
-
|
|
38
|
+
const lane = str(ctx, 'chatId') ?? str(ctx, 'sessionId');
|
|
39
|
+
return lane ? laneUnderAgreement(lane, str(ctx, 'wakeAgreementId')) : undefined;
|
|
34
40
|
}
|
|
35
41
|
/**
|
|
36
42
|
* The creds a tool should act under. Throws when the context is missing what a
|
package/dist/types.d.ts
CHANGED
|
@@ -504,6 +504,8 @@ export type Effect = {
|
|
|
504
504
|
stateId?: string;
|
|
505
505
|
/** Replay-stable write keys for this wake — write-capable tools derive their idempotency key from here, never from the LLM. */
|
|
506
506
|
writeKeys?: DeliveryWriteKeys;
|
|
507
|
+
/** The checkout the host opened for this wake; the checkout_* tools read it off their context. */
|
|
508
|
+
checkout?: import('./checkout/tools.js').CheckoutSession;
|
|
507
509
|
}
|
|
508
510
|
/**
|
|
509
511
|
* `receiverId` is optional: in a room with one other participant the backend
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ziggs-ai/agent-sdk",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.39.0",
|
|
4
4
|
"description": "Agent framework SDK for building autonomous agents on the Ziggs platform",
|
|
5
5
|
"homepage": "https://ziggsai.com/docs",
|
|
6
6
|
"bugs": {
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
"@anthropic-ai/claude-agent-sdk": "^0.3.284",
|
|
31
31
|
"@anthropic-ai/sdk": "^0.110.0",
|
|
32
32
|
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
33
|
-
"@ziggs-ai/api-client": "0.37.
|
|
33
|
+
"@ziggs-ai/api-client": "0.37.21",
|
|
34
34
|
"@ziggs-ai/contracts": "^0.23.3",
|
|
35
35
|
"ajv": "^8.17.1",
|
|
36
36
|
"dotenv": "^17.2.3",
|