@agentproto/storage 0.1.0-alpha.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/LICENSE +21 -0
- package/README.md +23 -0
- package/dist/chunk-JMBOQNBX.mjs +48 -0
- package/dist/chunk-JMBOQNBX.mjs.map +1 -0
- package/dist/index.d.ts +136 -0
- package/dist/index.mjs +19 -0
- package/dist/index.mjs.map +1 -0
- package/dist/manifest/index.d.ts +55 -0
- package/dist/manifest/index.mjs +28 -0
- package/dist/manifest/index.mjs.map +1 -0
- package/dist/types-DZAjXcqA.d.ts +166 -0
- package/package.json +68 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 agentproto contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# @agentproto/storage
|
|
2
|
+
|
|
3
|
+
AIP-35 `STORAGE.md` reference implementation. A composable schema block defining the `storage` field — provider, config, sync semantics, auth ref, exclude rules — for any manifest that names a backing store. Reused by WORKSPACE.md (AIP-34) and any future manifest that names persistent state. Inline or ref, mirroring AIP-17 RUNNER and AIP-19 SECRETS.
|
|
4
|
+
|
|
5
|
+
> **Status: 0.1.0-alpha.** Generated by `scripts/scaffold-aip.mjs` — `build()` and `validate()` bodies are TODOs.
|
|
6
|
+
|
|
7
|
+
Spec: <https://agentproto.sh/docs/aip-35>
|
|
8
|
+
|
|
9
|
+
## Usage
|
|
10
|
+
|
|
11
|
+
```ts
|
|
12
|
+
import { defineStorage } from "@agentproto/storage"
|
|
13
|
+
|
|
14
|
+
const x = defineStorage({
|
|
15
|
+
id: "my-storage",
|
|
16
|
+
description: "Short purpose.",
|
|
17
|
+
// ...
|
|
18
|
+
})
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## License
|
|
22
|
+
|
|
23
|
+
MIT — see [LICENSE](./LICENSE).
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { createDoctype } from '@agentproto/define-doctype';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* @agentproto/storage v0.1.0-alpha
|
|
6
|
+
* AIP-35 STORAGE.md `defineStorage` reference implementation.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
var storageFrontmatterSchema = z.object({ "schema": z.literal("storage/v1").describe("Standalone-only. Identifies the doctype + version. Absent when the block is inlined in another manifest.").optional(), "id": z.string().regex(new RegExp("^@[a-z0-9][a-z0-9-]*/[a-z0-9][a-z0-9-]*$")).describe("Standalone-only. Globally addressable id `@<owner-slug>/<storage-slug>`.").optional(), "version": z.string().regex(new RegExp("^\\d+\\.\\d+\\.\\d+(?:[-+][\\w.\\-]+)?$")).describe("Standalone-only. Spec version of THIS file. Bump on breaking shape change.").optional(), "provider": z.string().min(1).describe("Backend kind. Day-1 enumerated set: cloud-bucket | self-bucket | github | local-fs | dev-local | mastra-s3 | mastra-azure. Hosts MAY register additional ids; the schema accepts any non-empty string and host-side validation narrows."), "config": z.record(z.string(), z.any()).describe("Provider-specific connection fields. Shape varies per provider (see AIP-35 \xA7Provider config shapes)."), "sync": z.any().describe("Sync semantics. Lifecycle triggers reference AIP-37 event names.").optional(), "auth": z.any().describe("Reference to AIP-19 SECRETS.md (or future ENV.md) for credentials.").optional(), "identity": z.any().describe("AIP-23 identity-ref block \u2014 commit author(s) for syncing providers (github). Supports multi-attribution (primary + co-authors).").optional(), "exclude": z.array(z.string()).describe("Paths NOT mirrored to the backing store. Glob-ish, prefix-matched.").default([]), "read_only": z.boolean().describe("Reject writes at the storage layer.").default(false), "metadata": z.record(z.string(), z.any()).describe("Free-form, namespaced. Authors MAY stash adapter-specific hints under namespaced keys.").optional() }).strict().describe("Validates the YAML frontmatter portion of an AIP-35 STORAGE.md manifest, OR the inline form embedded in any other manifest's `storage:` block. Filesystem-only \u2014 sandbox-shaped backends (e2b/modal/...) live in AIP-36 SANDBOX.md.");
|
|
10
|
+
var defineStorageInner = createDoctype({
|
|
11
|
+
aip: 35,
|
|
12
|
+
name: "storage",
|
|
13
|
+
readDescription: false,
|
|
14
|
+
// AIP-35 makes `id` standalone-only — inline storage blocks (every
|
|
15
|
+
// host registration we care about) carry only `provider` + `config`.
|
|
16
|
+
// Fall back to `provider` for the cross-AIP id-pattern check; the
|
|
17
|
+
// resolution order mirrors AIP-43 § Identity (id → provider → slug).
|
|
18
|
+
readIdentity: (def) => {
|
|
19
|
+
if (typeof def.id === "string" && def.id.length > 0) return def.id;
|
|
20
|
+
return def.provider;
|
|
21
|
+
},
|
|
22
|
+
validate(def) {
|
|
23
|
+
const { factory: _factory, capabilities: _capabilities, ...manifest } = def;
|
|
24
|
+
const result = storageFrontmatterSchema.safeParse(manifest);
|
|
25
|
+
if (!result.success) {
|
|
26
|
+
throw new Error(
|
|
27
|
+
`defineStorage (AIP-35): ${result.error.issues.map((i) => `${i.path.join(".")}: ${i.message}`).join("; ")}`
|
|
28
|
+
);
|
|
29
|
+
}
|
|
30
|
+
},
|
|
31
|
+
build(def) {
|
|
32
|
+
const { factory, capabilities, ...manifest } = def;
|
|
33
|
+
return {
|
|
34
|
+
...manifest,
|
|
35
|
+
...factory !== void 0 ? { factory } : {},
|
|
36
|
+
...capabilities !== void 0 ? { capabilities: Object.freeze({ ...capabilities }) } : {}
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
});
|
|
40
|
+
function defineStorage(definition) {
|
|
41
|
+
return defineStorageInner(
|
|
42
|
+
definition
|
|
43
|
+
);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export { defineStorage, storageFrontmatterSchema };
|
|
47
|
+
//# sourceMappingURL=chunk-JMBOQNBX.mjs.map
|
|
48
|
+
//# sourceMappingURL=chunk-JMBOQNBX.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/schema.ts","../src/define-storage.ts"],"names":[],"mappings":"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","file":"chunk-JMBOQNBX.mjs","sourcesContent":["/**\n * AIP-35 STORAGE.md frontmatter zod schema.\n *\n * Generated from `resources/aip-35/draft/STORAGE.schema.json` via\n * json-schema-to-zod. Imported by both `define-storage.ts` (TS path\n * validation) and `manifest/index.ts` (.md path validation) so every\n * field-level constraint runs in both authoring paths from a single\n * source of truth — re-run scaffold-aip to refresh after spec changes.\n *\n * Cross-field rules (if/then/allOf in JSON Schema) don't translate\n * cleanly and live in `define-storage.ts`'s `validate(def)` instead.\n */\n\nimport { z } from \"zod\"\n\nexport const storageFrontmatterSchema = z.object({ \"schema\": z.literal(\"storage/v1\").describe(\"Standalone-only. Identifies the doctype + version. Absent when the block is inlined in another manifest.\").optional(), \"id\": z.string().regex(new RegExp(\"^@[a-z0-9][a-z0-9-]*/[a-z0-9][a-z0-9-]*$\")).describe(\"Standalone-only. Globally addressable id `@<owner-slug>/<storage-slug>`.\").optional(), \"version\": z.string().regex(new RegExp(\"^\\\\d+\\\\.\\\\d+\\\\.\\\\d+(?:[-+][\\\\w.\\\\-]+)?$\")).describe(\"Standalone-only. Spec version of THIS file. Bump on breaking shape change.\").optional(), \"provider\": z.string().min(1).describe(\"Backend kind. Day-1 enumerated set: cloud-bucket | self-bucket | github | local-fs | dev-local | mastra-s3 | mastra-azure. Hosts MAY register additional ids; the schema accepts any non-empty string and host-side validation narrows.\"), \"config\": z.record(z.string(), z.any()).describe(\"Provider-specific connection fields. Shape varies per provider (see AIP-35 §Provider config shapes).\"), \"sync\": z.any().describe(\"Sync semantics. Lifecycle triggers reference AIP-37 event names.\").optional(), \"auth\": z.any().describe(\"Reference to AIP-19 SECRETS.md (or future ENV.md) for credentials.\").optional(), \"identity\": z.any().describe(\"AIP-23 identity-ref block — commit author(s) for syncing providers (github). Supports multi-attribution (primary + co-authors).\").optional(), \"exclude\": z.array(z.string()).describe(\"Paths NOT mirrored to the backing store. Glob-ish, prefix-matched.\").default([] as never), \"read_only\": z.boolean().describe(\"Reject writes at the storage layer.\").default(false), \"metadata\": z.record(z.string(), z.any()).describe(\"Free-form, namespaced. Authors MAY stash adapter-specific hints under namespaced keys.\").optional() }).strict().describe(\"Validates the YAML frontmatter portion of an AIP-35 STORAGE.md manifest, OR the inline form embedded in any other manifest's `storage:` block. Filesystem-only — sandbox-shaped backends (e2b/modal/...) live in AIP-36 SANDBOX.md.\")\n\nexport type StorageFrontmatter = z.infer<typeof storageFrontmatterSchema>\n","import { createDoctype } from \"@agentproto/define-doctype\"\nimport { storageFrontmatterSchema } from \"./schema.js\"\nimport type {\n StorageRuntimeHandle,\n StorageRuntimeInput,\n} from \"./types.js\"\n\n/**\n * AIP-35 reference implementation of `defineStorage`.\n *\n * Built on `createDoctype` so the cross-AIP invariants (id pattern,\n * description length, top-level freeze, \"defineStorage (AIP-35): …\"\n * error prefix) run uniformly with every other AIP defineX.\n *\n * Field-level validation runs the schema-derived zod from\n * `./schema.ts` against the manifest portion of the input. The\n * AIP-43 runtime slots (`factory`, `capabilities`) are HOST-OPAQUE\n * TS-runtime metadata — they don't exist in the AIP-35 frontmatter\n * schema, so we strip them before validation and re-attach them in\n * `build`. The zod schema stays `.strict()` (typo-catching for MD\n * authors); runtime callers get the extra slots via the input type.\n *\n * Generic params:\n * TFactory — host-typed factory function shape (e.g. a Mastra\n * `(input) => MastraFilesystem` for the Guilde host).\n * Defaults to `unknown`.\n * TCapabilities — opaque metadata the registry queries on. Per\n * AIP-43 § Capability metadata namespace, hosts\n * SHOULD agree on conventional keys\n * (bridgeable / transport / pairsWith / serverReachable).\n */\nconst defineStorageInner = createDoctype<\n StorageRuntimeInput,\n StorageRuntimeHandle\n>({\n aip: 35,\n name: \"storage\",\n readDescription: false,\n // AIP-35 makes `id` standalone-only — inline storage blocks (every\n // host registration we care about) carry only `provider` + `config`.\n // Fall back to `provider` for the cross-AIP id-pattern check; the\n // resolution order mirrors AIP-43 § Identity (id → provider → slug).\n readIdentity: def => {\n if (typeof def.id === \"string\" && def.id.length > 0) return def.id\n return def.provider\n },\n validate(def) {\n // Strip runtime-only slots before AIP-35 schema validation —\n // they're not part of the manifest spec, can't round-trip\n // through YAML, and adding them to the strict schema would mean\n // every STORAGE.md author has to know about TS internals.\n const { factory: _factory, capabilities: _capabilities, ...manifest } = def\n const result = storageFrontmatterSchema.safeParse(manifest)\n if (!result.success) {\n throw new Error(\n `defineStorage (AIP-35): ${result.error.issues\n .map(i => `${i.path.join(\".\")}: ${i.message}`)\n .join(\"; \")}`,\n )\n }\n // TODO: spec-35-specific cross-field rules (if/then/allOf in\n // the JSON Schema) — those don't translate to zod cleanly and\n // belong here. See @agentproto/operator's autonomy=gated rule.\n },\n build(def) {\n // Re-attach the runtime slots after validation. Capabilities are\n // shallow-frozen here so registry consumers can rely on\n // immutability; factory is left as-is (it's a function ref).\n const { factory, capabilities, ...manifest } = def\n return {\n ...manifest,\n ...(factory !== undefined ? { factory } : {}),\n ...(capabilities !== undefined\n ? { capabilities: Object.freeze({ ...capabilities }) }\n : {}),\n } as StorageRuntimeHandle\n },\n})\n\n/**\n * Type-aware wrapper preserving `TFactory` / `TCapabilities` generics\n * across the call (the underlying `createDoctype` factory is invariant\n * over its TDef/THandle pair, so we expose the parametric face here).\n */\nexport function defineStorage<\n TFactory = unknown,\n TCapabilities extends Record<string, unknown> = Record<string, unknown>,\n>(\n definition: StorageRuntimeInput<TFactory, TCapabilities>,\n): StorageRuntimeHandle<TFactory, TCapabilities> {\n return defineStorageInner(\n definition as StorageRuntimeInput,\n ) as StorageRuntimeHandle<TFactory, TCapabilities>\n}\n"]}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
import { S as StorageRuntimeInput, a as StorageRuntimeHandle } from './types-DZAjXcqA.js';
|
|
2
|
+
export { b as StorageDefinition, c as StorageHandle } from './types-DZAjXcqA.js';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Type-aware wrapper preserving `TFactory` / `TCapabilities` generics
|
|
6
|
+
* across the call (the underlying `createDoctype` factory is invariant
|
|
7
|
+
* over its TDef/THandle pair, so we expose the parametric face here).
|
|
8
|
+
*/
|
|
9
|
+
declare function defineStorage<TFactory = unknown, TCapabilities extends Record<string, unknown> = Record<string, unknown>>(definition: StorageRuntimeInput<TFactory, TCapabilities>): StorageRuntimeHandle<TFactory, TCapabilities>;
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* WorkspaceSync — the imperative counterpart to the AIP-35 `sync`
|
|
13
|
+
* policy block (the `pull` / `commit` / `push` sub-blocks). A provider
|
|
14
|
+
* that backs a workspace with a remote origin (git repo, bucket)
|
|
15
|
+
* implements this to seed a local working tree FROM the origin (`pull`)
|
|
16
|
+
* and materialise local writes BACK to it (`push`).
|
|
17
|
+
*
|
|
18
|
+
* This is `sync.mode: "pull-push"` made concrete: the local filesystem
|
|
19
|
+
* stays the runtime truth (fast, offline-capable, the "filesystem on
|
|
20
|
+
* sait jamais" safety), while the remote repo is the durable, visible,
|
|
21
|
+
* versioned origin. Contrast `sync.mode: "canonical"`, where the
|
|
22
|
+
* provider's MastraFilesystem IS the live backing and every read/write
|
|
23
|
+
* hits the remote per-file — that mode needs no WorkspaceSync.
|
|
24
|
+
*
|
|
25
|
+
* Both consumers share one contract:
|
|
26
|
+
* - a cloud workstation seeds its sandbox on spawn, pushes on close
|
|
27
|
+
* - a corpus seeds its workspace on resolve, pushes on promote
|
|
28
|
+
*
|
|
29
|
+
* Spec: https://agentproto.sh/docs/aip-35 (sync block) + AIP-37 (hooks)
|
|
30
|
+
*/
|
|
31
|
+
/**
|
|
32
|
+
* The minimal tree surface `pull` / `push` operate on. A structural
|
|
33
|
+
* subset of `FsPort` (@agentproto/corpus) — declared here so
|
|
34
|
+
* `@agentproto/storage` stays dependency-free; any `FsPort` or
|
|
35
|
+
* `MastraFilesystem` adapter satisfies it by shape. Paths are
|
|
36
|
+
* workspace-relative (no leading slash); `""` / `.` is the root.
|
|
37
|
+
*/
|
|
38
|
+
interface SyncTree {
|
|
39
|
+
exists(path: string): Promise<boolean>;
|
|
40
|
+
readFile(path: string): Promise<string>;
|
|
41
|
+
writeFile(path: string, content: string): Promise<void>;
|
|
42
|
+
/** Recursive listing — workspace-relative paths of every file under
|
|
43
|
+
* `path`. Skips dot-directories (matches FsPort.walk). */
|
|
44
|
+
walk(path: string): Promise<readonly string[]>;
|
|
45
|
+
}
|
|
46
|
+
interface PullResult {
|
|
47
|
+
/** False when the tree was already populated and `force` was unset. */
|
|
48
|
+
seeded: boolean;
|
|
49
|
+
files: number;
|
|
50
|
+
bytes: number;
|
|
51
|
+
message: string;
|
|
52
|
+
}
|
|
53
|
+
type PushResult = {
|
|
54
|
+
kind: "pushed";
|
|
55
|
+
/** The ref the commit landed on (branch name). */
|
|
56
|
+
ref: string;
|
|
57
|
+
commit?: string;
|
|
58
|
+
prUrl?: string;
|
|
59
|
+
prNumber?: number;
|
|
60
|
+
files: number;
|
|
61
|
+
/** Bytes materialised to the origin, when the provider tracks it. */
|
|
62
|
+
bytes?: number;
|
|
63
|
+
/** Files the provider intentionally left behind (size caps,
|
|
64
|
+
* exclude rules) — telemetry, not a failure. */
|
|
65
|
+
filesSkipped?: number;
|
|
66
|
+
/** Non-fatal errors during a best-effort push. The push still
|
|
67
|
+
* landed; these are per-file warnings a UI may surface. */
|
|
68
|
+
errors?: readonly string[];
|
|
69
|
+
message: string;
|
|
70
|
+
}
|
|
71
|
+
/** Working tree matches the origin — nothing to push. */
|
|
72
|
+
| {
|
|
73
|
+
kind: "no_changes";
|
|
74
|
+
message: string;
|
|
75
|
+
}
|
|
76
|
+
/** No credential resolved for the origin — refuse rather than fall
|
|
77
|
+
* back to a host token (would cross-tenant commits). */
|
|
78
|
+
| {
|
|
79
|
+
kind: "no_credentials";
|
|
80
|
+
message: string;
|
|
81
|
+
}
|
|
82
|
+
/** Credential reads the origin but cannot write to it. */
|
|
83
|
+
| {
|
|
84
|
+
kind: "no_permission";
|
|
85
|
+
message: string;
|
|
86
|
+
} | {
|
|
87
|
+
kind: "failed";
|
|
88
|
+
message: string;
|
|
89
|
+
};
|
|
90
|
+
interface PushOptions {
|
|
91
|
+
/** Short label for the commit / branch (e.g. operator or run id). */
|
|
92
|
+
label?: string;
|
|
93
|
+
/** Human summary woven into the commit message / PR body. */
|
|
94
|
+
summary?: string;
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Pull-push lifecycle for a remote-backed workspace. Providers expose
|
|
98
|
+
* this alongside their `MastraFilesystem`; callers feature-detect it
|
|
99
|
+
* (`if ("pull" in fs)`) — no parallel registry, the provider id is the
|
|
100
|
+
* single dispatch key.
|
|
101
|
+
*/
|
|
102
|
+
interface WorkspaceSync {
|
|
103
|
+
/**
|
|
104
|
+
* Seed `tree` from the remote origin. Idempotent. Refuses to clobber
|
|
105
|
+
* a non-empty tree unless `opts.force` — a fresh workspace starts
|
|
106
|
+
* empty, but a misrouted call against a warm tree must not silently
|
|
107
|
+
* overwrite ongoing work.
|
|
108
|
+
*/
|
|
109
|
+
pull(tree: SyncTree, opts?: {
|
|
110
|
+
force?: boolean;
|
|
111
|
+
}): Promise<PullResult>;
|
|
112
|
+
/**
|
|
113
|
+
* Materialise the current `tree` state to the origin as a single
|
|
114
|
+
* commit (plus a PR when the provider's `sync.push.prPolicy` calls
|
|
115
|
+
* for one). A no-op when the tree matches the origin.
|
|
116
|
+
*/
|
|
117
|
+
push(tree: SyncTree, opts?: PushOptions): Promise<PushResult>;
|
|
118
|
+
}
|
|
119
|
+
/** Feature-detect the sync capability on a resolved filesystem. */
|
|
120
|
+
declare function hasWorkspaceSync(fs: unknown): fs is WorkspaceSync;
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* @agentproto/storage — AIP-35 STORAGE.md `defineStorage` reference impl.
|
|
124
|
+
*
|
|
125
|
+
* A composable schema block defining the `storage` field — provider, config, sync semantics, auth ref, exclude rules — for any manifest that names a backing store. Reused by WORKSPACE.md (AIP-34) and any future manifest that names persistent state. Inline or ref, mirroring AIP-17 RUNNER and AIP-19 SECRETS.
|
|
126
|
+
*
|
|
127
|
+
* Spec: https://agentproto.sh/docs/aip-35
|
|
128
|
+
*
|
|
129
|
+
* Authoring paths:
|
|
130
|
+
* - TS: `defineStorage({...})` → `StorageHandle`
|
|
131
|
+
* - MD: `parseStorageManifest(src) → storageFromManifest({...})` → `StorageHandle`
|
|
132
|
+
*/
|
|
133
|
+
declare const SPEC_NAME: "agentstorage/v1";
|
|
134
|
+
declare const SPEC_VERSION: "1.0.0-alpha";
|
|
135
|
+
|
|
136
|
+
export { type PullResult, type PushOptions, type PushResult, SPEC_NAME, SPEC_VERSION, StorageRuntimeHandle, StorageRuntimeInput, type SyncTree, type WorkspaceSync, defineStorage, hasWorkspaceSync };
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export { defineStorage } from './chunk-JMBOQNBX.mjs';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @agentproto/storage v0.1.0-alpha
|
|
5
|
+
* AIP-35 STORAGE.md `defineStorage` reference implementation.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
// src/workspace-sync.ts
|
|
9
|
+
function hasWorkspaceSync(fs) {
|
|
10
|
+
return typeof fs === "object" && fs !== null && typeof fs.pull === "function" && typeof fs.push === "function";
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
// src/index.ts
|
|
14
|
+
var SPEC_NAME = "agentstorage/v1";
|
|
15
|
+
var SPEC_VERSION = "1.0.0-alpha";
|
|
16
|
+
|
|
17
|
+
export { SPEC_NAME, SPEC_VERSION, hasWorkspaceSync };
|
|
18
|
+
//# sourceMappingURL=index.mjs.map
|
|
19
|
+
//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/workspace-sync.ts","../src/index.ts"],"names":[],"mappings":";;;;;;;;AAwGO,SAAS,iBAAiB,EAAA,EAAkC;AACjE,EAAA,OACE,OAAO,EAAA,KAAO,QAAA,IACd,EAAA,KAAO,IAAA,IACP,OAAQ,EAAA,CAAqB,IAAA,KAAS,UAAA,IACtC,OAAQ,EAAA,CAAqB,IAAA,KAAS,UAAA;AAE1C;;;ACnGO,IAAM,SAAA,GAAY;AAClB,IAAM,YAAA,GAAe","file":"index.mjs","sourcesContent":["/**\n * WorkspaceSync — the imperative counterpart to the AIP-35 `sync`\n * policy block (the `pull` / `commit` / `push` sub-blocks). A provider\n * that backs a workspace with a remote origin (git repo, bucket)\n * implements this to seed a local working tree FROM the origin (`pull`)\n * and materialise local writes BACK to it (`push`).\n *\n * This is `sync.mode: \"pull-push\"` made concrete: the local filesystem\n * stays the runtime truth (fast, offline-capable, the \"filesystem on\n * sait jamais\" safety), while the remote repo is the durable, visible,\n * versioned origin. Contrast `sync.mode: \"canonical\"`, where the\n * provider's MastraFilesystem IS the live backing and every read/write\n * hits the remote per-file — that mode needs no WorkspaceSync.\n *\n * Both consumers share one contract:\n * - a cloud workstation seeds its sandbox on spawn, pushes on close\n * - a corpus seeds its workspace on resolve, pushes on promote\n *\n * Spec: https://agentproto.sh/docs/aip-35 (sync block) + AIP-37 (hooks)\n */\n\n/**\n * The minimal tree surface `pull` / `push` operate on. A structural\n * subset of `FsPort` (@agentproto/corpus) — declared here so\n * `@agentproto/storage` stays dependency-free; any `FsPort` or\n * `MastraFilesystem` adapter satisfies it by shape. Paths are\n * workspace-relative (no leading slash); `\"\"` / `.` is the root.\n */\nexport interface SyncTree {\n exists(path: string): Promise<boolean>\n readFile(path: string): Promise<string>\n writeFile(path: string, content: string): Promise<void>\n /** Recursive listing — workspace-relative paths of every file under\n * `path`. Skips dot-directories (matches FsPort.walk). */\n walk(path: string): Promise<readonly string[]>\n}\n\nexport interface PullResult {\n /** False when the tree was already populated and `force` was unset. */\n seeded: boolean\n files: number\n bytes: number\n message: string\n}\n\nexport type PushResult =\n | {\n kind: \"pushed\"\n /** The ref the commit landed on (branch name). */\n ref: string\n commit?: string\n prUrl?: string\n prNumber?: number\n files: number\n /** Bytes materialised to the origin, when the provider tracks it. */\n bytes?: number\n /** Files the provider intentionally left behind (size caps,\n * exclude rules) — telemetry, not a failure. */\n filesSkipped?: number\n /** Non-fatal errors during a best-effort push. The push still\n * landed; these are per-file warnings a UI may surface. */\n errors?: readonly string[]\n message: string\n }\n /** Working tree matches the origin — nothing to push. */\n | { kind: \"no_changes\"; message: string }\n /** No credential resolved for the origin — refuse rather than fall\n * back to a host token (would cross-tenant commits). */\n | { kind: \"no_credentials\"; message: string }\n /** Credential reads the origin but cannot write to it. */\n | { kind: \"no_permission\"; message: string }\n | { kind: \"failed\"; message: string }\n\nexport interface PushOptions {\n /** Short label for the commit / branch (e.g. operator or run id). */\n label?: string\n /** Human summary woven into the commit message / PR body. */\n summary?: string\n}\n\n/**\n * Pull-push lifecycle for a remote-backed workspace. Providers expose\n * this alongside their `MastraFilesystem`; callers feature-detect it\n * (`if (\"pull\" in fs)`) — no parallel registry, the provider id is the\n * single dispatch key.\n */\nexport interface WorkspaceSync {\n /**\n * Seed `tree` from the remote origin. Idempotent. Refuses to clobber\n * a non-empty tree unless `opts.force` — a fresh workspace starts\n * empty, but a misrouted call against a warm tree must not silently\n * overwrite ongoing work.\n */\n pull(tree: SyncTree, opts?: { force?: boolean }): Promise<PullResult>\n\n /**\n * Materialise the current `tree` state to the origin as a single\n * commit (plus a PR when the provider's `sync.push.prPolicy` calls\n * for one). A no-op when the tree matches the origin.\n */\n push(tree: SyncTree, opts?: PushOptions): Promise<PushResult>\n}\n\n/** Feature-detect the sync capability on a resolved filesystem. */\nexport function hasWorkspaceSync(fs: unknown): fs is WorkspaceSync {\n return (\n typeof fs === \"object\" &&\n fs !== null &&\n typeof (fs as WorkspaceSync).pull === \"function\" &&\n typeof (fs as WorkspaceSync).push === \"function\"\n )\n}\n","/**\n * @agentproto/storage — AIP-35 STORAGE.md `defineStorage` reference impl.\n *\n * A composable schema block defining the `storage` field — provider, config, sync semantics, auth ref, exclude rules — for any manifest that names a backing store. Reused by WORKSPACE.md (AIP-34) and any future manifest that names persistent state. Inline or ref, mirroring AIP-17 RUNNER and AIP-19 SECRETS.\n *\n * Spec: https://agentproto.sh/docs/aip-35\n *\n * Authoring paths:\n * - TS: `defineStorage({...})` → `StorageHandle`\n * - MD: `parseStorageManifest(src) → storageFromManifest({...})` → `StorageHandle`\n */\n\nexport const SPEC_NAME = \"agentstorage/v1\" as const\nexport const SPEC_VERSION = \"1.0.0-alpha\" as const\n\nexport { defineStorage } from \"./define-storage.js\"\nexport type {\n StorageDefinition,\n StorageHandle,\n StorageRuntimeInput,\n StorageRuntimeHandle,\n} from \"./types.js\"\n\nexport { hasWorkspaceSync } from \"./workspace-sync.js\"\nexport type {\n WorkspaceSync,\n SyncTree,\n PullResult,\n PushResult,\n PushOptions,\n} from \"./workspace-sync.js\"\n"]}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { c as StorageHandle } from '../types-DZAjXcqA.js';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* AIP-35 STORAGE.md frontmatter zod schema.
|
|
6
|
+
*
|
|
7
|
+
* Generated from `resources/aip-35/draft/STORAGE.schema.json` via
|
|
8
|
+
* json-schema-to-zod. Imported by both `define-storage.ts` (TS path
|
|
9
|
+
* validation) and `manifest/index.ts` (.md path validation) so every
|
|
10
|
+
* field-level constraint runs in both authoring paths from a single
|
|
11
|
+
* source of truth — re-run scaffold-aip to refresh after spec changes.
|
|
12
|
+
*
|
|
13
|
+
* Cross-field rules (if/then/allOf in JSON Schema) don't translate
|
|
14
|
+
* cleanly and live in `define-storage.ts`'s `validate(def)` instead.
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
declare const storageFrontmatterSchema: z.ZodObject<{
|
|
18
|
+
schema: z.ZodOptional<z.ZodLiteral<"storage/v1">>;
|
|
19
|
+
id: z.ZodOptional<z.ZodString>;
|
|
20
|
+
version: z.ZodOptional<z.ZodString>;
|
|
21
|
+
provider: z.ZodString;
|
|
22
|
+
config: z.ZodRecord<z.ZodString, z.ZodAny>;
|
|
23
|
+
sync: z.ZodOptional<z.ZodAny>;
|
|
24
|
+
auth: z.ZodOptional<z.ZodAny>;
|
|
25
|
+
identity: z.ZodOptional<z.ZodAny>;
|
|
26
|
+
exclude: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
27
|
+
read_only: z.ZodDefault<z.ZodBoolean>;
|
|
28
|
+
metadata: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodAny>>;
|
|
29
|
+
}, z.core.$strict>;
|
|
30
|
+
type StorageFrontmatter = z.infer<typeof storageFrontmatterSchema>;
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* AIP-35 STORAGE.md sidecar parser + manifest-to-handle constructor.
|
|
34
|
+
*
|
|
35
|
+
* Mirror of `@agentproto/tool/manifest` and `@agentproto/driver/manifest`:
|
|
36
|
+
* the .md provides metadata; the TS module supplies any spec-specific
|
|
37
|
+
* runtime bits (schemas, execute bodies, …) that can't live in
|
|
38
|
+
* frontmatter. Both inputs end up in `defineStorage` so the cross-AIP
|
|
39
|
+
* invariants run uniformly.
|
|
40
|
+
*
|
|
41
|
+
*
|
|
42
|
+
* The frontmatter zod schema below was generated from
|
|
43
|
+
* `resources/aip-35/draft/STORAGE.schema.json` via json-schema-to-zod.
|
|
44
|
+
* Re-run scaffold-aip to refresh after spec changes (or hand-tune
|
|
45
|
+
* any constraint the converter doesn't capture cleanly).
|
|
46
|
+
*/
|
|
47
|
+
|
|
48
|
+
interface StorageManifest {
|
|
49
|
+
frontmatter: StorageFrontmatter;
|
|
50
|
+
body: string;
|
|
51
|
+
}
|
|
52
|
+
declare function parseStorageManifest(source: string): StorageManifest;
|
|
53
|
+
declare function storageFromManifest(manifest: StorageManifest): StorageHandle;
|
|
54
|
+
|
|
55
|
+
export { type StorageFrontmatter, type StorageManifest, parseStorageManifest, storageFromManifest, storageFrontmatterSchema };
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { storageFrontmatterSchema, defineStorage } from '../chunk-JMBOQNBX.mjs';
|
|
2
|
+
export { storageFrontmatterSchema } from '../chunk-JMBOQNBX.mjs';
|
|
3
|
+
import matter from 'gray-matter';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* @agentproto/storage v0.1.0-alpha
|
|
7
|
+
* AIP-35 STORAGE.md `defineStorage` reference implementation.
|
|
8
|
+
*/
|
|
9
|
+
function parseStorageManifest(source) {
|
|
10
|
+
const parsed = matter(source);
|
|
11
|
+
if (Object.keys(parsed.data).length === 0) {
|
|
12
|
+
throw new Error("parseStorageManifest: missing or empty frontmatter");
|
|
13
|
+
}
|
|
14
|
+
const result = storageFrontmatterSchema.safeParse(parsed.data);
|
|
15
|
+
if (!result.success) {
|
|
16
|
+
throw new Error(
|
|
17
|
+
`parseStorageManifest: invalid frontmatter \u2014 ${result.error.issues.map((i) => `${i.path.join(".")}: ${i.message}`).join("; ")}`
|
|
18
|
+
);
|
|
19
|
+
}
|
|
20
|
+
return { frontmatter: result.data, body: parsed.content };
|
|
21
|
+
}
|
|
22
|
+
function storageFromManifest(manifest) {
|
|
23
|
+
return defineStorage(manifest.frontmatter);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export { parseStorageManifest, storageFromManifest };
|
|
27
|
+
//# sourceMappingURL=index.mjs.map
|
|
28
|
+
//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/manifest/index.ts"],"names":[],"mappings":";;;;;;;;AA8BO,SAAS,qBAAqB,MAAA,EAAiC;AACpE,EAAA,MAAM,MAAA,GAAS,OAAO,MAAM,CAAA;AAC5B,EAAA,IAAI,OAAO,IAAA,CAAK,MAAA,CAAO,IAAI,CAAA,CAAE,WAAW,CAAA,EAAG;AACzC,IAAA,MAAM,IAAI,MAAM,oDAAoD,CAAA;AAAA,EACtE;AACA,EAAA,MAAM,MAAA,GAAS,wBAAA,CAAyB,SAAA,CAAU,MAAA,CAAO,IAAI,CAAA;AAC7D,EAAA,IAAI,CAAC,OAAO,OAAA,EAAS;AACnB,IAAA,MAAM,IAAI,KAAA;AAAA,MACR,CAAA,iDAAA,EAA+C,OAAO,KAAA,CAAM,MAAA,CACzD,IAAI,CAAC,CAAA,KAAM,GAAG,CAAA,CAAE,IAAA,CAAK,KAAK,GAAG,CAAC,KAAK,CAAA,CAAE,OAAO,EAAE,CAAA,CAC9C,IAAA,CAAK,IAAI,CAAC,CAAA;AAAA,KACf;AAAA,EACF;AACA,EAAA,OAAO,EAAE,WAAA,EAAa,MAAA,CAAO,IAAA,EAAM,IAAA,EAAM,OAAO,OAAA,EAAQ;AAC1D;AAEO,SAAS,oBAAoB,QAAA,EAA0C;AAK5E,EAAA,OAAO,aAAA,CAAc,SAAS,WAA2C,CAAA;AAC3E","file":"index.mjs","sourcesContent":["/**\n * AIP-35 STORAGE.md sidecar parser + manifest-to-handle constructor.\n *\n * Mirror of `@agentproto/tool/manifest` and `@agentproto/driver/manifest`:\n * the .md provides metadata; the TS module supplies any spec-specific\n * runtime bits (schemas, execute bodies, …) that can't live in\n * frontmatter. Both inputs end up in `defineStorage` so the cross-AIP\n * invariants run uniformly.\n *\n *\n * The frontmatter zod schema below was generated from\n * `resources/aip-35/draft/STORAGE.schema.json` via json-schema-to-zod.\n * Re-run scaffold-aip to refresh after spec changes (or hand-tune\n * any constraint the converter doesn't capture cleanly).\n */\n\nimport matter from \"gray-matter\"\nimport { storageFrontmatterSchema, type StorageFrontmatter } from \"../schema.js\"\nimport { defineStorage } from \"../define-storage.js\"\nimport type { StorageDefinition, StorageHandle } from \"../types.js\"\n\n// Re-export so consumers can import the schema + inferred type either\n// from \"@@agentproto/storage/manifest\" or directly from \"@@agentproto/storage/schema\".\nexport { storageFrontmatterSchema, type StorageFrontmatter }\n\nexport interface StorageManifest {\n frontmatter: StorageFrontmatter\n body: string\n}\n\nexport function parseStorageManifest(source: string): StorageManifest {\n const parsed = matter(source)\n if (Object.keys(parsed.data).length === 0) {\n throw new Error(\"parseStorageManifest: missing or empty frontmatter\")\n }\n const result = storageFrontmatterSchema.safeParse(parsed.data)\n if (!result.success) {\n throw new Error(\n `parseStorageManifest: invalid frontmatter — ${result.error.issues\n .map((i) => `${i.path.join(\".\")}: ${i.message}`)\n .join(\"; \")}`,\n )\n }\n return { frontmatter: result.data, body: parsed.content }\n}\n\nexport function storageFromManifest(manifest: StorageManifest): StorageHandle {\n // The zod-validated frontmatter is structurally compatible with\n // StorageDefinition; the cast pins the typing once the manifest\n // schema and the TS interface diverge (e.g. handle has frozen fields\n // a literal config doesn't carry yet).\n return defineStorage(manifest.frontmatter as unknown as StorageDefinition)\n}\n"]}
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AIP-35 StorageDefinition + StorageHandle.
|
|
3
|
+
*
|
|
4
|
+
* `StorageDefinition` was generated from
|
|
5
|
+
* `resources/aip-35/draft/STORAGE.schema.json` via json-schema-to-typescript.
|
|
6
|
+
* `StorageHandle` is the readonly view of the same shape; tighten it
|
|
7
|
+
* by hand for fields that get defaults applied in build().
|
|
8
|
+
*/
|
|
9
|
+
type IdentityRefEntry = {
|
|
10
|
+
name: string;
|
|
11
|
+
email: string;
|
|
12
|
+
avatar?: string;
|
|
13
|
+
gpg_key?: string;
|
|
14
|
+
role?: string;
|
|
15
|
+
metadata?: {};
|
|
16
|
+
[k: string]: unknown;
|
|
17
|
+
} | {
|
|
18
|
+
ref: string;
|
|
19
|
+
role?: string;
|
|
20
|
+
[k: string]: unknown;
|
|
21
|
+
} | {
|
|
22
|
+
file: string;
|
|
23
|
+
role?: string;
|
|
24
|
+
[k: string]: unknown;
|
|
25
|
+
};
|
|
26
|
+
/**
|
|
27
|
+
* Validates the YAML frontmatter portion of an AIP-35 STORAGE.md manifest, OR the inline form embedded in any other manifest's `storage:` block. Filesystem-only — sandbox-shaped backends (e2b/modal/...) live in AIP-36 SANDBOX.md.
|
|
28
|
+
*/
|
|
29
|
+
interface StorageDefinition {
|
|
30
|
+
/**
|
|
31
|
+
* Standalone-only. Identifies the doctype + version. Absent when the block is inlined in another manifest.
|
|
32
|
+
*/
|
|
33
|
+
schema?: "storage/v1";
|
|
34
|
+
/**
|
|
35
|
+
* Standalone-only. Globally addressable id `@<owner-slug>/<storage-slug>`.
|
|
36
|
+
*/
|
|
37
|
+
id?: string;
|
|
38
|
+
/**
|
|
39
|
+
* Standalone-only. Spec version of THIS file. Bump on breaking shape change.
|
|
40
|
+
*/
|
|
41
|
+
version?: string;
|
|
42
|
+
/**
|
|
43
|
+
* Backend kind. Day-1 enumerated set: cloud-bucket | self-bucket | github | local-fs | dev-local | mastra-s3 | mastra-azure. Hosts MAY register additional ids; the schema accepts any non-empty string and host-side validation narrows.
|
|
44
|
+
*/
|
|
45
|
+
provider: string;
|
|
46
|
+
/**
|
|
47
|
+
* Provider-specific connection fields. Shape varies per provider (see AIP-35 §Provider config shapes).
|
|
48
|
+
*/
|
|
49
|
+
config: {};
|
|
50
|
+
sync?: SyncBlock;
|
|
51
|
+
auth?: AuthBlock;
|
|
52
|
+
/**
|
|
53
|
+
* AIP-23 identity-ref block — commit author(s) for syncing providers (github). Supports multi-attribution (primary + co-authors).
|
|
54
|
+
*/
|
|
55
|
+
identity?: IdentityRefEntry | [IdentityRefEntry, ...IdentityRefEntry[]];
|
|
56
|
+
/**
|
|
57
|
+
* Paths NOT mirrored to the backing store. Glob-ish, prefix-matched.
|
|
58
|
+
*/
|
|
59
|
+
exclude?: string[];
|
|
60
|
+
/**
|
|
61
|
+
* Reject writes at the storage layer.
|
|
62
|
+
*/
|
|
63
|
+
read_only?: boolean;
|
|
64
|
+
/**
|
|
65
|
+
* Free-form, namespaced. Authors MAY stash adapter-specific hints under namespaced keys.
|
|
66
|
+
*/
|
|
67
|
+
metadata?: {
|
|
68
|
+
[k: string]: unknown;
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Sync semantics. Lifecycle triggers reference AIP-37 event names.
|
|
73
|
+
*/
|
|
74
|
+
interface SyncBlock {
|
|
75
|
+
mode?: "canonical" | "pull-push" | "watch";
|
|
76
|
+
pull?: {
|
|
77
|
+
/**
|
|
78
|
+
* AIP-37 lifecycle event name. Standard: workspace-open | turn-start | manual. Aliases (per-turn, each-write) resolve via AIP-37.
|
|
79
|
+
*/
|
|
80
|
+
on?: string;
|
|
81
|
+
/**
|
|
82
|
+
* Cache validity for pull-push providers (e.g. github clone).
|
|
83
|
+
*/
|
|
84
|
+
ttl_seconds?: number;
|
|
85
|
+
};
|
|
86
|
+
commit?: {
|
|
87
|
+
/**
|
|
88
|
+
* AIP-37 event name. Common: each-write | per-turn | per-conversation | manual.
|
|
89
|
+
*/
|
|
90
|
+
on?: string;
|
|
91
|
+
/**
|
|
92
|
+
* Debounce window for each-write commit mode.
|
|
93
|
+
*/
|
|
94
|
+
batch_window_ms?: number;
|
|
95
|
+
/**
|
|
96
|
+
* Template for commit message. Provider-specific tokens (e.g. {{operator}}, {{summary}}).
|
|
97
|
+
*/
|
|
98
|
+
message_template?: string;
|
|
99
|
+
};
|
|
100
|
+
push?: {
|
|
101
|
+
/**
|
|
102
|
+
* AIP-37 event name. Common: per-commit | per-turn | per-conversation | manual.
|
|
103
|
+
*/
|
|
104
|
+
on?: string;
|
|
105
|
+
/**
|
|
106
|
+
* Github only. Where commits land.
|
|
107
|
+
*/
|
|
108
|
+
branch_policy?: "main" | "per-conversation" | "per-turn";
|
|
109
|
+
/**
|
|
110
|
+
* Github only. Whether to open PRs automatically.
|
|
111
|
+
*/
|
|
112
|
+
pr_policy?: "none" | "auto" | "manual";
|
|
113
|
+
};
|
|
114
|
+
conflict?: {
|
|
115
|
+
policy?: "rebase" | "merge" | "abort" | "manual" | "last-writer-wins" | "split-conflicts";
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Reference to AIP-19 SECRETS.md (or future ENV.md) for credentials.
|
|
120
|
+
*/
|
|
121
|
+
interface AuthBlock {
|
|
122
|
+
/**
|
|
123
|
+
* Path or registry slug pointing to a SECRETS.md (or future ENV.md) inventory.
|
|
124
|
+
*/
|
|
125
|
+
ref?: string;
|
|
126
|
+
state?: {
|
|
127
|
+
/**
|
|
128
|
+
* Env-var names this consumer expects to be revealed from the referenced inventory.
|
|
129
|
+
*/
|
|
130
|
+
env?: string[];
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
type StorageHandle = Readonly<StorageDefinition>;
|
|
134
|
+
/**
|
|
135
|
+
* In-TS authoring shape — what callers pass to `defineStorage(...)`
|
|
136
|
+
* when constructing a handle programmatically (vs. parsing one from
|
|
137
|
+
* STORAGE.md). Extends `StorageDefinition` with two optional
|
|
138
|
+
* host-runtime slots that don't exist in the manifest schema.
|
|
139
|
+
*/
|
|
140
|
+
interface StorageRuntimeInput<TFactory = unknown, TCapabilities extends Record<string, unknown> = Record<string, unknown>> extends StorageDefinition {
|
|
141
|
+
/**
|
|
142
|
+
* Host-typed factory function. Given config (and optionally a host-
|
|
143
|
+
* specific input bundle), returns a usable filesystem implementation
|
|
144
|
+
* in whatever shape the host expects (Mastra `MastraFilesystem`,
|
|
145
|
+
* MCP client, etc). The slot is opaque to agentproto; the host owns
|
|
146
|
+
* the type.
|
|
147
|
+
*/
|
|
148
|
+
factory?: TFactory;
|
|
149
|
+
/**
|
|
150
|
+
* Free-form metadata the registry indexes for cross-handle lookups.
|
|
151
|
+
* Suggested namespace conventions live in the AIP-43 § Capability
|
|
152
|
+
* metadata namespace section; the schema is otherwise unconstrained.
|
|
153
|
+
*/
|
|
154
|
+
capabilities?: TCapabilities;
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* What `defineStorage(...)` returns. Carries `factory` + `capabilities`
|
|
158
|
+
* through unchanged so registry consumers and host code can read them
|
|
159
|
+
* off the handle.
|
|
160
|
+
*/
|
|
161
|
+
type StorageRuntimeHandle<TFactory = unknown, TCapabilities extends Record<string, unknown> = Record<string, unknown>> = Readonly<StorageDefinition> & {
|
|
162
|
+
readonly factory?: TFactory;
|
|
163
|
+
readonly capabilities?: Readonly<TCapabilities>;
|
|
164
|
+
};
|
|
165
|
+
|
|
166
|
+
export type { StorageRuntimeInput as S, StorageRuntimeHandle as a, StorageDefinition as b, StorageHandle as c };
|
package/package.json
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@agentproto/storage",
|
|
3
|
+
"version": "0.1.0-alpha.0",
|
|
4
|
+
"description": "@agentproto/storage — AIP-35 STORAGE.md reference implementation. A composable schema block defining the `storage` field — provider, config, sync semantics, auth ref, exclude rules — for any manifest that names a backing store. Reused by WORKSPACE.md (AIP-34) and any future manifest that names persistent state. Inline or ref, mirroring AIP-17 RUNNER and AIP-19 SECRETS.",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"agentproto",
|
|
7
|
+
"aip-35",
|
|
8
|
+
"storage",
|
|
9
|
+
"defineStorage",
|
|
10
|
+
"open-standard",
|
|
11
|
+
"agentic"
|
|
12
|
+
],
|
|
13
|
+
"homepage": "https://agentproto.sh/docs/aip-35",
|
|
14
|
+
"repository": {
|
|
15
|
+
"type": "git",
|
|
16
|
+
"url": "https://github.com/agentproto/ts",
|
|
17
|
+
"directory": "packages/storage"
|
|
18
|
+
},
|
|
19
|
+
"bugs": {
|
|
20
|
+
"url": "https://github.com/agentproto/ts/issues"
|
|
21
|
+
},
|
|
22
|
+
"license": "MIT",
|
|
23
|
+
"type": "module",
|
|
24
|
+
"main": "dist/index.mjs",
|
|
25
|
+
"module": "dist/index.mjs",
|
|
26
|
+
"types": "dist/index.d.ts",
|
|
27
|
+
"exports": {
|
|
28
|
+
".": {
|
|
29
|
+
"types": "./dist/index.d.ts",
|
|
30
|
+
"import": "./dist/index.mjs",
|
|
31
|
+
"default": "./dist/index.mjs"
|
|
32
|
+
},
|
|
33
|
+
"./manifest": {
|
|
34
|
+
"types": "./dist/manifest/index.d.ts",
|
|
35
|
+
"import": "./dist/manifest/index.mjs",
|
|
36
|
+
"default": "./dist/manifest/index.mjs"
|
|
37
|
+
},
|
|
38
|
+
"./package.json": "./package.json"
|
|
39
|
+
},
|
|
40
|
+
"files": [
|
|
41
|
+
"dist",
|
|
42
|
+
"README.md",
|
|
43
|
+
"LICENSE"
|
|
44
|
+
],
|
|
45
|
+
"publishConfig": {
|
|
46
|
+
"access": "public"
|
|
47
|
+
},
|
|
48
|
+
"dependencies": {
|
|
49
|
+
"gray-matter": "^4.0.3",
|
|
50
|
+
"zod": "^4.4.3",
|
|
51
|
+
"@agentproto/define-doctype": "0.1.0"
|
|
52
|
+
},
|
|
53
|
+
"devDependencies": {
|
|
54
|
+
"@types/node": "^25.6.2",
|
|
55
|
+
"tsup": "^8.5.1",
|
|
56
|
+
"typescript": "^5.9.3",
|
|
57
|
+
"vitest": "^3.2.4",
|
|
58
|
+
"@agentproto/tooling": "0.1.0-alpha.0"
|
|
59
|
+
},
|
|
60
|
+
"scripts": {
|
|
61
|
+
"dev": "tsup --watch",
|
|
62
|
+
"build": "tsup",
|
|
63
|
+
"clean": "rm -rf dist",
|
|
64
|
+
"check-types": "tsc --noEmit",
|
|
65
|
+
"test": "vitest run --passWithNoTests",
|
|
66
|
+
"test:watch": "vitest"
|
|
67
|
+
}
|
|
68
|
+
}
|