@datalayer/agent-runtimes 1.3.94 → 1.3.96
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-embed/chunks/AgentInspector-DaMCROPs.js +1 -0
- package/dist-embed/chunks/{AgentInspectorDialog-LBbHMnDa.js → AgentInspectorDialog-zGMiFR5z.js} +1 -1
- package/dist-embed/chunks/ChatView-DE-jo1oJ.js +288 -0
- package/dist-embed/datalayer-app-main.js +110 -110
- package/dist-embed/datalayer-app.js +1 -1
- package/lib/apps/__tests__/fixtures/sceneCheckCases.json +352 -0
- package/lib/apps/apps/computer.d.ts +25 -1
- package/lib/apps/apps/computer.js +45 -2
- package/lib/apps/apps/sceneChecks.d.ts +92 -0
- package/lib/apps/apps/sceneChecks.js +649 -0
- package/lib/apps/apps/sceneShape.d.ts +8 -0
- package/lib/apps/apps/sceneShape.js +191 -0
- package/lib/apps/apps/sceneYaml.d.ts +64 -0
- package/lib/apps/apps/sceneYaml.js +253 -0
- package/lib/apps/core/canvasParts.d.ts +28 -0
- package/lib/apps/core/canvasParts.js +14 -0
- package/lib/apps/core/index.d.ts +1 -0
- package/lib/apps/core/index.js +2 -0
- package/lib/apps/embed/loader.js +10 -0
- package/lib/apps/plugins/agents/SandboxSelector.js +13 -2
- package/lib/apps/plugins/agents/host.d.ts +2 -0
- package/lib/apps/plugins/agents/host.js +16 -0
- package/lib/apps/plugins/agents/plugin.js +10 -2
- package/lib/apps/plugins/agents/switchable.d.ts +12 -0
- package/lib/apps/plugins/agents/switchable.js +23 -0
- package/lib/apps/plugins/app-computer/AppComputer.js +18 -2
- package/lib/apps/plugins/canvas-parts/index.d.ts +44 -0
- package/lib/apps/plugins/canvas-parts/index.js +209 -0
- package/lib/components/teams/useA2ATeam.js +1 -1
- package/lib/examples/HomeExample.js +1 -1
- package/lib/examples/ScenesExample.d.ts +1 -1
- package/lib/examples/example-selector.js +1 -1
- package/lib/hooks/useAgUi.js +4 -1
- package/lib/protocols/AGUIAdapter.js +5 -1
- package/lib/protocols/agUiRefusal.d.ts +47 -0
- package/lib/protocols/agUiRefusal.js +87 -0
- package/lib/specs/apps.js +32 -24
- package/lib/specs/scenes.js +147 -142
- package/lib/specs/teams/teams.js +13 -13
- package/package.json +3 -1
- package/scripts/dist-embed.mjs +116 -0
- package/scripts/record-scene-checks.py +600 -0
- package/dist-embed/chunks/AgentInspector-DfPciQ79.js +0 -1
- package/dist-embed/chunks/ChatView-BzFbN_mp.js +0 -288
|
@@ -1 +1 @@
|
|
|
1
|
-
(()=>{(function(){const
|
|
1
|
+
(()=>{(function(){const s="datalayer-app-main.js",t=document.currentScript;if(!t||!t.src){console.error("datalayer-app: the script has to be loaded by a script tag with a src, so it knows where its module is.");return}const n=window;n.__webpack_public_path__===void 0&&(n.__webpack_public_path__="");const e=new URL(s,t.src).href;import(e).catch(a=>{const i=a instanceof Error?a.message:String(a),o=`The application could not be loaded: ${e} did not load (${i}).`;console.error(`datalayer-app: ${o}`),document.querySelectorAll("datalayer-app").forEach(c=>{if(c.shadowRoot)return;const r=document.createElement("p");r.textContent=o,c.attachShadow({mode:"open"}).appendChild(r)})})})();})();
|
|
@@ -0,0 +1,352 @@
|
|
|
1
|
+
{
|
|
2
|
+
"says": "What `loop` refuses of a scene, recorded from agentspecs (plans/STUDIO.md S-10).",
|
|
3
|
+
"recordedWith": "scripts/record-scene-checks.py",
|
|
4
|
+
"cases": [
|
|
5
|
+
{
|
|
6
|
+
"name": "a scene with nobody on stage",
|
|
7
|
+
"yaml": "schema: loop.scene/v1\nid: probe\nversion: 0.0.1\nname: Probe\n",
|
|
8
|
+
"says": [
|
|
9
|
+
"probe: the scene stages nobody: it names a `team`, or writes its `cast`"
|
|
10
|
+
]
|
|
11
|
+
},
|
|
12
|
+
{
|
|
13
|
+
"name": "the entry is not in the cast",
|
|
14
|
+
"yaml": "schema: loop.scene/v1\nid: probe\nversion: 0.0.1\nname: Probe\nentry: nobody\ncast:\n - member: sales\n app: sales\n role: initiator\n runs_in: runtime\n persona:\n name: Sales\n",
|
|
15
|
+
"says": ["The scene enters at 'nobody', which is not in its cast."]
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
"name": "the entry is a system",
|
|
19
|
+
"yaml": "schema: loop.scene/v1\nid: probe\nversion: 0.0.1\nname: Probe\nentry: odoo\ncast:\n - member: odoo\n server: odoo-accounting\n persona:\n name: Odoo\n",
|
|
20
|
+
"says": [
|
|
21
|
+
"Its cast makes no team: supervisor 'Odoo' needs a `ref` into the agent catalogue, an `app` from the application catalogue, or a `model` and `instructions` of its own"
|
|
22
|
+
]
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
"name": "a system asks",
|
|
26
|
+
"yaml": "schema: loop.scene/v1\nid: probe\nversion: 0.0.1\nname: Probe\nentry: sales\ncast:\n - member: sales\n app: sales\n role: initiator\n runs_in: runtime\n persona:\n name: Sales\n - member: odoo\n server: odoo-accounting\n persona:\n name: Odoo\n talks_to:\n - member: sales\n over: a2a\n",
|
|
27
|
+
"says": [
|
|
28
|
+
"Its cast makes no team: member 'odoo' is a server: it answers over MCP and asks nobody"
|
|
29
|
+
]
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
"name": "a member talks to itself",
|
|
33
|
+
"yaml": "schema: loop.scene/v1\nid: probe\nversion: 0.0.1\nname: Probe\nentry: sales\ncast:\n - member: sales\n app: sales\n role: initiator\n runs_in: runtime\n persona:\n name: Sales\n talks_to:\n - member: sales\n over: a2a\n",
|
|
34
|
+
"says": ["Its cast makes no team: member 'sales' talks to itself"]
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
"name": "a member talks to nobody of the cast",
|
|
38
|
+
"yaml": "schema: loop.scene/v1\nid: probe\nversion: 0.0.1\nname: Probe\nentry: sales\ncast:\n - member: sales\n app: sales\n role: initiator\n runs_in: runtime\n persona:\n name: Sales\n talks_to:\n - member: ghost\n over: a2a\n",
|
|
39
|
+
"says": [
|
|
40
|
+
"Its cast makes no team: member 'sales' talks to 'ghost', which is not a member of team 'probe'"
|
|
41
|
+
]
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
"name": "a system asked over a2a",
|
|
45
|
+
"yaml": "schema: loop.scene/v1\nid: probe\nversion: 0.0.1\nname: Probe\nentry: sales\ncast:\n - member: sales\n app: sales\n role: initiator\n runs_in: runtime\n persona:\n name: Sales\n talks_to:\n - member: odoo\n over: a2a\n - member: odoo\n server: odoo-accounting\n persona:\n name: Odoo\n",
|
|
46
|
+
"says": [
|
|
47
|
+
"Its cast makes no team: member 'sales' talks to 'odoo' over a2a, which is a server: a server is asked over mcp"
|
|
48
|
+
]
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
"name": "an agent asked over mcp",
|
|
52
|
+
"yaml": "schema: loop.scene/v1\nid: probe\nversion: 0.0.1\nname: Probe\nentry: sales\ncast:\n - member: sales\n app: sales\n role: initiator\n runs_in: runtime\n persona:\n name: Sales\n talks_to:\n - member: books\n over: mcp\n - member: books\n app: accounting\n role: contributor\n runs_in: runtime\n persona:\n name: Accounting\n",
|
|
53
|
+
"says": [
|
|
54
|
+
"Its cast makes no team: member 'sales' talks to 'books' over mcp, which is not a server: an agent or an application is asked over a2a"
|
|
55
|
+
]
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
"name": "a member named twice",
|
|
59
|
+
"yaml": "schema: loop.scene/v1\nid: probe\nversion: 0.0.1\nname: Probe\nentry: sales\ncast:\n - member: sales\n app: sales\n role: initiator\n runs_in: runtime\n persona:\n name: Sales\n - member: sales\n app: sales\n role: initiator\n runs_in: runtime\n persona:\n name: Sales\n",
|
|
60
|
+
"says": ["probe: the cast names 'sales' twice"]
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
"name": "two beats with one name",
|
|
64
|
+
"yaml": "schema: loop.scene/v1\nid: probe\nversion: 0.0.1\nname: Probe\nentry: sales\ncast:\n - member: sales\n app: sales\n role: initiator\n runs_in: runtime\n persona:\n name: Sales\nscript:\n - id: open\n cue:\n say: Show the books\n expect: The books are read\n moves:\n - who: sales\n answers: words\n - id: open\n cue:\n say: Show them again\n expect: The books are read again\n moves:\n - who: sales\n answers: words\n",
|
|
65
|
+
"says": ["probe: the script has two beats named 'open'"]
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
"name": "a member placed outside the box",
|
|
69
|
+
"yaml": "schema: loop.scene/v1\nid: probe\nversion: 0.0.1\nname: Probe\nentry: sales\ncast:\n - member: sales\n app: sales\n role: initiator\n runs_in: runtime\n persona:\n name: Sales\nstage:\n positions:\n sales:\n x: 40\n y: 0.5\n",
|
|
70
|
+
"says": [
|
|
71
|
+
"probe: stage.positions.sales.x: Input should be less than or equal to 1"
|
|
72
|
+
]
|
|
73
|
+
},
|
|
74
|
+
{
|
|
75
|
+
"name": "a member that is nothing at all",
|
|
76
|
+
"yaml": "schema: loop.scene/v1\nid: probe\nversion: 0.0.1\nname: Probe\nentry: sales\ncast:\n - member: sales\n app: sales\n role: initiator\n runs_in: runtime\n persona:\n name: Sales\n - member: ghost\n",
|
|
77
|
+
"says": [
|
|
78
|
+
"Its cast makes no team: member 'ghost' needs a `ref` into the agent catalogue, an `app` from the application catalogue, a `server` from the MCP server catalogue, or enough of its own definition (`name`, `goal`) to stand alone"
|
|
79
|
+
]
|
|
80
|
+
},
|
|
81
|
+
{
|
|
82
|
+
"name": "the scene wears a member's face",
|
|
83
|
+
"yaml": "schema: loop.scene/v1\nid: probe\nversion: 0.0.1\nname: Probe\nemoji: 🧮\nentry: sales\ncast:\n - member: sales\n app: sales\n role: initiator\n runs_in: runtime\n persona:\n name: Sales\n face: 🧮\n",
|
|
84
|
+
"says": [
|
|
85
|
+
"The scene wears 🧮, a member's face: a scene has a face of its own."
|
|
86
|
+
]
|
|
87
|
+
},
|
|
88
|
+
{
|
|
89
|
+
"name": "a system of the setting that is no server",
|
|
90
|
+
"yaml": "schema: loop.scene/v1\nid: probe\nversion: 0.0.1\nname: Probe\nentry: sales\ncast:\n - member: sales\n app: sales\n role: initiator\n runs_in: runtime\n persona:\n name: Sales\nsetting:\n systems:\n - server: nosuch\n as: Nope\n",
|
|
91
|
+
"says": ["There is no MCP server named 'nosuch'."]
|
|
92
|
+
},
|
|
93
|
+
{
|
|
94
|
+
"name": "a system nobody reaches",
|
|
95
|
+
"yaml": "schema: loop.scene/v1\nid: probe\nversion: 0.0.1\nname: Probe\nentry: sales\ncast:\n - member: sales\n app: sales\n role: initiator\n runs_in: runtime\n persona:\n name: Sales\nsetting:\n systems:\n - server: odoo-accounting\n as: Odoo\n",
|
|
96
|
+
"says": [
|
|
97
|
+
"The system 'Odoo' (odoo-accounting) is on stage, and no member of the cast reaches it."
|
|
98
|
+
]
|
|
99
|
+
},
|
|
100
|
+
{
|
|
101
|
+
"name": "a system reached through a connection",
|
|
102
|
+
"yaml": "schema: loop.scene/v1\nid: probe\nversion: 0.0.1\nname: Probe\nentry: books\ncast:\n - member: books\n app: accounting\n role: contributor\n runs_in: runtime\n persona:\n name: Accounting\nsetting:\n systems:\n - server: odoo-accounting\n as: Odoo\n",
|
|
103
|
+
"says": []
|
|
104
|
+
},
|
|
105
|
+
{
|
|
106
|
+
"name": "a Frame the catalogue has not",
|
|
107
|
+
"yaml": "schema: loop.scene/v1\nid: probe\nversion: 0.0.1\nname: Probe\nentry: sales\ncast:\n - member: sales\n app: sales\n role: initiator\n runs_in: runtime\n persona:\n name: Sales\nsetting:\n frames:\n - nosuch\n",
|
|
108
|
+
"says": ["There is no Frame named 'nosuch'."]
|
|
109
|
+
},
|
|
110
|
+
{
|
|
111
|
+
"name": "the stage places someone not in the cast",
|
|
112
|
+
"yaml": "schema: loop.scene/v1\nid: probe\nversion: 0.0.1\nname: Probe\nentry: sales\ncast:\n - member: sales\n app: sales\n role: initiator\n runs_in: runtime\n persona:\n name: Sales\nstage:\n positions:\n ghost:\n x: 0.2\n y: 0.4\n",
|
|
113
|
+
"says": ["The stage places 'ghost', which is not in the cast."]
|
|
114
|
+
},
|
|
115
|
+
{
|
|
116
|
+
"name": "a balloon opens first for someone not in the cast",
|
|
117
|
+
"yaml": "schema: loop.scene/v1\nid: probe\nversion: 0.0.1\nname: Probe\nentry: sales\ncast:\n - member: sales\n app: sales\n role: initiator\n runs_in: runtime\n persona:\n name: Sales\nstage:\n opens_first: ghost\n",
|
|
118
|
+
"says": ["The balloon of 'ghost' opens first, and it is not in the cast."]
|
|
119
|
+
},
|
|
120
|
+
{
|
|
121
|
+
"name": "an address for someone not in the cast",
|
|
122
|
+
"yaml": "schema: loop.scene/v1\nid: probe\nversion: 0.0.1\nname: Probe\nentry: sales\ncast:\n - member: sales\n app: sales\n role: initiator\n runs_in: runtime\n persona:\n name: Sales\ndeployment:\n addresses:\n ghost: GHOST_URL\n",
|
|
123
|
+
"says": ["An address is read for 'ghost', which is not in the cast."]
|
|
124
|
+
},
|
|
125
|
+
{
|
|
126
|
+
"name": "an address for a member in the browser",
|
|
127
|
+
"yaml": "schema: loop.scene/v1\nid: probe\nversion: 0.0.1\nname: Probe\nentry: sales\ncast:\n - member: sales\n app: sales\n role: initiator\n runs_in: browser\n persona:\n name: Sales\ndeployment:\n addresses:\n sales: SALES_URL\n",
|
|
128
|
+
"says": ["'sales' runs in the browser: it has no address."]
|
|
129
|
+
},
|
|
130
|
+
{
|
|
131
|
+
"name": "visitors may watch and a member has no address",
|
|
132
|
+
"yaml": "schema: loop.scene/v1\nid: probe\nversion: 0.0.1\nname: Probe\nentry: sales\ncast:\n - member: sales\n app: sales\n role: initiator\n runs_in: runtime\n persona:\n name: Sales\naudience:\n who: visitors\n",
|
|
133
|
+
"says": [
|
|
134
|
+
"Visitors may watch, and 'sales' runs on a runtime with no address: deployment.addresses names none for it."
|
|
135
|
+
]
|
|
136
|
+
},
|
|
137
|
+
{
|
|
138
|
+
"name": "a beat its entry does not answer",
|
|
139
|
+
"yaml": "schema: loop.scene/v1\nid: probe\nversion: 0.0.1\nname: Probe\nentry: sales\ncast:\n - member: sales\n app: sales\n role: initiator\n runs_in: runtime\n persona:\n name: Sales\n - member: books\n app: accounting\n role: contributor\n runs_in: runtime\n persona:\n name: Accounting\nscript:\n - id: open\n cue:\n say: Show the books\n expect: The books are read\n moves:\n - who: books\n answers: table\n",
|
|
140
|
+
"says": [
|
|
141
|
+
"Beat 'open': its cue is answered by nobody — no move is the entry's ('sales')."
|
|
142
|
+
]
|
|
143
|
+
},
|
|
144
|
+
{
|
|
145
|
+
"name": "a beat moved by someone not in the cast",
|
|
146
|
+
"yaml": "schema: loop.scene/v1\nid: probe\nversion: 0.0.1\nname: Probe\nentry: sales\ncast:\n - member: sales\n app: sales\n role: initiator\n runs_in: runtime\n persona:\n name: Sales\nscript:\n - id: open\n cue:\n say: Show the books\n expect: The books are read\n moves:\n - who: sales\n answers: words\n - who: ghost\n answers: words\n",
|
|
147
|
+
"says": ["Beat 'open': 'ghost' moves, and is not in the cast."]
|
|
148
|
+
},
|
|
149
|
+
{
|
|
150
|
+
"name": "a beat moved by a system",
|
|
151
|
+
"yaml": "schema: loop.scene/v1\nid: probe\nversion: 0.0.1\nname: Probe\nentry: sales\ncast:\n - member: sales\n app: sales\n role: initiator\n runs_in: runtime\n persona:\n name: Sales\n - member: odoo\n server: odoo-accounting\n persona:\n name: Odoo\nscript:\n - id: open\n cue:\n say: Show the books\n expect: The books are read\n moves:\n - who: sales\n answers: words\n - who: odoo\n answers: words\n",
|
|
152
|
+
"says": [
|
|
153
|
+
"Beat 'open': 'odoo' moves, and a system answers tool by tool: it asks nobody."
|
|
154
|
+
]
|
|
155
|
+
},
|
|
156
|
+
{
|
|
157
|
+
"name": "a move that asks someone not in the cast",
|
|
158
|
+
"yaml": "schema: loop.scene/v1\nid: probe\nversion: 0.0.1\nname: Probe\nentry: sales\ncast:\n - member: sales\n app: sales\n role: initiator\n runs_in: runtime\n persona:\n name: Sales\nscript:\n - id: open\n cue:\n say: Show the books\n expect: The books are read\n moves:\n - who: sales\n asks: ghost\n over: a2a\n what: the books\n",
|
|
159
|
+
"says": ["Beat 'open': 'sales' asks 'ghost', which is not in the cast."]
|
|
160
|
+
},
|
|
161
|
+
{
|
|
162
|
+
"name": "a move over mcp that asks no system",
|
|
163
|
+
"yaml": "schema: loop.scene/v1\nid: probe\nversion: 0.0.1\nname: Probe\nentry: sales\ncast:\n - member: sales\n app: sales\n role: initiator\n runs_in: runtime\n persona:\n name: Sales\n - member: books\n app: accounting\n role: contributor\n runs_in: runtime\n persona:\n name: Accounting\nscript:\n - id: open\n cue:\n say: Show the books\n expect: The books are read\n moves:\n - who: sales\n asks: books\n over: mcp\n what: the books\n",
|
|
164
|
+
"says": [
|
|
165
|
+
"Beat 'open': 'sales' asks 'books' over mcp, which is not a system of the scene."
|
|
166
|
+
]
|
|
167
|
+
},
|
|
168
|
+
{
|
|
169
|
+
"name": "a move over a2a that asks a system",
|
|
170
|
+
"yaml": "schema: loop.scene/v1\nid: probe\nversion: 0.0.1\nname: Probe\nentry: sales\ncast:\n - member: sales\n app: sales\n role: initiator\n runs_in: runtime\n persona:\n name: Sales\n - member: odoo\n server: odoo-accounting\n persona:\n name: Odoo\nscript:\n - id: open\n cue:\n say: Show the books\n expect: The books are read\n moves:\n - who: sales\n asks: odoo\n over: a2a\n what: the books\n",
|
|
171
|
+
"says": [
|
|
172
|
+
"Beat 'open': 'sales' asks 'odoo' over a2a, a system: a system is asked over mcp."
|
|
173
|
+
]
|
|
174
|
+
},
|
|
175
|
+
{
|
|
176
|
+
"name": "a move that asks a member it does not talk to",
|
|
177
|
+
"yaml": "schema: loop.scene/v1\nid: probe\nversion: 0.0.1\nname: Probe\nentry: sales\ncast:\n - member: sales\n app: sales\n role: initiator\n runs_in: runtime\n persona:\n name: Sales\n - member: books\n app: accounting\n role: contributor\n runs_in: runtime\n persona:\n name: Accounting\nscript:\n - id: open\n cue:\n say: Show the books\n expect: The books are read\n moves:\n - who: sales\n asks: books\n over: a2a\n what: the books\n",
|
|
178
|
+
"says": [
|
|
179
|
+
"Beat 'open': 'sales' asks 'books', which the team does not have it talk to."
|
|
180
|
+
]
|
|
181
|
+
},
|
|
182
|
+
{
|
|
183
|
+
"name": "a branch that goes on to no beat",
|
|
184
|
+
"yaml": "schema: loop.scene/v1\nid: probe\nversion: 0.0.1\nname: Probe\nentry: sales\ncast:\n - member: sales\n app: sales\n role: initiator\n runs_in: runtime\n persona:\n name: Sales\nscript:\n - id: open\n cue:\n say: Show the books\n expect: The books are read\n moves:\n - who: sales\n answers: words\n branch:\n - decision: there is nothing to read\n expect: it says so\n then: nowhere\n",
|
|
185
|
+
"says": [
|
|
186
|
+
"Beat 'open': its branch goes on to 'nowhere', which is no beat."
|
|
187
|
+
]
|
|
188
|
+
},
|
|
189
|
+
{
|
|
190
|
+
"name": "a rehearsal of a beat that is not in the script",
|
|
191
|
+
"yaml": "schema: loop.scene/v1\nid: probe\nversion: 0.0.1\nname: Probe\nentry: sales\ncast:\n - member: sales\n app: sales\n role: initiator\n runs_in: runtime\n persona:\n name: Sales\nrehearsal:\n beats:\n - beat: nowhere\n lines:\n - 'You → Sales'\n",
|
|
192
|
+
"says": [
|
|
193
|
+
"The rehearsal names the beat 'nowhere', which is not in the script."
|
|
194
|
+
]
|
|
195
|
+
},
|
|
196
|
+
{
|
|
197
|
+
"name": "a rehearsal that names a beat twice",
|
|
198
|
+
"yaml": "schema: loop.scene/v1\nid: probe\nversion: 0.0.1\nname: Probe\nentry: sales\ncast:\n - member: sales\n app: sales\n role: initiator\n runs_in: runtime\n persona:\n name: Sales\nscript:\n - id: open\n cue:\n say: Show the books\n expect: The books are read\n moves:\n - who: sales\n answers: words\nrehearsal:\n beats:\n - beat: open\n lines:\n - 'You → Sales'\n - beat: open\n lines:\n - 'Sales: a table'\n",
|
|
199
|
+
"says": ["The rehearsal names the beat 'open' twice."]
|
|
200
|
+
},
|
|
201
|
+
{
|
|
202
|
+
"name": "a rehearsal that names someone not on stage",
|
|
203
|
+
"yaml": "schema: loop.scene/v1\nid: probe\nversion: 0.0.1\nname: Probe\nentry: sales\ncast:\n - member: sales\n app: sales\n role: initiator\n runs_in: runtime\n persona:\n name: Sales\nscript:\n - id: open\n cue:\n say: Show the books\n expect: The books are read\n moves:\n - who: sales\n answers: words\nrehearsal:\n beats:\n - beat: open\n lines:\n - 'You → Stranger'\n",
|
|
204
|
+
"says": [
|
|
205
|
+
"The rehearsal of 'open' names 'Stranger', which is not on stage."
|
|
206
|
+
]
|
|
207
|
+
},
|
|
208
|
+
{
|
|
209
|
+
"name": "a scene that plays",
|
|
210
|
+
"yaml": "schema: loop.scene/v1\nid: probe\nversion: 0.0.1\nname: Probe\nentry: sales\ncast:\n - member: sales\n app: sales\n role: initiator\n runs_in: runtime\n persona:\n name: Sales\n talks_to:\n - member: books\n over: a2a\n - member: books\n app: accounting\n role: contributor\n runs_in: runtime\n persona:\n name: Accounting\nsetting:\n systems:\n - server: odoo-accounting\n as: Odoo\n holds: Datalayer's books\nstage:\n positions:\n sales:\n x: 0\n y: 0\n books:\n x: 0.5\n y: 0\n opens_first: sales\nscript:\n - id: open\n cue:\n say: Show the books\n expect: The books are read\n moves:\n - who: sales\n asks: books\n over: a2a\n what: the open invoices\n - who: sales\n answers: table\nrehearsal:\n beats:\n - beat: open\n lines:\n - 'You → Sales'\n - 'Sales → Accounting'\n - 'Sales: a table'\n",
|
|
211
|
+
"says": []
|
|
212
|
+
},
|
|
213
|
+
{
|
|
214
|
+
"name": "a scene of a team that plays",
|
|
215
|
+
"yaml": "schema: loop.scene/v1\nid: probe\nversion: 0.0.1\nname: Probe\nteam: sales-and-accounting\ncast:\n - member: sales\n persona:\n name: Sales\n brief: Ask for the open invoices.\n",
|
|
216
|
+
"says": []
|
|
217
|
+
},
|
|
218
|
+
{
|
|
219
|
+
"name": "a cast under a team names someone not in it",
|
|
220
|
+
"yaml": "schema: loop.scene/v1\nid: probe\nversion: 0.0.1\nname: Probe\nteam: sales-and-accounting\ncast:\n - member: ghost\n persona:\n name: Ghost\n",
|
|
221
|
+
"says": [
|
|
222
|
+
"The cast names 'ghost', which is not a member of the team 'sales-and-accounting'."
|
|
223
|
+
]
|
|
224
|
+
},
|
|
225
|
+
{
|
|
226
|
+
"name": "a cast under a team says what a member is",
|
|
227
|
+
"yaml": "schema: loop.scene/v1\nid: probe\nversion: 0.0.1\nname: Probe\nteam: sales-and-accounting\ncast:\n - member: sales\n app: sales\n persona:\n name: Sales\n",
|
|
228
|
+
"says": [
|
|
229
|
+
"The cast member 'sales' is the team's: it says its persona and its brief, nothing of what it is."
|
|
230
|
+
]
|
|
231
|
+
},
|
|
232
|
+
{
|
|
233
|
+
"name": "a move asks a system for a tool it does not offer",
|
|
234
|
+
"yaml": "schema: loop.scene/v1\nid: probe\nversion: 0.0.1\nname: Probe\nentry: books\ncast:\n - member: books\n app: accounting\n role: contributor\n runs_in: runtime\n persona:\n name: Accounting\nsetting:\n systems:\n - server: odoo-accounting\n as: Odoo\nscript:\n - id: open\n cue:\n say: Show the books\n expect: It is answered\n moves:\n - who: books\n asks: odoo-accounting\n over: mcp\n tool: odoo_accounting_burn_the_books\n",
|
|
235
|
+
"says": [
|
|
236
|
+
"Beat 'open': 'books' asks 'odoo-accounting' for 'odoo_accounting_burn_the_books', which odoo-accounting does not offer."
|
|
237
|
+
]
|
|
238
|
+
},
|
|
239
|
+
{
|
|
240
|
+
"name": "a move asks for a tool to do what it does not",
|
|
241
|
+
"yaml": "schema: loop.scene/v1\nid: probe\nversion: 0.0.1\nname: Probe\nentry: crop\ncast:\n - member: crop\n app: crop-monitoring\n role: contributor\n runs_in: runtime\n persona:\n name: Crop\nsetting:\n systems:\n - server: earthdata\n as: Odoo\nscript:\n - id: look\n cue:\n say: What is there\n expect: It is answered\n moves:\n - who: crop\n asks: earthdata\n over: mcp\n tool: download_earth_data_granules\n does: read\n",
|
|
242
|
+
"says": [
|
|
243
|
+
"Beat 'look': 'crop' asks 'earthdata' for 'download_earth_data_granules' to read, and it writes."
|
|
244
|
+
]
|
|
245
|
+
},
|
|
246
|
+
{
|
|
247
|
+
"name": "a move asks for a tool no connection of the member offers",
|
|
248
|
+
"yaml": "schema: loop.scene/v1\nid: probe\nversion: 0.0.1\nname: Probe\nentry: inbox\ncast:\n - member: inbox\n app: inbox-triage\n role: contributor\n runs_in: runtime\n persona:\n name: Inbox\nsetting:\n systems:\n - server: google-workspace\n as: Odoo\nscript:\n - id: mail\n cue:\n say: What came in\n expect: It is answered\n moves:\n - who: inbox\n asks: google-workspace\n over: mcp\n tool: list_calendar_events\n",
|
|
249
|
+
"says": [
|
|
250
|
+
"Beat 'mail': 'inbox' asks 'google-workspace' for 'list_calendar_events', a tool no connection of Inbox offers."
|
|
251
|
+
]
|
|
252
|
+
},
|
|
253
|
+
{
|
|
254
|
+
"name": "a rehearsal expects a tool a system does not offer",
|
|
255
|
+
"yaml": "schema: loop.scene/v1\nid: probe\nversion: 0.0.1\nname: Probe\nentry: books\ncast:\n - member: books\n app: accounting\n role: contributor\n runs_in: runtime\n persona:\n name: Accounting\nsetting:\n systems:\n - server: odoo-accounting\n as: Odoo\nscript:\n - id: open\n cue:\n say: Show the books\n expect: It is answered\n moves:\n - who: books\n answers: table\nrehearsal:\n beats:\n - beat: open\n lines:\n - 'Accounting → Odoo: odoo_accounting_burn_the_books'\n - 'Accounting: a table'\n",
|
|
256
|
+
"says": [
|
|
257
|
+
"The rehearsal of 'open' expects 'odoo_accounting_burn_the_books', which odoo-accounting does not offer."
|
|
258
|
+
]
|
|
259
|
+
},
|
|
260
|
+
{
|
|
261
|
+
"name": "a cast that is a word",
|
|
262
|
+
"yaml": "schema: loop.scene/v1\nid: probe\nversion: 0.0.1\nname: Probe\nentry: sales\ncast: sales\n",
|
|
263
|
+
"says": ["probe: cast: Input should be a valid list"]
|
|
264
|
+
},
|
|
265
|
+
{
|
|
266
|
+
"name": "a name that is a number",
|
|
267
|
+
"yaml": "schema: loop.scene/v1\nid: probe\nversion: 0.0.1\nname: 123\nentry: sales\ncast:\n - member: sales\n app: sales\n role: initiator\n runs_in: runtime\n persona:\n name: Sales\n",
|
|
268
|
+
"says": ["probe: name: Input should be a valid string"]
|
|
269
|
+
},
|
|
270
|
+
{
|
|
271
|
+
"name": "a scene with no name",
|
|
272
|
+
"yaml": "schema: loop.scene/v1\nid: probe\nversion: 0.0.1\nentry: sales\ncast:\n - member: sales\n app: sales\n role: initiator\n runs_in: runtime\n persona:\n name: Sales\n",
|
|
273
|
+
"says": ["probe: name is missing"]
|
|
274
|
+
},
|
|
275
|
+
{
|
|
276
|
+
"name": "a field the spec does not have",
|
|
277
|
+
"yaml": "schema: loop.scene/v1\nid: probe\nversion: 0.0.1\nname: Probe\ncolour: red\nentry: sales\ncast:\n - member: sales\n app: sales\n role: initiator\n runs_in: runtime\n persona:\n name: Sales\n",
|
|
278
|
+
"says": ["probe: colour is not a field of the spec"]
|
|
279
|
+
},
|
|
280
|
+
{
|
|
281
|
+
"name": "a member with a field it does not have",
|
|
282
|
+
"yaml": "schema: loop.scene/v1\nid: probe\nversion: 0.0.1\nname: Probe\nentry: sales\ncast:\n - member: sales\n app: sales\n role: initiator\n runs_in: runtime\n persona:\n name: Sales\n mood: happy\n",
|
|
283
|
+
"says": ["probe: cast.0.mood is not a field of the spec"]
|
|
284
|
+
},
|
|
285
|
+
{
|
|
286
|
+
"name": "a member running nowhere",
|
|
287
|
+
"yaml": "schema: loop.scene/v1\nid: probe\nversion: 0.0.1\nname: Probe\nentry: sales\ncast:\n - member: sales\n app: sales\n role: initiator\n runs_in: nowhere\n persona:\n name: Sales\n",
|
|
288
|
+
"says": ["probe: cast.0.runs_in: Input should be 'browser' or 'runtime'"]
|
|
289
|
+
},
|
|
290
|
+
{
|
|
291
|
+
"name": "a member's role nobody plays",
|
|
292
|
+
"yaml": "schema: loop.scene/v1\nid: probe\nversion: 0.0.1\nname: Probe\nentry: sales\ncast:\n - member: sales\n app: sales\n role: boss\n runs_in: runtime\n persona:\n name: Sales\n",
|
|
293
|
+
"says": [
|
|
294
|
+
"probe: cast.0.role: Input should be 'coordinator', 'initiator', 'contributor', 'reviewer' or 'finalizer'"
|
|
295
|
+
]
|
|
296
|
+
},
|
|
297
|
+
{
|
|
298
|
+
"name": "an audience that is a word",
|
|
299
|
+
"yaml": "schema: loop.scene/v1\nid: probe\nversion: 0.0.1\nname: Probe\nentry: sales\ncast:\n - member: sales\n app: sales\n role: initiator\n runs_in: runtime\n persona:\n name: Sales\naudience: everyone\n",
|
|
300
|
+
"says": [
|
|
301
|
+
"probe: audience: Input should be a valid dictionary or instance of SceneAudience"
|
|
302
|
+
]
|
|
303
|
+
},
|
|
304
|
+
{
|
|
305
|
+
"name": "an audience nobody can be",
|
|
306
|
+
"yaml": "schema: loop.scene/v1\nid: probe\nversion: 0.0.1\nname: Probe\nentry: sales\ncast:\n - member: sales\n app: sales\n role: initiator\n runs_in: runtime\n persona:\n name: Sales\naudience:\n who: nobody-at-all\n",
|
|
307
|
+
"says": [
|
|
308
|
+
"probe: audience.who: Input should be 'visitors', 'signed-in' or 'nobody'"
|
|
309
|
+
]
|
|
310
|
+
},
|
|
311
|
+
{
|
|
312
|
+
"name": "a ceiling below nothing",
|
|
313
|
+
"yaml": "schema: loop.scene/v1\nid: probe\nversion: 0.0.1\nname: Probe\nentry: sales\ncast:\n - member: sales\n app: sales\n role: initiator\n runs_in: runtime\n persona:\n name: Sales\naudience:\n ceiling_per_ask: -1\n",
|
|
314
|
+
"says": [
|
|
315
|
+
"probe: audience.ceiling_per_ask: Input should be greater than or equal to 0"
|
|
316
|
+
]
|
|
317
|
+
},
|
|
318
|
+
{
|
|
319
|
+
"name": "a ceiling that is no number",
|
|
320
|
+
"yaml": "schema: loop.scene/v1\nid: probe\nversion: 0.0.1\nname: Probe\nentry: sales\ncast:\n - member: sales\n app: sales\n role: initiator\n runs_in: runtime\n persona:\n name: Sales\naudience:\n ceiling_per_ask: lots\n",
|
|
321
|
+
"says": [
|
|
322
|
+
"probe: audience.ceiling_per_ask: Input should be a valid number, unable to parse string as a number"
|
|
323
|
+
]
|
|
324
|
+
},
|
|
325
|
+
{
|
|
326
|
+
"name": "a rehearsal bound that is no duration",
|
|
327
|
+
"yaml": "schema: loop.scene/v1\nid: probe\nversion: 0.0.1\nname: Probe\nentry: sales\ncast:\n - member: sales\n app: sales\n role: initiator\n runs_in: runtime\n persona:\n name: Sales\nrehearsal:\n within: soon\n",
|
|
328
|
+
"says": [
|
|
329
|
+
"probe: rehearsal.within: String should match pattern '^(?:[1-9]\\d*(?:ms|s|m|h))?$'"
|
|
330
|
+
]
|
|
331
|
+
},
|
|
332
|
+
{
|
|
333
|
+
"name": "a stage that is a list",
|
|
334
|
+
"yaml": "schema: loop.scene/v1\nid: probe\nversion: 0.0.1\nname: Probe\nentry: sales\ncast:\n - member: sales\n app: sales\n role: initiator\n runs_in: runtime\n persona:\n name: Sales\nstage: []\n",
|
|
335
|
+
"says": [
|
|
336
|
+
"probe: stage: Input should be a valid dictionary or instance of SceneStage"
|
|
337
|
+
]
|
|
338
|
+
},
|
|
339
|
+
{
|
|
340
|
+
"name": "places that are a word",
|
|
341
|
+
"yaml": "schema: loop.scene/v1\nid: probe\nversion: 0.0.1\nname: Probe\nentry: sales\ncast:\n - member: sales\n app: sales\n role: initiator\n runs_in: runtime\n persona:\n name: Sales\nstage:\n positions: everywhere\n",
|
|
342
|
+
"says": ["probe: stage.positions: Input should be a valid dictionary"]
|
|
343
|
+
},
|
|
344
|
+
{
|
|
345
|
+
"name": "two things wrong at once",
|
|
346
|
+
"yaml": "schema: loop.scene/v1\nid: probe\nversion: 0.0.1\nname: Probe\nentry: sales\ncast: sales\nrehearsal:\n within: soon\n",
|
|
347
|
+
"says": [
|
|
348
|
+
"probe: cast: Input should be a valid list; rehearsal.within: String should match pattern '^(?:[1-9]\\d*(?:ms|s|m|h))?$'"
|
|
349
|
+
]
|
|
350
|
+
}
|
|
351
|
+
]
|
|
352
|
+
}
|
|
@@ -89,6 +89,12 @@ export type ComputerState = {
|
|
|
89
89
|
held: ComputerHolder | null;
|
|
90
90
|
/** Whether the person asking is who has it. */
|
|
91
91
|
yours: boolean;
|
|
92
|
+
/**
|
|
93
|
+
* The origin its files are served from, as the runtime says it (D-22):
|
|
94
|
+
* the host kept for what applications serve, or empty where the plane
|
|
95
|
+
* keeps none and the runtime's own host serves them.
|
|
96
|
+
*/
|
|
97
|
+
servedFrom?: string;
|
|
92
98
|
};
|
|
93
99
|
/** One entry of a directory of its computer. */
|
|
94
100
|
export type ComputerFile = {
|
|
@@ -112,14 +118,32 @@ export type ComputerContext = {
|
|
|
112
118
|
agentId: string;
|
|
113
119
|
/** The person's token; none on the machine itself. */
|
|
114
120
|
token?: string;
|
|
121
|
+
/**
|
|
122
|
+
* Where what an application serves a person is served from (STUDIO D-22):
|
|
123
|
+
* `user-apps.datalayer.run`, the same runtime behind another name. A file
|
|
124
|
+
* fetched from the runtimes' host would be same-origin with every other
|
|
125
|
+
* runtime; from this one it is origin of its own. Unset, the runtime's own
|
|
126
|
+
* host serves it, as it did.
|
|
127
|
+
*/
|
|
128
|
+
userAppsUrl?: string;
|
|
115
129
|
};
|
|
116
130
|
/** The computer's routes, for an agent. */
|
|
117
131
|
export declare const computerUrl: (context: ComputerContext, tail?: string) => string;
|
|
132
|
+
/**
|
|
133
|
+
* Where a file of its computer is read (STUDIO D-22): the same path, on the
|
|
134
|
+
* host kept for what applications serve when there is one. Only the origin
|
|
135
|
+
* changes — the runtime is the same, and its prefix is answered there too.
|
|
136
|
+
*/
|
|
137
|
+
export declare function computerFileUrl(context: ComputerContext, path: string): string;
|
|
118
138
|
/** Its parts, whether it started, who has it. */
|
|
119
139
|
export declare const readComputer: (context: ComputerContext) => Promise<ComputerState>;
|
|
120
140
|
/** A directory of its working directory. */
|
|
121
141
|
export declare const listComputerFiles: (context: ComputerContext, path?: string) => Promise<ComputerFile[]>;
|
|
122
|
-
/**
|
|
142
|
+
/**
|
|
143
|
+
* One of its files, to save. Fetched from the host kept for what
|
|
144
|
+
* applications serve when there is one (D-22), with the person's token: the
|
|
145
|
+
* runtime is the same, only the name it answers to differs.
|
|
146
|
+
*/
|
|
123
147
|
export declare const downloadComputerFile: (context: ComputerContext, path: string) => Promise<Blob>;
|
|
124
148
|
/** Take it over: what runs is interrupted, its agent's calls wait. */
|
|
125
149
|
export declare const takeOverComputer: (context: ComputerContext) => Promise<{
|
|
@@ -140,6 +140,29 @@ export function terminalEntries(conversation) {
|
|
|
140
140
|
}
|
|
141
141
|
/** The computer's routes, for an agent. */
|
|
142
142
|
export const computerUrl = (context, tail = '') => `${context.serverUrl.replace(/\/+$/, '')}/api/v1/apps/agents/${encodeURIComponent(context.agentId)}/computer${tail}`;
|
|
143
|
+
/**
|
|
144
|
+
* Where a file of its computer is read (STUDIO D-22): the same path, on the
|
|
145
|
+
* host kept for what applications serve when there is one. Only the origin
|
|
146
|
+
* changes — the runtime is the same, and its prefix is answered there too.
|
|
147
|
+
*/
|
|
148
|
+
export function computerFileUrl(context, path) {
|
|
149
|
+
const url = computerUrl(context, `/file?path=${encodeURIComponent(path)}`);
|
|
150
|
+
const served = (context.userAppsUrl || '').trim();
|
|
151
|
+
if (!served) {
|
|
152
|
+
return url;
|
|
153
|
+
}
|
|
154
|
+
try {
|
|
155
|
+
const asked = new URL(url);
|
|
156
|
+
const host = new URL(served);
|
|
157
|
+
asked.protocol = host.protocol;
|
|
158
|
+
asked.host = host.host;
|
|
159
|
+
return asked.toString();
|
|
160
|
+
}
|
|
161
|
+
catch {
|
|
162
|
+
// An address that is not one: the runtime's own host serves it.
|
|
163
|
+
return url;
|
|
164
|
+
}
|
|
165
|
+
}
|
|
143
166
|
async function asked(context, tail, init = {}) {
|
|
144
167
|
const response = await fetch(computerUrl(context, tail), {
|
|
145
168
|
...init,
|
|
@@ -169,8 +192,28 @@ export const listComputerFiles = async (context, path = '.') => {
|
|
|
169
192
|
const body = (await response.json());
|
|
170
193
|
return body.entries;
|
|
171
194
|
};
|
|
172
|
-
/**
|
|
173
|
-
|
|
195
|
+
/**
|
|
196
|
+
* One of its files, to save. Fetched from the host kept for what
|
|
197
|
+
* applications serve when there is one (D-22), with the person's token: the
|
|
198
|
+
* runtime is the same, only the name it answers to differs.
|
|
199
|
+
*/
|
|
200
|
+
export const downloadComputerFile = async (context, path) => {
|
|
201
|
+
const response = await fetch(computerFileUrl(context, path), {
|
|
202
|
+
headers: context.token ? { Authorization: `Bearer ${context.token}` } : {},
|
|
203
|
+
});
|
|
204
|
+
if (!response.ok) {
|
|
205
|
+
let detail = `${response.status}`;
|
|
206
|
+
try {
|
|
207
|
+
const body = (await response.json());
|
|
208
|
+
detail = typeof body.detail === 'string' ? body.detail : detail;
|
|
209
|
+
}
|
|
210
|
+
catch {
|
|
211
|
+
// A refusal without a sentence: its status says it.
|
|
212
|
+
}
|
|
213
|
+
throw new Error(detail);
|
|
214
|
+
}
|
|
215
|
+
return response.blob();
|
|
216
|
+
};
|
|
174
217
|
/** Take it over: what runs is interrupted, its agent's calls wait. */
|
|
175
218
|
export const takeOverComputer = async (context) => (await asked(context, '/take-over', { method: 'POST' })).json();
|
|
176
219
|
/** Hand it back to its agent. */
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import type { SceneSpec } from '../../types/scenes';
|
|
2
|
+
/** The part of a scene a refusal is about: the sections of its spec. */
|
|
3
|
+
export type SceneSection = 'scene' | 'cast' | 'setting' | 'script' | 'stage' | 'audience' | 'rehearsal';
|
|
4
|
+
/** One refusal: the sentence agentspecs says, and the section it is about. */
|
|
5
|
+
export type SceneProblem = {
|
|
6
|
+
says: string;
|
|
7
|
+
section: SceneSection;
|
|
8
|
+
};
|
|
9
|
+
/**
|
|
10
|
+
* The sections a stage is written in (S-09): where each player runs and
|
|
11
|
+
* what it is given (`stage`, `deployment`, a member's `runs_in`), and what
|
|
12
|
+
* the audience may do (`audience`).
|
|
13
|
+
*/
|
|
14
|
+
export declare const STAGE_SECTIONS: readonly SceneSection[];
|
|
15
|
+
/**
|
|
16
|
+
* The parts a person reads one at a time in the spec editor (S-08, S-09),
|
|
17
|
+
* in the order a scene is written. The scene's own fields are always in
|
|
18
|
+
* view, so they are not one of them.
|
|
19
|
+
*/
|
|
20
|
+
export declare const SCENE_PARTS: readonly SceneSection[];
|
|
21
|
+
/**
|
|
22
|
+
* Each section of a scene, and the keys of the spec it is written in.
|
|
23
|
+
* *Where it plays* is the stage directions and the addresses together: where
|
|
24
|
+
* each player runs is one thing, said in two keys. Read by the editor's
|
|
25
|
+
* parts (S-09) and by `sceneShape`, which files a refusal of the scene's
|
|
26
|
+
* shape under the part whose key it names.
|
|
27
|
+
*/
|
|
28
|
+
export declare const SCENE_SECTION_KEYS: Readonly<Record<SceneSection, readonly string[]>>;
|
|
29
|
+
/** The section a key of the spec is written in; the scene's own otherwise. */
|
|
30
|
+
export declare const sectionOfKey: (key: string) => SceneSection;
|
|
31
|
+
/** What a person reads each section as, in the editor's panel. */
|
|
32
|
+
export declare const SECTION_WORDS: Record<SceneSection, string>;
|
|
33
|
+
/**
|
|
34
|
+
* The checks that are not the browser's: made by agentspecs when `loop`
|
|
35
|
+
* loads the scene. Said here so that no second set of them is written.
|
|
36
|
+
*/
|
|
37
|
+
export declare const AGENTSPECS_OWN: readonly string[];
|
|
38
|
+
/** The entry agentspecs reads: the one said, else the initiator, else the first of the cast. */
|
|
39
|
+
export declare function entryOf(spec: SceneSpec): string;
|
|
40
|
+
/**
|
|
41
|
+
* One of the person's own applications, kept in their Space: what the checks
|
|
42
|
+
* read of it when a member of the cast is one of them rather than an
|
|
43
|
+
* application of the catalogue — its name and face, and what its connections
|
|
44
|
+
* reach. agentspecs reads the catalogue only, so to `loop` a member that is
|
|
45
|
+
* the person's own application reaches no system at all; the Studio has the
|
|
46
|
+
* person's applications, and judges them by what they truly reach, in the
|
|
47
|
+
* same sentences (decided 2026-10-10, S-10).
|
|
48
|
+
*/
|
|
49
|
+
export type SceneOwnApp = {
|
|
50
|
+
name: string;
|
|
51
|
+
emoji?: string;
|
|
52
|
+
connections: readonly {
|
|
53
|
+
server: string;
|
|
54
|
+
only?: readonly string[];
|
|
55
|
+
}[];
|
|
56
|
+
};
|
|
57
|
+
/** The person's own applications, by uid — the reference a scene's cast writes for one. */
|
|
58
|
+
export type SceneOwnApps = Readonly<Record<string, SceneOwnApp>>;
|
|
59
|
+
/**
|
|
60
|
+
* A line of a rehearsal's shape, as agentspecs reads it (`parse_line`):
|
|
61
|
+
* *Sales → Accounting* (an ask), *Accounting → Odoo: odoo_*\** (a tool),
|
|
62
|
+
* *Accounting: a table* (an answer).
|
|
63
|
+
*/
|
|
64
|
+
export declare function transcriptLineOf(text: string): {
|
|
65
|
+
who: string;
|
|
66
|
+
whom: string;
|
|
67
|
+
detail: string;
|
|
68
|
+
} | undefined;
|
|
69
|
+
/**
|
|
70
|
+
* What is wrong with the shape of the scene, as agentspecs reads it
|
|
71
|
+
* (`SceneSpec._stages_somebody`), said as `parse_scene` says it — the
|
|
72
|
+
* scene's id, then the sentence. The first stops, as the reader stops.
|
|
73
|
+
*/
|
|
74
|
+
export declare function sceneShapeProblem(spec: SceneSpec): SceneProblem | undefined;
|
|
75
|
+
/**
|
|
76
|
+
* What stops a scene from being played, each in agentspecs' sentence with
|
|
77
|
+
* the section it is about; empty when nothing does.
|
|
78
|
+
*/
|
|
79
|
+
export declare function sceneCheck(spec: SceneSpec, own?: SceneOwnApps, { written, }?: {
|
|
80
|
+
/**
|
|
81
|
+
* Whether the spec is what a person wrote, read from its text. A cast
|
|
82
|
+
* under a team is judged on what was written, and only a text says that:
|
|
83
|
+
* the catalogue's scenes reach the browser with every member filled in
|
|
84
|
+
* from its team (`cast_of`), so read from there a valid scene would be
|
|
85
|
+
* refused for what its team said (seen 2026-10-10).
|
|
86
|
+
*/
|
|
87
|
+
written?: boolean;
|
|
88
|
+
}): SceneProblem[];
|
|
89
|
+
/** What stops a scene from being played, in agentspecs' sentences; empty when nothing does. */
|
|
90
|
+
export declare const sceneProblems: (spec: SceneSpec, own?: SceneOwnApps) => string[];
|
|
91
|
+
/** The refusals of one section of the spec: the stage's, for S-09's own panel. */
|
|
92
|
+
export declare const problemsOfSections: (problems: readonly SceneProblem[], sections: readonly SceneSection[]) => SceneProblem[];
|