@botiverse/raft-sdk 1.0.0-alpha.4 → 1.0.0-alpha.5
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/README.md +7 -4
- package/dist/cjs/index.cjs +105 -13
- package/dist/esm/index.js +105 -13
- package/dist/index.d.ts +17 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -147,10 +147,13 @@ if (!signal.ok) return new Response(signal.message, { status: 401 });
|
|
|
147
147
|
- `raft.messages.search / resolve / react / unreact` — find a specific
|
|
148
148
|
message (previews neutralise `@handles` and `#channels`), resolve one id to
|
|
149
149
|
its canonical form and reply target, add or remove a reaction.
|
|
150
|
-
- `raft.attachments.upload({ target, filename, bytes })` —
|
|
151
|
-
upload
|
|
152
|
-
|
|
153
|
-
|
|
150
|
+
- `raft.attachments.upload({ target, filename, bytes })` — multipart below the
|
|
151
|
+
Server's direct-upload threshold, an upload session (presigned PUT with
|
|
152
|
+
`fetch`, then complete) at or above it, exactly as the CLI chooses. The
|
|
153
|
+
target is resolved to a channel id first. `download`, `comments`.
|
|
154
|
+
- `raft.actions.prepare({ target, action })` — post an action card
|
|
155
|
+
(`channel:create`, `channel:add_member`, `agent:create`, integration cards)
|
|
156
|
+
for a human to confirm; the human who clicks it executes it.
|
|
154
157
|
- `raft.mentions.pending / execute / deliveries` — @mentions you sent that
|
|
155
158
|
reached nobody, the notify/add recovery, and per-target delivery outcomes.
|
|
156
159
|
- `raft.manual.get / search` — the Raft Manual for Agents; both need a short
|
package/dist/cjs/index.cjs
CHANGED
|
@@ -12929,10 +12929,9 @@ function inferAttachmentMimeType(filename, bytes, explicit) {
|
|
|
12929
12929
|
return sniffMimeType(bytes) ?? FILENAME_MIME_MAP[ext] ?? "application/octet-stream";
|
|
12930
12930
|
}
|
|
12931
12931
|
/**
|
|
12932
|
-
*
|
|
12933
|
-
* direct-upload threshold
|
|
12934
|
-
*
|
|
12935
|
-
* next action rather than attempting silently.
|
|
12932
|
+
* Upload bytes into a conversation, choosing the path the CLI would: multipart
|
|
12933
|
+
* `POST /upload` below the Server's direct-upload threshold, an upload session
|
|
12934
|
+
* (create → PUT to a presigned URL → complete) at or above it.
|
|
12936
12935
|
*/
|
|
12937
12936
|
async function uploadAttachment(client, transport, request) {
|
|
12938
12937
|
if (!request.target?.trim() || !request.filename?.trim()) return failureOutcome(opError("INVALID_REQUEST", { message: "A target and a filename are required to upload." }));
|
|
@@ -12942,15 +12941,11 @@ async function uploadAttachment(client, transport, request) {
|
|
|
12942
12941
|
const maxBytes = capability.ok ? capability.data.maxBytes : AGENT_ATTACHMENT_UPLOAD_FALLBACK_MAX_BYTES;
|
|
12943
12942
|
const threshold = capability.ok && capability.data.directUploadEnabled ? capability.data.directUploadThresholdBytes : null;
|
|
12944
12943
|
if (request.bytes.byteLength > maxBytes) return failureOutcome(opError("INVALID_REQUEST", { message: `Attachment is ${request.bytes.byteLength} bytes; the Server's maximum is ${maxBytes}.` }));
|
|
12945
|
-
if (threshold !== null && request.bytes.byteLength >= threshold) return failureOutcome(opError("UNAVAILABLE", {
|
|
12946
|
-
message: `Files of ${threshold} bytes or more use the direct-upload session routes, which this operation does not drive yet.`,
|
|
12947
|
-
nextAction: "Use routes.attachments.createUploadSession / completeUploadSession, or upload a smaller file.",
|
|
12948
|
-
retryable: false
|
|
12949
|
-
}));
|
|
12950
12944
|
const resolved = await client.channels.resolve({ target: request.target });
|
|
12951
12945
|
if (!resolved.ok) return failureFromClientResult(resolved);
|
|
12952
12946
|
const channelId = resolved.data.channelId;
|
|
12953
12947
|
const mimeType = inferAttachmentMimeType(request.filename, request.bytes, request.mimeType);
|
|
12948
|
+
if (threshold !== null && request.bytes.byteLength >= threshold) return uploadThroughSession(client, transport, request, channelId, mimeType);
|
|
12954
12949
|
const copy = new Uint8Array(request.bytes.byteLength);
|
|
12955
12950
|
copy.set(request.bytes);
|
|
12956
12951
|
const form = new FormData();
|
|
@@ -12990,20 +12985,22 @@ async function uploadAttachment(client, transport, request) {
|
|
|
12990
12985
|
}
|
|
12991
12986
|
const parsed = agentApiContract.attachmentUpload.response.body.safeParse(body);
|
|
12992
12987
|
if (!parsed.success) return failureOutcome(opError("INVALID_RESPONSE"));
|
|
12993
|
-
|
|
12988
|
+
return uploadedOutcome(request.target, parsed.data, mimeType);
|
|
12989
|
+
}
|
|
12990
|
+
function uploadedOutcome(target, data, mimeType) {
|
|
12994
12991
|
return {
|
|
12995
12992
|
ok: true,
|
|
12996
12993
|
state: "uploaded",
|
|
12997
12994
|
data: {
|
|
12998
12995
|
...data,
|
|
12999
|
-
target
|
|
12996
|
+
target,
|
|
13000
12997
|
mimeType: data.mimeType ?? mimeType
|
|
13001
12998
|
},
|
|
13002
12999
|
next: {
|
|
13003
13000
|
kind: "send_with_attachment",
|
|
13004
|
-
command: `raft message send --target "${
|
|
13001
|
+
command: `raft message send --target "${target}" --attachment-id ${data.id}`,
|
|
13005
13002
|
args: {
|
|
13006
|
-
target
|
|
13003
|
+
target,
|
|
13007
13004
|
attachmentIds: [data.id]
|
|
13008
13005
|
},
|
|
13009
13006
|
why: "The upload alone posts nothing; send a message that links the attachment id."
|
|
@@ -13011,6 +13008,69 @@ async function uploadAttachment(client, transport, request) {
|
|
|
13011
13008
|
text: formatAgentAttachmentUploaded(data)
|
|
13012
13009
|
};
|
|
13013
13010
|
}
|
|
13011
|
+
const wait = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
13012
|
+
/**
|
|
13013
|
+
* Direct upload for files at or above the Server's threshold, mirroring the
|
|
13014
|
+
* CLI: create a session, PUT the bytes to the presigned URL (fetch; one retry
|
|
13015
|
+
* when the object store may have committed), then complete, which the Server
|
|
13016
|
+
* verifies against the object store. A PUT that definitely failed cancels the
|
|
13017
|
+
* session; a PUT whose outcome is unknown leaves it for completion to verify.
|
|
13018
|
+
*/
|
|
13019
|
+
async function uploadThroughSession(client, transport, request, channelId, mimeType) {
|
|
13020
|
+
const created = await client.attachments.createUploadSession({
|
|
13021
|
+
channelId,
|
|
13022
|
+
filename: request.filename,
|
|
13023
|
+
mimeType,
|
|
13024
|
+
sizeBytes: request.bytes.byteLength,
|
|
13025
|
+
clientRequestId: crypto.randomUUID()
|
|
13026
|
+
});
|
|
13027
|
+
if (!created.ok) return failureFromClientResult(created);
|
|
13028
|
+
const { uploadId, upload } = created.data;
|
|
13029
|
+
const body = new Uint8Array(request.bytes.byteLength);
|
|
13030
|
+
body.set(request.bytes);
|
|
13031
|
+
let definitelyFailed = null;
|
|
13032
|
+
for (let attempt = 0; attempt < 2; attempt += 1) {
|
|
13033
|
+
let response;
|
|
13034
|
+
try {
|
|
13035
|
+
response = await transport.fetch(upload.url, {
|
|
13036
|
+
method: upload.method ?? "PUT",
|
|
13037
|
+
headers: { ...upload.headers },
|
|
13038
|
+
body: body.buffer,
|
|
13039
|
+
redirect: "error"
|
|
13040
|
+
});
|
|
13041
|
+
} catch {
|
|
13042
|
+
if (attempt === 0) continue;
|
|
13043
|
+
break;
|
|
13044
|
+
}
|
|
13045
|
+
if (response.ok || response.status === 412) {
|
|
13046
|
+
definitelyFailed = null;
|
|
13047
|
+
break;
|
|
13048
|
+
}
|
|
13049
|
+
const mayExist = response.status === 408 || response.status === 429 || response.status >= 500;
|
|
13050
|
+
if (mayExist && attempt === 0) continue;
|
|
13051
|
+
if (!mayExist) definitelyFailed = response.status;
|
|
13052
|
+
break;
|
|
13053
|
+
}
|
|
13054
|
+
if (definitelyFailed !== null) {
|
|
13055
|
+
await client.attachments.cancelUploadSession({ uploadId }).catch(() => void 0);
|
|
13056
|
+
return failureOutcome(opError("HTTP_ERROR", {
|
|
13057
|
+
message: `Direct object upload failed with HTTP ${definitelyFailed}; the upload session was cancelled.`,
|
|
13058
|
+
status: definitelyFailed,
|
|
13059
|
+
nextAction: "Retry the upload; nothing was attached."
|
|
13060
|
+
}));
|
|
13061
|
+
}
|
|
13062
|
+
for (let attempt = 0; attempt < 3; attempt += 1) {
|
|
13063
|
+
const completed = await client.attachments.completeUploadSession({ uploadId });
|
|
13064
|
+
if (completed.ok) {
|
|
13065
|
+
const attachment = completed.data.attachment;
|
|
13066
|
+
return uploadedOutcome(request.target, attachment, mimeType);
|
|
13067
|
+
}
|
|
13068
|
+
const code = completed.error.kind === "http" ? completed.error.errorCode : null;
|
|
13069
|
+
if (!(code === "UPLOAD_OBJECT_NOT_FOUND" || code === "UPLOAD_VERIFICATION_IN_PROGRESS") || attempt === 2) return failureFromClientResult(completed);
|
|
13070
|
+
await wait(250 * (attempt + 1));
|
|
13071
|
+
}
|
|
13072
|
+
return failureOutcome(opError("UNAVAILABLE", { message: "Direct upload completion ended without a terminal response." }));
|
|
13073
|
+
}
|
|
13014
13074
|
async function downloadAttachment(client, request) {
|
|
13015
13075
|
if (!request.attachmentId?.trim()) return failureOutcome(opError("INVALID_REQUEST", { message: "An attachment id is required." }));
|
|
13016
13076
|
const result = await client.attachments.download({ attachmentId: request.attachmentId });
|
|
@@ -13772,6 +13832,37 @@ var RaftStateSession = class {
|
|
|
13772
13832
|
}
|
|
13773
13833
|
};
|
|
13774
13834
|
//#endregion
|
|
13835
|
+
//#region ../shared/src/agentOps/actions.ts
|
|
13836
|
+
/** Text is the CLI's `raft action prepare` output. */
|
|
13837
|
+
function formatAgentActionCardPosted(target, messageId) {
|
|
13838
|
+
const shortId = messageId ? messageId.slice(0, 8) : null;
|
|
13839
|
+
return shortId ? `Action card posted to ${target} as message ${messageId} (short ${shortId}). The human can click the action verb to commit.\n` : `Action card posted to ${target}.\n`;
|
|
13840
|
+
}
|
|
13841
|
+
async function prepareActionCard(client, request) {
|
|
13842
|
+
if (!request?.target?.trim() || !request.action) return failureOutcome(opError("INVALID_REQUEST", { message: "A target and an action are required to prepare a card." }));
|
|
13843
|
+
const result = await client.actions.prepare(request);
|
|
13844
|
+
if (!result.ok) return failureFromClientResult(result);
|
|
13845
|
+
const card = {
|
|
13846
|
+
target: request.target,
|
|
13847
|
+
messageId: result.data.messageId
|
|
13848
|
+
};
|
|
13849
|
+
return {
|
|
13850
|
+
ok: true,
|
|
13851
|
+
state: "prepared",
|
|
13852
|
+
data: card,
|
|
13853
|
+
next: {
|
|
13854
|
+
kind: "await_confirmation",
|
|
13855
|
+
command: `raft message read --target "${request.target}" --around ${card.messageId.slice(0, 8)}`,
|
|
13856
|
+
args: {
|
|
13857
|
+
target: request.target,
|
|
13858
|
+
messageId: card.messageId
|
|
13859
|
+
},
|
|
13860
|
+
why: "A human must click the card to commit it; its outcome arrives in your inbox."
|
|
13861
|
+
},
|
|
13862
|
+
text: formatAgentActionCardPosted(request.target, card.messageId)
|
|
13863
|
+
};
|
|
13864
|
+
}
|
|
13865
|
+
//#endregion
|
|
13775
13866
|
//#region src/raft.ts
|
|
13776
13867
|
function createRaft(options) {
|
|
13777
13868
|
const serverUrl = requireServerUrl(options.serverUrl);
|
|
@@ -13904,6 +13995,7 @@ function createRaft(options) {
|
|
|
13904
13995
|
execute: (request) => executeMentionAction(routes, request),
|
|
13905
13996
|
deliveries: (request) => senderMentionDeliveries(routes, request)
|
|
13906
13997
|
},
|
|
13998
|
+
actions: { prepare: (request) => prepareActionCard(routes, request) },
|
|
13907
13999
|
manual: {
|
|
13908
14000
|
get: (request) => getManualTopic(routes, request),
|
|
13909
14001
|
search: (request) => searchManual(routes, request)
|
package/dist/esm/index.js
CHANGED
|
@@ -12928,10 +12928,9 @@ function inferAttachmentMimeType(filename, bytes, explicit) {
|
|
|
12928
12928
|
return sniffMimeType(bytes) ?? FILENAME_MIME_MAP[ext] ?? "application/octet-stream";
|
|
12929
12929
|
}
|
|
12930
12930
|
/**
|
|
12931
|
-
*
|
|
12932
|
-
* direct-upload threshold
|
|
12933
|
-
*
|
|
12934
|
-
* next action rather than attempting silently.
|
|
12931
|
+
* Upload bytes into a conversation, choosing the path the CLI would: multipart
|
|
12932
|
+
* `POST /upload` below the Server's direct-upload threshold, an upload session
|
|
12933
|
+
* (create → PUT to a presigned URL → complete) at or above it.
|
|
12935
12934
|
*/
|
|
12936
12935
|
async function uploadAttachment(client, transport, request) {
|
|
12937
12936
|
if (!request.target?.trim() || !request.filename?.trim()) return failureOutcome(opError("INVALID_REQUEST", { message: "A target and a filename are required to upload." }));
|
|
@@ -12941,15 +12940,11 @@ async function uploadAttachment(client, transport, request) {
|
|
|
12941
12940
|
const maxBytes = capability.ok ? capability.data.maxBytes : AGENT_ATTACHMENT_UPLOAD_FALLBACK_MAX_BYTES;
|
|
12942
12941
|
const threshold = capability.ok && capability.data.directUploadEnabled ? capability.data.directUploadThresholdBytes : null;
|
|
12943
12942
|
if (request.bytes.byteLength > maxBytes) return failureOutcome(opError("INVALID_REQUEST", { message: `Attachment is ${request.bytes.byteLength} bytes; the Server's maximum is ${maxBytes}.` }));
|
|
12944
|
-
if (threshold !== null && request.bytes.byteLength >= threshold) return failureOutcome(opError("UNAVAILABLE", {
|
|
12945
|
-
message: `Files of ${threshold} bytes or more use the direct-upload session routes, which this operation does not drive yet.`,
|
|
12946
|
-
nextAction: "Use routes.attachments.createUploadSession / completeUploadSession, or upload a smaller file.",
|
|
12947
|
-
retryable: false
|
|
12948
|
-
}));
|
|
12949
12943
|
const resolved = await client.channels.resolve({ target: request.target });
|
|
12950
12944
|
if (!resolved.ok) return failureFromClientResult(resolved);
|
|
12951
12945
|
const channelId = resolved.data.channelId;
|
|
12952
12946
|
const mimeType = inferAttachmentMimeType(request.filename, request.bytes, request.mimeType);
|
|
12947
|
+
if (threshold !== null && request.bytes.byteLength >= threshold) return uploadThroughSession(client, transport, request, channelId, mimeType);
|
|
12953
12948
|
const copy = new Uint8Array(request.bytes.byteLength);
|
|
12954
12949
|
copy.set(request.bytes);
|
|
12955
12950
|
const form = new FormData();
|
|
@@ -12989,20 +12984,22 @@ async function uploadAttachment(client, transport, request) {
|
|
|
12989
12984
|
}
|
|
12990
12985
|
const parsed = agentApiContract.attachmentUpload.response.body.safeParse(body);
|
|
12991
12986
|
if (!parsed.success) return failureOutcome(opError("INVALID_RESPONSE"));
|
|
12992
|
-
|
|
12987
|
+
return uploadedOutcome(request.target, parsed.data, mimeType);
|
|
12988
|
+
}
|
|
12989
|
+
function uploadedOutcome(target, data, mimeType) {
|
|
12993
12990
|
return {
|
|
12994
12991
|
ok: true,
|
|
12995
12992
|
state: "uploaded",
|
|
12996
12993
|
data: {
|
|
12997
12994
|
...data,
|
|
12998
|
-
target
|
|
12995
|
+
target,
|
|
12999
12996
|
mimeType: data.mimeType ?? mimeType
|
|
13000
12997
|
},
|
|
13001
12998
|
next: {
|
|
13002
12999
|
kind: "send_with_attachment",
|
|
13003
|
-
command: `raft message send --target "${
|
|
13000
|
+
command: `raft message send --target "${target}" --attachment-id ${data.id}`,
|
|
13004
13001
|
args: {
|
|
13005
|
-
target
|
|
13002
|
+
target,
|
|
13006
13003
|
attachmentIds: [data.id]
|
|
13007
13004
|
},
|
|
13008
13005
|
why: "The upload alone posts nothing; send a message that links the attachment id."
|
|
@@ -13010,6 +13007,69 @@ async function uploadAttachment(client, transport, request) {
|
|
|
13010
13007
|
text: formatAgentAttachmentUploaded(data)
|
|
13011
13008
|
};
|
|
13012
13009
|
}
|
|
13010
|
+
const wait = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
13011
|
+
/**
|
|
13012
|
+
* Direct upload for files at or above the Server's threshold, mirroring the
|
|
13013
|
+
* CLI: create a session, PUT the bytes to the presigned URL (fetch; one retry
|
|
13014
|
+
* when the object store may have committed), then complete, which the Server
|
|
13015
|
+
* verifies against the object store. A PUT that definitely failed cancels the
|
|
13016
|
+
* session; a PUT whose outcome is unknown leaves it for completion to verify.
|
|
13017
|
+
*/
|
|
13018
|
+
async function uploadThroughSession(client, transport, request, channelId, mimeType) {
|
|
13019
|
+
const created = await client.attachments.createUploadSession({
|
|
13020
|
+
channelId,
|
|
13021
|
+
filename: request.filename,
|
|
13022
|
+
mimeType,
|
|
13023
|
+
sizeBytes: request.bytes.byteLength,
|
|
13024
|
+
clientRequestId: crypto.randomUUID()
|
|
13025
|
+
});
|
|
13026
|
+
if (!created.ok) return failureFromClientResult(created);
|
|
13027
|
+
const { uploadId, upload } = created.data;
|
|
13028
|
+
const body = new Uint8Array(request.bytes.byteLength);
|
|
13029
|
+
body.set(request.bytes);
|
|
13030
|
+
let definitelyFailed = null;
|
|
13031
|
+
for (let attempt = 0; attempt < 2; attempt += 1) {
|
|
13032
|
+
let response;
|
|
13033
|
+
try {
|
|
13034
|
+
response = await transport.fetch(upload.url, {
|
|
13035
|
+
method: upload.method ?? "PUT",
|
|
13036
|
+
headers: { ...upload.headers },
|
|
13037
|
+
body: body.buffer,
|
|
13038
|
+
redirect: "error"
|
|
13039
|
+
});
|
|
13040
|
+
} catch {
|
|
13041
|
+
if (attempt === 0) continue;
|
|
13042
|
+
break;
|
|
13043
|
+
}
|
|
13044
|
+
if (response.ok || response.status === 412) {
|
|
13045
|
+
definitelyFailed = null;
|
|
13046
|
+
break;
|
|
13047
|
+
}
|
|
13048
|
+
const mayExist = response.status === 408 || response.status === 429 || response.status >= 500;
|
|
13049
|
+
if (mayExist && attempt === 0) continue;
|
|
13050
|
+
if (!mayExist) definitelyFailed = response.status;
|
|
13051
|
+
break;
|
|
13052
|
+
}
|
|
13053
|
+
if (definitelyFailed !== null) {
|
|
13054
|
+
await client.attachments.cancelUploadSession({ uploadId }).catch(() => void 0);
|
|
13055
|
+
return failureOutcome(opError("HTTP_ERROR", {
|
|
13056
|
+
message: `Direct object upload failed with HTTP ${definitelyFailed}; the upload session was cancelled.`,
|
|
13057
|
+
status: definitelyFailed,
|
|
13058
|
+
nextAction: "Retry the upload; nothing was attached."
|
|
13059
|
+
}));
|
|
13060
|
+
}
|
|
13061
|
+
for (let attempt = 0; attempt < 3; attempt += 1) {
|
|
13062
|
+
const completed = await client.attachments.completeUploadSession({ uploadId });
|
|
13063
|
+
if (completed.ok) {
|
|
13064
|
+
const attachment = completed.data.attachment;
|
|
13065
|
+
return uploadedOutcome(request.target, attachment, mimeType);
|
|
13066
|
+
}
|
|
13067
|
+
const code = completed.error.kind === "http" ? completed.error.errorCode : null;
|
|
13068
|
+
if (!(code === "UPLOAD_OBJECT_NOT_FOUND" || code === "UPLOAD_VERIFICATION_IN_PROGRESS") || attempt === 2) return failureFromClientResult(completed);
|
|
13069
|
+
await wait(250 * (attempt + 1));
|
|
13070
|
+
}
|
|
13071
|
+
return failureOutcome(opError("UNAVAILABLE", { message: "Direct upload completion ended without a terminal response." }));
|
|
13072
|
+
}
|
|
13013
13073
|
async function downloadAttachment(client, request) {
|
|
13014
13074
|
if (!request.attachmentId?.trim()) return failureOutcome(opError("INVALID_REQUEST", { message: "An attachment id is required." }));
|
|
13015
13075
|
const result = await client.attachments.download({ attachmentId: request.attachmentId });
|
|
@@ -13771,6 +13831,37 @@ var RaftStateSession = class {
|
|
|
13771
13831
|
}
|
|
13772
13832
|
};
|
|
13773
13833
|
//#endregion
|
|
13834
|
+
//#region ../shared/src/agentOps/actions.ts
|
|
13835
|
+
/** Text is the CLI's `raft action prepare` output. */
|
|
13836
|
+
function formatAgentActionCardPosted(target, messageId) {
|
|
13837
|
+
const shortId = messageId ? messageId.slice(0, 8) : null;
|
|
13838
|
+
return shortId ? `Action card posted to ${target} as message ${messageId} (short ${shortId}). The human can click the action verb to commit.\n` : `Action card posted to ${target}.\n`;
|
|
13839
|
+
}
|
|
13840
|
+
async function prepareActionCard(client, request) {
|
|
13841
|
+
if (!request?.target?.trim() || !request.action) return failureOutcome(opError("INVALID_REQUEST", { message: "A target and an action are required to prepare a card." }));
|
|
13842
|
+
const result = await client.actions.prepare(request);
|
|
13843
|
+
if (!result.ok) return failureFromClientResult(result);
|
|
13844
|
+
const card = {
|
|
13845
|
+
target: request.target,
|
|
13846
|
+
messageId: result.data.messageId
|
|
13847
|
+
};
|
|
13848
|
+
return {
|
|
13849
|
+
ok: true,
|
|
13850
|
+
state: "prepared",
|
|
13851
|
+
data: card,
|
|
13852
|
+
next: {
|
|
13853
|
+
kind: "await_confirmation",
|
|
13854
|
+
command: `raft message read --target "${request.target}" --around ${card.messageId.slice(0, 8)}`,
|
|
13855
|
+
args: {
|
|
13856
|
+
target: request.target,
|
|
13857
|
+
messageId: card.messageId
|
|
13858
|
+
},
|
|
13859
|
+
why: "A human must click the card to commit it; its outcome arrives in your inbox."
|
|
13860
|
+
},
|
|
13861
|
+
text: formatAgentActionCardPosted(request.target, card.messageId)
|
|
13862
|
+
};
|
|
13863
|
+
}
|
|
13864
|
+
//#endregion
|
|
13774
13865
|
//#region src/raft.ts
|
|
13775
13866
|
function createRaft(options) {
|
|
13776
13867
|
const serverUrl = requireServerUrl(options.serverUrl);
|
|
@@ -13903,6 +13994,7 @@ function createRaft(options) {
|
|
|
13903
13994
|
execute: (request) => executeMentionAction(routes, request),
|
|
13904
13995
|
deliveries: (request) => senderMentionDeliveries(routes, request)
|
|
13905
13996
|
},
|
|
13997
|
+
actions: { prepare: (request) => prepareActionCard(routes, request) },
|
|
13906
13998
|
manual: {
|
|
13907
13999
|
get: (request) => getManualTopic(routes, request),
|
|
13908
14000
|
search: (request) => searchManual(routes, request)
|
package/dist/index.d.ts
CHANGED
|
@@ -980,6 +980,14 @@ export declare function parseRaftState(value: unknown): RaftState | null;
|
|
|
980
980
|
/** Hex SHA-256 identifying one logical message (WebCrypto; Workers-safe). */
|
|
981
981
|
export declare function hashRaftSendContent(target: string, content: string, attachmentIds?: readonly string[]): Promise<string>;
|
|
982
982
|
//#endregion
|
|
983
|
+
//#region ../shared/src/agentOps/actions.d.ts
|
|
984
|
+
type PrepareActionCardRequest = AgentApiActionPrepareBody;
|
|
985
|
+
interface RaftPreparedCard {
|
|
986
|
+
target: string;
|
|
987
|
+
/** The card message; a human commits it by clicking its action verb. */
|
|
988
|
+
messageId: string;
|
|
989
|
+
}
|
|
990
|
+
//#endregion
|
|
983
991
|
//#region ../shared/src/agentApiRawClient.d.ts
|
|
984
992
|
type AgentApiRawClientErrorReason = "missing_route" | "missing_path_param" | "request_contract_mismatch" | "transport_error" | "http_error" | "empty_response" | "response_contract_mismatch";
|
|
985
993
|
interface AgentApiRawTransportRequest<K extends AgentApiRouteKey = AgentApiRouteKey> {
|
|
@@ -9451,6 +9459,14 @@ interface Raft {
|
|
|
9451
9459
|
messageId: string;
|
|
9452
9460
|
}): Promise<RaftOutcome<AgentApiSenderMentionDeliveriesResponse, "deliveries" | "empty">>;
|
|
9453
9461
|
};
|
|
9462
|
+
actions: {
|
|
9463
|
+
/**
|
|
9464
|
+
* Post an action card for a human to confirm (channel:create,
|
|
9465
|
+
* channel:add_member, agent:create, and the integration card types). The
|
|
9466
|
+
* human who clicks it executes it as themselves.
|
|
9467
|
+
*/
|
|
9468
|
+
prepare(request: PrepareActionCardRequest): Promise<RaftOutcome<RaftPreparedCard, "prepared">>;
|
|
9469
|
+
};
|
|
9454
9470
|
manual: {
|
|
9455
9471
|
/** Fetch a Manual topic; `intent` and `reason` are required and must never carry prompts, credentials, or message payloads. */
|
|
9456
9472
|
get(request: {
|
|
@@ -9543,4 +9559,4 @@ interface Raft {
|
|
|
9543
9559
|
}
|
|
9544
9560
|
export declare function createRaft(options: CreateRaftOptions): Raft;
|
|
9545
9561
|
//#endregion
|
|
9546
|
-
export type { AmendTaskOutcome, AmendTaskRequest, AssignTaskRequest, BootstrapRaftCredentialOptions, CheckInboxOutcome, CheckInboxRequest, ClaimTasksOutcome, ClaimTasksRequest, CreateRaftClientFromStoreOptions, CreateRaftClientOptions, CreateRaftOptions, CreateRaftRoutesOptions, CreateTasksRequest, DrainInboxRequest, ExecuteMentionActionRequest, ListInboxRequest, ListTasksRequest, ManualContext, Raft, RaftAckMode, RaftActionPrepareRequest, RaftActionPrepared, RaftApiError, RaftApiResult, RaftAppConfig, RaftAppConfigPatch, RaftAttachmentBytes, RaftAttachmentUploaded, RaftAvatarUpload, RaftChannelJoinClient, RaftChannelJoinClientResult, RaftChannelJoinError, RaftChannelJoinFailure, RaftChannelJoinOperation, RaftChannelJoinRequest, RaftChannelJoinResult, RaftChannelJoinSuccess, RaftChannelJoinTransportError, RaftChannelMuteState, RaftChannelRef, RaftClaimHeld, RaftClaimHeldLike, RaftClaimResult, RaftClaimRow, RaftClaimRowState, RaftClient, RaftClientError, RaftClientFailure, RaftClientResult, RaftClientSuccess, RaftClientThrottleOptions, RaftClientTransportRequest, RaftContextAgent, RaftContextData, RaftContextError, RaftContextResult, RaftContextServer, RaftCredentialErrorCode, RaftCredentialIdentity, RaftCredentialStore, RaftEvent, RaftEventAttachment, RaftEventExternalMessage, RaftEventsReceiveData, RaftEventsReceiveError, RaftEventsReceiveRequest, RaftEventsReceiveResult, RaftFailure, RaftHeld, RaftHeldBase, RaftHistoryPage, RaftInboxBatch, RaftInboxCommitResult, RaftInboxConversation, RaftInboxDrainSummary, RaftInboxListing, RaftInboxNotice, RaftManageClient, RaftMessage, RaftMessageAttachment, RaftMessageTask, RaftNextStep, RaftNoticeFlag, RaftNoticeTarget, RaftOpError, RaftOpErrorCode, RaftOutcome, RaftPendingMentions, RaftProfile, RaftProfileUpdate, RaftRouteAnnotations, RaftRouteInfo, RaftRouteKey, RaftRouteMeta, RaftRouteResult, RaftRouteRetryPolicy, RaftRoutes, RaftSdkConfigurationErrorCode, RaftSearchPage, RaftSendContinuation, RaftSenderType, RaftSent, RaftServerInfo, RaftServerProfile, RaftServerUpdate, RaftState, RaftStateContinuation, RaftStateSaveErrorHandler, RaftStateStore, RaftTaskBoard, RaftTaskStatus, RaftTasksCreated, RaftWebhookStatus, ReactRequest, ReadHistoryRequest, SearchMessagesRequest, SeenAttestation, SeenFrontierSnapshot, SendMessageOutcome, SendMessageRequest, ServerInfoRequest, ServerInfoSection, StoredRaftCredential, TaskRef, UpdateTaskStatusOutcome, UpdateTaskStatusRequest, UploadAttachmentRequest, VerifyNoticeInput, VerifyNoticeRejection, VerifyNoticeResult };
|
|
9562
|
+
export type { AmendTaskOutcome, AmendTaskRequest, AssignTaskRequest, BootstrapRaftCredentialOptions, CheckInboxOutcome, CheckInboxRequest, ClaimTasksOutcome, ClaimTasksRequest, CreateRaftClientFromStoreOptions, CreateRaftClientOptions, CreateRaftOptions, CreateRaftRoutesOptions, CreateTasksRequest, DrainInboxRequest, ExecuteMentionActionRequest, ListInboxRequest, ListTasksRequest, ManualContext, PrepareActionCardRequest, Raft, RaftAckMode, RaftActionPrepareRequest, RaftActionPrepared, RaftApiError, RaftApiResult, RaftAppConfig, RaftAppConfigPatch, RaftAttachmentBytes, RaftAttachmentUploaded, RaftAvatarUpload, RaftChannelJoinClient, RaftChannelJoinClientResult, RaftChannelJoinError, RaftChannelJoinFailure, RaftChannelJoinOperation, RaftChannelJoinRequest, RaftChannelJoinResult, RaftChannelJoinSuccess, RaftChannelJoinTransportError, RaftChannelMuteState, RaftChannelRef, RaftClaimHeld, RaftClaimHeldLike, RaftClaimResult, RaftClaimRow, RaftClaimRowState, RaftClient, RaftClientError, RaftClientFailure, RaftClientResult, RaftClientSuccess, RaftClientThrottleOptions, RaftClientTransportRequest, RaftContextAgent, RaftContextData, RaftContextError, RaftContextResult, RaftContextServer, RaftCredentialErrorCode, RaftCredentialIdentity, RaftCredentialStore, RaftEvent, RaftEventAttachment, RaftEventExternalMessage, RaftEventsReceiveData, RaftEventsReceiveError, RaftEventsReceiveRequest, RaftEventsReceiveResult, RaftFailure, RaftHeld, RaftHeldBase, RaftHistoryPage, RaftInboxBatch, RaftInboxCommitResult, RaftInboxConversation, RaftInboxDrainSummary, RaftInboxListing, RaftInboxNotice, RaftManageClient, RaftMessage, RaftMessageAttachment, RaftMessageTask, RaftNextStep, RaftNoticeFlag, RaftNoticeTarget, RaftOpError, RaftOpErrorCode, RaftOutcome, RaftPendingMentions, RaftPreparedCard, RaftProfile, RaftProfileUpdate, RaftRouteAnnotations, RaftRouteInfo, RaftRouteKey, RaftRouteMeta, RaftRouteResult, RaftRouteRetryPolicy, RaftRoutes, RaftSdkConfigurationErrorCode, RaftSearchPage, RaftSendContinuation, RaftSenderType, RaftSent, RaftServerInfo, RaftServerProfile, RaftServerUpdate, RaftState, RaftStateContinuation, RaftStateSaveErrorHandler, RaftStateStore, RaftTaskBoard, RaftTaskStatus, RaftTasksCreated, RaftWebhookStatus, ReactRequest, ReadHistoryRequest, SearchMessagesRequest, SeenAttestation, SeenFrontierSnapshot, SendMessageOutcome, SendMessageRequest, ServerInfoRequest, ServerInfoSection, StoredRaftCredential, TaskRef, UpdateTaskStatusOutcome, UpdateTaskStatusRequest, UploadAttachmentRequest, VerifyNoticeInput, VerifyNoticeRejection, VerifyNoticeResult };
|