@datalayer/agent-runtimes 1.5.39 โ 1.5.42
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/datalayer-app-main.js +1 -1
- package/lib/examples/ShieldHarnessExample.d.ts +26 -0
- package/lib/examples/ShieldHarnessExample.js +51 -0
- package/lib/examples/ShieldPolicyExample.d.ts +18 -0
- package/lib/examples/ShieldPolicyExample.js +50 -0
- package/lib/examples/example-selector.js +3 -0
- package/lib/examples/exampleGroups.d.ts +1 -1
- package/lib/examples/exampleGroups.js +4 -0
- package/lib/examples/shield/shieldHarness.d.ts +14 -0
- package/lib/examples/shield/shieldHarness.js +21 -0
- package/lib/examples/shield/shieldPolicyDemo.d.ts +85 -0
- package/lib/examples/shield/shieldPolicyDemo.js +112 -0
- package/lib/specs/harnesses.d.ts +9 -1
- package/lib/specs/harnesses.js +513 -0
- package/lib/specs/policies.js +2 -1
- package/lib/specs/teams/teams.d.ts +5 -4
- package/lib/specs/teams/teams.js +84 -12
- package/lib/types/agentspecs.d.ts +47 -1
- package/lib/types/teams.d.ts +7 -1
- package/package.json +1 -1
- package/scripts/codegen/generate_harnesses.py +41 -3
- package/scripts/codegen/generate_teams.py +3 -0
package/lib/specs/teams/teams.js
CHANGED
|
@@ -572,6 +572,77 @@ export const AUTOMATE_REGULATORY_REPORTING_TEAM_SPEC_0_0_1 = {
|
|
|
572
572
|
storage: 's3://reports/regulatory-submissions/',
|
|
573
573
|
},
|
|
574
574
|
};
|
|
575
|
+
export const CODING_AGENTS_TEAM_SPEC_0_0_1 = {
|
|
576
|
+
id: 'coding-agents',
|
|
577
|
+
version: '0.0.1',
|
|
578
|
+
name: 'Coding Agents',
|
|
579
|
+
description: `Claude Code writes the change and Codex reviews it, each behind the Shield: a supervisor delegates to them over ACP with a budget, a deadline and the files it may touch, and reads back their plans and their diffs.`,
|
|
580
|
+
tags: ['coding', 'harness', 'review'],
|
|
581
|
+
enabled: true,
|
|
582
|
+
icon: 'code',
|
|
583
|
+
emoji: '๐ก๏ธ',
|
|
584
|
+
color: '#1F6FEB',
|
|
585
|
+
agentSpecId: '',
|
|
586
|
+
orchestrationProtocol: 'datalayer',
|
|
587
|
+
executionMode: 'sequential',
|
|
588
|
+
supervisor: {
|
|
589
|
+
name: 'Lead',
|
|
590
|
+
ref: '',
|
|
591
|
+
model: 'bedrock:us.anthropic.claude-sonnet-4-6',
|
|
592
|
+
goal: `Split the request into a change and its review: hand the change to the Coder with the files it may touch, then the diff to the Reviewer, and answer with the change and what the review found.`,
|
|
593
|
+
instructions: `You lead two coding agents. Hand the change to the Coder with the files it may touch and a deadline, wait for its diff, hand the diff to the Reviewer, and answer with the change and the review. Never edit a file yourself.`,
|
|
594
|
+
approval: 'auto',
|
|
595
|
+
canTerminate: true,
|
|
596
|
+
},
|
|
597
|
+
routingInstructions: ``,
|
|
598
|
+
suggestions: [
|
|
599
|
+
{
|
|
600
|
+
text: 'Add a test for the function in the open file, then review it.',
|
|
601
|
+
summary: 'A change and its review',
|
|
602
|
+
icon: 'code',
|
|
603
|
+
emoji: '๐งช',
|
|
604
|
+
},
|
|
605
|
+
],
|
|
606
|
+
delegation: {
|
|
607
|
+
maxDepth: 2,
|
|
608
|
+
allowPeerDelegation: false,
|
|
609
|
+
includeGeneralPurpose: false,
|
|
610
|
+
},
|
|
611
|
+
context: { sharing: 'shared' },
|
|
612
|
+
validation: undefined,
|
|
613
|
+
agents: [
|
|
614
|
+
{
|
|
615
|
+
id: 'coder',
|
|
616
|
+
name: 'Coder',
|
|
617
|
+
ref: '',
|
|
618
|
+
harness: 'claude-code',
|
|
619
|
+
role: 'contributor',
|
|
620
|
+
goal: `Make the change asked, inside the workspace, in the files the manifest names; answer with what changed and why.`,
|
|
621
|
+
dependsOn: [],
|
|
622
|
+
subagents: [],
|
|
623
|
+
model: '',
|
|
624
|
+
mcpServer: '',
|
|
625
|
+
tools: [],
|
|
626
|
+
trigger: '',
|
|
627
|
+
approval: 'auto',
|
|
628
|
+
},
|
|
629
|
+
{
|
|
630
|
+
id: 'reviewer',
|
|
631
|
+
name: 'Reviewer',
|
|
632
|
+
ref: '',
|
|
633
|
+
harness: 'codex',
|
|
634
|
+
role: 'reviewer',
|
|
635
|
+
goal: `Read the Coder's diff and say what is wrong with it, file by file; edit nothing.`,
|
|
636
|
+
dependsOn: ['coder'],
|
|
637
|
+
subagents: [],
|
|
638
|
+
model: '',
|
|
639
|
+
mcpServer: '',
|
|
640
|
+
tools: [],
|
|
641
|
+
trigger: '',
|
|
642
|
+
approval: 'auto',
|
|
643
|
+
},
|
|
644
|
+
],
|
|
645
|
+
};
|
|
575
646
|
export const COMPREHENSIVE_SALES_ANALYTICS_TEAM_SPEC_0_0_1 = {
|
|
576
647
|
id: 'comprehensive-sales-analytics',
|
|
577
648
|
version: '0.0.1',
|
|
@@ -704,9 +775,9 @@ export const COMPREHENSIVE_SALES_ANALYTICS_TEAM_SPEC_0_0_1 = {
|
|
|
704
775
|
storage: 's3://reports/sales-analytics/',
|
|
705
776
|
},
|
|
706
777
|
};
|
|
707
|
-
export const
|
|
778
|
+
export const CROP_MONITORING_TEAM_SPEC_0_0_2 = {
|
|
708
779
|
id: 'crop-monitoring',
|
|
709
|
-
version: '0.0.
|
|
780
|
+
version: '0.0.2',
|
|
710
781
|
name: 'Crop Monitoring',
|
|
711
782
|
description: `One agent, its data: Crop Monitoring follows crop vigour and growth over a season from the satellite imagery NASA Earthdata holds, and flags the fields that need attention.`,
|
|
712
783
|
tags: [
|
|
@@ -780,9 +851,9 @@ export const CROP_MONITORING_TEAM_SPEC_0_0_1 = {
|
|
|
780
851
|
},
|
|
781
852
|
],
|
|
782
853
|
};
|
|
783
|
-
export const
|
|
854
|
+
export const DISASTER_ASSESSMENT_TEAM_SPEC_0_0_2 = {
|
|
784
855
|
id: 'disaster-assessment',
|
|
785
|
-
version: '0.0.
|
|
856
|
+
version: '0.0.2',
|
|
786
857
|
name: 'Disaster Assessment',
|
|
787
858
|
description: `An event desk in the browser that gets the area a disaster affected and the damage from Disaster Assessment, and what changed on the ground from Change detection, each on a runtime over A2A, each reading NASA Earthdata. Event response takes the event and reports; the two others read the imagery and answer.`,
|
|
788
859
|
tags: [
|
|
@@ -1117,9 +1188,9 @@ export const JUPYTER_TEAM_SPEC_0_0_1 = {
|
|
|
1117
1188
|
storage: '',
|
|
1118
1189
|
},
|
|
1119
1190
|
};
|
|
1120
|
-
export const
|
|
1191
|
+
export const MONTH_END_CLOSE_TEAM_SPEC_0_0_2 = {
|
|
1121
1192
|
id: 'month-end-close',
|
|
1122
|
-
version: '0.0.
|
|
1193
|
+
version: '0.0.2',
|
|
1123
1194
|
name: 'Month-end Close',
|
|
1124
1195
|
description: `One agent, its data: Month-end Close drives the close from the Odoo books, which it only reads โ the checklist, the accruals to book, the reconciliation gaps that remain.`,
|
|
1125
1196
|
tags: ['example', 'scene', 'accounting', 'finance', 'odoo', 'a2a'],
|
|
@@ -1719,9 +1790,9 @@ export const PROCESS_CLINICAL_TRIAL_DATA_TEAM_SPEC_0_0_1 = {
|
|
|
1719
1790
|
storage: 's3://reports/clinical-trials/',
|
|
1720
1791
|
},
|
|
1721
1792
|
};
|
|
1722
|
-
export const
|
|
1793
|
+
export const SALES_AND_ACCOUNTING_TEAM_SPEC_0_0_2 = {
|
|
1723
1794
|
id: 'sales-and-accounting',
|
|
1724
|
-
version: '0.0.
|
|
1795
|
+
version: '0.0.2',
|
|
1725
1796
|
name: 'Sales and Accounting',
|
|
1726
1797
|
description: `A sales desk in the browser that gets financial reports from an accounting application on a runtime, over A2A. Sales takes the request and reports the answer; Accounting reads the Odoo books and answers.`,
|
|
1727
1798
|
tags: ['example', 'sales', 'accounting', 'finance', 'a2a', 'odoo'],
|
|
@@ -1940,16 +2011,17 @@ export const TEAM_SPECS = {
|
|
|
1940
2011
|
'analyze-support-tickets': ANALYZE_SUPPORT_TICKETS_TEAM_SPEC_0_0_1,
|
|
1941
2012
|
'audit-inventory-levels': AUDIT_INVENTORY_LEVELS_TEAM_SPEC_0_0_1,
|
|
1942
2013
|
'automate-regulatory-reporting': AUTOMATE_REGULATORY_REPORTING_TEAM_SPEC_0_0_1,
|
|
2014
|
+
'coding-agents': CODING_AGENTS_TEAM_SPEC_0_0_1,
|
|
1943
2015
|
'comprehensive-sales-analytics': COMPREHENSIVE_SALES_ANALYTICS_TEAM_SPEC_0_0_1,
|
|
1944
|
-
'crop-monitoring':
|
|
1945
|
-
'disaster-assessment':
|
|
2016
|
+
'crop-monitoring': CROP_MONITORING_TEAM_SPEC_0_0_2,
|
|
2017
|
+
'disaster-assessment': DISASTER_ASSESSMENT_TEAM_SPEC_0_0_2,
|
|
1946
2018
|
jupyter: JUPYTER_TEAM_SPEC_0_0_1,
|
|
1947
|
-
'month-end-close':
|
|
2019
|
+
'month-end-close': MONTH_END_CLOSE_TEAM_SPEC_0_0_2,
|
|
1948
2020
|
'notebook-benchmark': NOTEBOOK_BENCHMARK_TEAM_SPEC_0_0_1,
|
|
1949
2021
|
'optimize-grid-operations': OPTIMIZE_GRID_OPERATIONS_TEAM_SPEC_0_0_1,
|
|
1950
2022
|
'process-citizen-requests': PROCESS_CITIZEN_REQUESTS_TEAM_SPEC_0_0_1,
|
|
1951
2023
|
'process-clinical-trial-data': PROCESS_CLINICAL_TRIAL_DATA_TEAM_SPEC_0_0_1,
|
|
1952
|
-
'sales-and-accounting':
|
|
2024
|
+
'sales-and-accounting': SALES_AND_ACCOUNTING_TEAM_SPEC_0_0_2,
|
|
1953
2025
|
'sync-crm-contacts': SYNC_CRM_CONTACTS_TEAM_SPEC_0_0_1,
|
|
1954
2026
|
};
|
|
1955
2027
|
function resolveTeamId(teamId) {
|
|
@@ -238,7 +238,7 @@ export interface PolicySpec {
|
|
|
238
238
|
description: string;
|
|
239
239
|
enabled: boolean;
|
|
240
240
|
tags: string[];
|
|
241
|
-
/** The Shield's document: scope, version, rules, limits, network, mcp, harnesses. */
|
|
241
|
+
/** The Shield's document: scope, version, rules, limits, network, mcp, harnesses, authorize, authorizer. */
|
|
242
242
|
policy: {
|
|
243
243
|
scope: 'organization' | 'team' | 'session';
|
|
244
244
|
version?: number;
|
|
@@ -267,6 +267,32 @@ export interface PolicySpec {
|
|
|
267
267
|
admit?: string[];
|
|
268
268
|
credentials?: 'account' | 'platform' | 'either';
|
|
269
269
|
};
|
|
270
|
+
/** The classes that need an authorizer's allow beside the Rules (SHIELD ยง6.11). */
|
|
271
|
+
authorize?: Array<'read' | 'write' | 'send' | 'buy' | 'delete' | 'execute'>;
|
|
272
|
+
/** The standalone Shield's decision point: exactly one of these. */
|
|
273
|
+
authorizer?: {
|
|
274
|
+
local?: {
|
|
275
|
+
grants?: Array<{
|
|
276
|
+
subject: string;
|
|
277
|
+
relation: string;
|
|
278
|
+
object: string;
|
|
279
|
+
}>;
|
|
280
|
+
};
|
|
281
|
+
openfga?: {
|
|
282
|
+
url: string;
|
|
283
|
+
store: string;
|
|
284
|
+
model?: string | null;
|
|
285
|
+
};
|
|
286
|
+
authzen?: {
|
|
287
|
+
url: string;
|
|
288
|
+
headers?: Record<string, string>;
|
|
289
|
+
};
|
|
290
|
+
opa?: {
|
|
291
|
+
url: string;
|
|
292
|
+
package?: string;
|
|
293
|
+
headers?: Record<string, string>;
|
|
294
|
+
};
|
|
295
|
+
} | null;
|
|
270
296
|
};
|
|
271
297
|
}
|
|
272
298
|
/**
|
|
@@ -334,6 +360,26 @@ export interface StandardSpec {
|
|
|
334
360
|
}>;
|
|
335
361
|
controls: StandardControl[];
|
|
336
362
|
}
|
|
363
|
+
/**
|
|
364
|
+
* A harness of the register's *listed* tier (SHIELD SH-57): known to speak ACP,
|
|
365
|
+
* its documented command, licence, terms and credential read and cited; not
|
|
366
|
+
* drilled, so offered by nothing โ naming one is refused *listed, not drilled yet*.
|
|
367
|
+
*/
|
|
368
|
+
export interface ListedHarness {
|
|
369
|
+
id: string;
|
|
370
|
+
name: string;
|
|
371
|
+
docs: string;
|
|
372
|
+
adapter: string;
|
|
373
|
+
version: string;
|
|
374
|
+
/** The launch command its project documents; null when undocumented. */
|
|
375
|
+
command: string | null;
|
|
376
|
+
licence: string;
|
|
377
|
+
licenceSource: string;
|
|
378
|
+
termsSource: string;
|
|
379
|
+
credential: string;
|
|
380
|
+
servedToThirdParties: 'api_key_only' | 'permitted' | 'refused' | 'unknown';
|
|
381
|
+
note: string;
|
|
382
|
+
}
|
|
337
383
|
export interface HarnessSpec {
|
|
338
384
|
/** What `harness:` names (e.g. 'claude-code'). */
|
|
339
385
|
id: string;
|
package/lib/types/teams.d.ts
CHANGED
|
@@ -66,7 +66,7 @@ export interface TeamLinkSpec {
|
|
|
66
66
|
/** The member asked, by its id in the team. */
|
|
67
67
|
member: string;
|
|
68
68
|
/** The protocol: `a2a` to an agent or an application, `mcp` to a server member. */
|
|
69
|
-
over: 'a2a' | 'mcp';
|
|
69
|
+
over: 'a2a' | 'mcp' | 'acp';
|
|
70
70
|
}
|
|
71
71
|
export interface TeamAgentspec {
|
|
72
72
|
/** Agent identifier within the team */
|
|
@@ -91,6 +91,12 @@ export interface TeamAgentspec {
|
|
|
91
91
|
* (LOOP A-04). It asks nobody.
|
|
92
92
|
*/
|
|
93
93
|
server?: string;
|
|
94
|
+
/**
|
|
95
|
+
* Harness catalogue id, in place of `ref`, `app` and `server`: the member is
|
|
96
|
+
* that agent program over ACP behind the Shield โ Claude Code, Codex, an
|
|
97
|
+
* organization's own โ asked over A2A or ACP (SHIELD SH-45).
|
|
98
|
+
*/
|
|
99
|
+
harness?: string;
|
|
94
100
|
/** Where its loop turns: in the person's `browser`, or on a `runtime`. */
|
|
95
101
|
runsIn?: 'browser' | 'runtime';
|
|
96
102
|
/** The members it asks directly while it works, and over what. */
|
package/package.json
CHANGED
|
@@ -209,7 +209,22 @@ def _t(value: Any) -> str:
|
|
|
209
209
|
return json.dumps(" ".join(str(value or "").split()), ensure_ascii=False)
|
|
210
210
|
|
|
211
211
|
|
|
212
|
-
def
|
|
212
|
+
def load_listed(specs_dir: Path) -> list[dict[str, Any]]:
|
|
213
|
+
"""The register's listed tier (SH-57): known to speak ACP, not drilled, offered by nothing."""
|
|
214
|
+
register = yaml.safe_load((specs_dir / REGISTER).read_text()) or {}
|
|
215
|
+
return sorted(
|
|
216
|
+
(
|
|
217
|
+
entry
|
|
218
|
+
for entry in register.get("entries") or []
|
|
219
|
+
if entry.get("tier") == "listed"
|
|
220
|
+
),
|
|
221
|
+
key=lambda entry: str(entry["harness"]),
|
|
222
|
+
)
|
|
223
|
+
|
|
224
|
+
|
|
225
|
+
def generate_typescript_code(
|
|
226
|
+
specs: list[dict[str, Any]], listed: list[dict[str, Any]] = ()
|
|
227
|
+
) -> str:
|
|
213
228
|
lines = [
|
|
214
229
|
"/*",
|
|
215
230
|
" * Copyright (c) 2025-2026 Datalayer, Inc.",
|
|
@@ -225,7 +240,7 @@ def generate_typescript_code(specs: list[dict[str, Any]]) -> str:
|
|
|
225
240
|
" * DO NOT EDIT MANUALLY - run 'make specs' to regenerate.",
|
|
226
241
|
" */",
|
|
227
242
|
"",
|
|
228
|
-
"import type { HarnessSpec } from '../types/agentspecs';",
|
|
243
|
+
"import type { HarnessSpec, ListedHarness } from '../types/agentspecs';",
|
|
229
244
|
]
|
|
230
245
|
for spec in specs:
|
|
231
246
|
acp = spec.get("acp")
|
|
@@ -307,6 +322,27 @@ def generate_typescript_code(specs: list[dict[str, Any]]) -> str:
|
|
|
307
322
|
" return Object.values(HARNESS_CATALOGUE);",
|
|
308
323
|
"}",
|
|
309
324
|
"",
|
|
325
|
+
"/**",
|
|
326
|
+
" * The register's listed tier (SH-57): agents known to speak ACP, registered",
|
|
327
|
+
" * with their documented command and their terms, not drilled โ offered by",
|
|
328
|
+
" * nothing until moved to the catalogue.",
|
|
329
|
+
" */",
|
|
330
|
+
"export const LISTED_HARNESSES: ListedHarness[] = [",
|
|
331
|
+
*[
|
|
332
|
+
" {"
|
|
333
|
+
+ f" id: {_t(entry['harness'])}, name: {_t(entry.get('name'))}, docs: {_t(entry.get('docs'))},"
|
|
334
|
+
+ f" adapter: {_t(entry.get('adapter'))}, version: {_t(entry.get('version'))},"
|
|
335
|
+
+ f" command: {_t(entry['command']) if entry.get('command') else 'null'},"
|
|
336
|
+
+ f" licence: {_t(entry.get('licence'))}, licenceSource: {_t(entry.get('licence_source'))},"
|
|
337
|
+
+ f" termsSource: {_t(entry.get('terms_source'))}, credential: {_t(entry.get('credential'))},"
|
|
338
|
+
+ f" servedToThirdParties: {_t(entry.get('served_to_third_parties'))}, note: {_t(entry.get('note'))} }},"
|
|
339
|
+
for entry in listed
|
|
340
|
+
],
|
|
341
|
+
"];",
|
|
342
|
+
"",
|
|
343
|
+
"/** The sentence a listed harness is refused in (agentspecs' LISTED_NOT_DRILLED). */",
|
|
344
|
+
"export const LISTED_NOT_DRILLED = 'listed, not drilled yet';",
|
|
345
|
+
"",
|
|
310
346
|
]
|
|
311
347
|
return "\n".join(lines)
|
|
312
348
|
|
|
@@ -319,7 +355,9 @@ def main() -> None:
|
|
|
319
355
|
args = parser.parse_args()
|
|
320
356
|
specs = load_harness_specs(args.specs_dir)
|
|
321
357
|
args.python_output.write_text(generate_python_code(specs))
|
|
322
|
-
args.typescript_output.write_text(
|
|
358
|
+
args.typescript_output.write_text(
|
|
359
|
+
generate_typescript_code(specs, load_listed(args.specs_dir))
|
|
360
|
+
)
|
|
323
361
|
print(
|
|
324
362
|
f"Generated {len(specs)} harnesses: {args.python_output}, {args.typescript_output}"
|
|
325
363
|
)
|
|
@@ -153,6 +153,8 @@ def _generate_team_agent_py(agent: Dict[str, Any]) -> str:
|
|
|
153
153
|
lines.append(f' app="{agent["app"]}",')
|
|
154
154
|
if agent.get("server"):
|
|
155
155
|
lines.append(f' server="{agent["server"]}",')
|
|
156
|
+
if agent.get("harness"):
|
|
157
|
+
lines.append(f' harness="{agent["harness"]}",')
|
|
156
158
|
if agent.get("runs_in"):
|
|
157
159
|
lines.append(f' runs_in="{agent["runs_in"]}",')
|
|
158
160
|
links = agent.get("talks_to") or []
|
|
@@ -223,6 +225,7 @@ def _generate_team_agent_ts(agent: Dict[str, Any]) -> str:
|
|
|
223
225
|
application = (
|
|
224
226
|
(f"\n app: '{agent['app']}'," if agent.get("app") else "")
|
|
225
227
|
+ (f"\n server: '{agent['server']}'," if agent.get("server") else "")
|
|
228
|
+
+ (f"\n harness: '{agent['harness']}'," if agent.get("harness") else "")
|
|
226
229
|
+ (f"\n runsIn: '{agent['runs_in']}'," if agent.get("runs_in") else "")
|
|
227
230
|
+ (
|
|
228
231
|
"\n talksTo: ["
|