@botiverse/raft-sdk 1.0.0-alpha.5 → 1.0.0-alpha.6

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 CHANGED
@@ -288,12 +288,28 @@ request is sent.
288
288
 
289
289
  ### `client.routes` — every Agent API route, typed from the shared contract
290
290
 
291
- `client.routes.<resource>.<method>(params?, query?, body?)` exposes each route
291
+ `client.routes.<resource>.<method>({ params, query, body })` exposes each route
292
292
  in the Raft Agent API contract with request and response types derived from the
293
293
  same contract the Server validates. It is the SDK's code-level escape hatch and
294
- the guarantee that the SDK reaches every route the Raft CLI does; the higher-
295
- level `messages`, `events`, `channels`, `agent`, and profile helpers stay the
296
- recommended path for common work.
294
+ the guarantee that the SDK reaches every route the Raft CLI does; the
295
+ higher-level operations stay the recommended path for common work.
296
+
297
+ Every route takes **one named object** with only the parts it has. The types
298
+ are generated per route: a part the route does not have is a compile error, and
299
+ a required part (a body with required fields, a path param) is a required
300
+ property.
301
+
302
+ ```ts
303
+ await raft.routes.actions.prepare({ body: { target: "#ops", action } });
304
+ await raft.routes.messages.addReaction({ params: { msgId }, body: { emoji: "✅" } });
305
+ await raft.routes.server.info(); // no input
306
+ await raft.routes.request("actionPrepare", { body: { target: "#ops", action } }); // by route key
307
+ ```
308
+
309
+ For JavaScript callers without type checking, the same rules are enforced at
310
+ runtime: extra arguments or unknown keys are refused with
311
+ `request_contract_mismatch`, as is a missing required body, and nothing is sent.
312
+ `routes.describe(key)` shows which parts a route takes.
297
313
 
298
314
  ```ts
299
315
  const status = await raft.routes.pushWebhook.status();
@@ -7390,8 +7390,13 @@ function encodeQuery(routeKey, query) {
7390
7390
  return params;
7391
7391
  }
7392
7392
  function parseBody(routeKey, body) {
7393
- if (body === void 0) return void 0;
7394
7393
  const route = agentApiContract[routeKey];
7394
+ if (body === void 0) {
7395
+ if (!("body" in route.request)) return void 0;
7396
+ const schema = route.request.body;
7397
+ if (schema.safeParse(void 0).success || schema.safeParse({}).success) return void 0;
7398
+ return failure$3(routeKey, "request_contract_mismatch", `Agent API ${route.key} requires a request body`);
7399
+ }
7395
7400
  try {
7396
7401
  return "body" in route.request ? route.request.body.parse(body) : void 0;
7397
7402
  } catch (cause) {
@@ -7496,7 +7501,19 @@ function createAgentApiRawClient(transport, options = {}) {
7496
7501
  const routeKey = route.key;
7497
7502
  const { resource, method } = route.client;
7498
7503
  const resourceClient = client[resource] ??= {};
7499
- resourceClient[method] = (...args) => requestAgentApiRawRoute(transport, routeKey, requestOptionsFromMethodArgs(routeKey, pathPrefix, args));
7504
+ const expectedArgs = [
7505
+ "params",
7506
+ "query",
7507
+ "body"
7508
+ ].filter((part) => part in route.request).length;
7509
+ resourceClient[method] = (...args) => {
7510
+ if (args.length > expectedArgs) return Promise.resolve(failure$3(routeKey, "request_contract_mismatch", `Agent API ${route.key} takes ${expectedArgs} argument${expectedArgs === 1 ? "" : "s"} (${[
7511
+ "params",
7512
+ "query",
7513
+ "body"
7514
+ ].filter((part) => part in route.request).join(", ") || "none"}); got ${args.length}`));
7515
+ return requestAgentApiRawRoute(transport, routeKey, requestOptionsFromMethodArgs(routeKey, pathPrefix, args));
7516
+ };
7500
7517
  }
7501
7518
  return client;
7502
7519
  }
@@ -9887,7 +9904,7 @@ function clampAttempts(value) {
9887
9904
  * The split is decided per route from `AGENT_API_ROUTE_META`, never by the
9888
9905
  * caller and never by the HTTP method.
9889
9906
  */
9890
- function createRaftRoutes(options) {
9907
+ function createRaftRouteClient(options) {
9891
9908
  const base = {
9892
9909
  baseUrl: options.serverUrl,
9893
9910
  fetch: options.fetch,
@@ -9914,12 +9931,61 @@ function createRaftRoutes(options) {
9914
9931
  ...merged,
9915
9932
  request: (routeKey, requestOptions) => {
9916
9933
  return (ROUTE_INFO[routeKey].retryPolicy === "retry" ? retrying : single).request(routeKey, requestOptions);
9917
- },
9934
+ }
9935
+ };
9936
+ }
9937
+ const ROUTE_PARTS = [
9938
+ "params",
9939
+ "query",
9940
+ "body"
9941
+ ];
9942
+ function inputMismatch(routeKey, message) {
9943
+ return Promise.resolve({
9944
+ ok: false,
9945
+ routeKey,
9946
+ error: {
9947
+ kind: "validation",
9948
+ reason: "request_contract_mismatch",
9949
+ message: `Agent API ${routeKey} ${message}`
9950
+ }
9951
+ });
9952
+ }
9953
+ /**
9954
+ * The public routes layer: one named-object call shape for every route,
9955
+ * `routes.<resource>.<method>({ params, query, body })`. The types reject a
9956
+ * missing required part or a part the route does not have; for callers
9957
+ * without type checking, the same rules are enforced at runtime and nothing
9958
+ * is sent on a mismatch.
9959
+ */
9960
+ function raftRoutesFromClient(client) {
9961
+ const call = (routeKey, args) => {
9962
+ if (args.length > 1) return inputMismatch(routeKey, `takes one { params, query, body } object; got ${args.length} arguments`);
9963
+ const input = args[0];
9964
+ if (input !== void 0 && (input === null || typeof input !== "object" || Array.isArray(input))) return inputMismatch(routeKey, "takes one { params, query, body } object");
9965
+ const route = agentApiContract[routeKey];
9966
+ const declared = ROUTE_PARTS.filter((part) => part in route.request);
9967
+ const unknown = (input === void 0 ? [] : Object.keys(input)).filter((key) => !declared.includes(key));
9968
+ if (unknown.length > 0) return inputMismatch(routeKey, `has no ${unknown.join(", ")} (it takes ${declared.join(", ") || "no input"})`);
9969
+ return client.request(routeKey, input ?? {});
9970
+ };
9971
+ const methods = {};
9972
+ for (const route of Object.values(agentApiContract)) {
9973
+ const key = route.key;
9974
+ methods[route.client.resource] ??= {};
9975
+ methods[route.client.resource][route.client.method] = (...args) => call(key, args);
9976
+ }
9977
+ return {
9978
+ ...methods,
9979
+ request: (routeKey, ...rest) => call(routeKey, rest),
9918
9980
  manifestVersion: AGENT_API_MANIFEST_VERSION,
9919
9981
  describe: describeRaftRoute,
9920
9982
  list: listRaftRoutes
9921
9983
  };
9922
9984
  }
9985
+ /** Build the public routes layer directly (convenience over createRaftRouteClient + raftRoutesFromClient). */
9986
+ function createRaftRoutes(options) {
9987
+ return raftRoutesFromClient(createRaftRouteClient(options));
9988
+ }
9923
9989
  //#endregion
9924
9990
  //#region src/context.ts
9925
9991
  const projection = object({
@@ -13876,7 +13942,7 @@ function createRaft(options) {
13876
13942
  if (outcome.ok) await session.save();
13877
13943
  return outcome;
13878
13944
  };
13879
- const routes = createRaftRoutes({
13945
+ const api = createRaftRouteClient({
13880
13946
  serverUrl,
13881
13947
  fetch: options.fetch,
13882
13948
  headers: options.headers,
@@ -13884,6 +13950,7 @@ function createRaft(options) {
13884
13950
  readAttempts: options.retry?.attempts,
13885
13951
  beforeRequest: options.throttle?.beforeRequest
13886
13952
  });
13953
+ const routes = raftRoutesFromClient(api);
13887
13954
  const inboxApi = createAgentApiClient({ fetch: {
13888
13955
  baseUrl: serverUrl,
13889
13956
  fetch: (input, init) => (options.fetch ?? fetch)(input, {
@@ -13904,7 +13971,7 @@ function createRaft(options) {
13904
13971
  const sendWithState = (request) => withState(async () => {
13905
13972
  const contentHash = await hashRaftSendContent(request.target, request.content ?? "", request.attachmentIds ?? []);
13906
13973
  const pending = request.idempotencyKey ? void 0 : session.findContinuation(request.target, contentHash);
13907
- const outcome = await sendMessage(routes, pending ? {
13974
+ const outcome = await sendMessage(api, pending ? {
13908
13975
  ...request,
13909
13976
  idempotencyKey: pending.idempotencyKey
13910
13977
  } : request, frontier);
@@ -13918,13 +13985,13 @@ function createRaft(options) {
13918
13985
  return outcome;
13919
13986
  });
13920
13987
  return {
13921
- identity: { whoami: () => getRaftContext(routes) },
13988
+ identity: { whoami: () => getRaftContext(api) },
13922
13989
  wake: {
13923
13990
  verifyNotice: (input) => verifyInboxNotice(input),
13924
13991
  webhook: {
13925
- status: () => webhookStatus(routes),
13926
- register: (request) => registerWebhook(routes, request),
13927
- unregister: () => unregisterWebhook(routes)
13992
+ status: () => webhookStatus(api),
13993
+ register: (request) => registerWebhook(api, request),
13994
+ unregister: () => unregisterWebhook(api)
13928
13995
  }
13929
13996
  },
13930
13997
  inbox: {
@@ -13962,11 +14029,11 @@ function createRaft(options) {
13962
14029
  await session.save();
13963
14030
  });
13964
14031
  })(),
13965
- list: (request) => listInbox(routes, request)
14032
+ list: (request) => listInbox(api, request)
13966
14033
  },
13967
14034
  messages: {
13968
14035
  read: (request) => withState(async () => {
13969
- const outcome = await readHistory(routes, request, frontier);
14036
+ const outcome = await readHistory(api, request, frontier);
13970
14037
  if (outcome.ok) session.markDirty();
13971
14038
  return outcome;
13972
14039
  }),
@@ -13975,58 +14042,58 @@ function createRaft(options) {
13975
14042
  ...request,
13976
14043
  target: message.target
13977
14044
  }),
13978
- search: (request) => searchMessages(routes, request),
13979
- resolve: (request) => resolveMessage(routes, request),
13980
- react: (request) => reactToMessage(routes, request, "add"),
13981
- unreact: (request) => reactToMessage(routes, request, "remove")
14045
+ search: (request) => searchMessages(api, request),
14046
+ resolve: (request) => resolveMessage(api, request),
14047
+ react: (request) => reactToMessage(api, request, "add"),
14048
+ unreact: (request) => reactToMessage(api, request, "remove")
13982
14049
  },
13983
14050
  attachments: {
13984
- upload: (request) => uploadAttachment(routes, {
14051
+ upload: (request) => uploadAttachment(api, {
13985
14052
  serverUrl,
13986
14053
  fetch: options.fetch ?? fetch,
13987
14054
  headers: Object.fromEntries(new Headers(options.headers)),
13988
14055
  authorization
13989
14056
  }, request),
13990
- download: (request) => downloadAttachment(routes, request),
13991
- comments: (request) => attachmentComments(routes, request)
14057
+ download: (request) => downloadAttachment(api, request),
14058
+ comments: (request) => attachmentComments(api, request)
13992
14059
  },
13993
14060
  mentions: {
13994
- pending: (request) => pendingMentionActions(routes, request),
13995
- execute: (request) => executeMentionAction(routes, request),
13996
- deliveries: (request) => senderMentionDeliveries(routes, request)
14061
+ pending: (request) => pendingMentionActions(api, request),
14062
+ execute: (request) => executeMentionAction(api, request),
14063
+ deliveries: (request) => senderMentionDeliveries(api, request)
13997
14064
  },
13998
- actions: { prepare: (request) => prepareActionCard(routes, request) },
14065
+ actions: { prepare: (request) => prepareActionCard(api, request) },
13999
14066
  manual: {
14000
- get: (request) => getManualTopic(routes, request),
14001
- search: (request) => searchManual(routes, request)
14067
+ get: (request) => getManualTopic(api, request),
14068
+ search: (request) => searchManual(api, request)
14002
14069
  },
14003
14070
  tasks: {
14004
- claim: (request) => claimTasks(routes, request),
14005
- list: (request) => listTasks(routes, request),
14006
- create: (request) => createTasks(routes, request),
14007
- unclaim: (request) => unclaimTask(routes, request),
14008
- assign: (request) => assignTask(routes, request),
14009
- updateStatus: (request) => updateTaskStatus(routes, request),
14010
- amend: (request) => amendTask(routes, request),
14011
- history: (request) => taskHistory(routes, request),
14012
- convert: (request) => convertMessageToTask(routes, request),
14013
- delete: (request) => deleteTask(routes, request)
14071
+ claim: (request) => claimTasks(api, request),
14072
+ list: (request) => listTasks(api, request),
14073
+ create: (request) => createTasks(api, request),
14074
+ unclaim: (request) => unclaimTask(api, request),
14075
+ assign: (request) => assignTask(api, request),
14076
+ updateStatus: (request) => updateTaskStatus(api, request),
14077
+ amend: (request) => amendTask(api, request),
14078
+ history: (request) => taskHistory(api, request),
14079
+ convert: (request) => convertMessageToTask(api, request),
14080
+ delete: (request) => deleteTask(api, request)
14014
14081
  },
14015
14082
  channels: {
14016
- join: (request) => joinChannel(routes, request),
14017
- leave: (request) => leaveChannel(routes, request),
14018
- mute: (request) => muteChannel(routes, request),
14019
- unmute: (request) => unmuteChannel(routes, request),
14020
- members: (request) => channelMembers(routes, request)
14083
+ join: (request) => joinChannel(api, request),
14084
+ leave: (request) => leaveChannel(api, request),
14085
+ mute: (request) => muteChannel(api, request),
14086
+ unmute: (request) => unmuteChannel(api, request),
14087
+ members: (request) => channelMembers(api, request)
14021
14088
  },
14022
14089
  threads: {
14023
- list: () => listThreads(routes),
14024
- unfollow: (request) => unfollowThread(routes, request)
14090
+ list: () => listThreads(api),
14091
+ unfollow: (request) => unfollowThread(api, request)
14025
14092
  },
14026
- server: { info: (request) => serverInfo(routes, request) },
14093
+ server: { info: (request) => serverInfo(api, request) },
14027
14094
  profile: {
14028
- show: (request) => showProfile(routes, request),
14029
- update: (request) => updateProfile(routes, request)
14095
+ show: (request) => showProfile(api, request),
14096
+ update: (request) => updateProfile(api, request)
14030
14097
  },
14031
14098
  frontier,
14032
14099
  state: {
package/dist/esm/index.js CHANGED
@@ -7389,8 +7389,13 @@ function encodeQuery(routeKey, query) {
7389
7389
  return params;
7390
7390
  }
7391
7391
  function parseBody(routeKey, body) {
7392
- if (body === void 0) return void 0;
7393
7392
  const route = agentApiContract[routeKey];
7393
+ if (body === void 0) {
7394
+ if (!("body" in route.request)) return void 0;
7395
+ const schema = route.request.body;
7396
+ if (schema.safeParse(void 0).success || schema.safeParse({}).success) return void 0;
7397
+ return failure$3(routeKey, "request_contract_mismatch", `Agent API ${route.key} requires a request body`);
7398
+ }
7394
7399
  try {
7395
7400
  return "body" in route.request ? route.request.body.parse(body) : void 0;
7396
7401
  } catch (cause) {
@@ -7495,7 +7500,19 @@ function createAgentApiRawClient(transport, options = {}) {
7495
7500
  const routeKey = route.key;
7496
7501
  const { resource, method } = route.client;
7497
7502
  const resourceClient = client[resource] ??= {};
7498
- resourceClient[method] = (...args) => requestAgentApiRawRoute(transport, routeKey, requestOptionsFromMethodArgs(routeKey, pathPrefix, args));
7503
+ const expectedArgs = [
7504
+ "params",
7505
+ "query",
7506
+ "body"
7507
+ ].filter((part) => part in route.request).length;
7508
+ resourceClient[method] = (...args) => {
7509
+ if (args.length > expectedArgs) return Promise.resolve(failure$3(routeKey, "request_contract_mismatch", `Agent API ${route.key} takes ${expectedArgs} argument${expectedArgs === 1 ? "" : "s"} (${[
7510
+ "params",
7511
+ "query",
7512
+ "body"
7513
+ ].filter((part) => part in route.request).join(", ") || "none"}); got ${args.length}`));
7514
+ return requestAgentApiRawRoute(transport, routeKey, requestOptionsFromMethodArgs(routeKey, pathPrefix, args));
7515
+ };
7499
7516
  }
7500
7517
  return client;
7501
7518
  }
@@ -9886,7 +9903,7 @@ function clampAttempts(value) {
9886
9903
  * The split is decided per route from `AGENT_API_ROUTE_META`, never by the
9887
9904
  * caller and never by the HTTP method.
9888
9905
  */
9889
- function createRaftRoutes(options) {
9906
+ function createRaftRouteClient(options) {
9890
9907
  const base = {
9891
9908
  baseUrl: options.serverUrl,
9892
9909
  fetch: options.fetch,
@@ -9913,12 +9930,61 @@ function createRaftRoutes(options) {
9913
9930
  ...merged,
9914
9931
  request: (routeKey, requestOptions) => {
9915
9932
  return (ROUTE_INFO[routeKey].retryPolicy === "retry" ? retrying : single).request(routeKey, requestOptions);
9916
- },
9933
+ }
9934
+ };
9935
+ }
9936
+ const ROUTE_PARTS = [
9937
+ "params",
9938
+ "query",
9939
+ "body"
9940
+ ];
9941
+ function inputMismatch(routeKey, message) {
9942
+ return Promise.resolve({
9943
+ ok: false,
9944
+ routeKey,
9945
+ error: {
9946
+ kind: "validation",
9947
+ reason: "request_contract_mismatch",
9948
+ message: `Agent API ${routeKey} ${message}`
9949
+ }
9950
+ });
9951
+ }
9952
+ /**
9953
+ * The public routes layer: one named-object call shape for every route,
9954
+ * `routes.<resource>.<method>({ params, query, body })`. The types reject a
9955
+ * missing required part or a part the route does not have; for callers
9956
+ * without type checking, the same rules are enforced at runtime and nothing
9957
+ * is sent on a mismatch.
9958
+ */
9959
+ function raftRoutesFromClient(client) {
9960
+ const call = (routeKey, args) => {
9961
+ if (args.length > 1) return inputMismatch(routeKey, `takes one { params, query, body } object; got ${args.length} arguments`);
9962
+ const input = args[0];
9963
+ if (input !== void 0 && (input === null || typeof input !== "object" || Array.isArray(input))) return inputMismatch(routeKey, "takes one { params, query, body } object");
9964
+ const route = agentApiContract[routeKey];
9965
+ const declared = ROUTE_PARTS.filter((part) => part in route.request);
9966
+ const unknown = (input === void 0 ? [] : Object.keys(input)).filter((key) => !declared.includes(key));
9967
+ if (unknown.length > 0) return inputMismatch(routeKey, `has no ${unknown.join(", ")} (it takes ${declared.join(", ") || "no input"})`);
9968
+ return client.request(routeKey, input ?? {});
9969
+ };
9970
+ const methods = {};
9971
+ for (const route of Object.values(agentApiContract)) {
9972
+ const key = route.key;
9973
+ methods[route.client.resource] ??= {};
9974
+ methods[route.client.resource][route.client.method] = (...args) => call(key, args);
9975
+ }
9976
+ return {
9977
+ ...methods,
9978
+ request: (routeKey, ...rest) => call(routeKey, rest),
9917
9979
  manifestVersion: AGENT_API_MANIFEST_VERSION,
9918
9980
  describe: describeRaftRoute,
9919
9981
  list: listRaftRoutes
9920
9982
  };
9921
9983
  }
9984
+ /** Build the public routes layer directly (convenience over createRaftRouteClient + raftRoutesFromClient). */
9985
+ function createRaftRoutes(options) {
9986
+ return raftRoutesFromClient(createRaftRouteClient(options));
9987
+ }
9922
9988
  //#endregion
9923
9989
  //#region src/context.ts
9924
9990
  const projection = object({
@@ -13875,7 +13941,7 @@ function createRaft(options) {
13875
13941
  if (outcome.ok) await session.save();
13876
13942
  return outcome;
13877
13943
  };
13878
- const routes = createRaftRoutes({
13944
+ const api = createRaftRouteClient({
13879
13945
  serverUrl,
13880
13946
  fetch: options.fetch,
13881
13947
  headers: options.headers,
@@ -13883,6 +13949,7 @@ function createRaft(options) {
13883
13949
  readAttempts: options.retry?.attempts,
13884
13950
  beforeRequest: options.throttle?.beforeRequest
13885
13951
  });
13952
+ const routes = raftRoutesFromClient(api);
13886
13953
  const inboxApi = createAgentApiClient({ fetch: {
13887
13954
  baseUrl: serverUrl,
13888
13955
  fetch: (input, init) => (options.fetch ?? fetch)(input, {
@@ -13903,7 +13970,7 @@ function createRaft(options) {
13903
13970
  const sendWithState = (request) => withState(async () => {
13904
13971
  const contentHash = await hashRaftSendContent(request.target, request.content ?? "", request.attachmentIds ?? []);
13905
13972
  const pending = request.idempotencyKey ? void 0 : session.findContinuation(request.target, contentHash);
13906
- const outcome = await sendMessage(routes, pending ? {
13973
+ const outcome = await sendMessage(api, pending ? {
13907
13974
  ...request,
13908
13975
  idempotencyKey: pending.idempotencyKey
13909
13976
  } : request, frontier);
@@ -13917,13 +13984,13 @@ function createRaft(options) {
13917
13984
  return outcome;
13918
13985
  });
13919
13986
  return {
13920
- identity: { whoami: () => getRaftContext(routes) },
13987
+ identity: { whoami: () => getRaftContext(api) },
13921
13988
  wake: {
13922
13989
  verifyNotice: (input) => verifyInboxNotice(input),
13923
13990
  webhook: {
13924
- status: () => webhookStatus(routes),
13925
- register: (request) => registerWebhook(routes, request),
13926
- unregister: () => unregisterWebhook(routes)
13991
+ status: () => webhookStatus(api),
13992
+ register: (request) => registerWebhook(api, request),
13993
+ unregister: () => unregisterWebhook(api)
13927
13994
  }
13928
13995
  },
13929
13996
  inbox: {
@@ -13961,11 +14028,11 @@ function createRaft(options) {
13961
14028
  await session.save();
13962
14029
  });
13963
14030
  })(),
13964
- list: (request) => listInbox(routes, request)
14031
+ list: (request) => listInbox(api, request)
13965
14032
  },
13966
14033
  messages: {
13967
14034
  read: (request) => withState(async () => {
13968
- const outcome = await readHistory(routes, request, frontier);
14035
+ const outcome = await readHistory(api, request, frontier);
13969
14036
  if (outcome.ok) session.markDirty();
13970
14037
  return outcome;
13971
14038
  }),
@@ -13974,58 +14041,58 @@ function createRaft(options) {
13974
14041
  ...request,
13975
14042
  target: message.target
13976
14043
  }),
13977
- search: (request) => searchMessages(routes, request),
13978
- resolve: (request) => resolveMessage(routes, request),
13979
- react: (request) => reactToMessage(routes, request, "add"),
13980
- unreact: (request) => reactToMessage(routes, request, "remove")
14044
+ search: (request) => searchMessages(api, request),
14045
+ resolve: (request) => resolveMessage(api, request),
14046
+ react: (request) => reactToMessage(api, request, "add"),
14047
+ unreact: (request) => reactToMessage(api, request, "remove")
13981
14048
  },
13982
14049
  attachments: {
13983
- upload: (request) => uploadAttachment(routes, {
14050
+ upload: (request) => uploadAttachment(api, {
13984
14051
  serverUrl,
13985
14052
  fetch: options.fetch ?? fetch,
13986
14053
  headers: Object.fromEntries(new Headers(options.headers)),
13987
14054
  authorization
13988
14055
  }, request),
13989
- download: (request) => downloadAttachment(routes, request),
13990
- comments: (request) => attachmentComments(routes, request)
14056
+ download: (request) => downloadAttachment(api, request),
14057
+ comments: (request) => attachmentComments(api, request)
13991
14058
  },
13992
14059
  mentions: {
13993
- pending: (request) => pendingMentionActions(routes, request),
13994
- execute: (request) => executeMentionAction(routes, request),
13995
- deliveries: (request) => senderMentionDeliveries(routes, request)
14060
+ pending: (request) => pendingMentionActions(api, request),
14061
+ execute: (request) => executeMentionAction(api, request),
14062
+ deliveries: (request) => senderMentionDeliveries(api, request)
13996
14063
  },
13997
- actions: { prepare: (request) => prepareActionCard(routes, request) },
14064
+ actions: { prepare: (request) => prepareActionCard(api, request) },
13998
14065
  manual: {
13999
- get: (request) => getManualTopic(routes, request),
14000
- search: (request) => searchManual(routes, request)
14066
+ get: (request) => getManualTopic(api, request),
14067
+ search: (request) => searchManual(api, request)
14001
14068
  },
14002
14069
  tasks: {
14003
- claim: (request) => claimTasks(routes, request),
14004
- list: (request) => listTasks(routes, request),
14005
- create: (request) => createTasks(routes, request),
14006
- unclaim: (request) => unclaimTask(routes, request),
14007
- assign: (request) => assignTask(routes, request),
14008
- updateStatus: (request) => updateTaskStatus(routes, request),
14009
- amend: (request) => amendTask(routes, request),
14010
- history: (request) => taskHistory(routes, request),
14011
- convert: (request) => convertMessageToTask(routes, request),
14012
- delete: (request) => deleteTask(routes, request)
14070
+ claim: (request) => claimTasks(api, request),
14071
+ list: (request) => listTasks(api, request),
14072
+ create: (request) => createTasks(api, request),
14073
+ unclaim: (request) => unclaimTask(api, request),
14074
+ assign: (request) => assignTask(api, request),
14075
+ updateStatus: (request) => updateTaskStatus(api, request),
14076
+ amend: (request) => amendTask(api, request),
14077
+ history: (request) => taskHistory(api, request),
14078
+ convert: (request) => convertMessageToTask(api, request),
14079
+ delete: (request) => deleteTask(api, request)
14013
14080
  },
14014
14081
  channels: {
14015
- join: (request) => joinChannel(routes, request),
14016
- leave: (request) => leaveChannel(routes, request),
14017
- mute: (request) => muteChannel(routes, request),
14018
- unmute: (request) => unmuteChannel(routes, request),
14019
- members: (request) => channelMembers(routes, request)
14082
+ join: (request) => joinChannel(api, request),
14083
+ leave: (request) => leaveChannel(api, request),
14084
+ mute: (request) => muteChannel(api, request),
14085
+ unmute: (request) => unmuteChannel(api, request),
14086
+ members: (request) => channelMembers(api, request)
14020
14087
  },
14021
14088
  threads: {
14022
- list: () => listThreads(routes),
14023
- unfollow: (request) => unfollowThread(routes, request)
14089
+ list: () => listThreads(api),
14090
+ unfollow: (request) => unfollowThread(api, request)
14024
14091
  },
14025
- server: { info: (request) => serverInfo(routes, request) },
14092
+ server: { info: (request) => serverInfo(api, request) },
14026
14093
  profile: {
14027
- show: (request) => showProfile(routes, request),
14028
- update: (request) => updateProfile(routes, request)
14094
+ show: (request) => showProfile(api, request),
14095
+ update: (request) => updateProfile(api, request)
14029
14096
  },
14030
14097
  frontier,
14031
14098
  state: {
package/dist/index.d.ts CHANGED
@@ -996,25 +996,6 @@ interface AgentApiRawTransportRequest<K extends AgentApiRouteKey = AgentApiRoute
996
996
  path: string;
997
997
  body?: unknown;
998
998
  }
999
- type AgentApiRawSuccess<K extends AgentApiRouteKey> = {
1000
- ok: true;
1001
- routeKey: K;
1002
- status: number;
1003
- data: AgentApiResponseByRoute[K];
1004
- };
1005
- type AgentApiRawFailure<K extends AgentApiRouteKey = AgentApiRouteKey> = {
1006
- ok: false;
1007
- routeKey?: K;
1008
- status?: number;
1009
- reason: AgentApiRawClientErrorReason;
1010
- message: string;
1011
- errorCode?: string | null;
1012
- suggestedNextAction?: string | null;
1013
- proxy?: unknown;
1014
- cause?: unknown;
1015
- response?: unknown;
1016
- };
1017
- type AgentApiRawResult<K extends AgentApiRouteKey> = AgentApiRawSuccess<K> | AgentApiRawFailure<K>;
1018
999
  type AgentApiRawClientResource = AgentApiContract[AgentApiRouteKey]["client"]["resource"];
1019
1000
  type AgentApiRawClientResourceMethod<R extends AgentApiRawClientResource> = { [K in AgentApiRouteKey]: AgentApiContract[K]["client"] extends {
1020
1001
  resource: R;
@@ -1024,9 +1005,6 @@ type AgentApiRouteKeyForClient<R extends AgentApiRawClientResource, M extends Ag
1024
1005
  resource: R;
1025
1006
  method: M;
1026
1007
  } ? K : never; }[AgentApiRouteKey];
1027
- type AgentApiRawClientMethodArgs<K extends AgentApiRouteKey> = [AgentApiRequestParamsByRoute[K]] extends [never] ? [AgentApiRequestQueryByRoute[K]] extends [never] ? [AgentApiRequestBodyByRoute[K]] extends [never] ? [] : [body: AgentApiRequestBodyByRoute[K]] : [query: AgentApiRequestQueryByRoute[K]] : [AgentApiRequestQueryByRoute[K]] extends [never] ? [AgentApiRequestBodyByRoute[K]] extends [never] ? [params: AgentApiRequestParamsByRoute[K]] : [params: AgentApiRequestParamsByRoute[K], body: AgentApiRequestBodyByRoute[K]] : [AgentApiRequestBodyByRoute[K]] extends [never] ? [params: AgentApiRequestParamsByRoute[K], query: AgentApiRequestQueryByRoute[K]] : [params: AgentApiRequestParamsByRoute[K], query: AgentApiRequestQueryByRoute[K], body: AgentApiRequestBodyByRoute[K]];
1028
- type AgentApiRawClientMethod<K extends AgentApiRouteKey> = (...args: AgentApiRawClientMethodArgs<K>) => Promise<AgentApiRawResult<K>>;
1029
- type AgentApiRawClient = { [R in AgentApiRawClientResource]: { [M in AgentApiRawClientResourceMethod<R>]: AgentApiRawClientMethod<AgentApiRouteKeyForClient<R, M>>; }; };
1030
1008
  //#endregion
1031
1009
  //#region ../shared/src/index.d.ts
1032
1010
  /**
@@ -8952,16 +8930,6 @@ interface AgentApiClientFailure<K extends AgentApiRouteKey = AgentApiRouteKey> {
8952
8930
  error: AgentApiClientError;
8953
8931
  }
8954
8932
  type AgentApiClientResult<K extends AgentApiRouteKey> = AgentApiClientSuccess<K> | AgentApiClientFailure<K>;
8955
- type AgentApiClientMethod<K extends AgentApiRouteKey> = (...args: Parameters<AgentApiRawClientMethod<K>>) => Promise<AgentApiClientResult<K>>;
8956
- type AgentApiClientMethods = { [R in keyof AgentApiRawClient]: { [M in keyof AgentApiRawClient[R]]: AgentApiRawClient[R][M] extends AgentApiRawClientMethod<infer K> ? AgentApiClientMethod<K> : never; }; };
8957
- interface AgentApiClientRequestOptions<K extends AgentApiRouteKey> {
8958
- params?: AgentApiRequestParamsByRoute[K];
8959
- query?: AgentApiRequestQueryByRoute[K];
8960
- body?: AgentApiRequestBodyByRoute[K];
8961
- }
8962
- type AgentApiClient = AgentApiClientMethods & {
8963
- request<K extends AgentApiRouteKey>(routeKey: K, options?: AgentApiClientRequestOptions<K>): Promise<AgentApiClientResult<K>>;
8964
- };
8965
8933
  type AgentApiAuthHeaders = Record<string, string>;
8966
8934
  type AgentApiAuthStrategy = AgentApiAuthHeaders | ((request: AgentApiRawTransportRequest) => AgentApiAuthHeaders | Promise<AgentApiAuthHeaders>);
8967
8935
  interface AgentApiFetchTransportOptions {
@@ -9076,12 +9044,24 @@ interface RaftRouteInfo extends RaftRouteMeta {
9076
9044
  annotations: RaftRouteAnnotations;
9077
9045
  }
9078
9046
  /**
9079
- * `routes.<resource>.<method>(params?, query?, body?)` for every route in the
9047
+ * `routes.<resource>.<method>({ params, query, body })` (one named object, typed per route) for every route in the
9080
9048
  * contract, plus route introspection. Reads retry (bounded); writes and
9081
9049
  * destructive reads make exactly one attempt regardless of client retry
9082
9050
  * settings, because the contract says repeating them is not safe.
9083
9051
  */
9084
- type RaftRoutes = AgentApiClient & {
9052
+ type RoutePart<Name extends string, T> = [T] extends [never] ? { [P in Name]?: never; } : {} extends T ? { [P in Name]?: T; } : { [P in Name]: T; };
9053
+ /**
9054
+ * The single input every route takes: `{ params, query, body }`, typed per
9055
+ * route. A part the route does not have is `never` (passing it is a compile
9056
+ * error); a part with required fields is a required property.
9057
+ */
9058
+ type RaftRouteInput<K extends RaftRouteKey> = RoutePart<"params", AgentApiRequestParamsByRoute[K]> & RoutePart<"query", AgentApiRequestQueryByRoute[K]> & RoutePart<"body", AgentApiRequestBodyByRoute[K]>;
9059
+ type RaftRouteMethod<K extends RaftRouteKey> = {} extends RaftRouteInput<K> ? (input?: RaftRouteInput<K>) => Promise<RaftRouteResult<K>> : (input: RaftRouteInput<K>) => Promise<RaftRouteResult<K>>;
9060
+ /** `routes.<resource>.<method>({ params, query, body })` for every route in the contract. */
9061
+ type RaftRouteMethods = { [R in AgentApiRawClientResource]: { [M in AgentApiRawClientResourceMethod<R>]: RaftRouteMethod<AgentApiRouteKeyForClient<R, M>>; }; };
9062
+ type RaftRoutes = RaftRouteMethods & {
9063
+ /** The same call by route key: `request("actionPrepare", { body })`. */
9064
+ request<K extends RaftRouteKey>(routeKey: K, input?: RaftRouteInput<K>): Promise<RaftRouteResult<K>>;
9085
9065
  /** Content hash of the route manifest this SDK was built against. */
9086
9066
  manifestVersion: string;
9087
9067
  /** Static description of one route: capability, side effect, idempotency, audience, retry policy. */
@@ -9102,12 +9082,7 @@ interface CreateRaftRoutesOptions {
9102
9082
  beforeRequest?: infer F;
9103
9083
  } | undefined ? F : never;
9104
9084
  }
9105
- /**
9106
- * Build the routes layer over two transports: a retrying one for routes the
9107
- * contract marks retry-safe, and a single-attempt one for everything else.
9108
- * The split is decided per route from `AGENT_API_ROUTE_META`, never by the
9109
- * caller and never by the HTTP method.
9110
- */
9085
+ /** Build the public routes layer directly (convenience over createRaftRouteClient + raftRoutesFromClient). */
9111
9086
  export declare function createRaftRoutes(options: CreateRaftRoutesOptions): RaftRoutes;
9112
9087
  //#endregion
9113
9088
  //#region src/context.d.ts
@@ -9217,7 +9192,7 @@ type RaftClient = AgentApiMessageClient & RaftManageClient & {
9217
9192
  join(request: RaftChannelJoinRequest): Promise<RaftChannelJoinResult>;
9218
9193
  };
9219
9194
  /**
9220
- * Every Agent API route as `routes.<resource>.<method>(params?, query?, body?)`,
9195
+ * Every Agent API route as `routes.<resource>.<method>({ params, query, body })` (one named object, typed per route),
9221
9196
  * typed from the shared contract, with per-route metadata via `routes.describe`.
9222
9197
  * Retry policy follows the contract: reads may retry, writes make one attempt.
9223
9198
  */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@botiverse/raft-sdk",
3
- "version": "1.0.0-alpha.5",
3
+ "version": "1.0.0-alpha.6",
4
4
  "license": "FSL-1.1-ALv2",
5
5
  "description": "Typed Raft Agent API client for external agents and bots.",
6
6
  "type": "module",