@usenaive-sdk/blueprints 0.5.0 → 0.6.0
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.d.ts +73 -2
- package/dist/index.js +321 -138
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -788,7 +788,11 @@ var SessionSchema = z6.object({
|
|
|
788
788
|
var SendMessageSchema = z6.object({
|
|
789
789
|
message: z6.string(),
|
|
790
790
|
interrupt: z6.boolean().optional(),
|
|
791
|
+
queue: z6.boolean().optional(),
|
|
791
792
|
idempotency_key: z6.string().optional()
|
|
793
|
+
}).refine((body) => !(body.interrupt === true && body.queue === true), {
|
|
794
|
+
message: "a send is either an interrupt or queued, not both",
|
|
795
|
+
path: ["queue"]
|
|
792
796
|
});
|
|
793
797
|
var SendAcceptedSchema = z6.object({
|
|
794
798
|
session_id: z6.string(),
|
|
@@ -892,11 +896,16 @@ var BoardCardSchema = z8.object({
|
|
|
892
896
|
object: z8.literal("board_card"),
|
|
893
897
|
board_id: idOf("brd"),
|
|
894
898
|
title: z8.string().min(1),
|
|
899
|
+
/** The brief — what was asked. */
|
|
895
900
|
body: z8.string(),
|
|
901
|
+
/** What the holder wrote back; a `done` carries one. */
|
|
902
|
+
note: z8.string().nullable(),
|
|
896
903
|
status: BoardStatusSchema,
|
|
897
904
|
assignee: z8.string().nullable(),
|
|
898
905
|
/** The cards this one waits on. A `blocked` card with an empty list is stuck on the world. */
|
|
899
906
|
blocked_by: z8.array(idOf("crd")),
|
|
907
|
+
woken_session_id: idOf("ses").nullable(),
|
|
908
|
+
reported_status: BoardStatusSchema.nullable(),
|
|
900
909
|
created_at: Timestamp,
|
|
901
910
|
updated_at: Timestamp
|
|
902
911
|
});
|
|
@@ -1337,6 +1346,8 @@ var BlueprintReportSchema = z14.object({
|
|
|
1337
1346
|
agents: z14.array(ResourceReportSchema),
|
|
1338
1347
|
schedules: z14.array(ResourceReportSchema),
|
|
1339
1348
|
intake: z14.array(ResourceReportSchema),
|
|
1349
|
+
/** One line per declared task (§31.11), `id` the card's `crd_`. Defaulted so older rows parse. */
|
|
1350
|
+
tasks: z14.array(ResourceReportSchema).default([]),
|
|
1340
1351
|
skipped: z14.array(z14.string()),
|
|
1341
1352
|
deselected: z14.array(z14.string()).default([])
|
|
1342
1353
|
});
|
|
@@ -1426,202 +1437,221 @@ var ProjectContextSchema = z14.object({
|
|
|
1426
1437
|
});
|
|
1427
1438
|
|
|
1428
1439
|
// ../core/src/schema/blueprint.ts
|
|
1440
|
+
import { z as z16 } from "zod";
|
|
1441
|
+
|
|
1442
|
+
// ../core/src/schema/social.ts
|
|
1429
1443
|
import { z as z15 } from "zod";
|
|
1430
|
-
var
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
|
|
1444
|
+
var SOCIAL_PLATFORMS = [
|
|
1445
|
+
"bluesky",
|
|
1446
|
+
"facebook",
|
|
1447
|
+
"instagram",
|
|
1448
|
+
"linkedin",
|
|
1449
|
+
"mastodon",
|
|
1450
|
+
"pinterest",
|
|
1451
|
+
"reddit",
|
|
1452
|
+
"threads",
|
|
1453
|
+
"tiktok",
|
|
1454
|
+
"x",
|
|
1455
|
+
"youtube"
|
|
1456
|
+
];
|
|
1457
|
+
var SOCIAL_TEXT_PLATFORMS = [
|
|
1458
|
+
"bluesky",
|
|
1459
|
+
"facebook",
|
|
1460
|
+
"linkedin",
|
|
1461
|
+
"mastodon",
|
|
1462
|
+
"threads",
|
|
1463
|
+
"x"
|
|
1464
|
+
];
|
|
1465
|
+
var SOCIAL_MEDIA_PLATFORMS = ["instagram", "tiktok", "youtube"];
|
|
1466
|
+
var SOCIAL_VISIBILITIES = ["public", "unlisted", "private"];
|
|
1467
|
+
var SOCIAL_VISIBILITY_PLATFORMS = ["mastodon", "youtube"];
|
|
1468
|
+
var SocialVisibilitySchema = z15.enum(SOCIAL_VISIBILITIES);
|
|
1469
|
+
var SOCIAL_VISIBILITY_RULE = `visibility is ${SOCIAL_VISIBILITIES.join(", ")} and only ${SOCIAL_VISIBILITY_PLATFORMS.join(" and ")} accept it; omit it and the post publishes at the account's own default, which on a video channel is normally public`;
|
|
1470
|
+
var SocialPlatformSchema = z15.enum(SOCIAL_PLATFORMS);
|
|
1471
|
+
var SocialTextPlatformSchema = z15.enum(SOCIAL_TEXT_PLATFORMS);
|
|
1472
|
+
var isText = (platform) => SOCIAL_TEXT_PLATFORMS.includes(platform);
|
|
1473
|
+
var isMedia = (platform) => SOCIAL_MEDIA_PLATFORMS.includes(platform);
|
|
1474
|
+
var SOCIAL_PLATFORM_RULE = `${SOCIAL_TEXT_PLATFORMS.join(", ")} take a text-only post; ${SOCIAL_MEDIA_PLATFORMS.join(", ")} may be named only when the post carries media_urls or file_ids; ${SOCIAL_PLATFORMS.filter((platform) => !isText(platform) && !isMedia(platform)).join(", ")} cannot be posted to`;
|
|
1475
|
+
var SocialAccountSchema = z15.object({
|
|
1476
|
+
id: z15.string().min(1),
|
|
1477
|
+
object: z15.literal("social_account"),
|
|
1478
|
+
identity_id: idOf("idn"),
|
|
1479
|
+
platform: SocialPlatformSchema,
|
|
1480
|
+
username: z15.string().nullable(),
|
|
1481
|
+
display_name: z15.string().nullable(),
|
|
1482
|
+
avatar_url: z15.url().nullable(),
|
|
1483
|
+
connected_at: Timestamp.nullable()
|
|
1484
|
+
});
|
|
1485
|
+
var SocialPostStatusSchema = z15.enum([
|
|
1486
|
+
"draft",
|
|
1487
|
+
"scheduled",
|
|
1488
|
+
"processing",
|
|
1489
|
+
"posted",
|
|
1490
|
+
"failed",
|
|
1491
|
+
"deleted"
|
|
1492
|
+
]);
|
|
1493
|
+
var SocialPostSchema = z15.object({
|
|
1494
|
+
id: z15.string().min(1),
|
|
1495
|
+
object: z15.literal("social_post"),
|
|
1496
|
+
identity_id: idOf("idn"),
|
|
1497
|
+
title: z15.string(),
|
|
1498
|
+
platforms: z15.array(SocialPlatformSchema),
|
|
1499
|
+
status: SocialPostStatusSchema,
|
|
1500
|
+
scheduled_at: Timestamp.nullable(),
|
|
1501
|
+
posted_at: Timestamp.nullable(),
|
|
1502
|
+
error: z15.string().nullable()
|
|
1503
|
+
});
|
|
1504
|
+
var SocialUploadSchema = z15.object({
|
|
1505
|
+
id: z15.string().min(1),
|
|
1506
|
+
object: z15.literal("social_upload"),
|
|
1507
|
+
identity_id: idOf("idn"),
|
|
1508
|
+
type: z15.enum(["image", "video", "document"]),
|
|
1509
|
+
url: z15.url().nullable()
|
|
1510
|
+
});
|
|
1511
|
+
var SocialAnalyticsSchema = z15.object({
|
|
1512
|
+
object: z15.literal("social_analytics"),
|
|
1513
|
+
identity_id: idOf("idn"),
|
|
1514
|
+
resource_id: z15.string().min(1),
|
|
1515
|
+
platform: SocialPlatformSchema.nullable(),
|
|
1516
|
+
data: z15.unknown()
|
|
1517
|
+
});
|
|
1518
|
+
var SocialCommentSchema = z15.object({
|
|
1519
|
+
id: z15.string().min(1),
|
|
1520
|
+
object: z15.literal("social_comment"),
|
|
1521
|
+
identity_id: idOf("idn"),
|
|
1522
|
+
post_id: z15.string().min(1),
|
|
1523
|
+
platforms: z15.array(SocialPlatformSchema),
|
|
1524
|
+
status: SocialPostStatusSchema,
|
|
1525
|
+
posted_at: Timestamp.nullable(),
|
|
1526
|
+
data: z15.unknown()
|
|
1527
|
+
});
|
|
1528
|
+
|
|
1529
|
+
// ../core/src/schema/blueprint.ts
|
|
1530
|
+
var BlueprintScheduleSchema = z16.object({
|
|
1531
|
+
agent: z16.string().min(1),
|
|
1532
|
+
cron: z16.string().min(1),
|
|
1533
|
+
timezone: z16.string().nullable(),
|
|
1434
1534
|
/** The message each fire opens its session with — the sentence worth printing. */
|
|
1435
|
-
input:
|
|
1535
|
+
input: z16.string().min(1),
|
|
1436
1536
|
budget_micro_usd: MicroUsdField.nonnegative()
|
|
1437
1537
|
});
|
|
1438
1538
|
var BlueprintBudgetSchema = BlueprintScheduleSchema.pick({ agent: true, cron: true, budget_micro_usd: true });
|
|
1439
|
-
var BlueprintCrewSchema =
|
|
1440
|
-
name:
|
|
1441
|
-
description:
|
|
1442
|
-
model:
|
|
1443
|
-
briefed:
|
|
1444
|
-
intake:
|
|
1539
|
+
var BlueprintCrewSchema = z16.object({
|
|
1540
|
+
name: z16.string().min(1),
|
|
1541
|
+
description: z16.string().nullable(),
|
|
1542
|
+
model: z16.string().min(1),
|
|
1543
|
+
briefed: z16.boolean(),
|
|
1544
|
+
intake: z16.string().nullable().optional(),
|
|
1445
1545
|
/** What the first session may spend: the intake's own cap, else the agent's (§31.4). Set iff `briefed`. */
|
|
1446
1546
|
intake_micro_usd: MicroUsdField.nonnegative().optional(),
|
|
1447
|
-
role:
|
|
1448
|
-
skills:
|
|
1449
|
-
tools:
|
|
1450
|
-
required:
|
|
1547
|
+
role: z16.string().min(1).optional(),
|
|
1548
|
+
skills: z16.array(SkillRefSchema).optional(),
|
|
1549
|
+
tools: z16.array(z16.string().min(1)).optional(),
|
|
1550
|
+
required: z16.boolean().optional()
|
|
1451
1551
|
});
|
|
1452
|
-
var BlueprintAppSchema =
|
|
1453
|
-
name:
|
|
1552
|
+
var BlueprintAppSchema = z16.object({
|
|
1553
|
+
name: z16.string().min(1),
|
|
1454
1554
|
type: AppTypeSchema,
|
|
1455
|
-
description:
|
|
1456
|
-
mcp:
|
|
1457
|
-
tools:
|
|
1555
|
+
description: z16.string().nullable(),
|
|
1556
|
+
mcp: z16.string().nullable().optional(),
|
|
1557
|
+
tools: z16.array(z16.string().min(1)).optional(),
|
|
1458
1558
|
/** Whether an install may deselect it (§31.2). Optional: the rollout argument above. */
|
|
1459
|
-
required:
|
|
1559
|
+
required: z16.boolean().optional()
|
|
1560
|
+
});
|
|
1561
|
+
var BlueprintIdentityConnectionsSchema = z16.object({
|
|
1562
|
+
social: z16.object({
|
|
1563
|
+
from: z16.string().min(1),
|
|
1564
|
+
map: z16.record(z16.string().min(1), SocialPlatformSchema)
|
|
1565
|
+
}).optional()
|
|
1460
1566
|
});
|
|
1461
|
-
var
|
|
1462
|
-
|
|
1567
|
+
var BlueprintIdentitySchema = z16.object({
|
|
1568
|
+
name: z16.string().min(1),
|
|
1569
|
+
description: z16.string().nullable(),
|
|
1570
|
+
connections: BlueprintIdentityConnectionsSchema.optional()
|
|
1571
|
+
});
|
|
1572
|
+
var ContentHashSchema = z16.string().regex(/^[0-9a-f]{64}$/, "a lowercase sha-256 hex digest");
|
|
1573
|
+
var BlueprintTreeSchema = z16.object({
|
|
1463
1574
|
/** `apps[].name` in the declaration — the same name §31.5 prints and the install ensures by. */
|
|
1464
|
-
app:
|
|
1575
|
+
app: z16.string().min(1),
|
|
1465
1576
|
content_hash: ContentHashSchema
|
|
1466
1577
|
});
|
|
1467
|
-
var BlueprintArtifactSchema =
|
|
1578
|
+
var BlueprintArtifactSchema = z16.object({
|
|
1468
1579
|
id: idOf("bpa"),
|
|
1469
|
-
object:
|
|
1580
|
+
object: z16.literal("blueprint_artifact"),
|
|
1470
1581
|
/** The machine — its repository, screens and `/api/*`. */
|
|
1471
|
-
blueprint:
|
|
1582
|
+
blueprint: z16.string().min(1),
|
|
1472
1583
|
/** Which of that blueprint's templates provides the crew. */
|
|
1473
|
-
template:
|
|
1584
|
+
template: z16.string().min(1),
|
|
1474
1585
|
/** The blueprint repository's own released version. Stored, never parsed (ADR-0401). */
|
|
1475
|
-
version:
|
|
1586
|
+
version: z16.string().min(1),
|
|
1476
1587
|
/**
|
|
1477
1588
|
* The built trees, one per deployable app, ordered as the declaration orders its apps. Never
|
|
1478
1589
|
* empty: an artifact that built nothing is not an artifact, and the column behind it says so
|
|
1479
1590
|
* (migration 0040) exactly as the single `content_hash` it replaces was `not null`.
|
|
1480
1591
|
*/
|
|
1481
|
-
trees:
|
|
1592
|
+
trees: z16.array(BlueprintTreeSchema).min(1),
|
|
1482
1593
|
/**
|
|
1483
1594
|
* The setup questions, asked by the studio **before** provisioning. `QuestionField` (§7.1) is
|
|
1484
1595
|
* reused rather than restated: a setup question and a question a parked agent asks are the same
|
|
1485
1596
|
* object at different times, so one component renders both.
|
|
1486
1597
|
*/
|
|
1487
|
-
questions:
|
|
1488
|
-
schedules:
|
|
1598
|
+
questions: z16.array(QuestionFieldSchema),
|
|
1599
|
+
schedules: z16.array(BlueprintScheduleSchema),
|
|
1489
1600
|
/** Who the crew is, and what it deploys — §31.5. Derived from `declaration`, never stored twice. */
|
|
1490
|
-
agents:
|
|
1491
|
-
apps:
|
|
1601
|
+
agents: z16.array(BlueprintCrewSchema),
|
|
1602
|
+
apps: z16.array(BlueprintAppSchema),
|
|
1492
1603
|
/**
|
|
1493
1604
|
* The agents a template creates per client the operator signs — printed, never provisioned by an
|
|
1494
1605
|
* apply (§31.1). Absent on rows published before WS12 v2, hence optional.
|
|
1495
1606
|
*/
|
|
1496
|
-
crew_per_client:
|
|
1607
|
+
crew_per_client: z16.array(BlueprintCrewSchema).optional(),
|
|
1608
|
+
/**
|
|
1609
|
+
* The personas the crew posts from, and which accounts to connect to each before the crew
|
|
1610
|
+
* exists (§31.10). Derived from `declaration` like `agents`; optional for the §31.5 rollout reason.
|
|
1611
|
+
*/
|
|
1612
|
+
identities: z16.array(BlueprintIdentitySchema).optional(),
|
|
1497
1613
|
/**
|
|
1498
1614
|
* The creator template a row was published from (§42.8), `null` on every first-party row.
|
|
1499
1615
|
* `creator_name` is the public display name the landing page credits. The API sends all three
|
|
1500
1616
|
* on every row; they are optional here only so an artifact typed before §42 still reads.
|
|
1501
1617
|
*/
|
|
1502
1618
|
creator_template_id: idOf("ctp").nullish(),
|
|
1503
|
-
creator_template_version:
|
|
1504
|
-
creator_name:
|
|
1619
|
+
creator_template_version: z16.number().int().positive().nullish(),
|
|
1620
|
+
creator_name: z16.string().min(1).nullish(),
|
|
1505
1621
|
published_at: Timestamp
|
|
1506
1622
|
});
|
|
1507
1623
|
|
|
1508
1624
|
// ../core/src/schema/vault.ts
|
|
1509
|
-
import { z as
|
|
1510
|
-
var VaultCredentialKindSchema =
|
|
1511
|
-
var VaultSchema =
|
|
1625
|
+
import { z as z17 } from "zod";
|
|
1626
|
+
var VaultCredentialKindSchema = z17.enum(["env_var", "static_bearer", "mcp_oauth"]);
|
|
1627
|
+
var VaultSchema = z17.object({
|
|
1512
1628
|
id: idOf("vlt"),
|
|
1513
|
-
object:
|
|
1629
|
+
object: z17.literal("vault"),
|
|
1514
1630
|
identity_id: idOf("idn").nullable(),
|
|
1515
|
-
display_name:
|
|
1516
|
-
credential_count:
|
|
1631
|
+
display_name: z17.string().min(1).max(128),
|
|
1632
|
+
credential_count: z17.number().int().nonnegative(),
|
|
1517
1633
|
created_at: Timestamp
|
|
1518
1634
|
});
|
|
1519
|
-
var VaultCredentialSchema =
|
|
1635
|
+
var VaultCredentialSchema = z17.object({
|
|
1520
1636
|
id: idOf("vcr"),
|
|
1521
|
-
object:
|
|
1637
|
+
object: z17.literal("vault_credential"),
|
|
1522
1638
|
vault_id: idOf("vlt"),
|
|
1523
1639
|
kind: VaultCredentialKindSchema,
|
|
1524
1640
|
/** For `env_var`, the environment variable name. For the MCP kinds, a display label. */
|
|
1525
|
-
key:
|
|
1641
|
+
key: z17.string().min(1).max(128),
|
|
1526
1642
|
/** The exact destination host an `env_var` credential is bound to. Never a wildcard. */
|
|
1527
|
-
host:
|
|
1643
|
+
host: z17.string().nullable(),
|
|
1528
1644
|
/** The exact MCP server URL an `mcp_*` token is matched to. */
|
|
1529
|
-
mcp_server_url:
|
|
1530
|
-
placeholder_ref:
|
|
1645
|
+
mcp_server_url: z17.url().nullable(),
|
|
1646
|
+
placeholder_ref: z17.string(),
|
|
1531
1647
|
expires_at: Timestamp.nullable(),
|
|
1532
1648
|
last_injected_at: Timestamp.nullable(),
|
|
1533
1649
|
created_at: Timestamp
|
|
1534
1650
|
});
|
|
1535
1651
|
|
|
1536
|
-
// ../core/src/schema/social.ts
|
|
1537
|
-
import { z as z17 } from "zod";
|
|
1538
|
-
var SOCIAL_PLATFORMS = [
|
|
1539
|
-
"bluesky",
|
|
1540
|
-
"facebook",
|
|
1541
|
-
"instagram",
|
|
1542
|
-
"linkedin",
|
|
1543
|
-
"mastodon",
|
|
1544
|
-
"pinterest",
|
|
1545
|
-
"reddit",
|
|
1546
|
-
"threads",
|
|
1547
|
-
"tiktok",
|
|
1548
|
-
"x",
|
|
1549
|
-
"youtube"
|
|
1550
|
-
];
|
|
1551
|
-
var SOCIAL_TEXT_PLATFORMS = [
|
|
1552
|
-
"bluesky",
|
|
1553
|
-
"facebook",
|
|
1554
|
-
"linkedin",
|
|
1555
|
-
"mastodon",
|
|
1556
|
-
"threads",
|
|
1557
|
-
"x"
|
|
1558
|
-
];
|
|
1559
|
-
var SOCIAL_MEDIA_PLATFORMS = ["instagram", "tiktok", "youtube"];
|
|
1560
|
-
var SOCIAL_VISIBILITIES = ["public", "unlisted", "private"];
|
|
1561
|
-
var SOCIAL_VISIBILITY_PLATFORMS = ["mastodon", "youtube"];
|
|
1562
|
-
var SocialVisibilitySchema = z17.enum(SOCIAL_VISIBILITIES);
|
|
1563
|
-
var SOCIAL_VISIBILITY_RULE = `visibility is ${SOCIAL_VISIBILITIES.join(", ")} and only ${SOCIAL_VISIBILITY_PLATFORMS.join(" and ")} accept it; omit it and the post publishes at the account's own default, which on a video channel is normally public`;
|
|
1564
|
-
var SocialPlatformSchema = z17.enum(SOCIAL_PLATFORMS);
|
|
1565
|
-
var SocialTextPlatformSchema = z17.enum(SOCIAL_TEXT_PLATFORMS);
|
|
1566
|
-
var isText = (platform) => SOCIAL_TEXT_PLATFORMS.includes(platform);
|
|
1567
|
-
var isMedia = (platform) => SOCIAL_MEDIA_PLATFORMS.includes(platform);
|
|
1568
|
-
var SOCIAL_PLATFORM_RULE = `${SOCIAL_TEXT_PLATFORMS.join(", ")} take a text-only post; ${SOCIAL_MEDIA_PLATFORMS.join(", ")} may be named only when the post carries media_urls or file_ids; ${SOCIAL_PLATFORMS.filter((platform) => !isText(platform) && !isMedia(platform)).join(", ")} cannot be posted to`;
|
|
1569
|
-
var SocialAccountSchema = z17.object({
|
|
1570
|
-
id: z17.string().min(1),
|
|
1571
|
-
object: z17.literal("social_account"),
|
|
1572
|
-
identity_id: idOf("idn"),
|
|
1573
|
-
platform: SocialPlatformSchema,
|
|
1574
|
-
username: z17.string().nullable(),
|
|
1575
|
-
display_name: z17.string().nullable(),
|
|
1576
|
-
avatar_url: z17.url().nullable(),
|
|
1577
|
-
connected_at: Timestamp.nullable()
|
|
1578
|
-
});
|
|
1579
|
-
var SocialPostStatusSchema = z17.enum([
|
|
1580
|
-
"draft",
|
|
1581
|
-
"scheduled",
|
|
1582
|
-
"processing",
|
|
1583
|
-
"posted",
|
|
1584
|
-
"failed",
|
|
1585
|
-
"deleted"
|
|
1586
|
-
]);
|
|
1587
|
-
var SocialPostSchema = z17.object({
|
|
1588
|
-
id: z17.string().min(1),
|
|
1589
|
-
object: z17.literal("social_post"),
|
|
1590
|
-
identity_id: idOf("idn"),
|
|
1591
|
-
title: z17.string(),
|
|
1592
|
-
platforms: z17.array(SocialPlatformSchema),
|
|
1593
|
-
status: SocialPostStatusSchema,
|
|
1594
|
-
scheduled_at: Timestamp.nullable(),
|
|
1595
|
-
posted_at: Timestamp.nullable(),
|
|
1596
|
-
error: z17.string().nullable()
|
|
1597
|
-
});
|
|
1598
|
-
var SocialUploadSchema = z17.object({
|
|
1599
|
-
id: z17.string().min(1),
|
|
1600
|
-
object: z17.literal("social_upload"),
|
|
1601
|
-
identity_id: idOf("idn"),
|
|
1602
|
-
type: z17.enum(["image", "video", "document"]),
|
|
1603
|
-
url: z17.url().nullable()
|
|
1604
|
-
});
|
|
1605
|
-
var SocialAnalyticsSchema = z17.object({
|
|
1606
|
-
object: z17.literal("social_analytics"),
|
|
1607
|
-
identity_id: idOf("idn"),
|
|
1608
|
-
resource_id: z17.string().min(1),
|
|
1609
|
-
platform: SocialPlatformSchema.nullable(),
|
|
1610
|
-
data: z17.unknown()
|
|
1611
|
-
});
|
|
1612
|
-
var SocialCommentSchema = z17.object({
|
|
1613
|
-
id: z17.string().min(1),
|
|
1614
|
-
object: z17.literal("social_comment"),
|
|
1615
|
-
identity_id: idOf("idn"),
|
|
1616
|
-
post_id: z17.string().min(1),
|
|
1617
|
-
platforms: z17.array(SocialPlatformSchema),
|
|
1618
|
-
status: SocialPostStatusSchema,
|
|
1619
|
-
posted_at: Timestamp.nullable(),
|
|
1620
|
-
data: z17.unknown()
|
|
1621
|
-
});
|
|
1622
|
-
|
|
1623
1652
|
// ../core/src/schema/handoff.ts
|
|
1624
1653
|
import { z as z18 } from "zod";
|
|
1654
|
+
var MAX_HANDOFF_TARGETS = 6;
|
|
1625
1655
|
var HandoffRequestSchema = z18.object({
|
|
1626
1656
|
agent: z18.string().min(1),
|
|
1627
1657
|
message: z18.string().min(1),
|
|
@@ -1634,12 +1664,42 @@ var HandoffSchema = z18.object({
|
|
|
1634
1664
|
status: z18.enum(["queued", "already_running"]),
|
|
1635
1665
|
handoff_key: z18.string().nullable()
|
|
1636
1666
|
});
|
|
1667
|
+
var SessionHandoffRequestSchema = z18.object({
|
|
1668
|
+
agents: z18.array(z18.string().min(1)).min(1).max(MAX_HANDOFF_TARGETS),
|
|
1669
|
+
message: z18.string().min(1),
|
|
1670
|
+
handoff_key: z18.string().min(1).max(128).optional(),
|
|
1671
|
+
budget_micro_usd: z18.number().int().positive().optional()
|
|
1672
|
+
});
|
|
1673
|
+
var HandoffRefusalSchema = z18.object({
|
|
1674
|
+
object: z18.literal("handoff_refusal"),
|
|
1675
|
+
agent: z18.string(),
|
|
1676
|
+
code: z18.string(),
|
|
1677
|
+
message: z18.string()
|
|
1678
|
+
});
|
|
1679
|
+
var HandoffBatchSchema = z18.object({
|
|
1680
|
+
object: z18.literal("handoff_batch"),
|
|
1681
|
+
handoffs: z18.array(HandoffSchema.extend({ agent_id: idOf("agt") })),
|
|
1682
|
+
refusals: z18.array(HandoffRefusalSchema)
|
|
1683
|
+
});
|
|
1637
1684
|
var SessionHandoffSchema = z18.object({
|
|
1638
1685
|
from_session: idOf("ses"),
|
|
1639
1686
|
from_agent: idOf("agt"),
|
|
1640
1687
|
key: z18.string().nullable(),
|
|
1641
1688
|
depth: z18.number().int().positive()
|
|
1642
1689
|
});
|
|
1690
|
+
var ChannelBriefSchema = z18.object({
|
|
1691
|
+
root_session_id: idOf("ses"),
|
|
1692
|
+
name: z18.string().min(1),
|
|
1693
|
+
members: z18.array(z18.string().min(1))
|
|
1694
|
+
});
|
|
1695
|
+
var ChannelPostRequestSchema = z18.object({
|
|
1696
|
+
message: z18.string().min(1).max(2e4)
|
|
1697
|
+
});
|
|
1698
|
+
var ChannelPostSchema = z18.object({
|
|
1699
|
+
object: z18.literal("channel_post"),
|
|
1700
|
+
root_session_id: idOf("ses"),
|
|
1701
|
+
queued: z18.boolean()
|
|
1702
|
+
});
|
|
1643
1703
|
|
|
1644
1704
|
// ../core/src/schema/media.ts
|
|
1645
1705
|
import { z as z19 } from "zod";
|
|
@@ -2675,6 +2735,7 @@ var WalletDeclSchema = CreateWalletSchema.or(
|
|
|
2675
2735
|
);
|
|
2676
2736
|
var CardDeclSchema = IssueCardSchema;
|
|
2677
2737
|
var IdentityDeclSchema = IdentitySchema.pick({ name: true, description: true }).partial({ description: true }).extend({
|
|
2738
|
+
connections: BlueprintIdentityConnectionsSchema.optional(),
|
|
2678
2739
|
legal: z28.array(LegalDeclSchema).optional(),
|
|
2679
2740
|
wallet: WalletDeclSchema.optional(),
|
|
2680
2741
|
cards: z28.array(CardDeclSchema).optional()
|
|
@@ -2687,6 +2748,13 @@ var RemovedSchema = z28.object({
|
|
|
2687
2748
|
vaults: z28.array(z28.string().min(1)).default([])
|
|
2688
2749
|
});
|
|
2689
2750
|
var KeptSchema = z28.object({ agents: z28.array(z28.string().min(1)).default([]) });
|
|
2751
|
+
var TaskDeclSchema = z28.object({
|
|
2752
|
+
key: z28.string().min(1),
|
|
2753
|
+
title: z28.string().min(1).max(200),
|
|
2754
|
+
body: z28.string().max(8192).optional(),
|
|
2755
|
+
assignee: z28.string().min(1).optional(),
|
|
2756
|
+
blocked_by: z28.array(z28.string().min(1)).optional()
|
|
2757
|
+
});
|
|
2690
2758
|
var ProjectSchema = z28.object({
|
|
2691
2759
|
name: z28.string().min(1),
|
|
2692
2760
|
/** The machine this project runs: its repo, its screens, its `/api/*` (`template.ts`). */
|
|
@@ -2717,6 +2785,8 @@ var ProjectSchema = z28.object({
|
|
|
2717
2785
|
* crew's business at the moment a client is signed, not the declaration's.
|
|
2718
2786
|
*/
|
|
2719
2787
|
crew_per_client: z28.array(z28.object({ name: z28.string().min(1), role: z28.string().min(1).optional(), description: z28.string().optional() })).optional(),
|
|
2788
|
+
/** The crew's first work, as cards on the organization's board rather than N private intakes (§31.11). */
|
|
2789
|
+
tasks: z28.array(TaskDeclSchema).default([]),
|
|
2720
2790
|
removed: RemovedSchema.default({ apps: [], agents: [], skills: [], identities: [], vaults: [] }),
|
|
2721
2791
|
kept: KeptSchema.default({ agents: [] })
|
|
2722
2792
|
});
|
|
@@ -2732,6 +2802,20 @@ function assertUniqueNames(kind, names) {
|
|
|
2732
2802
|
seen.add(name);
|
|
2733
2803
|
}
|
|
2734
2804
|
}
|
|
2805
|
+
function inDependencyOrder(tasks) {
|
|
2806
|
+
const placed = /* @__PURE__ */ new Set();
|
|
2807
|
+
const out = [];
|
|
2808
|
+
while (out.length < tasks.length) {
|
|
2809
|
+
const next = tasks.find((task) => !placed.has(task.key) && (task.blocked_by ?? []).every((key) => placed.has(key)));
|
|
2810
|
+
if (next === void 0) {
|
|
2811
|
+
const stuck = tasks.filter((task) => !placed.has(task.key)).map((task) => `"${task.key}"`);
|
|
2812
|
+
refuse(`tasks ${stuck.join(", ")}: blocked_by forms a cycle \u2014 a card cannot wait on a card that waits on it`);
|
|
2813
|
+
}
|
|
2814
|
+
placed.add(next.key);
|
|
2815
|
+
out.push(next);
|
|
2816
|
+
}
|
|
2817
|
+
return out;
|
|
2818
|
+
}
|
|
2735
2819
|
function deepFreeze(value) {
|
|
2736
2820
|
if (value !== null && typeof value === "object") {
|
|
2737
2821
|
for (const child of Object.values(value)) deepFreeze(child);
|
|
@@ -2779,6 +2863,20 @@ function parseProject(input) {
|
|
|
2779
2863
|
assertUniqueNames("bucket", (app.buckets ?? []).map((bucket) => bucket.name));
|
|
2780
2864
|
}
|
|
2781
2865
|
const identityNames = new Set(config.identities.map((i) => i.name));
|
|
2866
|
+
const connectable = config.identities.filter((i) => i.connections !== void 0).map((i) => i.name);
|
|
2867
|
+
if (connectable.length > 1) {
|
|
2868
|
+
refuse(`identities ${connectable.map((n) => `"${n}"`).join(", ")} each declare connections, but the studio's Add connections step connects one persona \u2014 declare connections on the one the crew publishes through`);
|
|
2869
|
+
}
|
|
2870
|
+
for (const identity of config.identities) {
|
|
2871
|
+
const social = identity.connections?.social;
|
|
2872
|
+
if (social === void 0) continue;
|
|
2873
|
+
const question = config.questions.find((q) => q.key === social.from);
|
|
2874
|
+
if (question === void 0) refuse(`identity "${identity.name}": connections.social.from names "${social.from}", but no question with that key is declared in this project`);
|
|
2875
|
+
if (question.type !== "choice") refuse(`identity "${identity.name}": connections.social.from names "${social.from}", which is a ${question.type} question \u2014 the map is keyed by a choice question's options`);
|
|
2876
|
+
for (const label of Object.keys(social.map)) {
|
|
2877
|
+
if (!question.options.includes(label)) refuse(`identity "${identity.name}": connections.social.map names "${label}", which is not one of question "${social.from}"'s options \u2014 a key no answer can equal is a row nobody can reach`);
|
|
2878
|
+
}
|
|
2879
|
+
}
|
|
2782
2880
|
for (const vault of config.vaults) {
|
|
2783
2881
|
if (vault.identity !== void 0 && !identityNames.has(vault.identity)) {
|
|
2784
2882
|
refuse(`vault "${vault.name}": identity names "${vault.identity}", but no identity with that name is declared in this project`);
|
|
@@ -2837,6 +2935,21 @@ function parseProject(input) {
|
|
|
2837
2935
|
}
|
|
2838
2936
|
}
|
|
2839
2937
|
}
|
|
2938
|
+
assertUniqueNames("task", config.tasks.map((task) => task.key));
|
|
2939
|
+
const taskKeys = new Set(config.tasks.map((task) => task.key));
|
|
2940
|
+
for (const task of config.tasks) {
|
|
2941
|
+
if (`${config.name}:${task.key}`.length > 128) {
|
|
2942
|
+
refuse(`task "${task.key}": "${config.name}:${task.key}" is longer than the 128 characters a card key holds \u2014 shorten the key`);
|
|
2943
|
+
}
|
|
2944
|
+
if (task.assignee !== void 0 && !agentNames.has(task.assignee)) {
|
|
2945
|
+
refuse(`task "${task.key}": assignee names "${task.assignee}", but no agent with that name is declared in this project`);
|
|
2946
|
+
}
|
|
2947
|
+
for (const key of task.blocked_by ?? []) {
|
|
2948
|
+
if (key === task.key) refuse(`task "${task.key}": blocked_by names itself \u2014 a card cannot wait on itself`);
|
|
2949
|
+
if (!taskKeys.has(key)) refuse(`task "${task.key}": blocked_by names "${key}", but no task with that key is declared in this project`);
|
|
2950
|
+
}
|
|
2951
|
+
}
|
|
2952
|
+
inDependencyOrder(config.tasks);
|
|
2840
2953
|
return deepFreeze(config);
|
|
2841
2954
|
}
|
|
2842
2955
|
function withTemplate(input, templates) {
|
|
@@ -3527,6 +3640,75 @@ async function reportLegal(client, decls, identityId, skipped) {
|
|
|
3527
3640
|
);
|
|
3528
3641
|
}
|
|
3529
3642
|
|
|
3643
|
+
// src/tasks.ts
|
|
3644
|
+
var ORCHESTRATOR_MARKER = "orchestrator";
|
|
3645
|
+
var CEO_LABEL = "CEO";
|
|
3646
|
+
var CEO_DETAIL = "Hires and directs the crew";
|
|
3647
|
+
var CEO_BUDGET = { cap_micro_usd: 5e7, max_task_micro_usd: 5e6, period: "month" };
|
|
3648
|
+
var isOrchestrator = (agent) => agent.metadata["role"] === ORCHESTRATOR_MARKER;
|
|
3649
|
+
function seated(live, members) {
|
|
3650
|
+
const roster = live?.agents ?? [];
|
|
3651
|
+
const already = new Set(roster.flatMap((entry) => entry.type === "agent" ? [entry.id] : []));
|
|
3652
|
+
const joining = members.filter((id) => !already.has(id)).map((id) => ({ type: "agent", id }));
|
|
3653
|
+
return { type: "coordinator", board: true, agents: [...roster, ...joining] };
|
|
3654
|
+
}
|
|
3655
|
+
async function ensureOrchestrator(client, existing, members, dryRun) {
|
|
3656
|
+
const current = existing.find(isOrchestrator);
|
|
3657
|
+
const live = current === void 0 ? null : normaliseMultiagent(current.multiagent);
|
|
3658
|
+
const team = seated(live, members);
|
|
3659
|
+
if (current === void 0) {
|
|
3660
|
+
if (dryRun) return { name: CEO_LABEL, action: "created" };
|
|
3661
|
+
const model = (await client.models.list({ window: "immediate", limit: 1 })).data[0];
|
|
3662
|
+
if (model === void 0) throw new BlueprintRefusal("no model is served, so the board's owner cannot be created");
|
|
3663
|
+
const made = await client.agents.create({
|
|
3664
|
+
name: CEO_LABEL,
|
|
3665
|
+
harness: "pi",
|
|
3666
|
+
model: model.id,
|
|
3667
|
+
description: CEO_DETAIL,
|
|
3668
|
+
budget: CEO_BUDGET,
|
|
3669
|
+
metadata: { role: ORCHESTRATOR_MARKER },
|
|
3670
|
+
multiagent: team
|
|
3671
|
+
});
|
|
3672
|
+
return { name: CEO_LABEL, action: "created", id: made.id };
|
|
3673
|
+
}
|
|
3674
|
+
if (live !== null && !changed(team, live)) return { name: current.name, action: "unchanged", id: current.id };
|
|
3675
|
+
if (!dryRun) await client.agents.update(current.id, { multiagent: team });
|
|
3676
|
+
return { name: current.name, action: "updated", id: current.id };
|
|
3677
|
+
}
|
|
3678
|
+
async function seedTasks(client, config, existing, agents, dryRun, into, skipped) {
|
|
3679
|
+
const members = agents.flatMap((one) => one.id === void 0 ? [] : [one.id]);
|
|
3680
|
+
const owner = await line(CEO_LABEL, () => ensureOrchestrator(client, existing, members, dryRun));
|
|
3681
|
+
agents.push(owner);
|
|
3682
|
+
const board = owner.action === "refused" || dryRun || owner.id === void 0 ? null : await client.board.create(owner.id);
|
|
3683
|
+
const before = board === null ? [] : await listAll(client.config, `/v1/boards/${board.id}/cards`, BoardCardSchema, skipped);
|
|
3684
|
+
const known = new Set(before.map((card) => card.id));
|
|
3685
|
+
const ids = /* @__PURE__ */ new Map();
|
|
3686
|
+
for (const task of inDependencyOrder(config.tasks)) {
|
|
3687
|
+
into.push(
|
|
3688
|
+
await line(task.key, async () => {
|
|
3689
|
+
if (owner.action === "refused") return { name: task.key, action: "refused", reason: `board owner "${owner.name}" was refused: ${owner.reason}` };
|
|
3690
|
+
const assignee = task.assignee;
|
|
3691
|
+
if (assignee !== void 0 && !agents.some((one) => one.name === assignee && one.action !== "refused")) {
|
|
3692
|
+
return { name: task.key, action: "refused", reason: `assignee "${assignee}" was not provisioned in this run` };
|
|
3693
|
+
}
|
|
3694
|
+
if (board === null) return { name: task.key, action: "created" };
|
|
3695
|
+
const blockers = task.blocked_by ?? [];
|
|
3696
|
+
const unmet = blockers.find((key) => !ids.has(key));
|
|
3697
|
+
if (unmet !== void 0) return { name: task.key, action: "refused", reason: `blocked_by "${unmet}" was not seeded in this run` };
|
|
3698
|
+
const card = await client.board.cards.create(board.id, {
|
|
3699
|
+
key: `${config.name}:${task.key}`,
|
|
3700
|
+
title: task.title,
|
|
3701
|
+
body: task.body,
|
|
3702
|
+
assignee,
|
|
3703
|
+
blocked_by: blockers.map((key) => ids.get(key))
|
|
3704
|
+
});
|
|
3705
|
+
ids.set(task.key, card.id);
|
|
3706
|
+
return { name: task.key, action: known.has(card.id) ? "unchanged" : "created", id: card.id };
|
|
3707
|
+
})
|
|
3708
|
+
);
|
|
3709
|
+
}
|
|
3710
|
+
}
|
|
3711
|
+
|
|
3530
3712
|
// src/vaults.ts
|
|
3531
3713
|
async function upsertVault(client, decl, existing, identityIds, dryRun) {
|
|
3532
3714
|
const identityId = decl.identity === void 0 ? void 0 : identityIds.get(decl.identity);
|
|
@@ -3737,7 +3919,7 @@ async function up(config, client, opts = {}) {
|
|
|
3737
3919
|
const dir = opts.dir ?? process.cwd();
|
|
3738
3920
|
const ids = { apps: /* @__PURE__ */ new Map(), identities: /* @__PURE__ */ new Map() };
|
|
3739
3921
|
const taken = selectCrew(config, opts.select);
|
|
3740
|
-
const report2 = { dry_run: dryRun, ...applied(config), skills: [], identities: [], vaults: [], apps: [], agents: [], schedules: [], intake: [], skipped: [], deselected: taken.deselected };
|
|
3922
|
+
const report2 = { dry_run: dryRun, ...applied(config), skills: [], identities: [], vaults: [], apps: [], agents: [], schedules: [], intake: [], tasks: [], skipped: [], deselected: taken.deselected };
|
|
3741
3923
|
const owner = { project: config.name, adopt: opts.adopt ?? false, skipped: report2.skipped };
|
|
3742
3924
|
const hosted = opts.trees !== void 0;
|
|
3743
3925
|
for (const decl of config.skills) {
|
|
@@ -3800,7 +3982,7 @@ async function up(config, client, opts = {}) {
|
|
|
3800
3982
|
)
|
|
3801
3983
|
)
|
|
3802
3984
|
);
|
|
3803
|
-
const existing = taken.agents.length > 0 || config.removed.agents.length > 0 || config.kept.agents.length > 0 ? await listAll(client.config, "/v1/agents", AgentSchema, report2.skipped) : [];
|
|
3985
|
+
const existing = taken.agents.length > 0 || config.removed.agents.length > 0 || config.kept.agents.length > 0 || config.tasks.length > 0 ? await listAll(client.config, "/v1/agents", AgentSchema, report2.skipped) : [];
|
|
3804
3986
|
const deployments = taken.agents.some((decl) => decl.schedules !== void 0) ? await listAll(client.config, "/v1/deployments", DeploymentSchema, report2.skipped) : [];
|
|
3805
3987
|
const scoped = config.apps.length > 0 ? [...ids.apps.values()] : void 0;
|
|
3806
3988
|
const crew = await eachInFlight(taken.agents, async (decl) => {
|
|
@@ -3827,6 +4009,7 @@ async function up(config, client, opts = {}) {
|
|
|
3827
4009
|
if (hasRoster(decl.multiagent)) await patchRoster(client, decl, decl.multiagent, existing, agentIds, dryRun, report2.agents);
|
|
3828
4010
|
}
|
|
3829
4011
|
reportKept(config, existing, report2.agents);
|
|
4012
|
+
if (config.tasks.length > 0) await seedTasks(client, config, existing, report2.agents, dryRun, report2.tasks, report2.skipped);
|
|
3830
4013
|
await applyRemoved(client, config.removed, { agents: existing, vaults }, owner, report2);
|
|
3831
4014
|
if (briefed.length > 0 && !dryRun) {
|
|
3832
4015
|
const serving = taken.apps.flatMap((decl) => {
|