@flowy-agent-store/protocol 0.1.0-beta.6 → 0.1.0-beta.8

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
@@ -57,8 +57,23 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
57
57
  * `source_kind: "zip"`, one archive whose root *is* the market root. The
58
58
  * official bundles move to it because the old `url` form made a first fetch
59
59
  * mirror 14,714 files (611 MiB) for `experts` alone (doc `30`).
60
+ * **`fp-8` adds expert definition export**: `agent/export` and `team/export`
61
+ * return an {@link ExpertPack} — the persona, model hints, skill references and
62
+ * (for a team) the roster with every member expanded. Nothing existing changes
63
+ * shape, but the response carries the Agent Markdown body, which the catalog
64
+ * faces deliberately never do; both methods are WebSocket-only, so the
65
+ * documented route split becomes `48 / 73` (doc `32`).
60
66
  */
61
- const APP_SERVER_PROTOCOL_VERSION = "fp-7";
67
+ const APP_SERVER_PROTOCOL_VERSION = "fp-12";
68
+ /**
69
+ * Format version of {@link ExpertPack}.
70
+ *
71
+ * **Independent of {@link APP_SERVER_PROTOCOL_VERSION}** on purpose: the
72
+ * fingerprint versions *our* wire compatibility, this versions the **artifact
73
+ * contract for third-party runtimes**. Gate on this one; the fingerprint is
74
+ * about whether your client can talk to the host at all.
75
+ */
76
+ const APP_SERVER_EXPERT_PACK_FORMAT = 1;
62
77
  //#endregion
63
78
  //#region src/errors.ts
64
79
  var AppServerError = class extends Error {
@@ -450,6 +465,7 @@ function decodeConversationEvent(event) {
450
465
  }
451
466
  }
452
467
  //#endregion
468
+ exports.APP_SERVER_EXPERT_PACK_FORMAT = APP_SERVER_EXPERT_PACK_FORMAT;
453
469
  exports.APP_SERVER_PROTOCOL_VERSION = APP_SERVER_PROTOCOL_VERSION;
454
470
  exports.AppServerError = AppServerError;
455
471
  exports.ProtocolError = ProtocolError;
package/dist/index.d.cts CHANGED
@@ -56,8 +56,14 @@
56
56
  * `source_kind: "zip"`, one archive whose root *is* the market root. The
57
57
  * official bundles move to it because the old `url` form made a first fetch
58
58
  * mirror 14,714 files (611 MiB) for `experts` alone (doc `30`).
59
+ * **`fp-8` adds expert definition export**: `agent/export` and `team/export`
60
+ * return an {@link ExpertPack} — the persona, model hints, skill references and
61
+ * (for a team) the roster with every member expanded. Nothing existing changes
62
+ * shape, but the response carries the Agent Markdown body, which the catalog
63
+ * faces deliberately never do; both methods are WebSocket-only, so the
64
+ * documented route split becomes `48 / 73` (doc `32`).
59
65
  */
60
- export declare const APP_SERVER_PROTOCOL_VERSION = "fp-7";
66
+ export declare const APP_SERVER_PROTOCOL_VERSION = "fp-12";
61
67
  export interface JsonRpcRequest {
62
68
  jsonrpc: "2.0";
63
69
  id: number | string;
@@ -193,6 +199,17 @@ export interface Capabilities {
193
199
  marketplaces: boolean;
194
200
  store: boolean;
195
201
  models: boolean;
202
+ /**
203
+ * The expert **definition export** face (`agent/export` / `team/export`,
204
+ * doc 32).
205
+ *
206
+ * Reports the *seam*, not the policy — same split as `connector_calls`. A host
207
+ * wires it and then decides per request whether its `[expert_export]` table
208
+ * allows the id, so this flag says the methods exist, not that any given
209
+ * expert is exportable: a refusal arrives as `policy_denied`. Do not use it to
210
+ * grey out a button and assume that is the whole answer.
211
+ */
212
+ expert_export: boolean;
196
213
  }
197
214
  export interface WorkspaceRef {
198
215
  id: string;
@@ -866,6 +883,31 @@ export interface SkillDeleteResult {
866
883
  revealed_origin?: SkillOrigin | null;
867
884
  }
868
885
  export type ConnectorStatus = "installed" | "configured" | "authorization_required" | "authenticated" | "connected" | "degraded" | "error" | "reauthorization_required";
886
+ /** `connector/register` — a connector the host never imported (doc `34` §6.5). */
887
+ export interface ConnectorRegistration {
888
+ /** Its name on this host. Re-registering the same name updates it. */
889
+ name: string;
890
+ description?: string | null;
891
+ /**
892
+ * The template the host will store and later resolve — the same shape it keeps
893
+ * for a marketplace connector. Whatever `${secret:NAME}` its URL, headers or env
894
+ * name becomes the credential form; `values` carries the connector's own
895
+ * non-secret settings.
896
+ */
897
+ transport: ConnectorTransport;
898
+ }
899
+ /** The transport template, mirroring the host's own stored shape. */
900
+ export type ConnectorTransport = {
901
+ type: "http" | "sse";
902
+ url: string;
903
+ headers?: Record<string, string>;
904
+ values?: Record<string, string>;
905
+ } | {
906
+ type: "stdio";
907
+ command: string;
908
+ args?: string[];
909
+ env?: Record<string, string>;
910
+ };
869
911
  export interface ConnectorSummary {
870
912
  id: string;
871
913
  name: string;
@@ -880,6 +922,58 @@ export interface ConnectorSummary {
880
922
  * Absent for builtin hosts and for markets that ship no icon for the entry.
881
923
  */
882
924
  avatar_url?: string | null;
925
+ /**
926
+ * What the connector needs the user to fill in, when the host can describe it
927
+ * (doc `34` §6.1). Absent for a connector with no declaration and nothing to
928
+ * ask for.
929
+ *
930
+ * **Never carries a secret value**: `fields[].value` exists only for `plain`
931
+ * fields, which are the connector's own settings (`HOST`, `PORT`), and
932
+ * `missing` holds key names.
933
+ */
934
+ credential?: ConnectorCredential | null;
935
+ }
936
+ /** Both languages, already resolved by the host (doc `34` §5.2). */
937
+ export interface LocalizedString {
938
+ zh: string;
939
+ en: string;
940
+ }
941
+ /** How a connector authenticates. */
942
+ export type CredentialMode = "none" | "oauth" | "token";
943
+ /** What the caller has to do about it. */
944
+ export type CredentialStatus = "not_required" | "requires_input" | "configured" | "error";
945
+ /** One row of the credential form. */
946
+ export interface CredentialField {
947
+ key: string;
948
+ /** `secret` (the host's credential store) or `plain` (the connector's own value). */
949
+ kind: "secret" | "plain";
950
+ required: boolean;
951
+ label: LocalizedString;
952
+ placeholder: LocalizedString;
953
+ description: LocalizedString;
954
+ /** Only for `plain`: the value in effect. A secret's value never crosses the wire. */
955
+ value?: string | null;
956
+ }
957
+ /** The credential form and its state, as this caller sees them (doc `34` §6.1). */
958
+ export interface ConnectorCredential {
959
+ connector_id: string;
960
+ mode: CredentialMode;
961
+ status: CredentialStatus;
962
+ /** Key names still missing for this caller — never values. */
963
+ missing: string[];
964
+ fields: CredentialField[];
965
+ /**
966
+ * Form-level text from the marketplace declaration (doc `34` §5.2).
967
+ *
968
+ * A `token-schema.json` declares its title, its description and its "where do I
969
+ * get a key" link **once, for the form** — the market ships no per-field links,
970
+ * and copying the form's onto every field reads as "how do I get a key" under
971
+ * `PORT`.
972
+ */
973
+ title?: LocalizedString | null;
974
+ description?: LocalizedString | null;
975
+ doc_url?: LocalizedString | null;
976
+ doc_label?: LocalizedString | null;
883
977
  }
884
978
  export interface ConnectorTool {
885
979
  name: string;
@@ -1221,7 +1315,8 @@ export interface StoreInstallResult {
1221
1315
  entry_name: string;
1222
1316
  snapshot_id: string;
1223
1317
  version: string;
1224
- /** true when the components were already registered (no-op install). */
1318
+ /** true when the components were already registered (no-op install), or — for
1319
+ * an update — when the entry was already at the advertised version. */
1225
1320
  reused: boolean;
1226
1321
  installed_count: number;
1227
1322
  warnings: string[];
@@ -1230,6 +1325,15 @@ export interface StoreInstallResult {
1230
1325
  * store install is as branchable as a direct `install/run`. Absent on a host
1231
1326
  * that predates the field. */
1232
1327
  outcomes?: InstallOutcome[];
1328
+ /** Version the entry was installed at before this call (`store/update-entry`
1329
+ * only; absent means "this was an install"). */
1330
+ previous_version?: string | null;
1331
+ /** The snapshot that was replaced. Same rule as `previous_version`. */
1332
+ previous_snapshot_id?: string | null;
1333
+ /** Components of the replaced snapshot whose runtime artifacts were actually
1334
+ * released. `0` on an install, on a no-op update, and when a failed update
1335
+ * left the previous installation in place. */
1336
+ released_count?: number;
1233
1337
  }
1234
1338
  export interface LocalizedText {
1235
1339
  en?: string | null;
@@ -1291,6 +1395,129 @@ export interface TeamDetail extends TeamSummary {
1291
1395
  */
1292
1396
  connectors: string[];
1293
1397
  }
1398
+ /**
1399
+ * Format version of {@link ExpertPack}.
1400
+ *
1401
+ * **Independent of {@link APP_SERVER_PROTOCOL_VERSION}** on purpose: the
1402
+ * fingerprint versions *our* wire compatibility, this versions the **artifact
1403
+ * contract for third-party runtimes**. Gate on this one; the fingerprint is
1404
+ * about whether your client can talk to the host at all.
1405
+ */
1406
+ export declare const APP_SERVER_EXPERT_PACK_FORMAT = 1;
1407
+ export type ExpertPackKind = "agent" | "team";
1408
+ /** The expert's persona — the only body of text this face carries. */
1409
+ export interface ExpertPersona {
1410
+ /**
1411
+ * The Agent Markdown body, verbatim. The catalog face deliberately has no
1412
+ * field that could carry it (`AgentDetail`), so this is the only place it
1413
+ * appears — see doc 32 §2.
1414
+ */
1415
+ instructions: string;
1416
+ memory?: string | null;
1417
+ background?: string | null;
1418
+ }
1419
+ export interface ExpertModelRef {
1420
+ /** Host-local row id on the host that produced the pack; not portable. */
1421
+ provider_id?: string | null;
1422
+ model: string;
1423
+ }
1424
+ /**
1425
+ * Declared and resolved model hints. Neither is binding: `declared` is the
1426
+ * source frontmatter string and `resolved` is what the producing host resolved
1427
+ * it to. A consumer resolves its own model (doc 32 §5 R6).
1428
+ */
1429
+ export interface ExpertModel {
1430
+ declared?: string | null;
1431
+ resolved?: ExpertModelRef | null;
1432
+ effort?: string | null;
1433
+ max_turns?: number | null;
1434
+ }
1435
+ /**
1436
+ * One Skill the expert declares, **by reference** — fetch the bytes with
1437
+ * `skills.files()` / `skills.readFile()`. `name` and `id` are the same string:
1438
+ * `skill/list` publishes the Skill name as its id.
1439
+ */
1440
+ export interface ExpertSkillRef {
1441
+ name: string;
1442
+ id: string;
1443
+ }
1444
+ /**
1445
+ * One Connector a **team's own snapshot** installed and left enabled. Identity
1446
+ * and switch only — never transport, env, headers or token (doc 24 §2/§5.3);
1447
+ * tool schemas stay on `connector/get`.
1448
+ *
1449
+ * An **agent** pack's list is always empty, faithfully: this format has no
1450
+ * agent-level connector dependency (doc 02 §5.1).
1451
+ */
1452
+ export interface ExpertConnectorRef {
1453
+ id: string;
1454
+ name: string;
1455
+ enabled: boolean;
1456
+ }
1457
+ /** A declaration, never a permission boundary (doc 32 §5 R9). */
1458
+ export interface ExpertToolPolicy {
1459
+ tools: string[];
1460
+ disallowed_tools: string[];
1461
+ }
1462
+ export interface ExpertProvenance {
1463
+ source: string;
1464
+ snapshot_id: string;
1465
+ content_digest: string;
1466
+ preset_id?: string | null;
1467
+ preset_revision?: number | null;
1468
+ }
1469
+ /**
1470
+ * Which engine the definition was bound to on the producing host.
1471
+ *
1472
+ * `portable: false` is the normal case, not an error: an installed expert is a
1473
+ * Preset pinned to that host's runtime agent, which no other runtime has.
1474
+ */
1475
+ export interface ExpertRuntimeBinding {
1476
+ runtime: string;
1477
+ portable: boolean;
1478
+ }
1479
+ /** Team roster and policy. The roster is a hard boundary; the rest is intent. */
1480
+ export interface ExpertTeamPack {
1481
+ lead_agent_id: string;
1482
+ member_agent_ids: string[];
1483
+ planner_policy: string;
1484
+ routing_constraints: string[];
1485
+ workflow_limits: Record<string, unknown>;
1486
+ team_runtime_capabilities: string[];
1487
+ /** Fully expanded member packs, **leader first**. */
1488
+ members: ExpertPack[];
1489
+ }
1490
+ /**
1491
+ * A portable expert definition (`agent/export` / `team/export`, doc 32).
1492
+ *
1493
+ * A **definition, not execution semantics**: how a team plans and schedules its
1494
+ * steps, how tool and credential policy is applied, and the shape of its events
1495
+ * are all enforced by the runtime and are absent here. Doc 32 §5 (R1–R11) lists
1496
+ * what a consumer has to implement itself — answer that list rather than only
1497
+ * reading this shape.
1498
+ *
1499
+ * There is deliberately no export timestamp, so two exports of one snapshot are
1500
+ * byte-identical: `provenance.content_digest` is usable as a cache key, and two
1501
+ * exports can be diffed to answer "what changed upstream".
1502
+ */
1503
+ export interface ExpertPack {
1504
+ pack_format: number;
1505
+ kind: ExpertPackKind;
1506
+ id: string;
1507
+ version: string;
1508
+ name: string;
1509
+ display_name?: LocalizedText | null;
1510
+ description?: string | null;
1511
+ persona: ExpertPersona;
1512
+ model: ExpertModel;
1513
+ skills: ExpertSkillRef[];
1514
+ connectors: ExpertConnectorRef[];
1515
+ tool_policy: ExpertToolPolicy;
1516
+ /** Present exactly when `kind === "team"`. */
1517
+ team?: ExpertTeamPack | null;
1518
+ provenance: ExpertProvenance;
1519
+ runtime_binding: ExpertRuntimeBinding;
1520
+ }
1294
1521
  //#endregion
1295
1522
  //#region src/errors.d.ts
1296
1523
  export type ErrorCode = string;
package/dist/index.d.mts CHANGED
@@ -56,8 +56,14 @@
56
56
  * `source_kind: "zip"`, one archive whose root *is* the market root. The
57
57
  * official bundles move to it because the old `url` form made a first fetch
58
58
  * mirror 14,714 files (611 MiB) for `experts` alone (doc `30`).
59
+ * **`fp-8` adds expert definition export**: `agent/export` and `team/export`
60
+ * return an {@link ExpertPack} — the persona, model hints, skill references and
61
+ * (for a team) the roster with every member expanded. Nothing existing changes
62
+ * shape, but the response carries the Agent Markdown body, which the catalog
63
+ * faces deliberately never do; both methods are WebSocket-only, so the
64
+ * documented route split becomes `48 / 73` (doc `32`).
59
65
  */
60
- export declare const APP_SERVER_PROTOCOL_VERSION = "fp-7";
66
+ export declare const APP_SERVER_PROTOCOL_VERSION = "fp-12";
61
67
  export interface JsonRpcRequest {
62
68
  jsonrpc: "2.0";
63
69
  id: number | string;
@@ -193,6 +199,17 @@ export interface Capabilities {
193
199
  marketplaces: boolean;
194
200
  store: boolean;
195
201
  models: boolean;
202
+ /**
203
+ * The expert **definition export** face (`agent/export` / `team/export`,
204
+ * doc 32).
205
+ *
206
+ * Reports the *seam*, not the policy — same split as `connector_calls`. A host
207
+ * wires it and then decides per request whether its `[expert_export]` table
208
+ * allows the id, so this flag says the methods exist, not that any given
209
+ * expert is exportable: a refusal arrives as `policy_denied`. Do not use it to
210
+ * grey out a button and assume that is the whole answer.
211
+ */
212
+ expert_export: boolean;
196
213
  }
197
214
  export interface WorkspaceRef {
198
215
  id: string;
@@ -866,6 +883,31 @@ export interface SkillDeleteResult {
866
883
  revealed_origin?: SkillOrigin | null;
867
884
  }
868
885
  export type ConnectorStatus = "installed" | "configured" | "authorization_required" | "authenticated" | "connected" | "degraded" | "error" | "reauthorization_required";
886
+ /** `connector/register` — a connector the host never imported (doc `34` §6.5). */
887
+ export interface ConnectorRegistration {
888
+ /** Its name on this host. Re-registering the same name updates it. */
889
+ name: string;
890
+ description?: string | null;
891
+ /**
892
+ * The template the host will store and later resolve — the same shape it keeps
893
+ * for a marketplace connector. Whatever `${secret:NAME}` its URL, headers or env
894
+ * name becomes the credential form; `values` carries the connector's own
895
+ * non-secret settings.
896
+ */
897
+ transport: ConnectorTransport;
898
+ }
899
+ /** The transport template, mirroring the host's own stored shape. */
900
+ export type ConnectorTransport = {
901
+ type: "http" | "sse";
902
+ url: string;
903
+ headers?: Record<string, string>;
904
+ values?: Record<string, string>;
905
+ } | {
906
+ type: "stdio";
907
+ command: string;
908
+ args?: string[];
909
+ env?: Record<string, string>;
910
+ };
869
911
  export interface ConnectorSummary {
870
912
  id: string;
871
913
  name: string;
@@ -880,6 +922,58 @@ export interface ConnectorSummary {
880
922
  * Absent for builtin hosts and for markets that ship no icon for the entry.
881
923
  */
882
924
  avatar_url?: string | null;
925
+ /**
926
+ * What the connector needs the user to fill in, when the host can describe it
927
+ * (doc `34` §6.1). Absent for a connector with no declaration and nothing to
928
+ * ask for.
929
+ *
930
+ * **Never carries a secret value**: `fields[].value` exists only for `plain`
931
+ * fields, which are the connector's own settings (`HOST`, `PORT`), and
932
+ * `missing` holds key names.
933
+ */
934
+ credential?: ConnectorCredential | null;
935
+ }
936
+ /** Both languages, already resolved by the host (doc `34` §5.2). */
937
+ export interface LocalizedString {
938
+ zh: string;
939
+ en: string;
940
+ }
941
+ /** How a connector authenticates. */
942
+ export type CredentialMode = "none" | "oauth" | "token";
943
+ /** What the caller has to do about it. */
944
+ export type CredentialStatus = "not_required" | "requires_input" | "configured" | "error";
945
+ /** One row of the credential form. */
946
+ export interface CredentialField {
947
+ key: string;
948
+ /** `secret` (the host's credential store) or `plain` (the connector's own value). */
949
+ kind: "secret" | "plain";
950
+ required: boolean;
951
+ label: LocalizedString;
952
+ placeholder: LocalizedString;
953
+ description: LocalizedString;
954
+ /** Only for `plain`: the value in effect. A secret's value never crosses the wire. */
955
+ value?: string | null;
956
+ }
957
+ /** The credential form and its state, as this caller sees them (doc `34` §6.1). */
958
+ export interface ConnectorCredential {
959
+ connector_id: string;
960
+ mode: CredentialMode;
961
+ status: CredentialStatus;
962
+ /** Key names still missing for this caller — never values. */
963
+ missing: string[];
964
+ fields: CredentialField[];
965
+ /**
966
+ * Form-level text from the marketplace declaration (doc `34` §5.2).
967
+ *
968
+ * A `token-schema.json` declares its title, its description and its "where do I
969
+ * get a key" link **once, for the form** — the market ships no per-field links,
970
+ * and copying the form's onto every field reads as "how do I get a key" under
971
+ * `PORT`.
972
+ */
973
+ title?: LocalizedString | null;
974
+ description?: LocalizedString | null;
975
+ doc_url?: LocalizedString | null;
976
+ doc_label?: LocalizedString | null;
883
977
  }
884
978
  export interface ConnectorTool {
885
979
  name: string;
@@ -1221,7 +1315,8 @@ export interface StoreInstallResult {
1221
1315
  entry_name: string;
1222
1316
  snapshot_id: string;
1223
1317
  version: string;
1224
- /** true when the components were already registered (no-op install). */
1318
+ /** true when the components were already registered (no-op install), or — for
1319
+ * an update — when the entry was already at the advertised version. */
1225
1320
  reused: boolean;
1226
1321
  installed_count: number;
1227
1322
  warnings: string[];
@@ -1230,6 +1325,15 @@ export interface StoreInstallResult {
1230
1325
  * store install is as branchable as a direct `install/run`. Absent on a host
1231
1326
  * that predates the field. */
1232
1327
  outcomes?: InstallOutcome[];
1328
+ /** Version the entry was installed at before this call (`store/update-entry`
1329
+ * only; absent means "this was an install"). */
1330
+ previous_version?: string | null;
1331
+ /** The snapshot that was replaced. Same rule as `previous_version`. */
1332
+ previous_snapshot_id?: string | null;
1333
+ /** Components of the replaced snapshot whose runtime artifacts were actually
1334
+ * released. `0` on an install, on a no-op update, and when a failed update
1335
+ * left the previous installation in place. */
1336
+ released_count?: number;
1233
1337
  }
1234
1338
  export interface LocalizedText {
1235
1339
  en?: string | null;
@@ -1291,6 +1395,129 @@ export interface TeamDetail extends TeamSummary {
1291
1395
  */
1292
1396
  connectors: string[];
1293
1397
  }
1398
+ /**
1399
+ * Format version of {@link ExpertPack}.
1400
+ *
1401
+ * **Independent of {@link APP_SERVER_PROTOCOL_VERSION}** on purpose: the
1402
+ * fingerprint versions *our* wire compatibility, this versions the **artifact
1403
+ * contract for third-party runtimes**. Gate on this one; the fingerprint is
1404
+ * about whether your client can talk to the host at all.
1405
+ */
1406
+ export declare const APP_SERVER_EXPERT_PACK_FORMAT = 1;
1407
+ export type ExpertPackKind = "agent" | "team";
1408
+ /** The expert's persona — the only body of text this face carries. */
1409
+ export interface ExpertPersona {
1410
+ /**
1411
+ * The Agent Markdown body, verbatim. The catalog face deliberately has no
1412
+ * field that could carry it (`AgentDetail`), so this is the only place it
1413
+ * appears — see doc 32 §2.
1414
+ */
1415
+ instructions: string;
1416
+ memory?: string | null;
1417
+ background?: string | null;
1418
+ }
1419
+ export interface ExpertModelRef {
1420
+ /** Host-local row id on the host that produced the pack; not portable. */
1421
+ provider_id?: string | null;
1422
+ model: string;
1423
+ }
1424
+ /**
1425
+ * Declared and resolved model hints. Neither is binding: `declared` is the
1426
+ * source frontmatter string and `resolved` is what the producing host resolved
1427
+ * it to. A consumer resolves its own model (doc 32 §5 R6).
1428
+ */
1429
+ export interface ExpertModel {
1430
+ declared?: string | null;
1431
+ resolved?: ExpertModelRef | null;
1432
+ effort?: string | null;
1433
+ max_turns?: number | null;
1434
+ }
1435
+ /**
1436
+ * One Skill the expert declares, **by reference** — fetch the bytes with
1437
+ * `skills.files()` / `skills.readFile()`. `name` and `id` are the same string:
1438
+ * `skill/list` publishes the Skill name as its id.
1439
+ */
1440
+ export interface ExpertSkillRef {
1441
+ name: string;
1442
+ id: string;
1443
+ }
1444
+ /**
1445
+ * One Connector a **team's own snapshot** installed and left enabled. Identity
1446
+ * and switch only — never transport, env, headers or token (doc 24 §2/§5.3);
1447
+ * tool schemas stay on `connector/get`.
1448
+ *
1449
+ * An **agent** pack's list is always empty, faithfully: this format has no
1450
+ * agent-level connector dependency (doc 02 §5.1).
1451
+ */
1452
+ export interface ExpertConnectorRef {
1453
+ id: string;
1454
+ name: string;
1455
+ enabled: boolean;
1456
+ }
1457
+ /** A declaration, never a permission boundary (doc 32 §5 R9). */
1458
+ export interface ExpertToolPolicy {
1459
+ tools: string[];
1460
+ disallowed_tools: string[];
1461
+ }
1462
+ export interface ExpertProvenance {
1463
+ source: string;
1464
+ snapshot_id: string;
1465
+ content_digest: string;
1466
+ preset_id?: string | null;
1467
+ preset_revision?: number | null;
1468
+ }
1469
+ /**
1470
+ * Which engine the definition was bound to on the producing host.
1471
+ *
1472
+ * `portable: false` is the normal case, not an error: an installed expert is a
1473
+ * Preset pinned to that host's runtime agent, which no other runtime has.
1474
+ */
1475
+ export interface ExpertRuntimeBinding {
1476
+ runtime: string;
1477
+ portable: boolean;
1478
+ }
1479
+ /** Team roster and policy. The roster is a hard boundary; the rest is intent. */
1480
+ export interface ExpertTeamPack {
1481
+ lead_agent_id: string;
1482
+ member_agent_ids: string[];
1483
+ planner_policy: string;
1484
+ routing_constraints: string[];
1485
+ workflow_limits: Record<string, unknown>;
1486
+ team_runtime_capabilities: string[];
1487
+ /** Fully expanded member packs, **leader first**. */
1488
+ members: ExpertPack[];
1489
+ }
1490
+ /**
1491
+ * A portable expert definition (`agent/export` / `team/export`, doc 32).
1492
+ *
1493
+ * A **definition, not execution semantics**: how a team plans and schedules its
1494
+ * steps, how tool and credential policy is applied, and the shape of its events
1495
+ * are all enforced by the runtime and are absent here. Doc 32 §5 (R1–R11) lists
1496
+ * what a consumer has to implement itself — answer that list rather than only
1497
+ * reading this shape.
1498
+ *
1499
+ * There is deliberately no export timestamp, so two exports of one snapshot are
1500
+ * byte-identical: `provenance.content_digest` is usable as a cache key, and two
1501
+ * exports can be diffed to answer "what changed upstream".
1502
+ */
1503
+ export interface ExpertPack {
1504
+ pack_format: number;
1505
+ kind: ExpertPackKind;
1506
+ id: string;
1507
+ version: string;
1508
+ name: string;
1509
+ display_name?: LocalizedText | null;
1510
+ description?: string | null;
1511
+ persona: ExpertPersona;
1512
+ model: ExpertModel;
1513
+ skills: ExpertSkillRef[];
1514
+ connectors: ExpertConnectorRef[];
1515
+ tool_policy: ExpertToolPolicy;
1516
+ /** Present exactly when `kind === "team"`. */
1517
+ team?: ExpertTeamPack | null;
1518
+ provenance: ExpertProvenance;
1519
+ runtime_binding: ExpertRuntimeBinding;
1520
+ }
1294
1521
  //#endregion
1295
1522
  //#region src/errors.d.ts
1296
1523
  export type ErrorCode = string;
package/dist/index.mjs CHANGED
@@ -56,8 +56,23 @@
56
56
  * `source_kind: "zip"`, one archive whose root *is* the market root. The
57
57
  * official bundles move to it because the old `url` form made a first fetch
58
58
  * mirror 14,714 files (611 MiB) for `experts` alone (doc `30`).
59
+ * **`fp-8` adds expert definition export**: `agent/export` and `team/export`
60
+ * return an {@link ExpertPack} — the persona, model hints, skill references and
61
+ * (for a team) the roster with every member expanded. Nothing existing changes
62
+ * shape, but the response carries the Agent Markdown body, which the catalog
63
+ * faces deliberately never do; both methods are WebSocket-only, so the
64
+ * documented route split becomes `48 / 73` (doc `32`).
59
65
  */
60
- const APP_SERVER_PROTOCOL_VERSION = "fp-7";
66
+ const APP_SERVER_PROTOCOL_VERSION = "fp-12";
67
+ /**
68
+ * Format version of {@link ExpertPack}.
69
+ *
70
+ * **Independent of {@link APP_SERVER_PROTOCOL_VERSION}** on purpose: the
71
+ * fingerprint versions *our* wire compatibility, this versions the **artifact
72
+ * contract for third-party runtimes**. Gate on this one; the fingerprint is
73
+ * about whether your client can talk to the host at all.
74
+ */
75
+ const APP_SERVER_EXPERT_PACK_FORMAT = 1;
61
76
  //#endregion
62
77
  //#region src/errors.ts
63
78
  var AppServerError = class extends Error {
@@ -449,4 +464,4 @@ function decodeConversationEvent(event) {
449
464
  }
450
465
  }
451
466
  //#endregion
452
- export { APP_SERVER_PROTOCOL_VERSION, AppServerError, ProtocolError, RequestTimeoutError, TransportError, booleanValue, contentToText, decodeConversationEvent, formatError, isAppServerError, isRecord, isRetryableError, isRetryableTransportError, numberValue, otherLocalizedLang, parseContextUsage, parseTurnUsage, pickEntryTags, pickEntryText, pickLocalized, pickLocalizedList, pickVariantList, pickVariantText, planData, stringValue, thinkingData, tipsData, toLocalizedLang, toolCallData };
467
+ export { APP_SERVER_EXPERT_PACK_FORMAT, APP_SERVER_PROTOCOL_VERSION, AppServerError, ProtocolError, RequestTimeoutError, TransportError, booleanValue, contentToText, decodeConversationEvent, formatError, isAppServerError, isRecord, isRetryableError, isRetryableTransportError, numberValue, otherLocalizedLang, parseContextUsage, parseTurnUsage, pickEntryTags, pickEntryText, pickLocalized, pickLocalizedList, pickVariantList, pickVariantText, planData, stringValue, thinkingData, tipsData, toLocalizedLang, toolCallData };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@flowy-agent-store/protocol",
3
- "version": "0.1.0-beta.6",
3
+ "version": "0.1.0-beta.8",
4
4
  "description": "Versioned App Server Protocol types and wire errors (no runtime, no DOM/Node deps)",
5
5
  "type": "module",
6
6
  "license": "Apache-2.0",