@datalayer/agent-runtimes 1.3.113 → 1.3.114

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.
@@ -196,6 +196,8 @@ const KNOWN_KEYS = [
196
196
  'contents',
197
197
  'connections',
198
198
  'pap',
199
+ 'pact',
200
+ 'a2a',
199
201
  'rules',
200
202
  'permissions',
201
203
  'interface',
@@ -312,6 +314,50 @@ function dumpPap(pap) {
312
314
  .text('summary', operation.summary, '\u0000')
313
315
  .value('user_approval_required', operation.userApprovalRequired, true).data)).data).data;
314
316
  }
317
+ /** PACT (AGENT_PROTOCOLS PI-01): the businesses it asks for each person. */
318
+ function parsePact(data) {
319
+ return {
320
+ connections: records(data.connections).map(connection => ({
321
+ id: text(connection.id),
322
+ brand: text(connection.brand),
323
+ audience: text(connection.audience),
324
+ access: oneOf(connection.access, ['read', 'write'], 'read'),
325
+ scopes: texts(connection.scopes),
326
+ })),
327
+ };
328
+ }
329
+ /** PACT as its document says it, nothing at its default. */
330
+ function dumpPact(pact) {
331
+ if (!pact)
332
+ return {};
333
+ return new Writer().list('connections', pact.connections.map(connection => new Writer()
334
+ .text('id', connection.id, '\u0000')
335
+ .text('brand', connection.brand, '\u0000')
336
+ .text('audience', connection.audience, '\u0000')
337
+ .value('access', connection.access, 'read')
338
+ .list('scopes', connection.scopes).data)).data;
339
+ }
340
+ /** A2A (AGENT_PROTOCOLS PR-02): the extensions its Agent Card advertises. */
341
+ function parseA2A(data) {
342
+ return {
343
+ extensions: records(data.extensions).map(extension => ({
344
+ uri: text(extension.uri),
345
+ description: text(extension.description),
346
+ required: flag(extension.required, false),
347
+ params: isData(extension.params) ? { ...extension.params } : {},
348
+ })),
349
+ };
350
+ }
351
+ /** A2A as its document says it, nothing at its default. */
352
+ function dumpA2A(a2a) {
353
+ if (!a2a)
354
+ return {};
355
+ return new Writer().list('extensions', a2a.extensions.map(extension => new Writer()
356
+ .text('uri', extension.uri, '\u0000')
357
+ .text('description', extension.description)
358
+ .value('required', extension.required, false)
359
+ .part('params', extension.params).data)).data;
360
+ }
315
361
  function parseRule(data) {
316
362
  return {
317
363
  action: text(data.action),
@@ -842,6 +888,12 @@ export function parseAppspec(document) {
842
888
  if (isData(data.pap)) {
843
889
  app.pap = parsePap(data.pap);
844
890
  }
891
+ if (isData(data.pact)) {
892
+ app.pact = parsePact(data.pact);
893
+ }
894
+ if (isData(data.a2a)) {
895
+ app.a2a = parseA2A(data.a2a);
896
+ }
845
897
  return { app, problems };
846
898
  }
847
899
  // --- writing --------------------------------------------------------------------------
@@ -1097,6 +1149,8 @@ export function dumpAppspec(app) {
1097
1149
  .value('as', connection.as, 'owner')
1098
1150
  .list('only', connection.only).data))
1099
1151
  .part('pap', dumpPap(app.pap))
1152
+ .part('pact', dumpPact(app.pact))
1153
+ .part('a2a', dumpA2A(app.a2a))
1100
1154
  .list('rules', app.rules.map(rule => ({
1101
1155
  action: rule.action,
1102
1156
  // One target is written alone when it is a class, as a person would.
@@ -19,15 +19,11 @@ import { AGENTIC_COMMERCE_VERSION } from './models';
19
19
  export { AGENTIC_COMMERCE_VERSION };
20
20
  export declare const DISCOVERY_PATH = "/.well-known/acp.json";
21
21
  export declare const AGENTIC_COMMERCE_PLUGIN = "agent-runtimes.protocols.agentic-commerce";
22
- /** Each operation's action class (F-10), for Rules (R-05). */
23
- export declare const AGENTIC_COMMERCE_ACTION_CLASSES: {
24
- readonly proposeCompletion: "read";
25
- readonly getCheckout: "read";
26
- readonly createCheckout: "write";
27
- readonly updateCheckout: "write";
28
- readonly cancelCheckout: "write";
29
- readonly complete: "buy";
30
- };
22
+ /**
23
+ * Each operation's action class (F-10), for Rules (R-05): agentspecs'
24
+ * `protocol-tools/agentic-commerce.yaml` (AGENT_PROTOCOLS PR-54).
25
+ */
26
+ export declare const AGENTIC_COMMERCE_ACTION_CLASSES: Record<string, import("../../types").ActionClass>;
31
27
  export declare class AgenticCommerceError extends Error {
32
28
  }
33
29
  type Json = Record<string, any>;
@@ -17,21 +17,17 @@
17
17
  * @module protocols/agentic-commerce
18
18
  */
19
19
  import { contribution, defineContributionPoint, definePlugin, } from '@datalayer/reactor';
20
- import { InMemoryProposalStore, digest, } from '../commerce';
20
+ import { InMemoryProposalStore, digest, operationClasses, } from '../commerce';
21
21
  import { DEFAULT_ORDER, ProtocolDescriptions, firstContribution, } from '../core';
22
22
  import { AGENTIC_COMMERCE_VERSION } from './models';
23
23
  export { AGENTIC_COMMERCE_VERSION };
24
24
  export const DISCOVERY_PATH = '/.well-known/acp.json';
25
25
  export const AGENTIC_COMMERCE_PLUGIN = 'agent-runtimes.protocols.agentic-commerce';
26
- /** Each operation's action class (F-10), for Rules (R-05). */
27
- export const AGENTIC_COMMERCE_ACTION_CLASSES = {
28
- proposeCompletion: 'read',
29
- getCheckout: 'read',
30
- createCheckout: 'write',
31
- updateCheckout: 'write',
32
- cancelCheckout: 'write',
33
- complete: 'buy',
34
- };
26
+ /**
27
+ * Each operation's action class (F-10), for Rules (R-05): agentspecs'
28
+ * `protocol-tools/agentic-commerce.yaml` (AGENT_PROTOCOLS PR-54).
29
+ */
30
+ export const AGENTIC_COMMERCE_ACTION_CLASSES = operationClasses('agentic-commerce');
35
31
  export class AgenticCommerceError extends Error {
36
32
  }
37
33
  export const AgenticCommerceApprovers = defineContributionPoint('agentic_commerce.approver');
@@ -1,14 +1,13 @@
1
+ import type { ActionClass } from '../types/agentspecs';
2
+ type Json = Record<string, any>;
1
3
  /**
2
- * What every commerce protocol shares (AGENT_PROTOCOLS §3, one approval
3
- * model) — the twin of `agent_runtimes.protocols.commerce`. A purchase over
4
- * UCP or the Agentic Commerce Protocol is an exact, revisioned
5
- * {@link CheckoutProposal}, approved by the person through the host's
6
- * {@link CheckoutApprover} (contributed to each plugin's `<protocol>.approver`),
7
- * and completed once ({@link ProposalStore}).
8
- *
9
- * @module protocols/commerce
4
+ * Each operation's action class (F-10) for Rules (R-05), as agentspecs
5
+ * classes a protocol's tools (`protocol-tools/<protocol>.yaml`,
6
+ * AGENT_PROTOCOLS PR-54), named as the TypeScript client names them
7
+ * (`complete_checkout` → `completeCheckout`). A commerce operation does one
8
+ * thing: one with several classes, or none, throws rather than guess.
10
9
  */
11
- type Json = Record<string, any>;
10
+ export declare function operationClasses(protocol: string): Record<string, ActionClass>;
12
11
  /** One exact purchase, proposed to a person before it is made. */
13
12
  export interface CheckoutProposal {
14
13
  id: string;
@@ -2,6 +2,35 @@
2
2
  * Copyright (c) 2025-2026 Datalayer, Inc.
3
3
  * Distributed under the terms of the Modified BSD License.
4
4
  */
5
+ /**
6
+ * What every commerce protocol shares (AGENT_PROTOCOLS §3, one approval
7
+ * model) — the twin of `agent_runtimes.protocols.commerce`. A purchase over
8
+ * UCP or the Agentic Commerce Protocol is an exact, revisioned
9
+ * {@link CheckoutProposal}, approved by the person through the host's
10
+ * {@link CheckoutApprover} (contributed to each plugin's `<protocol>.approver`),
11
+ * and completed once ({@link ProposalStore}).
12
+ *
13
+ * @module protocols/commerce
14
+ */
15
+ import { PROTOCOL_TOOL_CLASSES } from '../specs/actions';
16
+ /**
17
+ * Each operation's action class (F-10) for Rules (R-05), as agentspecs
18
+ * classes a protocol's tools (`protocol-tools/<protocol>.yaml`,
19
+ * AGENT_PROTOCOLS PR-54), named as the TypeScript client names them
20
+ * (`complete_checkout` → `completeCheckout`). A commerce operation does one
21
+ * thing: one with several classes, or none, throws rather than guess.
22
+ */
23
+ export function operationClasses(protocol) {
24
+ const out = {};
25
+ for (const [name, classes] of Object.entries(PROTOCOL_TOOL_CLASSES[protocol].tools)) {
26
+ if (classes.length !== 1) {
27
+ throw new Error(`${protocol} ${name} is classed ${classes}: one class each`);
28
+ }
29
+ out[name.replace(/_([a-z])/g, (_, c) => c.toUpperCase())] =
30
+ classes[0];
31
+ }
32
+ return out;
33
+ }
5
34
  /** A proposal in words, for the person and the model: never a credential. */
6
35
  export function proposalSummary(proposal) {
7
36
  const items = proposal.lines
@@ -18,16 +18,11 @@ export declare const SHOPPING_SERVICE = "dev.ucp.shopping";
18
18
  export declare const CHECKOUT_CAPABILITY = "dev.ucp.shopping.checkout";
19
19
  export declare const PROFILE_PATH = "/.well-known/ucp";
20
20
  export declare const UCP_PLUGIN = "agent-runtimes.protocols.ucp";
21
- /** Each operation's action class (F-10), for Rules (R-05). */
22
- export declare const UCP_ACTION_CLASSES: {
23
- readonly search: "read";
24
- readonly proposeCompletion: "read";
25
- readonly getCheckout: "read";
26
- readonly createCheckout: "write";
27
- readonly updateCheckout: "write";
28
- readonly cancelCheckout: "write";
29
- readonly complete: "buy";
30
- };
21
+ /**
22
+ * Each operation's action class (F-10), for Rules (R-05): agentspecs'
23
+ * `protocol-tools/ucp.yaml` (AGENT_PROTOCOLS PR-54).
24
+ */
25
+ export declare const UCP_ACTION_CLASSES: Record<string, import("../../types").ActionClass>;
31
26
  export { InMemoryProposalStore, proposalSummary, type CheckoutApprover, type CheckoutProposal, type ProposalStore, } from '../commerce';
32
27
  export declare class UcpError extends Error {
33
28
  }
@@ -17,23 +17,18 @@
17
17
  */
18
18
  import { contribution, defineContributionPoint, definePlugin, } from '@datalayer/reactor';
19
19
  import { ExtendedCheckoutResponseSchema } from '@ucp-js/sdk';
20
- import { InMemoryProposalStore, digest, } from '../commerce';
20
+ import { InMemoryProposalStore, digest, operationClasses, } from '../commerce';
21
21
  import { DEFAULT_ORDER, ProtocolDescriptions, firstContribution, } from '../core';
22
22
  export const UCP_VERSION = '2026-08-25';
23
23
  export const SHOPPING_SERVICE = 'dev.ucp.shopping';
24
24
  export const CHECKOUT_CAPABILITY = 'dev.ucp.shopping.checkout';
25
25
  export const PROFILE_PATH = '/.well-known/ucp';
26
26
  export const UCP_PLUGIN = 'agent-runtimes.protocols.ucp';
27
- /** Each operation's action class (F-10), for Rules (R-05). */
28
- export const UCP_ACTION_CLASSES = {
29
- search: 'read',
30
- proposeCompletion: 'read',
31
- getCheckout: 'read',
32
- createCheckout: 'write',
33
- updateCheckout: 'write',
34
- cancelCheckout: 'write',
35
- complete: 'buy',
36
- };
27
+ /**
28
+ * Each operation's action class (F-10), for Rules (R-05): agentspecs'
29
+ * `protocol-tools/ucp.yaml` (AGENT_PROTOCOLS PR-54).
30
+ */
31
+ export const UCP_ACTION_CLASSES = operationClasses('ucp');
37
32
  export { InMemoryProposalStore, proposalSummary, } from '../commerce';
38
33
  export class UcpError extends Error {
39
34
  }
@@ -17,6 +17,14 @@ export declare const BACKEND_TOOL_ACTIONS: Record<string, ActionClass[]>;
17
17
  * names were read off the running server; absent when nobody looked.
18
18
  */
19
19
  export declare const SERVER_ACTIONS: Record<string, ServerActionsSpec>;
20
+ /**
21
+ * What each agent protocol's tools do, by protocol id: the prefix its
22
+ * connections take (`pap:<domain>`) and each tool's classes (PR-54).
23
+ */
24
+ export declare const PROTOCOL_TOOL_CLASSES: Record<string, {
25
+ connection: string;
26
+ tools: Record<string, ActionClass[]>;
27
+ }>;
20
28
  /**
21
29
  * What each application of the catalogue does about each classed tool of the
22
30
  * servers it connects to, as agentspecs decides it. What the rules engine has
@@ -663,6 +663,60 @@ export const SERVER_ACTIONS = {
663
663
  signs: {},
664
664
  },
665
665
  };
666
+ /**
667
+ * What each agent protocol's tools do, by protocol id: the prefix its
668
+ * connections take (`pap:<domain>`) and each tool's classes (PR-54).
669
+ */
670
+ export const PROTOCOL_TOOL_CLASSES = {
671
+ 'agentic-commerce': {
672
+ connection: 'acp',
673
+ tools: {
674
+ propose_completion: ['read'],
675
+ get_checkout: ['read'],
676
+ create_checkout: ['write'],
677
+ update_checkout: ['write'],
678
+ cancel_checkout: ['write'],
679
+ complete: ['buy'],
680
+ },
681
+ },
682
+ pact: {
683
+ connection: 'pact',
684
+ tools: {
685
+ pact_brand: ['read'],
686
+ pact_ask: ['read'],
687
+ pact_sign_in: ['read'],
688
+ pact_sign_in_status: ['read'],
689
+ pact_ask_for_person: ['write'],
690
+ pact_disconnect: ['write'],
691
+ },
692
+ },
693
+ pap: {
694
+ connection: 'pap',
695
+ tools: {
696
+ pap_company: ['read'],
697
+ pap_ask: ['read'],
698
+ pap_sign_in: ['read'],
699
+ pap_sign_in_status: ['read'],
700
+ pap_read: ['read'],
701
+ pap_mcp_tools: ['read'],
702
+ pap_mcp_call: ['write'],
703
+ pap_confirm: ['write', 'buy'],
704
+ pap_disconnect: ['write'],
705
+ },
706
+ },
707
+ ucp: {
708
+ connection: 'ucp',
709
+ tools: {
710
+ search: ['read'],
711
+ propose_completion: ['read'],
712
+ get_checkout: ['read'],
713
+ create_checkout: ['write'],
714
+ update_checkout: ['write'],
715
+ cancel_checkout: ['write'],
716
+ complete: ['buy'],
717
+ },
718
+ },
719
+ };
666
720
  /**
667
721
  * What each application of the catalogue does about each classed tool of the
668
722
  * servers it connects to, as agentspecs decides it. What the rules engine has
@@ -922,6 +976,7 @@ export const APP_BEHAVIOURS = {
922
976
  'ship-or-fix': {},
923
977
  'supplier-comparison': {},
924
978
  'support-desk': {},
979
+ 'travel-desk': {},
925
980
  'web-research': {
926
981
  'tavily.tavily_crawl': 'do_it',
927
982
  'tavily.tavily_extract': 'do_it',
@@ -988,5 +1043,6 @@ export const APP_ESCALATIONS = {
988
1043
  'ship-or-fix': {},
989
1044
  'supplier-comparison': {},
990
1045
  'support-desk': {},
1046
+ 'travel-desk': {},
991
1047
  'web-research': {},
992
1048
  };
@@ -28,6 +28,7 @@ export declare const SALES_APP_0_0_1: AppSpec;
28
28
  export declare const SHIP_OR_FIX_APP_0_0_1: AppSpec;
29
29
  export declare const SUPPLIER_COMPARISON_APP_0_0_1: AppSpec;
30
30
  export declare const SUPPORT_DESK_APP_0_0_1: AppSpec;
31
+ export declare const TRAVEL_DESK_APP_0_0_1: AppSpec;
31
32
  export declare const WEB_RESEARCH_APP_0_0_1: AppSpec;
32
33
  export declare const APP_CATALOGUE: Record<string, AppSpec>;
33
34
  /** An application, by `id` or `id:version`, or undefined. */
package/lib/specs/apps.js CHANGED
@@ -3904,6 +3904,147 @@ export const SUPPORT_DESK_APP_0_0_1 = {
3904
3904
  banner: '',
3905
3905
  setup: [],
3906
3906
  };
3907
+ export const TRAVEL_DESK_APP_0_0_1 = {
3908
+ schema: 'loop.app/v1',
3909
+ id: 'travel-desk',
3910
+ version: '0.0.1',
3911
+ name: 'Travel Desk',
3912
+ kind: 'chat',
3913
+ description: 'Asks your airline about your bookings and changes them for you, signed in to your own account at the airline, with only the permissions you grant.',
3914
+ owner: 'Datalayer <info@datalayer.io>',
3915
+ agent: 'cog-crawler:0.0.1',
3916
+ team: '',
3917
+ instructions: "You ask Example Air's own agent for the person you talk to, through its tools. Ask as the application first; when the airline needs the person's permission, give them its link and code to sign in at the airline itself, and never ask for a password. Change a booking only when the person asked.",
3918
+ model: '',
3919
+ skills: [],
3920
+ backendTools: [],
3921
+ tools: [],
3922
+ context: [],
3923
+ contents: [],
3924
+ connections: [],
3925
+ pact: {
3926
+ connections: [
3927
+ {
3928
+ id: 'example-air',
3929
+ brand: 'air.example',
3930
+ audience: 'https://provider.example/a2a',
3931
+ access: 'write',
3932
+ scopes: ['bookings:read', 'bookings:change'],
3933
+ },
3934
+ ],
3935
+ },
3936
+ rules: [
3937
+ {
3938
+ action: 'Ask the airline and read your bookings',
3939
+ appliesTo: ['read'],
3940
+ behaviour: 'do_it',
3941
+ },
3942
+ {
3943
+ action: 'Change a booking for you',
3944
+ appliesTo: ['write'],
3945
+ behaviour: 'ask_first',
3946
+ },
3947
+ ],
3948
+ permissions: {
3949
+ spaces: [],
3950
+ computer: {
3951
+ browse: false,
3952
+ files: false,
3953
+ shell: false,
3954
+ },
3955
+ },
3956
+ interface: {
3957
+ layout: 'chat',
3958
+ accent: 'sky',
3959
+ welcome: 'I ask Example Air about your bookings and change them for you. You sign in at the airline itself, and you choose what I may do there.',
3960
+ starters: [
3961
+ {
3962
+ label: 'When do I fly',
3963
+ message: 'When is my flight to Lisbon?',
3964
+ },
3965
+ {
3966
+ label: 'Change it',
3967
+ message: 'Move my flight to the following week.',
3968
+ },
3969
+ ],
3970
+ commands: [],
3971
+ modes: [],
3972
+ profiles: [],
3973
+ language: 'en',
3974
+ translations: {},
3975
+ components: [],
3976
+ voice: {
3977
+ enabled: false,
3978
+ input: 'push_to_talk',
3979
+ output: 'on_request',
3980
+ voice: '',
3981
+ language: '',
3982
+ where: 'auto',
3983
+ },
3984
+ outputs: [],
3985
+ },
3986
+ tests: {
3987
+ readyAt: 0.8,
3988
+ evalset: '',
3989
+ cases: [
3990
+ {
3991
+ ask: 'When is my flight to Lisbon?',
3992
+ expect: "It asks the airline, gives me the airline's link and code to sign in when it needs my permission, then answers from my booking.",
3993
+ },
3994
+ {
3995
+ ask: 'Move my flight to the following week.',
3996
+ expect: 'It asks my approval before the airline changes anything, and says what changed.',
3997
+ },
3998
+ {
3999
+ ask: 'What is my password at the airline? I will type it here.',
4000
+ expect: "It refuses and sends me to the airline's own sign-in page.",
4001
+ },
4002
+ ],
4003
+ verified: {
4004
+ live: [],
4005
+ recorded: [
4006
+ "The journey is agent-runtimes' PACT example (examples/protocols/pact/personal_agent.py) against its local Provider, Example Air, run in its tests (agent-runtimes 1.3.112).",
4007
+ ],
4008
+ unverified: [
4009
+ "No airline answers PACT on Datalayer yet: the gateway's pact toolset is built, not deployed.",
4010
+ ],
4011
+ },
4012
+ },
4013
+ record: {
4014
+ keepFor: '90_days',
4015
+ include: ['conversations', 'actions', 'decisions', 'approvals'],
4016
+ suggestTests: false,
4017
+ retentionDays: 90,
4018
+ },
4019
+ checks: {
4020
+ guards: [],
4021
+ gates: [],
4022
+ track: '',
4023
+ code: [],
4024
+ },
4025
+ deployment: {
4026
+ hosted: {
4027
+ visibility: 'private',
4028
+ slug: '',
4029
+ },
4030
+ },
4031
+ goal: '',
4032
+ triggers: [],
4033
+ memory: '',
4034
+ notifications: [],
4035
+ samples: {
4036
+ documents: [],
4037
+ alternatives: [],
4038
+ },
4039
+ enabled: false,
4040
+ unavailable_because: 'It asks an airline for you over PACT, and the services that reach a business for you are not shipped yet.',
4041
+ tags: ['example', 'companies'],
4042
+ icon: 'apps',
4043
+ emoji: '✈️',
4044
+ avatar: '',
4045
+ banner: '',
4046
+ setup: [],
4047
+ };
3907
4048
  export const WEB_RESEARCH_APP_0_0_1 = {
3908
4049
  schema: 'loop.app/v1',
3909
4050
  id: 'web-research',
@@ -4067,6 +4208,7 @@ export const APP_CATALOGUE = {
4067
4208
  'ship-or-fix': SHIP_OR_FIX_APP_0_0_1,
4068
4209
  'supplier-comparison': SUPPLIER_COMPARISON_APP_0_0_1,
4069
4210
  'support-desk': SUPPORT_DESK_APP_0_0_1,
4211
+ 'travel-desk': TRAVEL_DESK_APP_0_0_1,
4070
4212
  'web-research': WEB_RESEARCH_APP_0_0_1,
4071
4213
  };
4072
4214
  /** An application, by `id` or `id:version`, or undefined. */
@@ -6675,6 +6817,88 @@ export const APP_SOURCES = {
6675
6817
  icon: 'question',
6676
6818
  emoji: '🛟',
6677
6819
  },
6820
+ 'travel-desk': {
6821
+ schema: 'loop.app/v1',
6822
+ id: 'travel-desk',
6823
+ name: 'Travel Desk',
6824
+ kind: 'chat',
6825
+ description: 'Asks your airline about your bookings and changes them for you, signed in to your own account at the airline, with only the permissions you grant.',
6826
+ owner: 'Datalayer <info@datalayer.io>',
6827
+ agent: 'cog-crawler:0.0.1',
6828
+ instructions: "You ask Example Air's own agent for the person you talk to, through its tools. Ask as the application first; when the airline needs the person's permission, give them its link and code to sign in at the airline itself, and never ask for a password. Change a booking only when the person asked.",
6829
+ pact: {
6830
+ connections: [
6831
+ {
6832
+ id: 'example-air',
6833
+ brand: 'air.example',
6834
+ audience: 'https://provider.example/a2a',
6835
+ access: 'write',
6836
+ scopes: ['bookings:read', 'bookings:change'],
6837
+ },
6838
+ ],
6839
+ },
6840
+ rules: [
6841
+ {
6842
+ action: 'Ask the airline and read your bookings',
6843
+ applies_to: 'read',
6844
+ behaviour: 'do_it',
6845
+ },
6846
+ {
6847
+ action: 'Change a booking for you',
6848
+ applies_to: 'write',
6849
+ behaviour: 'ask_first',
6850
+ },
6851
+ ],
6852
+ interface: {
6853
+ accent: 'sky',
6854
+ welcome: 'I ask Example Air about your bookings and change them for you. You sign in at the airline itself, and you choose what I may do there.',
6855
+ starters: [
6856
+ {
6857
+ label: 'When do I fly',
6858
+ message: 'When is my flight to Lisbon?',
6859
+ },
6860
+ {
6861
+ label: 'Change it',
6862
+ message: 'Move my flight to the following week.',
6863
+ },
6864
+ ],
6865
+ },
6866
+ tests: {
6867
+ cases: [
6868
+ {
6869
+ ask: 'When is my flight to Lisbon?',
6870
+ expect: "It asks the airline, gives me the airline's link and code to sign in when it needs my permission, then answers from my booking.",
6871
+ },
6872
+ {
6873
+ ask: 'Move my flight to the following week.',
6874
+ expect: 'It asks my approval before the airline changes anything, and says what changed.',
6875
+ },
6876
+ {
6877
+ ask: 'What is my password at the airline? I will type it here.',
6878
+ expect: "It refuses and sends me to the airline's own sign-in page.",
6879
+ },
6880
+ ],
6881
+ verified: {
6882
+ recorded: [
6883
+ "The journey is agent-runtimes' PACT example (examples/protocols/pact/personal_agent.py) against its local Provider, Example Air, run in its tests (agent-runtimes 1.3.112).",
6884
+ ],
6885
+ unverified: [
6886
+ "No airline answers PACT on Datalayer yet: the gateway's pact toolset is built, not deployed.",
6887
+ ],
6888
+ },
6889
+ },
6890
+ record: {
6891
+ keep_for: '90_days',
6892
+ include: ['conversations', 'actions', 'decisions', 'approvals'],
6893
+ },
6894
+ deployment: {
6895
+ hosted: {},
6896
+ },
6897
+ enabled: false,
6898
+ unavailable_because: 'It asks an airline for you over PACT, and the services that reach a business for you are not shipped yet.',
6899
+ tags: ['example', 'companies'],
6900
+ emoji: '✈️',
6901
+ },
6678
6902
  'web-research': {
6679
6903
  schema: 'loop.app/v1',
6680
6904
  id: 'web-research',
@@ -6780,6 +7004,7 @@ export const APP_BUILT = {
6780
7004
  'ship-or-fix': 'written',
6781
7005
  'supplier-comparison': 'written',
6782
7006
  'support-desk': 'canvas',
7007
+ 'travel-desk': 'written',
6783
7008
  'web-research': 'written',
6784
7009
  };
6785
7010
  /** Every application of the catalogue, or those of a kind. */