@nylorun/runtime 0.30.0-beta → 0.31.0-beta

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/CHANGELOG.md CHANGED
@@ -1,5 +1,21 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.31.0-beta
4
+
5
+ ### Minor Changes
6
+
7
+ - aaa079f: The Runtime saves agent folders (track T6). `PUT /v1/agent-manifests/{name}` with `Content-Type: application/vnd.nylorun.folder+json` takes a folder by hash (`PutAgentFolderRequestSchema`): the files uploaded first, the Markdown and JSON read back from the definition file store and compiled with `compileAgentFolder`. A folder that does not compile is `422 folder_invalid`, with the compiler's diagnostics by file, line and column in `details.diagnostics`. A save keeps the folder as the version's source: `AgentManifestView.source` summarises it, `GET /v1/agent-manifests/{name}/versions/{v}/source` lists its files and `.../source/files/{path}` returns one. With `?dryRun=true` the plan adds the compiled `manifest`, the `diagnostics` and the `compiler`. A folder whose manifest is unchanged saves no version, and says so (`source_not_saved`). New Host feature `agent-folders`; new error code `folder_invalid`.
8
+
9
+ ### Patch Changes
10
+
11
+ - Pin core to the tested release.
12
+ - Pin harness to the tested release.
13
+ - Updated dependencies [9ba6634]
14
+ - Updated dependencies [aaa079f]
15
+ - Updated dependencies
16
+ - @nylorun/core@0.27.0-beta
17
+ - @nylorun/harness@0.29.3-beta
18
+
3
19
  ## 0.30.0-beta
4
20
 
5
21
  ### Minor Changes
@@ -21,6 +21,7 @@ export declare const Rejected: z.ZodObject<{
21
21
  credential_rejected: "credential_rejected";
22
22
  credential_required: "credential_required";
23
23
  definition_files_missing: "definition_files_missing";
24
+ folder_invalid: "folder_invalid";
24
25
  harness_mismatch: "harness_mismatch";
25
26
  host_rejected: "host_rejected";
26
27
  incompatible_host: "incompatible_host";
@@ -517,6 +518,29 @@ export declare const PutAgentManifestRequest: z.ZodObject<{
517
518
  }, z.core.$strict>>;
518
519
  requestId: z.ZodOptional<z.ZodString>;
519
520
  }, z.core.$strict>;
521
+ export declare const PutAgentFolderRequest: z.ZodObject<{
522
+ requestId: z.ZodOptional<z.ZodString>;
523
+ format: z.ZodLiteral<"nylorun.folder.v2">;
524
+ entries: z.ZodArray<z.ZodObject<{
525
+ path: z.ZodString;
526
+ size: z.ZodNumber;
527
+ sha256: z.ZodString;
528
+ contentType: z.ZodOptional<z.ZodString>;
529
+ mode: z.ZodOptional<z.ZodNumber>;
530
+ }, z.core.$strict>>;
531
+ }, z.core.$strict>;
532
+ export declare const AgentManifestSource: z.ZodObject<{
533
+ name: z.ZodString;
534
+ version: z.ZodNumber;
535
+ compiler: z.ZodString;
536
+ files: z.ZodNumber;
537
+ bytes: z.ZodNumber;
538
+ entries: z.ZodArray<z.ZodObject<{
539
+ path: z.ZodString;
540
+ size: z.ZodNumber;
541
+ sha256: z.ZodString;
542
+ }, z.core.$strict>>;
543
+ }, z.core.$strict>;
520
544
  export declare const AgentManifestView: z.ZodObject<{
521
545
  name: z.ZodString;
522
546
  version: z.ZodNumber;
@@ -622,6 +646,11 @@ export declare const AgentManifestView: z.ZodObject<{
622
646
  }, z.core.$strict>;
623
647
  createdAt: z.ZodString;
624
648
  agents: z.ZodNumber;
649
+ source: z.ZodOptional<z.ZodObject<{
650
+ compiler: z.ZodString;
651
+ files: z.ZodNumber;
652
+ bytes: z.ZodNumber;
653
+ }, z.core.$strict>>;
625
654
  }, z.core.$strict>;
626
655
  export declare const AgentManifestPlan: z.ZodObject<{
627
656
  name: z.ZodString;
@@ -654,6 +683,117 @@ export declare const AgentManifestPlan: z.ZodObject<{
654
683
  nextStart: z.ZodNumber;
655
684
  secrets: z.ZodNumber;
656
685
  }, z.core.$strict>;
686
+ manifest: z.ZodOptional<z.ZodObject<{
687
+ manifestSchemaVersion: z.ZodLiteral<8>;
688
+ name: z.ZodString & z.ZodType<string, string, z.core.$ZodTypeInternals<string, string>>;
689
+ description: z.ZodOptional<z.ZodString>;
690
+ metadata: z.ZodOptional<z.ZodType<import("@nylorun/core/define").JsonObject, unknown, z.core.$ZodTypeInternals<import("@nylorun/core/define").JsonObject, unknown>>>;
691
+ harness: z.ZodUnion<readonly [z.ZodType<import("@nylorun/core/contracts").WorkflowHarnessSection, unknown, z.core.$ZodTypeInternals<import("@nylorun/core/contracts").WorkflowHarnessSection, unknown>>, z.ZodType<import("@nylorun/core/contracts").AgentHarnessSection, unknown, z.core.$ZodTypeInternals<import("@nylorun/core/contracts").AgentHarnessSection, unknown>>]>;
692
+ runtime: z.ZodOptional<z.ZodObject<{
693
+ kind: z.ZodEnum<{
694
+ none: "none";
695
+ pod: "pod";
696
+ virtual: "virtual";
697
+ }>;
698
+ image: z.ZodOptional<z.ZodString>;
699
+ resources: z.ZodOptional<z.ZodObject<{
700
+ cpus: z.ZodOptional<z.ZodNumber>;
701
+ memory: z.ZodOptional<z.ZodString>;
702
+ }, z.core.$strict>>;
703
+ storage: z.ZodOptional<z.ZodString>;
704
+ network: z.ZodOptional<z.ZodObject<{
705
+ allowedHosts: z.ZodOptional<z.ZodArray<z.ZodString>>;
706
+ }, z.core.$strict>>;
707
+ lifecycle: z.ZodOptional<z.ZodObject<{
708
+ idle: z.ZodOptional<z.ZodString>;
709
+ deleteAfter: z.ZodOptional<z.ZodString>;
710
+ }, z.core.$strict>>;
711
+ setup: z.ZodOptional<z.ZodArray<z.ZodObject<{
712
+ command: z.ZodString;
713
+ cwd: z.ZodOptional<z.ZodString>;
714
+ timeout: z.ZodOptional<z.ZodString>;
715
+ }, z.core.$strict>>>;
716
+ files: z.ZodOptional<z.ZodArray<z.ZodUnion<readonly [z.ZodObject<{
717
+ artifactId: z.ZodString & z.ZodType<string, string, z.core.$ZodTypeInternals<string, string>>;
718
+ version: z.ZodNumber;
719
+ path: z.ZodString;
720
+ }, z.core.$strict>, z.ZodObject<{
721
+ path: z.ZodString;
722
+ files: z.ZodRecord<z.ZodString, z.ZodString & z.ZodType<string, string, z.core.$ZodTypeInternals<string, string>>>;
723
+ }, z.core.$strict>]>>>;
724
+ limits: z.ZodOptional<z.ZodObject<{
725
+ artifacts: z.ZodOptional<z.ZodObject<{
726
+ fileBytes: z.ZodOptional<z.ZodNumber>;
727
+ totalBytes: z.ZodOptional<z.ZodNumber>;
728
+ }, z.core.$strict>>;
729
+ skills: z.ZodOptional<z.ZodObject<{
730
+ totalBytes: z.ZodOptional<z.ZodNumber>;
731
+ }, z.core.$strict>>;
732
+ disk: z.ZodOptional<z.ZodObject<{
733
+ versionBytes: z.ZodOptional<z.ZodNumber>;
734
+ versionEntries: z.ZodOptional<z.ZodNumber>;
735
+ }, z.core.$strict>>;
736
+ }, z.core.$strict>>;
737
+ secrets: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodDiscriminatedUnion<[z.ZodObject<{
738
+ required: z.ZodOptional<z.ZodBoolean>;
739
+ description: z.ZodOptional<z.ZodString>;
740
+ type: z.ZodLiteral<"environment_secret">;
741
+ allowedHosts: z.ZodArray<z.ZodString>;
742
+ inject: z.ZodOptional<z.ZodObject<{
743
+ header: z.ZodString;
744
+ format: z.ZodString;
745
+ }, z.core.$strict>>;
746
+ }, z.core.$strict>, z.ZodObject<{
747
+ required: z.ZodOptional<z.ZodBoolean>;
748
+ description: z.ZodOptional<z.ZodString>;
749
+ type: z.ZodLiteral<"environment_variable">;
750
+ }, z.core.$strict>, z.ZodObject<{
751
+ via: z.ZodOptional<z.ZodString>;
752
+ identity: z.ZodOptional<z.ZodObject<{
753
+ header: z.ZodString;
754
+ }, z.core.$strict>>;
755
+ required: z.ZodOptional<z.ZodBoolean>;
756
+ description: z.ZodOptional<z.ZodString>;
757
+ type: z.ZodLiteral<"bearer">;
758
+ url: z.ZodString;
759
+ }, z.core.$strict>, z.ZodObject<{
760
+ via: z.ZodOptional<z.ZodString>;
761
+ identity: z.ZodOptional<z.ZodObject<{
762
+ header: z.ZodString;
763
+ }, z.core.$strict>>;
764
+ required: z.ZodOptional<z.ZodBoolean>;
765
+ description: z.ZodOptional<z.ZodString>;
766
+ type: z.ZodLiteral<"headers">;
767
+ url: z.ZodString;
768
+ }, z.core.$strict>], "type">>>;
769
+ triggers: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodObject<{
770
+ schedule: z.ZodOptional<z.ZodString>;
771
+ timezone: z.ZodOptional<z.ZodString>;
772
+ at: z.ZodOptional<z.ZodISODateTime>;
773
+ webhook: z.ZodOptional<z.ZodEnum<{
774
+ "standard-webhooks": "standard-webhooks";
775
+ }>>;
776
+ session: z.ZodString;
777
+ prompt: z.ZodString;
778
+ }, z.core.$strict>>>;
779
+ selfWake: z.ZodOptional<z.ZodBoolean>;
780
+ }, z.core.$strict>>;
781
+ }, z.core.$strict>>;
782
+ diagnostics: z.ZodOptional<z.ZodArray<z.ZodObject<{
783
+ severity: z.ZodEnum<{
784
+ error: "error";
785
+ info: "info";
786
+ note: "note";
787
+ warning: "warning";
788
+ }>;
789
+ code: z.ZodString;
790
+ message: z.ZodString;
791
+ file: z.ZodOptional<z.ZodString>;
792
+ line: z.ZodOptional<z.ZodNumber>;
793
+ column: z.ZodOptional<z.ZodNumber>;
794
+ pointer: z.ZodOptional<z.ZodString>;
795
+ }, z.core.$strict>>>;
796
+ compiler: z.ZodOptional<z.ZodString>;
657
797
  }, z.core.$strict>;
658
798
  export declare const SaveAgentManifestResponse: z.ZodObject<{
659
799
  manifest: z.ZodObject<{
@@ -761,12 +901,31 @@ export declare const SaveAgentManifestResponse: z.ZodObject<{
761
901
  }, z.core.$strict>;
762
902
  createdAt: z.ZodString;
763
903
  agents: z.ZodNumber;
904
+ source: z.ZodOptional<z.ZodObject<{
905
+ compiler: z.ZodString;
906
+ files: z.ZodNumber;
907
+ bytes: z.ZodNumber;
908
+ }, z.core.$strict>>;
764
909
  }, z.core.$strict>;
765
910
  unchanged: z.ZodBoolean;
766
911
  warnings: z.ZodArray<z.ZodObject<{
767
912
  code: z.ZodString;
768
913
  message: z.ZodString;
769
914
  }, z.core.$strict>>;
915
+ diagnostics: z.ZodOptional<z.ZodArray<z.ZodObject<{
916
+ severity: z.ZodEnum<{
917
+ error: "error";
918
+ info: "info";
919
+ note: "note";
920
+ warning: "warning";
921
+ }>;
922
+ code: z.ZodString;
923
+ message: z.ZodString;
924
+ file: z.ZodOptional<z.ZodString>;
925
+ line: z.ZodOptional<z.ZodNumber>;
926
+ column: z.ZodOptional<z.ZodNumber>;
927
+ pointer: z.ZodOptional<z.ZodString>;
928
+ }, z.core.$strict>>>;
770
929
  }, z.core.$strict>;
771
930
  export declare const ListAgentManifestsResponse: z.ZodObject<{
772
931
  manifests: z.ZodArray<z.ZodObject<{
@@ -874,6 +1033,11 @@ export declare const ListAgentManifestsResponse: z.ZodObject<{
874
1033
  }, z.core.$strict>;
875
1034
  createdAt: z.ZodString;
876
1035
  agents: z.ZodNumber;
1036
+ source: z.ZodOptional<z.ZodObject<{
1037
+ compiler: z.ZodString;
1038
+ files: z.ZodNumber;
1039
+ bytes: z.ZodNumber;
1040
+ }, z.core.$strict>>;
877
1041
  }, z.core.$strict>>;
878
1042
  }, z.core.$strict>;
879
1043
  export declare const AgentManifestVersions: z.ZodObject<{
@@ -5,7 +5,7 @@
5
5
  * global registry.
6
6
  */
7
7
  import { z } from "zod";
8
- import { QueuedResponseSchema, TriggerListSchema, MemoryListSchema, MemorySchema, PutMemoryRequestSchema, MemoryVersionPageSchema, MemoryVersionDetailSchema, TriggerRunPageSchema, RunTriggerResponseSchema, WebhookSecretResponseSchema, WebhookAcceptedResponseSchema, AgentManifestV8Schema, EnvironmentSecretSlotsSchema, DeleteAgentManifestResponseSchema, AgentManifestPlanSchema, AgentManifestVersionsSchema, AgentManifestViewSchema, ListAgentManifestsResponseSchema, PutAgentManifestRequestSchema, PutAgentSecretValueRequestSchema, SaveAgentManifestResponseSchema, SessionListItemSchema, ModelCallSchema, SessionPageSchema, SessionManifestViewSchema, HistoryPageSchema, SessionUsageTotalsSchema, ModelCallsPageSchema, ModelCallExportPageSchema, AgentPageSchema, ToolCallSchema, ToolCallsPageSchema, TurnTraceSchema, JwksSchema, SigningKeyListSchema, SigningKeyViewSchema, RotateSigningKeysRequestSchema, RevokeSigningKeyRequestSchema, MeResponseSchema, TenantStatusSchema, ResetTenantRequestSchema, ResetTenantResponseSchema, SeedTenantConfigRequestSchema, SeedTenantConfigResponseSchema, HostModelCatalogSchema, TenantSandboxViewSchema, ModelUsageTotalsSchema, ModelBudgetsSchema, PutModelBudgetsRequestSchema, ToolPolicySchema, PutToolPolicyRequestSchema, PutModelInputsRequestSchema, ModelInputsViewSchema, PutTenantEnvironmentsRequestSchema, ListProvidersResponseSchema, HostModelViewSchema, PutHostModelRequestSchema, SelectHostModelRequestSchema, PutAgentSecretRequestSchema, AgentSecretViewSchema, ListAgentSecretsResponseSchema, McpPreviewRequestSchema, McpPreviewSchema, CredentialCoverageRequestSchema, CredentialCoverageSchema, DeletedResponseSchema, ListSessionsResponseSchema, LiveEventSchema, PutAgentRequestSchema, PutSessionRequestSchema, SessionItemsResponseSchema, SessionViewSchema, StreamClosedFrameSchema, AcceptedResponseSchema, SandboxToolOutcomeSchema, AgentViewSchema, AgentSnapshotSchema, RestoreAgentRequestSchema, ForkAgentRequestSchema, AgentForkPlanSchema, ForkAgentResponseSchema, PutAgentDryRunResponseSchema, RestartAgentRequestSchema, AgentRestoreSchema, AgentDiskVersionsSchema, ListAgentsResponseSchema, DeleteAgentResponseSchema, ListAgentEventsResponseSchema, ArtifactViewSchema, ArtifactListItemSchema, ArtifactPageSchema, ArtifactVersionViewSchema, ListArtifactsResponseSchema, UploadArtifactResponseSchema, DefinitionFileViewSchema, DeleteArtifactResponseSchema, CreateArtifactLinkRequestSchema, ArtifactLinkSchema, PutTenantArtifactsRequestSchema, PutTenantSkillsRequestSchema, PutTenantLimitsRequestSchema, TenantLimitsViewSchema, TenantArtifactsViewSchema, TenantSkillsViewSchema, ArtifactTreeSchema, ArtifactDiffSchema, SessionCommandSchema, ListOperatorKeysResponseSchema, PutOperatorKeyResponseSchema, DeleteOperatorKeyResponseSchema, OperatorKeySchema, ProtocolRejectedResponseSchema, RejectedResponseSchema, EVENT_SCHEMAS, EVENT_TYPES, } from "@nylorun/core/contracts";
8
+ import { QueuedResponseSchema, TriggerListSchema, MemoryListSchema, MemorySchema, PutMemoryRequestSchema, MemoryVersionPageSchema, MemoryVersionDetailSchema, TriggerRunPageSchema, RunTriggerResponseSchema, WebhookSecretResponseSchema, WebhookAcceptedResponseSchema, AgentManifestV8Schema, EnvironmentSecretSlotsSchema, DeleteAgentManifestResponseSchema, AgentManifestPlanSchema, AgentManifestVersionsSchema, AgentManifestViewSchema, ListAgentManifestsResponseSchema, PutAgentManifestRequestSchema, PutAgentFolderRequestSchema, AgentManifestSourceSchema, PutAgentSecretValueRequestSchema, SaveAgentManifestResponseSchema, SessionListItemSchema, ModelCallSchema, SessionPageSchema, SessionManifestViewSchema, HistoryPageSchema, SessionUsageTotalsSchema, ModelCallsPageSchema, ModelCallExportPageSchema, AgentPageSchema, ToolCallSchema, ToolCallsPageSchema, TurnTraceSchema, JwksSchema, SigningKeyListSchema, SigningKeyViewSchema, RotateSigningKeysRequestSchema, RevokeSigningKeyRequestSchema, MeResponseSchema, TenantStatusSchema, ResetTenantRequestSchema, ResetTenantResponseSchema, SeedTenantConfigRequestSchema, SeedTenantConfigResponseSchema, HostModelCatalogSchema, TenantSandboxViewSchema, ModelUsageTotalsSchema, ModelBudgetsSchema, PutModelBudgetsRequestSchema, ToolPolicySchema, PutToolPolicyRequestSchema, PutModelInputsRequestSchema, ModelInputsViewSchema, PutTenantEnvironmentsRequestSchema, ListProvidersResponseSchema, HostModelViewSchema, PutHostModelRequestSchema, SelectHostModelRequestSchema, PutAgentSecretRequestSchema, AgentSecretViewSchema, ListAgentSecretsResponseSchema, McpPreviewRequestSchema, McpPreviewSchema, CredentialCoverageRequestSchema, CredentialCoverageSchema, DeletedResponseSchema, ListSessionsResponseSchema, LiveEventSchema, PutAgentRequestSchema, PutSessionRequestSchema, SessionItemsResponseSchema, SessionViewSchema, StreamClosedFrameSchema, AcceptedResponseSchema, SandboxToolOutcomeSchema, AgentViewSchema, AgentSnapshotSchema, RestoreAgentRequestSchema, ForkAgentRequestSchema, AgentForkPlanSchema, ForkAgentResponseSchema, PutAgentDryRunResponseSchema, RestartAgentRequestSchema, AgentRestoreSchema, AgentDiskVersionsSchema, ListAgentsResponseSchema, DeleteAgentResponseSchema, ListAgentEventsResponseSchema, ArtifactViewSchema, ArtifactListItemSchema, ArtifactPageSchema, ArtifactVersionViewSchema, ListArtifactsResponseSchema, UploadArtifactResponseSchema, DefinitionFileViewSchema, DeleteArtifactResponseSchema, CreateArtifactLinkRequestSchema, ArtifactLinkSchema, PutTenantArtifactsRequestSchema, PutTenantSkillsRequestSchema, PutTenantLimitsRequestSchema, TenantLimitsViewSchema, TenantArtifactsViewSchema, TenantSkillsViewSchema, ArtifactTreeSchema, ArtifactDiffSchema, SessionCommandSchema, ListOperatorKeysResponseSchema, PutOperatorKeyResponseSchema, DeleteOperatorKeyResponseSchema, OperatorKeySchema, ProtocolRejectedResponseSchema, RejectedResponseSchema, EVENT_SCHEMAS, EVENT_TYPES, } from "@nylorun/core/contracts";
9
9
  function named(id, schema) {
10
10
  return schema.meta({ id });
11
11
  }
@@ -21,6 +21,8 @@ export const AgentView = named("AgentView", AgentViewSchema);
21
21
  export const EnvironmentSecretSlots = named("EnvironmentSecretSlots", EnvironmentSecretSlotsSchema);
22
22
  export const AgentManifest = named("AgentManifest", AgentManifestV8Schema);
23
23
  export const PutAgentManifestRequest = named("PutAgentManifestRequest", PutAgentManifestRequestSchema);
24
+ export const PutAgentFolderRequest = named("PutAgentFolderRequest", PutAgentFolderRequestSchema);
25
+ export const AgentManifestSource = named("AgentManifestSource", AgentManifestSourceSchema);
24
26
  export const AgentManifestView = named("AgentManifestView", AgentManifestViewSchema);
25
27
  export const AgentManifestPlan = named("AgentManifestPlan", AgentManifestPlanSchema);
26
28
  export const SaveAgentManifestResponse = named("SaveAgentManifestResponse", SaveAgentManifestResponseSchema);
@@ -3,7 +3,8 @@
3
3
  * versioned documents Agents are made from, each with a harness and a runtime section. A save
4
4
  * moves every Agent that tracks the manifest to the new version; a pinned one stays. Reading needs `agents:read` (or a write scope), saving and deleting
5
5
  * `agent-manifests:write`, from any client (Q12). A token caller reaches none: a manifest holds
6
- * an agent's instructions, tools and servers.
6
+ * an agent's instructions, tools and servers. A save may send an agent folder by hash instead of
7
+ * the manifest (track T6): the Runtime compiles it and keeps it as the version's source.
7
8
  */
8
9
  import type { OpenAPIHono } from "@hono/zod-openapi";
9
10
  import type { TenantEnv } from "../app.js";
@@ -1,9 +1,9 @@
1
1
  import { z } from "zod";
2
- import { isAgentManifestName, PutAgentManifestRequestSchema } from "@nylorun/core/contracts";
3
- import { AgentManifestPlan, AgentManifestVersions, AgentManifestView, DeleteAgentManifestResponse, ListAgentManifestsResponse, PutAgentManifestRequest, SaveAgentManifestResponse, } from "../../components.js";
2
+ import { AGENT_FOLDER_MEDIA_TYPE, contentTypeFor, isAgentManifestName, PutAgentFolderRequestSchema, PutAgentManifestRequestSchema, } from "@nylorun/core/contracts";
3
+ import { AgentManifestPlan, AgentManifestSource, AgentManifestVersions, AgentManifestView, DeleteAgentManifestResponse, ListAgentManifestsResponse, PutAgentFolderRequest, PutAgentManifestRequest, SaveAgentManifestResponse, } from "../../components.js";
4
4
  import { requirePrincipal } from "../../../tenant/auth.js";
5
5
  import { fail } from "../../../tenant/http.js";
6
- import { agentManifestVersions, deleteAgentManifest, getAgentManifest, listAgentManifests, saveAgentManifest, } from "../../../tenant/agent-manifests.js";
6
+ import { agentManifestVersions, deleteAgentManifest, getAgentManifest, getAgentManifestSource, listAgentManifests, readAgentManifestSourceFile, saveAgentFolder, saveAgentManifest, } from "../../../tenant/agent-manifests.js";
7
7
  import { readJson } from "../body.js";
8
8
  import { tenantRoute } from "../define.js";
9
9
  import { jsonResponse } from "../respond.js";
@@ -59,13 +59,19 @@ export function agentManifestRoutes(api) {
59
59
  path: "/v1/agent-manifests/{name}",
60
60
  tags: ["Agent manifests"],
61
61
  summary: "Save an agent manifest",
62
- description: "Saves the manifest as its next version, or answers the latest unchanged when nothing differs. Every Agent that tracks the manifest moves to the new version: at once, at its pod's next start for a runtime change a pod applies only when it starts, or once a required secret the version adds is set; a pinned one stays, and so does one whose kind, harness or storage the version changes (`agents_behind`). The Runtime checks the harness and runtime sections against each other: a custom harness needs a pod with an image, every credential the harness names is a declared slot of the right type, and the runtime's kind gives the loop the sandbox it needs; every gap is named in one `422 manifest_inconsistent` (`details.gaps`). `If-Match: <version>` refuses the save with `412 manifest_changed` when the latest version is no longer the one you read (`0` for a manifest that does not exist yet). With `?dryRun=true` the answer is the plan: the changes by section, every reason a save would be refused (`errors`, the gaps first), warnings, the Agents it would move (`moves`) and how many stay on older versions (`behind`); nothing is saved. Clients compose the authoring files and drop their `$schema` before they send one document.",
62
+ description: "Saves the manifest as its next version, or answers the latest unchanged when nothing differs. Every Agent that tracks the manifest moves to the new version: at once, at its pod's next start for a runtime change a pod applies only when it starts, or once a required secret the version adds is set; a pinned one stays, and so does one whose kind, harness or storage the version changes (`agents_behind`). The Runtime checks the harness and runtime sections against each other: a custom harness needs a pod with an image, every credential the harness names is a declared slot of the right type, and the runtime's kind gives the loop the sandbox it needs; every gap is named in one `422 manifest_inconsistent` (`details.gaps`). `If-Match: <version>` refuses the save with `412 manifest_changed` when the latest version is no longer the one you read (`0` for a manifest that does not exist yet). With `?dryRun=true` the answer is the plan: the changes by section, every reason a save would be refused (`errors`, the gaps first), warnings, the Agents it would move (`moves`) and how many stay on older versions (`behind`); nothing is saved. Clients compose the authoring files and drop their `$schema` before they send one document. With `Content-Type: application/vnd.nylorun.folder+json` the body is an agent folder by hash instead (feature `agent-folders`): every file uploaded first with `PUT /v1/files/sha256:<hex>`, the Runtime compiles it with `@nylorun/core/folder`, a folder that does not compile is `422 folder_invalid` (`details.diagnostics`, each with its file, line and column), and the version keeps the folder as its source; the plan adds the compiled `manifest`, the compiler's `diagnostics` and `compiler`.",
63
63
  request: {
64
64
  params: namePath,
65
65
  query: z.object({
66
66
  dryRun: z.enum(["true", "false"]).optional().meta({ description: "`true`: answer the plan and save nothing" }),
67
67
  }),
68
- body: { required: true, content: { "application/json": { schema: PutAgentManifestRequest } } },
68
+ body: {
69
+ required: true,
70
+ content: {
71
+ "application/json": { schema: PutAgentManifestRequest },
72
+ [AGENT_FOLDER_MEDIA_TYPE]: { schema: PutAgentFolderRequest },
73
+ },
74
+ },
69
75
  },
70
76
  responses: {
71
77
  200: json(z.union([SaveAgentManifestResponse, AgentManifestPlan]), "The version saved, or the plan with dryRun"),
@@ -74,16 +80,23 @@ export function agentManifestRoutes(api) {
74
80
  },
75
81
  412: { description: "If-Match named a version that is no longer the latest (`manifest_changed`)" },
76
82
  413: { description: "A skill's files hold more than the manifest's skill limit together (`limit_exceeded`)" },
77
- 422: { description: "The harness and runtime sections do not fit (`manifest_inconsistent`, `details.gaps`)" },
83
+ 422: {
84
+ description: "The harness and runtime sections do not fit (`manifest_inconsistent`, `details.gaps`), or an agent folder does not compile (`folder_invalid`, `details.diagnostics`)",
85
+ },
78
86
  },
79
87
  }, async (c) => {
80
88
  const name = nameOf(c.req.param("name"));
81
- const body = PutAgentManifestRequestSchema.parse(await readJson(c));
82
89
  const ifMatch = ifMatchOf(c.req.header("if-match"));
83
- const options = ifMatch === undefined ? {} : { ifMatch };
84
- return jsonResponse(200, c.req.query("dryRun") === "true"
90
+ const options = { ...(ifMatch === undefined ? {} : { ifMatch }), ...(c.req.query("dryRun") === "true" ? { dryRun: true } : {}) };
91
+ const media = (c.req.header("content-type") ?? "").split(";")[0].trim().toLowerCase();
92
+ if (media === AGENT_FOLDER_MEDIA_TYPE) {
93
+ const folder = PutAgentFolderRequestSchema.parse(await readJson(c));
94
+ return jsonResponse(200, await saveAgentFolder(c.env.tenant, name, folder, c.get("scope"), options));
95
+ }
96
+ const body = PutAgentManifestRequestSchema.parse(await readJson(c));
97
+ return jsonResponse(200, options.dryRun
85
98
  ? await saveAgentManifest(c.env.tenant, name, body, c.get("scope"), { ...options, dryRun: true })
86
- : await saveAgentManifest(c.env.tenant, name, body, c.get("scope"), options));
99
+ : await saveAgentManifest(c.env.tenant, name, body, c.get("scope"), { ...options, dryRun: false }));
87
100
  });
88
101
  tenantRoute(api, READ, {
89
102
  method: "get",
@@ -120,6 +133,45 @@ export function agentManifestRoutes(api) {
120
133
  requirePrincipal(c.get("scope"));
121
134
  return jsonResponse(200, await getAgentManifest(c.env.tenant, nameOf(c.req.param("name")), versionOf(c.req.param("version"))));
122
135
  });
136
+ tenantRoute(api, READ, {
137
+ method: "get",
138
+ path: "/v1/agent-manifests/{name}/versions/{version}/source",
139
+ tags: ["Agent manifests"],
140
+ summary: "Get the folder a version was compiled from",
141
+ description: "The agent folder the version was saved from (feature `agent-folders`): its compiler, size and every file, sorted by path. A version saved as JSON has none (`404`).",
142
+ request: { params: namePath.extend({ version: z.string().meta({ description: "The version number" }) }) },
143
+ responses: { 200: json(AgentManifestSource, "The folder") },
144
+ }, async (c) => {
145
+ requirePrincipal(c.get("scope"));
146
+ return jsonResponse(200, await getAgentManifestSource(c.env.tenant, nameOf(c.req.param("name")), versionOf(c.req.param("version"))));
147
+ });
148
+ tenantRoute(api, READ, {
149
+ method: "get",
150
+ path: "/v1/agent-manifests/{name}/versions/{version}/source/files/{path}",
151
+ tags: ["Agent manifests"],
152
+ summary: "Download one file of a version's folder",
153
+ description: "Streams the file at `path` (its path in the folder, with `/` percent-encoded as `%2F`) as it was saved.",
154
+ request: {
155
+ params: namePath.extend({
156
+ version: z.string().meta({ description: "The version number" }),
157
+ path: z.string().meta({ description: "The file's path in the folder, percent-encoded" }),
158
+ }),
159
+ },
160
+ responses: {
161
+ 200: {
162
+ description: "The file's bytes",
163
+ content: { "application/octet-stream": { schema: z.string().meta({ format: "binary" }) } },
164
+ },
165
+ },
166
+ }, async (c) => {
167
+ requirePrincipal(c.get("scope"));
168
+ const path = c.req.param("path");
169
+ const file = await readAgentManifestSourceFile(c.env.tenant, nameOf(c.req.param("name")), versionOf(c.req.param("version")), path);
170
+ return new Response(file.body, {
171
+ status: 200,
172
+ headers: { "content-type": contentTypeFor(path), "content-length": String(file.size) },
173
+ });
174
+ });
123
175
  tenantRoute(api, WRITE, {
124
176
  method: "delete",
125
177
  path: "/v1/agent-manifests/{name}",
@@ -119,6 +119,8 @@ const RUNTIME_TAGS = [
119
119
  "GET /v1/agent-manifests/{name}",
120
120
  "GET /v1/agent-manifests/{name}/versions",
121
121
  "GET /v1/agent-manifests/{name}/versions/{version}",
122
+ "GET /v1/agent-manifests/{name}/versions/{version}/source",
123
+ "GET /v1/agent-manifests/{name}/versions/{version}/source/files/{path}",
122
124
  "DELETE /v1/agent-manifests/{name}",
123
125
  ],
124
126
  },
package/dist/host/http.js CHANGED
@@ -1,6 +1,7 @@
1
1
  import { createHash, timingSafeEqual } from "node:crypto";
2
2
  import { jsonResponse } from "../api/http/respond.js";
3
3
  import { HOST_PROTOCOL, } from "@nylorun/core/compatibility";
4
+ import { AGENT_FOLDER_MEDIA_TYPE } from "@nylorun/core/contracts";
4
5
  export const OPAQUE_NOT_FOUND = {
5
6
  status: "rejected",
6
7
  code: "not_found",
@@ -113,7 +114,8 @@ export function isJsonContentType(value) {
113
114
  if (value === undefined)
114
115
  return false;
115
116
  const media = value.split(";")[0].trim().toLowerCase();
116
- return media === "application/json";
117
+ // An agent folder by hash (track T6) is JSON too.
118
+ return media === "application/json" || media === AGENT_FOLDER_MEDIA_TYPE;
117
119
  }
118
120
  /** True when the request carries a body (Content-Length > 0 or chunked). */
119
121
  export function requestHasBody(request) {
@@ -2,7 +2,7 @@
2
2
  "openapi": "3.2.0",
3
3
  "info": {
4
4
  "title": "Nylorun Management API",
5
- "version": "0.30.0-beta",
5
+ "version": "0.31.0-beta",
6
6
  "x-nylorun-protocol": {
7
7
  "min": 16,
8
8
  "max": 18,
@@ -33,7 +33,8 @@
33
33
  "tool-policy",
34
34
  "traces",
35
35
  "artifact-reads",
36
- "gateway-credentials"
36
+ "gateway-credentials",
37
+ "agent-folders"
37
38
  ]
38
39
  },
39
40
  "description": "For operators: the Tenant's models, vaults, signing keys, settings and application keys, at `/v1/tenant/*` on the Tenant's URL, through `@nylorun/admin`. Every operation takes a management key, acting as itself: never for a subject and never from a browser. Management keys are issued only on the Tenant's machine (`nylorun tenant keys put <id> --management`) or from `NYLORUN_MANAGEMENT_KEY_FILE`."
@@ -122,6 +123,7 @@
122
123
  "manifest_not_found",
123
124
  "manifest_in_use",
124
125
  "manifest_changed",
126
+ "folder_invalid",
125
127
  "internal_error"
126
128
  ]
127
129
  },