@flowy-agent-store/client 0.1.0-beta.4 → 0.1.0-beta.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/dist/index.cjs CHANGED
@@ -276,7 +276,7 @@ var WebSocketTransport = class {
276
276
  /** Header the server mints the per-call connection id under. */
277
277
  const CONNECTION_HEADER = "x-app-server-connection-id";
278
278
  /** Protocol version this binding announces on the one-shot handshake. */
279
- const PROTOCOL_VERSION = "fp-1";
279
+ const PROTOCOL_VERSION = "fp-7";
280
280
  /**
281
281
  * Protocol method → REST route. Verified from handler bodies, not from the
282
282
  * route list (a route existing does not prove which method it mirrors).
@@ -334,7 +334,10 @@ const HTTP_ROUTES = {
334
334
  body: [
335
335
  "content",
336
336
  "idempotency_key",
337
- "attachments"
337
+ "attachments",
338
+ "mentions",
339
+ "model",
340
+ "reasoning_effort"
338
341
  ],
339
342
  source: "conversation_send() -> send_conversation_message_for_user (shared with the WS arm)"
340
343
  },
@@ -795,7 +798,9 @@ var ConversationClient = class {
795
798
  name: input.name,
796
799
  model,
797
800
  workspace: input.workspaceId ? { id: input.workspaceId } : void 0,
798
- reasoning_effort: input.reasoningEffort || void 0
801
+ reasoning_effort: input.reasoningEffort || void 0,
802
+ agent_id: input.agentId || void 0,
803
+ team_id: input.teamId || void 0
799
804
  });
800
805
  }
801
806
  update(conversationId, input) {
@@ -828,17 +833,33 @@ var ConversationClient = class {
828
833
  }
829
834
  /**
830
835
  * R15(W10):`attachments` 是**会话工作区内的绝对路径**(图片附件)。
836
+ * doc `27` §4.1:`mentions` 是**本轮挂载的技能**(`kind: "skill"`)——技能的正文与
837
+ * 不可变快照都随这一轮走;`agent` / `connector` 在 send 上没有载体,服务端会以
838
+ * `invalid_request` **明确拒绝**(不是静默不挂)。
839
+ *
840
+ * 两者缺省都不上 wire,保持老调用方的形状逐字不变;服务端只接受会话工作区内的真实
841
+ * 文件(越界 / 相对路径 / 不存在一律拒),准入见 `nomifun-app-server` 的
842
+ * `resolve_conversation_attachments` 与 `send_mention_skills`。
831
843
  *
832
- * 缺省不传,保持老调用方的 wire 形状逐字不变;服务端只接受会话工作区内的真实
833
- * 文件(越界 / 相对路径 / 不存在一律拒),具体准入见
834
- * `nomifun-app-server` 的 `resolve_conversation_attachments`。
844
+ * 第 4 个参数同时接受旧的 `string[]`(附件)与选项对象——再堆一个位置参数会让调用点
845
+ * 变成一串没有名字的布尔/数组。
835
846
  */
836
- send(conversationId, content, idempotencyKey, attachments = []) {
847
+ send(conversationId, content, idempotencyKey, options = {}) {
848
+ const attachments = Array.isArray(options) ? options : options.attachments ?? [];
849
+ const mentions = Array.isArray(options) ? [] : options.mentions ?? [];
850
+ const model = Array.isArray(options) ? void 0 : options.model;
851
+ const reasoningEffort = Array.isArray(options) ? void 0 : options.reasoningEffort;
837
852
  return this.transport.request("conversation/send", {
838
853
  conversation_id: conversationId,
839
854
  content,
840
855
  idempotency_key: idempotencyKey,
841
- ...attachments.length > 0 ? { attachments } : {}
856
+ ...attachments.length > 0 ? { attachments } : {},
857
+ ...mentions.length > 0 ? { mentions } : {},
858
+ ...model ? { model: {
859
+ provider_id: model.provider_id,
860
+ model: model.model
861
+ } } : {},
862
+ ...reasoningEffort ? { reasoning_effort: reasoningEffort } : {}
842
863
  });
843
864
  }
844
865
  cancel(conversationId) {
@@ -1063,7 +1084,19 @@ var ConnectorClient = class {
1063
1084
  status(connectorId) {
1064
1085
  return this.transport.request("connector/status", { connector_id: connectorId });
1065
1086
  }
1066
- /** Run a connection probe; the server persists the result. */
1087
+ /**
1088
+ * Run a connection probe and report what the connector currently offers —
1089
+ * including each tool's `input_schema`.
1090
+ *
1091
+ * It really connects: a stdio connector gets its child process spawned, an
1092
+ * HTTP/SSE one gets `initialize` + `tools/list`. The result is **persisted**,
1093
+ * so this is also what refreshes the tool list `get()` reads back.
1094
+ *
1095
+ * Named `test` and not `probe` on purpose: this repo's split is `test` for the
1096
+ * action (wire `connector/test`, `test_connection`) and `probe` for its
1097
+ * artifact (`ConnectorProbeResult`, `probe_status`), and every method here is
1098
+ * the last segment of its wire method.
1099
+ */
1067
1100
  test(connectorId) {
1068
1101
  return this.transport.request("connector/test", { connector_id: connectorId });
1069
1102
  }
@@ -1088,9 +1121,17 @@ var ConnectorClient = class {
1088
1121
  * The host holds the transport, its headers and its OAuth token; this sends a
1089
1122
  * tool name and an argument object and nothing else — you cannot name a URL,
1090
1123
  * a command or a header. Whether the pair is callable at all is the host's
1091
- * `[connector_proxy]` allowlist, so expect `policy_denied` on a host whose
1092
- * operator has not listed this tool (that is the default, not a
1093
- * misconfiguration).
1124
+ * `[connector_proxy]` policy: once its operator turns the proxy on, the
1125
+ * enabled connectors are callable, and `allow` / `deny` are that operator's
1126
+ * optional narrowing and subtraction. So `policy_denied` means either that
1127
+ * the host never turned the proxy on, or that this pair was narrowed out or
1128
+ * explicitly denied — not that a tool name was misspelled in a list you were
1129
+ * supposed to maintain.
1130
+ *
1131
+ * Arguments are passed through verbatim (there is no client-side schema
1132
+ * check); `get()` / `test()` return each tool's `input_schema` so you can see
1133
+ * what it takes, and a parameter the server rejects comes back as
1134
+ * `is_error: true`, not as a rejected promise.
1094
1135
  *
1095
1136
  * Resolves even when the tool itself failed — check `is_error`. It rejects
1096
1137
  * only when the call never reached the tool: `connector_call_timeout`,
@@ -1389,7 +1430,12 @@ function toWire(input) {
1389
1430
  steps: input.steps,
1390
1431
  command_id: input.commandId,
1391
1432
  idempotency_key: input.idempotencyKey,
1392
- mentions: input.mentions
1433
+ mentions: input.mentions,
1434
+ model: input.model ? {
1435
+ provider_id: input.model.provider_id,
1436
+ model: input.model.model
1437
+ } : void 0,
1438
+ reasoning_effort: input.reasoningEffort || void 0
1393
1439
  };
1394
1440
  }
1395
1441
  function toTeamWire(input) {
package/dist/index.d.cts CHANGED
@@ -1,4 +1,4 @@
1
- import { AgentDetail, AgentRunInput, AgentSummary, AnswerDecisionInput, CancelRunInput, ClientCapabilities, ClientInfo, ConnectorCallResult, ConnectorDetail, ConnectorProbeResult, ConnectorStatusView, ConnectorSummary, ContextUsage, ConversationCreateInput, ConversationEvent, ConversationMessage, ConversationMessagesPage, ConversationMessagesQuery, ConversationModelOptions, ConversationSendReceipt, ConversationUpdateInput, ConversationView, ImportDetail, ImportRequest, ImportResult, ImportSummary, InitializeResult, InstallOutcome, InstallRequest, InstallResult, InstallStatus, MarketplaceAddRequest, MarketplaceDetail, MarketplaceRefreshResult, MarketplaceRemoveResult, MarketplaceSummary, ModelSummary, OAuthStartResult, OAuthStatusView, RunEvent, RunEventsQuery, RunPlan, RunReceipt, RunResult, RunStatus, RunView, ServerNotification, SkillDetail, SkillFileContent, SkillFileList, SkillSummary, SteerRunInput, StoreInstallResult, StoreItem, StoreItemKind, StoreList, TeamDetail, TeamRunInput, TeamRunReceipt, TeamSummary, WorkspaceRevokeResult, WorkspaceView } from "@flowy-agent-store/protocol";
1
+ import { AgentDetail, AgentRunInput, AgentSummary, AnswerDecisionInput, CancelRunInput, ClientCapabilities, ClientInfo, ConnectorCallResult, ConnectorDetail, ConnectorProbeResult, ConnectorStatusView, ConnectorSummary, ContextUsage, ConversationCreateInput, ConversationEvent, ConversationMessage, ConversationMessagesPage, ConversationMessagesQuery, ConversationModelOptions, ConversationSendReceipt, ConversationUpdateInput, ConversationView, ImportDetail, ImportRequest, ImportResult, ImportSummary, InitializeResult, InstallOutcome, InstallRequest, InstallResult, InstallStatus, MarketplaceAddRequest, MarketplaceDetail, MarketplaceRefreshResult, MarketplaceRemoveResult, MarketplaceSummary, MentionRef, ModelSummary, OAuthStartResult, OAuthStatusView, ProviderWithModel, RunEvent, RunEventsQuery, RunPlan, RunReceipt, RunResult, RunStatus, RunView, ServerNotification, SkillDetail, SkillFileContent, SkillFileList, SkillSummary, SteerRunInput, StoreInstallResult, StoreItem, StoreItemKind, StoreList, TeamDetail, TeamRunInput, TeamRunReceipt, TeamSummary, WorkspaceRevokeResult, WorkspaceView } from "@flowy-agent-store/protocol";
2
2
  //#region src/transport.d.ts
3
3
  export type NotificationListener = (notification: ServerNotification) => void;
4
4
  /**
@@ -196,6 +196,46 @@ export declare class AgentClient {
196
196
  }
197
197
  //#endregion
198
198
  //#region src/conversations.d.ts
199
+ /**
200
+ * Options for `send()`.
201
+ *
202
+ * Two scopes, deliberately different (doc `27` §4.1 and doc `29` §5.1):
203
+ *
204
+ * - **per turn** — `attachments` and `mentions` are this turn's payload, and
205
+ * nothing else changes;
206
+ * - **per conversation, taking effect this turn** — `model` and
207
+ * `reasoningEffort` are *sticky*: they are written to the conversation and
208
+ * every later turn keeps them, because the Nomi runtime is built from the
209
+ * persisted row. The host refuses them while a turn is running (`conflict`).
210
+ *
211
+ * Every field is **additive**: absent means the exact wire shape callers sent
212
+ * before that field existed, and a plain `send()` never writes the conversation.
213
+ */
214
+ export interface ConversationSendOptions {
215
+ /** Absolute paths inside the conversation's workspace (images only). */
216
+ attachments?: string[];
217
+ /**
218
+ * Skills to mount for **this turn** (`kind: "skill"`).
219
+ *
220
+ * The ids are `skill/list`'s ids (the skill's own name, not an
221
+ * `install/status` component id). A turn is the only scope a Skill has here:
222
+ * the conversation's frozen snapshot is create-time and immutable.
223
+ */
224
+ mentions?: MentionRef[];
225
+ /**
226
+ * Model to switch the conversation to **from this turn on** (doc `29` §5.1).
227
+ *
228
+ * Sticky, not per-turn: the Nomi runtime is built from the persisted row, so
229
+ * the value is written to the conversation and every later turn keeps it.
230
+ * Omit it and the conversation's current model stays untouched.
231
+ */
232
+ model?: ProviderWithModel;
233
+ /**
234
+ * Reasoning level to switch the conversation to **from this turn on**
235
+ * (doc `29` §5.1). Same sticky scope as `model`.
236
+ */
237
+ reasoningEffort?: string;
238
+ }
199
239
  export declare class ConversationClient {
200
240
  private readonly transport;
201
241
  constructor(transport: Transport);
@@ -207,12 +247,18 @@ export declare class ConversationClient {
207
247
  messages(query: ConversationMessagesQuery): Promise<ConversationMessagesPage>;
208
248
  /**
209
249
  * R15(W10):`attachments` 是**会话工作区内的绝对路径**(图片附件)。
250
+ * doc `27` §4.1:`mentions` 是**本轮挂载的技能**(`kind: "skill"`)——技能的正文与
251
+ * 不可变快照都随这一轮走;`agent` / `connector` 在 send 上没有载体,服务端会以
252
+ * `invalid_request` **明确拒绝**(不是静默不挂)。
253
+ *
254
+ * 两者缺省都不上 wire,保持老调用方的形状逐字不变;服务端只接受会话工作区内的真实
255
+ * 文件(越界 / 相对路径 / 不存在一律拒),准入见 `nomifun-app-server` 的
256
+ * `resolve_conversation_attachments` 与 `send_mention_skills`。
210
257
  *
211
- * 缺省不传,保持老调用方的 wire 形状逐字不变;服务端只接受会话工作区内的真实
212
- * 文件(越界 / 相对路径 / 不存在一律拒),具体准入见
213
- * `nomifun-app-server` 的 `resolve_conversation_attachments`。
258
+ * 第 4 个参数同时接受旧的 `string[]`(附件)与选项对象——再堆一个位置参数会让调用点
259
+ * 变成一串没有名字的布尔/数组。
214
260
  */
215
- send(conversationId: string, content: string, idempotencyKey: string, attachments?: string[]): Promise<ConversationSendReceipt>;
261
+ send(conversationId: string, content: string, idempotencyKey: string, options?: string[] | ConversationSendOptions): Promise<ConversationSendReceipt>;
216
262
  cancel(conversationId: string): Promise<ConversationView>;
217
263
  delete(conversationId: string): Promise<{
218
264
  conversation_id: string;
@@ -326,7 +372,19 @@ export declare class ConnectorClient {
326
372
  get(connectorId: string): Promise<ConnectorDetail>;
327
373
  /** Combined auth × probe status. `connected` only when auth is ready AND the last probe succeeded. */
328
374
  status(connectorId: string): Promise<ConnectorStatusView>;
329
- /** Run a connection probe; the server persists the result. */
375
+ /**
376
+ * Run a connection probe and report what the connector currently offers —
377
+ * including each tool's `input_schema`.
378
+ *
379
+ * It really connects: a stdio connector gets its child process spawned, an
380
+ * HTTP/SSE one gets `initialize` + `tools/list`. The result is **persisted**,
381
+ * so this is also what refreshes the tool list `get()` reads back.
382
+ *
383
+ * Named `test` and not `probe` on purpose: this repo's split is `test` for the
384
+ * action (wire `connector/test`, `test_connection`) and `probe` for its
385
+ * artifact (`ConnectorProbeResult`, `probe_status`), and every method here is
386
+ * the last segment of its wire method.
387
+ */
330
388
  test(connectorId: string): Promise<ConnectorProbeResult>;
331
389
  /** Check the current OAuth state for a connector. */
332
390
  authStatus(connectorId: string): Promise<OAuthStatusView>;
@@ -343,9 +401,17 @@ export declare class ConnectorClient {
343
401
  * The host holds the transport, its headers and its OAuth token; this sends a
344
402
  * tool name and an argument object and nothing else — you cannot name a URL,
345
403
  * a command or a header. Whether the pair is callable at all is the host's
346
- * `[connector_proxy]` allowlist, so expect `policy_denied` on a host whose
347
- * operator has not listed this tool (that is the default, not a
348
- * misconfiguration).
404
+ * `[connector_proxy]` policy: once its operator turns the proxy on, the
405
+ * enabled connectors are callable, and `allow` / `deny` are that operator's
406
+ * optional narrowing and subtraction. So `policy_denied` means either that
407
+ * the host never turned the proxy on, or that this pair was narrowed out or
408
+ * explicitly denied — not that a tool name was misspelled in a list you were
409
+ * supposed to maintain.
410
+ *
411
+ * Arguments are passed through verbatim (there is no client-side schema
412
+ * check); `get()` / `test()` return each tool's `input_schema` so you can see
413
+ * what it takes, and a parameter the server rejects comes back as
414
+ * `is_error: true`, not as a rejected promise.
349
415
  *
350
416
  * Resolves even when the tool itself failed — check `is_error`. It rejects
351
417
  * only when the call never reached the tool: `connector_call_timeout`,
package/dist/index.d.mts CHANGED
@@ -1,4 +1,4 @@
1
- import { AgentDetail, AgentRunInput, AgentSummary, AnswerDecisionInput, CancelRunInput, ClientCapabilities, ClientInfo, ConnectorCallResult, ConnectorDetail, ConnectorProbeResult, ConnectorStatusView, ConnectorSummary, ContextUsage, ConversationCreateInput, ConversationEvent, ConversationMessage, ConversationMessagesPage, ConversationMessagesQuery, ConversationModelOptions, ConversationSendReceipt, ConversationUpdateInput, ConversationView, ImportDetail, ImportRequest, ImportResult, ImportSummary, InitializeResult, InstallOutcome, InstallRequest, InstallResult, InstallStatus, MarketplaceAddRequest, MarketplaceDetail, MarketplaceRefreshResult, MarketplaceRemoveResult, MarketplaceSummary, ModelSummary, OAuthStartResult, OAuthStatusView, RunEvent, RunEventsQuery, RunPlan, RunReceipt, RunResult, RunStatus, RunView, ServerNotification, SkillDetail, SkillFileContent, SkillFileList, SkillSummary, SteerRunInput, StoreInstallResult, StoreItem, StoreItemKind, StoreList, TeamDetail, TeamRunInput, TeamRunReceipt, TeamSummary, WorkspaceRevokeResult, WorkspaceView } from "@flowy-agent-store/protocol";
1
+ import { AgentDetail, AgentRunInput, AgentSummary, AnswerDecisionInput, CancelRunInput, ClientCapabilities, ClientInfo, ConnectorCallResult, ConnectorDetail, ConnectorProbeResult, ConnectorStatusView, ConnectorSummary, ContextUsage, ConversationCreateInput, ConversationEvent, ConversationMessage, ConversationMessagesPage, ConversationMessagesQuery, ConversationModelOptions, ConversationSendReceipt, ConversationUpdateInput, ConversationView, ImportDetail, ImportRequest, ImportResult, ImportSummary, InitializeResult, InstallOutcome, InstallRequest, InstallResult, InstallStatus, MarketplaceAddRequest, MarketplaceDetail, MarketplaceRefreshResult, MarketplaceRemoveResult, MarketplaceSummary, MentionRef, ModelSummary, OAuthStartResult, OAuthStatusView, ProviderWithModel, RunEvent, RunEventsQuery, RunPlan, RunReceipt, RunResult, RunStatus, RunView, ServerNotification, SkillDetail, SkillFileContent, SkillFileList, SkillSummary, SteerRunInput, StoreInstallResult, StoreItem, StoreItemKind, StoreList, TeamDetail, TeamRunInput, TeamRunReceipt, TeamSummary, WorkspaceRevokeResult, WorkspaceView } from "@flowy-agent-store/protocol";
2
2
  //#region src/transport.d.ts
3
3
  export type NotificationListener = (notification: ServerNotification) => void;
4
4
  /**
@@ -196,6 +196,46 @@ export declare class AgentClient {
196
196
  }
197
197
  //#endregion
198
198
  //#region src/conversations.d.ts
199
+ /**
200
+ * Options for `send()`.
201
+ *
202
+ * Two scopes, deliberately different (doc `27` §4.1 and doc `29` §5.1):
203
+ *
204
+ * - **per turn** — `attachments` and `mentions` are this turn's payload, and
205
+ * nothing else changes;
206
+ * - **per conversation, taking effect this turn** — `model` and
207
+ * `reasoningEffort` are *sticky*: they are written to the conversation and
208
+ * every later turn keeps them, because the Nomi runtime is built from the
209
+ * persisted row. The host refuses them while a turn is running (`conflict`).
210
+ *
211
+ * Every field is **additive**: absent means the exact wire shape callers sent
212
+ * before that field existed, and a plain `send()` never writes the conversation.
213
+ */
214
+ export interface ConversationSendOptions {
215
+ /** Absolute paths inside the conversation's workspace (images only). */
216
+ attachments?: string[];
217
+ /**
218
+ * Skills to mount for **this turn** (`kind: "skill"`).
219
+ *
220
+ * The ids are `skill/list`'s ids (the skill's own name, not an
221
+ * `install/status` component id). A turn is the only scope a Skill has here:
222
+ * the conversation's frozen snapshot is create-time and immutable.
223
+ */
224
+ mentions?: MentionRef[];
225
+ /**
226
+ * Model to switch the conversation to **from this turn on** (doc `29` §5.1).
227
+ *
228
+ * Sticky, not per-turn: the Nomi runtime is built from the persisted row, so
229
+ * the value is written to the conversation and every later turn keeps it.
230
+ * Omit it and the conversation's current model stays untouched.
231
+ */
232
+ model?: ProviderWithModel;
233
+ /**
234
+ * Reasoning level to switch the conversation to **from this turn on**
235
+ * (doc `29` §5.1). Same sticky scope as `model`.
236
+ */
237
+ reasoningEffort?: string;
238
+ }
199
239
  export declare class ConversationClient {
200
240
  private readonly transport;
201
241
  constructor(transport: Transport);
@@ -207,12 +247,18 @@ export declare class ConversationClient {
207
247
  messages(query: ConversationMessagesQuery): Promise<ConversationMessagesPage>;
208
248
  /**
209
249
  * R15(W10):`attachments` 是**会话工作区内的绝对路径**(图片附件)。
250
+ * doc `27` §4.1:`mentions` 是**本轮挂载的技能**(`kind: "skill"`)——技能的正文与
251
+ * 不可变快照都随这一轮走;`agent` / `connector` 在 send 上没有载体,服务端会以
252
+ * `invalid_request` **明确拒绝**(不是静默不挂)。
253
+ *
254
+ * 两者缺省都不上 wire,保持老调用方的形状逐字不变;服务端只接受会话工作区内的真实
255
+ * 文件(越界 / 相对路径 / 不存在一律拒),准入见 `nomifun-app-server` 的
256
+ * `resolve_conversation_attachments` 与 `send_mention_skills`。
210
257
  *
211
- * 缺省不传,保持老调用方的 wire 形状逐字不变;服务端只接受会话工作区内的真实
212
- * 文件(越界 / 相对路径 / 不存在一律拒),具体准入见
213
- * `nomifun-app-server` 的 `resolve_conversation_attachments`。
258
+ * 第 4 个参数同时接受旧的 `string[]`(附件)与选项对象——再堆一个位置参数会让调用点
259
+ * 变成一串没有名字的布尔/数组。
214
260
  */
215
- send(conversationId: string, content: string, idempotencyKey: string, attachments?: string[]): Promise<ConversationSendReceipt>;
261
+ send(conversationId: string, content: string, idempotencyKey: string, options?: string[] | ConversationSendOptions): Promise<ConversationSendReceipt>;
216
262
  cancel(conversationId: string): Promise<ConversationView>;
217
263
  delete(conversationId: string): Promise<{
218
264
  conversation_id: string;
@@ -326,7 +372,19 @@ export declare class ConnectorClient {
326
372
  get(connectorId: string): Promise<ConnectorDetail>;
327
373
  /** Combined auth × probe status. `connected` only when auth is ready AND the last probe succeeded. */
328
374
  status(connectorId: string): Promise<ConnectorStatusView>;
329
- /** Run a connection probe; the server persists the result. */
375
+ /**
376
+ * Run a connection probe and report what the connector currently offers —
377
+ * including each tool's `input_schema`.
378
+ *
379
+ * It really connects: a stdio connector gets its child process spawned, an
380
+ * HTTP/SSE one gets `initialize` + `tools/list`. The result is **persisted**,
381
+ * so this is also what refreshes the tool list `get()` reads back.
382
+ *
383
+ * Named `test` and not `probe` on purpose: this repo's split is `test` for the
384
+ * action (wire `connector/test`, `test_connection`) and `probe` for its
385
+ * artifact (`ConnectorProbeResult`, `probe_status`), and every method here is
386
+ * the last segment of its wire method.
387
+ */
330
388
  test(connectorId: string): Promise<ConnectorProbeResult>;
331
389
  /** Check the current OAuth state for a connector. */
332
390
  authStatus(connectorId: string): Promise<OAuthStatusView>;
@@ -343,9 +401,17 @@ export declare class ConnectorClient {
343
401
  * The host holds the transport, its headers and its OAuth token; this sends a
344
402
  * tool name and an argument object and nothing else — you cannot name a URL,
345
403
  * a command or a header. Whether the pair is callable at all is the host's
346
- * `[connector_proxy]` allowlist, so expect `policy_denied` on a host whose
347
- * operator has not listed this tool (that is the default, not a
348
- * misconfiguration).
404
+ * `[connector_proxy]` policy: once its operator turns the proxy on, the
405
+ * enabled connectors are callable, and `allow` / `deny` are that operator's
406
+ * optional narrowing and subtraction. So `policy_denied` means either that
407
+ * the host never turned the proxy on, or that this pair was narrowed out or
408
+ * explicitly denied — not that a tool name was misspelled in a list you were
409
+ * supposed to maintain.
410
+ *
411
+ * Arguments are passed through verbatim (there is no client-side schema
412
+ * check); `get()` / `test()` return each tool's `input_schema` so you can see
413
+ * what it takes, and a parameter the server rejects comes back as
414
+ * `is_error: true`, not as a rejected promise.
349
415
  *
350
416
  * Resolves even when the tool itself failed — check `is_error`. It rejects
351
417
  * only when the call never reached the tool: `connector_call_timeout`,
package/dist/index.mjs CHANGED
@@ -275,7 +275,7 @@ var WebSocketTransport = class {
275
275
  /** Header the server mints the per-call connection id under. */
276
276
  const CONNECTION_HEADER = "x-app-server-connection-id";
277
277
  /** Protocol version this binding announces on the one-shot handshake. */
278
- const PROTOCOL_VERSION = "fp-1";
278
+ const PROTOCOL_VERSION = "fp-7";
279
279
  /**
280
280
  * Protocol method → REST route. Verified from handler bodies, not from the
281
281
  * route list (a route existing does not prove which method it mirrors).
@@ -333,7 +333,10 @@ const HTTP_ROUTES = {
333
333
  body: [
334
334
  "content",
335
335
  "idempotency_key",
336
- "attachments"
336
+ "attachments",
337
+ "mentions",
338
+ "model",
339
+ "reasoning_effort"
337
340
  ],
338
341
  source: "conversation_send() -> send_conversation_message_for_user (shared with the WS arm)"
339
342
  },
@@ -794,7 +797,9 @@ var ConversationClient = class {
794
797
  name: input.name,
795
798
  model,
796
799
  workspace: input.workspaceId ? { id: input.workspaceId } : void 0,
797
- reasoning_effort: input.reasoningEffort || void 0
800
+ reasoning_effort: input.reasoningEffort || void 0,
801
+ agent_id: input.agentId || void 0,
802
+ team_id: input.teamId || void 0
798
803
  });
799
804
  }
800
805
  update(conversationId, input) {
@@ -827,17 +832,33 @@ var ConversationClient = class {
827
832
  }
828
833
  /**
829
834
  * R15(W10):`attachments` 是**会话工作区内的绝对路径**(图片附件)。
835
+ * doc `27` §4.1:`mentions` 是**本轮挂载的技能**(`kind: "skill"`)——技能的正文与
836
+ * 不可变快照都随这一轮走;`agent` / `connector` 在 send 上没有载体,服务端会以
837
+ * `invalid_request` **明确拒绝**(不是静默不挂)。
838
+ *
839
+ * 两者缺省都不上 wire,保持老调用方的形状逐字不变;服务端只接受会话工作区内的真实
840
+ * 文件(越界 / 相对路径 / 不存在一律拒),准入见 `nomifun-app-server` 的
841
+ * `resolve_conversation_attachments` 与 `send_mention_skills`。
830
842
  *
831
- * 缺省不传,保持老调用方的 wire 形状逐字不变;服务端只接受会话工作区内的真实
832
- * 文件(越界 / 相对路径 / 不存在一律拒),具体准入见
833
- * `nomifun-app-server` 的 `resolve_conversation_attachments`。
843
+ * 第 4 个参数同时接受旧的 `string[]`(附件)与选项对象——再堆一个位置参数会让调用点
844
+ * 变成一串没有名字的布尔/数组。
834
845
  */
835
- send(conversationId, content, idempotencyKey, attachments = []) {
846
+ send(conversationId, content, idempotencyKey, options = {}) {
847
+ const attachments = Array.isArray(options) ? options : options.attachments ?? [];
848
+ const mentions = Array.isArray(options) ? [] : options.mentions ?? [];
849
+ const model = Array.isArray(options) ? void 0 : options.model;
850
+ const reasoningEffort = Array.isArray(options) ? void 0 : options.reasoningEffort;
836
851
  return this.transport.request("conversation/send", {
837
852
  conversation_id: conversationId,
838
853
  content,
839
854
  idempotency_key: idempotencyKey,
840
- ...attachments.length > 0 ? { attachments } : {}
855
+ ...attachments.length > 0 ? { attachments } : {},
856
+ ...mentions.length > 0 ? { mentions } : {},
857
+ ...model ? { model: {
858
+ provider_id: model.provider_id,
859
+ model: model.model
860
+ } } : {},
861
+ ...reasoningEffort ? { reasoning_effort: reasoningEffort } : {}
841
862
  });
842
863
  }
843
864
  cancel(conversationId) {
@@ -1062,7 +1083,19 @@ var ConnectorClient = class {
1062
1083
  status(connectorId) {
1063
1084
  return this.transport.request("connector/status", { connector_id: connectorId });
1064
1085
  }
1065
- /** Run a connection probe; the server persists the result. */
1086
+ /**
1087
+ * Run a connection probe and report what the connector currently offers —
1088
+ * including each tool's `input_schema`.
1089
+ *
1090
+ * It really connects: a stdio connector gets its child process spawned, an
1091
+ * HTTP/SSE one gets `initialize` + `tools/list`. The result is **persisted**,
1092
+ * so this is also what refreshes the tool list `get()` reads back.
1093
+ *
1094
+ * Named `test` and not `probe` on purpose: this repo's split is `test` for the
1095
+ * action (wire `connector/test`, `test_connection`) and `probe` for its
1096
+ * artifact (`ConnectorProbeResult`, `probe_status`), and every method here is
1097
+ * the last segment of its wire method.
1098
+ */
1066
1099
  test(connectorId) {
1067
1100
  return this.transport.request("connector/test", { connector_id: connectorId });
1068
1101
  }
@@ -1087,9 +1120,17 @@ var ConnectorClient = class {
1087
1120
  * The host holds the transport, its headers and its OAuth token; this sends a
1088
1121
  * tool name and an argument object and nothing else — you cannot name a URL,
1089
1122
  * a command or a header. Whether the pair is callable at all is the host's
1090
- * `[connector_proxy]` allowlist, so expect `policy_denied` on a host whose
1091
- * operator has not listed this tool (that is the default, not a
1092
- * misconfiguration).
1123
+ * `[connector_proxy]` policy: once its operator turns the proxy on, the
1124
+ * enabled connectors are callable, and `allow` / `deny` are that operator's
1125
+ * optional narrowing and subtraction. So `policy_denied` means either that
1126
+ * the host never turned the proxy on, or that this pair was narrowed out or
1127
+ * explicitly denied — not that a tool name was misspelled in a list you were
1128
+ * supposed to maintain.
1129
+ *
1130
+ * Arguments are passed through verbatim (there is no client-side schema
1131
+ * check); `get()` / `test()` return each tool's `input_schema` so you can see
1132
+ * what it takes, and a parameter the server rejects comes back as
1133
+ * `is_error: true`, not as a rejected promise.
1093
1134
  *
1094
1135
  * Resolves even when the tool itself failed — check `is_error`. It rejects
1095
1136
  * only when the call never reached the tool: `connector_call_timeout`,
@@ -1388,7 +1429,12 @@ function toWire(input) {
1388
1429
  steps: input.steps,
1389
1430
  command_id: input.commandId,
1390
1431
  idempotency_key: input.idempotencyKey,
1391
- mentions: input.mentions
1432
+ mentions: input.mentions,
1433
+ model: input.model ? {
1434
+ provider_id: input.model.provider_id,
1435
+ model: input.model.model
1436
+ } : void 0,
1437
+ reasoning_effort: input.reasoningEffort || void 0
1392
1438
  };
1393
1439
  }
1394
1440
  function toTeamWire(input) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@flowy-agent-store/client",
3
- "version": "0.1.0-beta.4",
3
+ "version": "0.1.0-beta.6",
4
4
  "description": "Transport-agnostic App Server client (docs/agent-store/07 §2.2)",
5
5
  "type": "module",
6
6
  "license": "Apache-2.0",
@@ -25,7 +25,7 @@
25
25
  "dist"
26
26
  ],
27
27
  "dependencies": {
28
- "@flowy-agent-store/protocol": "0.1.0-beta.4"
28
+ "@flowy-agent-store/protocol": "0.1.0-beta.6"
29
29
  },
30
30
  "scripts": {
31
31
  "build": "tsdown",