@usenaive-sdk/blueprints 0.1.0 → 0.3.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 CHANGED
@@ -80,6 +80,8 @@ declare const AppDeclSchema: z.ZodObject<{
80
80
  mcp: z.ZodOptional<z.ZodString>;
81
81
  env: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodString, z.ZodObject<{
82
82
  from_env: z.ZodString;
83
+ }, z.core.$strip>, z.ZodObject<{
84
+ generate: z.ZodLiteral<true>;
83
85
  }, z.core.$strip>]>>>;
84
86
  }, z.core.$strip>;
85
87
  /**
@@ -146,6 +148,10 @@ declare const AgentDeclSchema: z.ZodObject<{
146
148
  identity: z.ZodOptional<z.ZodString>;
147
149
  enabled: z.ZodOptional<z.ZodBoolean>;
148
150
  }, z.core.$strip>>>;
151
+ intake: z.ZodOptional<z.ZodObject<{
152
+ message: z.ZodString;
153
+ budget_micro_usd: z.ZodOptional<z.ZodNumber>;
154
+ }, z.core.$strip>>;
149
155
  }, z.core.$strip>;
150
156
  /**
151
157
  * A vault credential (§23) minus what `up` fills in. `value` is a real third-party secret, so it is
@@ -197,6 +203,21 @@ declare const ProjectSchema: z.ZodObject<{
197
203
  name: z.ZodString;
198
204
  blueprint: z.ZodOptional<z.ZodString>;
199
205
  template: z.ZodOptional<z.ZodString>;
206
+ questions: z.ZodDefault<z.ZodArray<z.ZodDiscriminatedUnion<[z.ZodObject<{
207
+ type: z.ZodLiteral<"text">;
208
+ placeholder: z.ZodOptional<z.ZodString>;
209
+ key: z.ZodString;
210
+ label: z.ZodString;
211
+ help: z.ZodOptional<z.ZodString>;
212
+ }, z.core.$strip>, z.ZodObject<{
213
+ type: z.ZodLiteral<"choice">;
214
+ options: z.ZodArray<z.ZodString>;
215
+ multiple: z.ZodDefault<z.ZodBoolean>;
216
+ other: z.ZodDefault<z.ZodBoolean>;
217
+ key: z.ZodString;
218
+ label: z.ZodString;
219
+ help: z.ZodOptional<z.ZodString>;
220
+ }, z.core.$strip>], "type">>>;
200
221
  skills: z.ZodDefault<z.ZodArray<z.ZodObject<{
201
222
  slug: z.ZodString;
202
223
  file: z.ZodString;
@@ -233,6 +254,8 @@ declare const ProjectSchema: z.ZodObject<{
233
254
  mcp: z.ZodOptional<z.ZodString>;
234
255
  env: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodString, z.ZodObject<{
235
256
  from_env: z.ZodString;
257
+ }, z.core.$strip>, z.ZodObject<{
258
+ generate: z.ZodLiteral<true>;
236
259
  }, z.core.$strip>]>>>;
237
260
  }, z.core.$strip>>>;
238
261
  agents: z.ZodDefault<z.ZodArray<z.ZodObject<{
@@ -283,6 +306,10 @@ declare const ProjectSchema: z.ZodObject<{
283
306
  identity: z.ZodOptional<z.ZodString>;
284
307
  enabled: z.ZodOptional<z.ZodBoolean>;
285
308
  }, z.core.$strip>>>;
309
+ intake: z.ZodOptional<z.ZodObject<{
310
+ message: z.ZodString;
311
+ budget_micro_usd: z.ZodOptional<z.ZodNumber>;
312
+ }, z.core.$strip>>;
286
313
  }, z.core.$strip>>>;
287
314
  removed: z.ZodDefault<z.ZodObject<{
288
315
  apps: z.ZodDefault<z.ZodArray<z.ZodString>>;
@@ -343,6 +370,75 @@ type ConfigLoad = {
343
370
  };
344
371
  declare function loadConfig(dir: string): Promise<ConfigLoad>;
345
372
 
373
+ /**
374
+ * A built tree, from either place one can be. A **directory** is the apply a person runs: a
375
+ * checkout on their laptop or in CI. A **file map** is the apply the platform runs on their
376
+ * behalf — the tree comes out of a published artifact's object-store entry (`canonical-spec §31.1`)
377
+ * and there is no checkout anywhere, because a hosted run never clones a blueprint.
378
+ */
379
+ type FileSource = string | Record<string, string>;
380
+ /**
381
+ * ONE FILTER, ONE DIGEST, BOTH SOURCES — which is the whole of why the map arm exists rather than
382
+ * the caller handing its map straight to `contentHash`.
383
+ *
384
+ * A published artifact's `content_hash` is compared against the newest deployment's to decide
385
+ * whether to upload at all (§31.1), and the two sides of that comparison are collected in different
386
+ * places: the deployment's from a directory here, the artifact's from a map on the server. If the
387
+ * map arm skipped one exclusion or one size cap, the digests would differ for two trees that ship
388
+ * the same bytes and every hosted install would re-upload, forever, with nothing to point at.
389
+ */
390
+ declare function collectFiles(source: FileSource): Record<string, string>;
391
+ /**
392
+ * sha-256 over the files in path order, each as `path NUL byte-length NUL bytes`: the same tree
393
+ * hashes the same from any walk order, and the length prefix keeps two trees from sharing an
394
+ * encoding. Hex, so it travels as a plain string.
395
+ */
396
+ declare function contentHash(files: Record<string, string>): string;
397
+
398
+ /**
399
+ * The blueprint install (`canonical-spec §29.6`) — one applied declaration per
400
+ * (organization, project), and the drift a `revision_conflict` names.
401
+ *
402
+ * `naive up` needed no server-side state while the only writer was a person with a clone: its
403
+ * working tree was the manifest. The studio applying the same declaration makes two writers on one
404
+ * organization, and neither can see the other. This row is what they share.
405
+ *
406
+ * It is not a second source of truth for what is provisioned — apps, agents, skills, identities and
407
+ * vaults stay keyed by name on their own routes. It records *that* an apply happened, with what, by
408
+ * whom, and against which revision.
409
+ */
410
+
411
+ /**
412
+ * What one apply did to one resource. This is the vocabulary `naive up` has printed since it
413
+ * existed; it is written HERE, and imported by `@usenaive-sdk/blueprints`, for the reason
414
+ * `CLAUDE.md §2` gives: the hosted apply publishes the engine's report on the install (below), so
415
+ * it is a wire shape, and a wire shape has exactly one definition. The engine re-exports these two
416
+ * names unchanged, so nothing downstream of it learns a second word for the same thing.
417
+ */
418
+ declare const ResourceActionSchema: z.ZodEnum<{
419
+ created: "created";
420
+ updated: "updated";
421
+ unchanged: "unchanged";
422
+ deleted: "deleted";
423
+ refused: "refused";
424
+ }>;
425
+ type ResourceAction = z.infer<typeof ResourceActionSchema>;
426
+ /** One line of an apply: what was named, what happened to it, and — for a refusal — why. */
427
+ declare const ResourceReportSchema: z.ZodObject<{
428
+ name: z.ZodString;
429
+ action: z.ZodEnum<{
430
+ created: "created";
431
+ updated: "updated";
432
+ unchanged: "unchanged";
433
+ deleted: "deleted";
434
+ refused: "refused";
435
+ }>;
436
+ id: z.ZodOptional<z.ZodString>;
437
+ url: z.ZodOptional<z.ZodNullable<z.ZodString>>;
438
+ reason: z.ZodOptional<z.ZodString>;
439
+ }, z.core.$strip>;
440
+ type ResourceReportLine = z.infer<typeof ResourceReportSchema>;
441
+
346
442
  /**
347
443
  * The report vocabulary `up` speaks (`workstreams/10-blueprints.md §2` item 4) and the handful of
348
444
  * client-side moves every resource kind shares: one line per attempt with refusals caught into
@@ -350,14 +446,62 @@ declare function loadConfig(dir: string): Promise<ConfigLoad>;
350
446
  * cursor pagination, and the by-name tombstone behind `removed`.
351
447
  */
352
448
 
353
- type ResourceAction = "created" | "updated" | "unchanged" | "deleted" | "refused";
354
- interface ResourceReport {
355
- name: string;
356
- action: ResourceAction;
357
- id?: string;
358
- url?: string | null;
359
- /** Why, for `refused`; what would happen, for a dry-run line that needs explaining. */
360
- reason?: string;
449
+ type ResourceReport = ResourceReportLine;
450
+
451
+ /**
452
+ * Apps in `naive up`: upsert by `GET /v1/apps?name=` (§29.2), `env` written as write-only secrets
453
+ * only when the live `value_hash` differs from the local one (ADR-0354, ADR-0357), and the
454
+ * `deploy_dir` shipped only when its content hash differs from the newest live deployment's
455
+ * (ADR-0357). Live secret names the config does not declare are reported, never deleted
456
+ * (ADR-0352). `mcp` is patched on drift, absent meaning `null` (§29.5); the platform mints the
457
+ * app's `VETTA_MCP_TOKEN` itself, so nothing here ever holds that token.
458
+ *
459
+ * A hosted apply also arrives with a PLATFORM ENVIRONMENT (`PlatformEnv`, §29.7) — the base URL, the
460
+ * identity the install runs as, and a scoped key it will mint for an app that asks. That layer is
461
+ * read before `{ from_env }`'s own environment, and a declaration may ask for a value nobody has
462
+ * with `{ generate: true }`. Both are provisioned ONCE per app, because a value the platform invents
463
+ * has no stable digest and rewriting it every apply would rotate a live credential.
464
+ *
465
+ * An app also records the project that made it (ADR-0375), and that stamp is compared before any
466
+ * write: a name this project does not own is refused rather than adopted, which is what standing
467
+ * up a second blueprint did to the first one's live deployment.
468
+ */
469
+
470
+ /** The platform environment's variable names (`canonical-spec §29.7`) — fixed, never inferred. */
471
+ declare const PLATFORM_ENV: {
472
+ /** The base URL of the API this apply ran through. */
473
+ readonly api_url: "NAIVE_API_URL";
474
+ /** The identity the install runs as, when the declaration declares exactly one. */
475
+ readonly identity_id: "NAIVE_IDENTITY_ID";
476
+ /** A scoped organization API key minted for the app that asks for it. */
477
+ readonly api_key: "NAIVE_API_KEY";
478
+ };
479
+ /**
480
+ * WHAT THE PLATFORM PROVIDES A HOSTED APPLY, AND THE ONE DISTINCTION THAT MATTERS
481
+ * (`canonical-spec §29.7`).
482
+ *
483
+ * Absent on a laptop apply, which reads the author's shell and nothing else — the hosted path gains
484
+ * a layer, the local path does not lose one.
485
+ *
486
+ * **What the platform KNOWS it always tells the app; what the platform must INVENT it invents only
487
+ * on request, and only once.** That is not a stylistic split. A known value has a stable digest, so
488
+ * the `value_hash` compare that makes `naive up` idempotent (§29.2) can say `unchanged` about it and
489
+ * re-asserting it every apply costs nothing. An invented one never matches its own previous digest,
490
+ * so re-inventing it every apply would rotate a live credential under a build that still holds the
491
+ * old one — and, for a minted key, leave one dead `api_key` row behind per apply.
492
+ */
493
+ interface PlatformEnv {
494
+ /**
495
+ * Values the platform knows. Written to every app this apply deploys that declares an `env` —
496
+ * whether or not the declaration names them, which is the `VETTA_MCP_TOKEN` precedent (§29.2) —
497
+ * and read FIRST by a `{ from_env }` that does name them.
498
+ */
499
+ known: Record<string, string>;
500
+ /**
501
+ * Values the platform must invent, by variable name, given the app that asked. Called at most
502
+ * once per app, and only when that app holds no secret of that name.
503
+ */
504
+ minted?: Record<string, (app: string) => Promise<string>>;
361
505
  }
362
506
 
363
507
  /**
@@ -370,6 +514,11 @@ interface ResourceReport {
370
514
  * bounded exception — a declared agent's `schedules` are owned as a complete set (`agents.ts`).
371
515
  * Skills and identities live here; apps, agents and vaults each have their own module, sharing the
372
516
  * report vocabulary in `report.ts`.
517
+ *
518
+ * One thing here is not a reconcile: an agent this apply **created** that declares an `intake` is
519
+ * sent its briefing as a started session (`agents.ts`, `canonical-spec §31.4`). It is what turns a
520
+ * provisioned crew into a crew that has started working, and it is idempotent for the same reason
521
+ * everything else here is — the agent is created exactly once.
373
522
  */
374
523
 
375
524
  interface UpReport {
@@ -385,6 +534,12 @@ interface UpReport {
385
534
  agents: ResourceReport[];
386
535
  /** One line per declared cron and per pruned live row, named `<agent> @ <cron>`. */
387
536
  schedules: ResourceReport[];
537
+ /**
538
+ * One line per agent this apply **created** that declares an `intake` — the session that was
539
+ * started, named by the agent, `id` the `ses_`. Empty on every later apply of the same crew: an
540
+ * agent is created once, so it is briefed once (`agents.ts`).
541
+ */
542
+ intake: ResourceReport[];
388
543
  /**
389
544
  * Live rows this client could not parse, named and stepped over (`report.ts`). One legacy row
390
545
  * used to abort the whole apply before any write; it is now a line here and nothing else.
@@ -401,8 +556,43 @@ interface UpOptions {
401
556
  * (ADR-0375). Off by default — adopting by default is what overwrote a live deployment.
402
557
  */
403
558
  adopt?: boolean;
559
+ /**
560
+ * The built trees, by app name, for an apply that runs where there is no checkout: the platform
561
+ * applying a published artifact on an operator's behalf (`canonical-spec §31.1`). The bytes come
562
+ * out of the artifact's object-store entry, in the same file map `deploy_dir` would have been
563
+ * collected into — which is why `collectFiles` takes both and there is one digest (`files.ts`).
564
+ *
565
+ * Present ⇒ the disk is never read for an app, and an app whose tree is not in the map is refused
566
+ * by name rather than deployed empty. Absent ⇒ `dir` + `deploy_dir`, exactly as before.
567
+ */
568
+ trees?: Record<string, Record<string, string>>;
569
+ /**
570
+ * Why a declared app is absent from `trees`, by app name — an object-store read that failed
571
+ * rather than an object that was never uploaded. Both come out of `builtTree` as one refusal;
572
+ * only the caller that did the reading can tell them apart, so only it can say (`apps.ts`).
573
+ */
574
+ tree_errors?: Record<string, string>;
575
+ /**
576
+ * What an app's `{ from_env }` reads (`apps.ts`). The process's own environment by default —
577
+ * the author's shell, which is the whole point of `from_env` on a laptop. A hosted apply has no
578
+ * shell and passes the operator's **answers** instead (`canonical-spec §31.2`): the same
579
+ * declaration, resolved against the only environment that apply has.
580
+ */
581
+ env?: Record<string, string | undefined>;
582
+ /**
583
+ * THE PLATFORM ENVIRONMENT (`canonical-spec §29.7`) — what the platform itself provides an app,
584
+ * read BEFORE `env` and written whether or not the declaration names it.
585
+ *
586
+ * Present only on a hosted apply, and that is the whole of the local/hosted difference: `naive up`
587
+ * from a checkout passes none, reads the author's shell, and behaves exactly as it always has.
588
+ *
589
+ * `NAIVE_IDENTITY_ID` is filled in here rather than by the caller, because the id does not exist
590
+ * until this run has created the identity — identities are upserted before apps for the same
591
+ * reason agents reference them by name.
592
+ */
593
+ platform?: PlatformEnv;
404
594
  }
405
595
  /** Plan → apply → report. Every refusal is one line in the report, never a thrown escape. */
406
596
  declare function up(config: Readonly<ProjectConfig>, client: VettaClient, opts?: UpOptions): Promise<UpReport>;
407
597
 
408
- export { type AgentDecl, type AppDecl, BLUEPRINTS, BlueprintRefusal, CONFIG_CANDIDATES, type ConfigLoad, type CredentialDecl, type DefineInput, type IdentityDecl, type ProjectConfig, type ResourceAction, type ResourceReport, type ScheduleDecl, type SkillDecl, type Template, type TemplateChoice, type TemplateKind, type UpOptions, type UpReport, type VaultDecl, chooseTemplate, defineProject, loadConfig, parseProject, up };
598
+ export { type AgentDecl, type AppDecl, BLUEPRINTS, BlueprintRefusal, CONFIG_CANDIDATES, type ConfigLoad, type CredentialDecl, type DefineInput, type FileSource, type IdentityDecl, PLATFORM_ENV, type PlatformEnv, type ProjectConfig, type ResourceAction, type ResourceReport, type ScheduleDecl, type SkillDecl, type Template, type TemplateChoice, type TemplateKind, type UpOptions, type UpReport, type VaultDecl, chooseTemplate, collectFiles, contentHash, defineProject, loadConfig, parseProject, up };