@agentproto/app-kit 1.5.0 → 1.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/README.md +2 -2
- package/dist/define-app.d.ts.map +1 -1
- package/dist/emit.d.ts +2 -1
- package/dist/emit.d.ts.map +1 -1
- package/dist/index.d.ts +4 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.mjs +269 -37
- package/dist/index.mjs.map +1 -1
- package/dist/manifest-fields.d.ts +4 -1
- package/dist/manifest-fields.d.ts.map +1 -1
- package/dist/pack.d.ts +46 -8
- package/dist/pack.d.ts.map +1 -1
- package/dist/types.d.ts +42 -3
- package/dist/types.d.ts.map +1 -1
- package/dist/version-range.d.ts +36 -0
- package/dist/version-range.d.ts.map +1 -0
- package/package.json +4 -4
package/README.md
CHANGED
|
@@ -140,7 +140,7 @@ runtime app registry:
|
|
|
140
140
|
/apps/:appId/ui`, the MCP panel cache, and `agentproto app serve` all call
|
|
141
141
|
the same `ensureAppUiBuilt` (`@agentproto/runtime/app-ui-build`) before
|
|
142
142
|
serving, single-flight per bundle path so concurrent first requests only
|
|
143
|
-
build once. Output is captured to
|
|
143
|
+
build once. Output is captured to `~/.agentproto/logs/app-ui-build/<app>-<hash>.log`; a
|
|
144
144
|
failing build surfaces that log's tail as the tool/route error instead of
|
|
145
145
|
a bare 404. No `ui.build` declared ⇒ today's behavior: the bundle must
|
|
146
146
|
already exist on disk.
|
|
@@ -394,7 +394,7 @@ ui:
|
|
|
394
394
|
`agentproto app serve` all resolve this the same way (`peekAppUi` +
|
|
395
395
|
`ensureAppUiBuilt` from `@agentproto/runtime/app-ui-build`): missing or
|
|
396
396
|
older than the newest matching source → run `command` once (single-flight
|
|
397
|
-
per bundle path, output captured to
|
|
397
|
+
per bundle path, output captured to `~/.agentproto/logs/app-ui-build/`) → serve.
|
|
398
398
|
Omit `build` to keep committing the bundle, unchanged from before this
|
|
399
399
|
existed.
|
|
400
400
|
|
package/dist/define-app.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"define-app.d.ts","sourceRoot":"","sources":["../src/define-app.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAQH,OAAO,KAAK,EAEV,aAAa,EACb,SAAS,
|
|
1
|
+
{"version":3,"file":"define-app.d.ts","sourceRoot":"","sources":["../src/define-app.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAQH,OAAO,KAAK,EAEV,aAAa,EACb,SAAS,EAET,aAAa,EACb,oBAAoB,EAKrB,MAAM,YAAY,CAAA;AAKnB,qBAAa,kBAAmB,SAAQ,KAAK;gBAC/B,OAAO,EAAE,MAAM;CAI5B;AAED,wBAAgB,SAAS,CAAC,GAAG,EAAE,aAAa,GAAG,SAAS,CA+LvD;AA8JD;;;;;;GAMG;AACH,wBAAgB,0BAA0B,CACxC,GAAG,EAAE,OAAO,EACZ,KAAK,EAAE,SAAS,MAAM,EAAE,GAAG,SAAS,EACpC,IAAI,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,KAAK,GAC/B,oBAAoB,GAAG,SAAS,CAsBlC;AAmPD,YAAY,EAAE,aAAa,EAAE,CAAA"}
|
package/dist/emit.d.ts
CHANGED
|
@@ -32,7 +32,7 @@
|
|
|
32
32
|
*/
|
|
33
33
|
import type { WorkflowHandle } from "@agentproto/workflow";
|
|
34
34
|
import type { WorkspaceHandle } from "@agentproto/workspace";
|
|
35
|
-
import type { AgentEntry, AppAccepts, AppArtifactDecl, AppArtifactSurface, AppBoundariesDefinition, AppDataDefinition, AppDevDefinition, AppExposes, AppPlacement, AppRequirements, AppSkillSurface, AppUiDefinition, EmittedApp } from "./types.js";
|
|
35
|
+
import type { AgentEntry, AppAccepts, AppArtifactDecl, AppArtifactSurface, AppBoundariesDefinition, AppDataDefinition, AppDevDefinition, AppExposes, AppPlacement, AppRequirement, AppRequirements, AppSkillSurface, AppUiDefinition, EmittedApp } from "./types.js";
|
|
36
36
|
interface EmitInput {
|
|
37
37
|
readonly agents: readonly AgentEntry[];
|
|
38
38
|
readonly workflows: readonly WorkflowHandle[];
|
|
@@ -43,6 +43,7 @@ interface EmitInput {
|
|
|
43
43
|
readonly description?: string;
|
|
44
44
|
readonly requires?: readonly string[];
|
|
45
45
|
readonly requirements?: AppRequirements;
|
|
46
|
+
readonly appRequirements?: readonly AppRequirement[];
|
|
46
47
|
readonly placement?: AppPlacement;
|
|
47
48
|
readonly exposes?: AppExposes;
|
|
48
49
|
readonly accepts?: AppAccepts;
|
package/dist/emit.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"emit.d.ts","sourceRoot":"","sources":["../src/emit.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AAKH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAA;AAC1D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAA;AAC5D,OAAO,KAAK,EAAE,UAAU,EAAE,UAAU,EAAE,eAAe,EAAE,kBAAkB,EAAE,uBAAuB,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,UAAU,EAAE,YAAY,EAAE,eAAe,EAAE,eAAe,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA;
|
|
1
|
+
{"version":3,"file":"emit.d.ts","sourceRoot":"","sources":["../src/emit.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AAKH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAA;AAC1D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAA;AAC5D,OAAO,KAAK,EAAE,UAAU,EAAE,UAAU,EAAE,eAAe,EAAE,kBAAkB,EAAE,uBAAuB,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,UAAU,EAAE,YAAY,EAAE,cAAc,EAAE,eAAe,EAAE,eAAe,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA;AAGpQ,UAAU,SAAS;IACjB,QAAQ,CAAC,MAAM,EAAE,SAAS,UAAU,EAAE,CAAA;IACtC,QAAQ,CAAC,SAAS,EAAE,SAAS,cAAc,EAAE,CAAA;IAC7C,QAAQ,CAAC,SAAS,CAAC,EAAE,eAAe,CAAA;IACpC,QAAQ,CAAC,EAAE,CAAC,EAAE,MAAM,CAAA;IACpB,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAA;IACtB,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAA;IACzB,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAA;IAC7B,QAAQ,CAAC,QAAQ,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;IACrC,QAAQ,CAAC,YAAY,CAAC,EAAE,eAAe,CAAA;IACvC,QAAQ,CAAC,eAAe,CAAC,EAAE,SAAS,cAAc,EAAE,CAAA;IACpD,QAAQ,CAAC,SAAS,CAAC,EAAE,YAAY,CAAA;IACjC,QAAQ,CAAC,OAAO,CAAC,EAAE,UAAU,CAAA;IAC7B,QAAQ,CAAC,OAAO,CAAC,EAAE,UAAU,CAAA;IAC7B,QAAQ,CAAC,EAAE,CAAC,EAAE,eAAe,CAAA;IAC7B,QAAQ,CAAC,QAAQ,CAAC,EAAE,kBAAkB,CAAA;IACtC,QAAQ,CAAC,KAAK,CAAC,EAAE,eAAe,CAAA;IAChC,QAAQ,CAAC,SAAS,CAAC,EAAE,SAAS,eAAe,EAAE,CAAA;IAC/C,QAAQ,CAAC,GAAG,CAAC,EAAE,gBAAgB,CAAA;IAC/B,QAAQ,CAAC,IAAI,CAAC,EAAE,iBAAiB,CAAA;IACjC,QAAQ,CAAC,iBAAiB,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;IAC9C,QAAQ,CAAC,UAAU,CAAC,EAAE,uBAAuB,CAAA;IAC7C,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAC3B;AAED,wBAAsB,OAAO,CAAC,GAAG,EAAE,SAAS,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CAwH9E"}
|
package/dist/index.d.ts
CHANGED
|
@@ -41,8 +41,9 @@ export { emitApp } from "./emit.js";
|
|
|
41
41
|
export { loadAppHandle, AppLoadError, resolveAppUIRoot, peekAppUi } from "./load-app.js";
|
|
42
42
|
export type { AppUiPeek } from "./load-app.js";
|
|
43
43
|
export { loadAppBundledTools } from "./load-app-tools.js";
|
|
44
|
-
export { packApp, unpackApp, aggregateSha256, collectFiles, isManifest, safeId, AGENTAPP_FORMAT, AgentAppPackError, } from "./pack.js";
|
|
45
|
-
export type { AgentAppManifest, BundleFile, AgentAppPackErrorCode } from "./pack.js";
|
|
44
|
+
export { packApp, unpackApp, aggregateSha256, collectFiles, isManifest, safeId, AGENTAPP_FORMAT, AgentAppPackError, RELEASE_DEFAULT_EXCLUDE, globToRegExp, readPackageRules, } from "./pack.js";
|
|
45
|
+
export type { AgentAppManifest, BundleFile, AgentAppPackErrorCode, AppPackageRules } from "./pack.js";
|
|
46
46
|
export { refKey, stripOwner } from "./refs.js";
|
|
47
|
-
export
|
|
47
|
+
export { versionSatisfies } from "./version-range.js";
|
|
48
|
+
export type { AppDefinition, AppHandle, AgentEntry, DoctypeHandle, WorkspaceShorthand, WorkspaceInput, AppUiDefinition, AppUiBuildConfig, OpenAIAppUiExtension, OpenAIEntrypoint, OpenAIIcon, AppArtifactSurface, AppSkillSurface, AppArtifactDecl, AppDevLaunchConfig, AppBoundariesDefinition, AppDataDefinition, AppDevDefinition, AppPlacement, AppRequirements, AppRequirement, AppRequirementEntry, AppExposes, AppAccepts, ToMastraAgentOptions, EmittedApp, } from "./types.js";
|
|
48
49
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCG;AAEH,OAAO,EAAE,SAAS,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAA;AAC/D,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AACnC,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,gBAAgB,EAAE,SAAS,EAAE,MAAM,eAAe,CAAA;AACxF,YAAY,EAAE,SAAS,EAAE,MAAM,eAAe,CAAA;AAC9C,OAAO,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAA;AACzD,OAAO,EACL,OAAO,EACP,SAAS,EACT,eAAe,EACf,YAAY,EACZ,UAAU,EACV,MAAM,EACN,eAAe,EACf,iBAAiB,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCG;AAEH,OAAO,EAAE,SAAS,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAA;AAC/D,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AACnC,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,gBAAgB,EAAE,SAAS,EAAE,MAAM,eAAe,CAAA;AACxF,YAAY,EAAE,SAAS,EAAE,MAAM,eAAe,CAAA;AAC9C,OAAO,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAA;AACzD,OAAO,EACL,OAAO,EACP,SAAS,EACT,eAAe,EACf,YAAY,EACZ,UAAU,EACV,MAAM,EACN,eAAe,EACf,iBAAiB,EACjB,uBAAuB,EACvB,YAAY,EACZ,gBAAgB,GACjB,MAAM,WAAW,CAAA;AAClB,YAAY,EAAE,gBAAgB,EAAE,UAAU,EAAE,qBAAqB,EAAE,eAAe,EAAE,MAAM,WAAW,CAAA;AACrG,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,WAAW,CAAA;AAC9C,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAA;AACrD,YAAY,EACV,aAAa,EACb,SAAS,EACT,UAAU,EACV,aAAa,EACb,kBAAkB,EAClB,cAAc,EACd,eAAe,EACf,gBAAgB,EAChB,oBAAoB,EACpB,gBAAgB,EAChB,UAAU,EACV,kBAAkB,EAClB,eAAe,EACf,eAAe,EACf,kBAAkB,EAClB,uBAAuB,EACvB,iBAAiB,EACjB,gBAAgB,EAChB,YAAY,EACZ,eAAe,EACf,cAAc,EACd,mBAAmB,EACnB,UAAU,EACV,UAAU,EACV,oBAAoB,EACpB,UAAU,GACX,MAAM,YAAY,CAAA"}
|
package/dist/index.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { join, relative, isAbsolute, dirname, resolve, basename } from 'path';
|
|
1
|
+
import { join, relative, isAbsolute, dirname, resolve, posix, basename } from 'path';
|
|
2
2
|
import { defineWorkspace } from '@agentproto/workspace';
|
|
3
|
-
import { mkdir, writeFile, copyFile, cp, readFile, mkdtemp, readdir, rm
|
|
3
|
+
import { mkdir, writeFile, copyFile, cp, readFile, mkdtemp, stat, readdir, rm } from 'fs/promises';
|
|
4
4
|
import matter2 from 'gray-matter';
|
|
5
5
|
import { parseAgentManifest, agentFromManifest } from '@agentproto/agent/manifest';
|
|
6
6
|
import { loadWorkflowHandle } from '@agentproto/workflow-loader';
|
|
@@ -143,13 +143,28 @@ async function emitApp(app, dir) {
|
|
|
143
143
|
}
|
|
144
144
|
function requiresFrontmatter(app) {
|
|
145
145
|
const r = app.requirements;
|
|
146
|
+
const apps = appsFrontmatter(app);
|
|
147
|
+
const hasAppDetail = (app.appRequirements ?? []).some(
|
|
148
|
+
(e) => e.version !== void 0 || e.workflows !== void 0 && e.workflows.length > 0
|
|
149
|
+
);
|
|
146
150
|
if (r && (r.browser || r.fs || r.gpu || r.secrets.length > 0)) {
|
|
147
151
|
return {
|
|
148
|
-
requires: { browser: r.browser, fs: r.fs, gpu: r.gpu, secrets: r.secrets, apps
|
|
152
|
+
requires: { browser: r.browser, fs: r.fs, gpu: r.gpu, secrets: r.secrets, apps }
|
|
149
153
|
};
|
|
150
154
|
}
|
|
155
|
+
if (hasAppDetail) {
|
|
156
|
+
return { requires: { apps } };
|
|
157
|
+
}
|
|
151
158
|
return app.requires !== void 0 ? { requires: app.requires } : {};
|
|
152
159
|
}
|
|
160
|
+
function appsFrontmatter(app) {
|
|
161
|
+
const entries = app.appRequirements ?? app.requires ?? [];
|
|
162
|
+
return entries.map((e) => {
|
|
163
|
+
if (typeof e === "string") return e;
|
|
164
|
+
if (e.version === void 0 && (e.workflows === void 0 || e.workflows.length === 0)) return e.id;
|
|
165
|
+
return e;
|
|
166
|
+
});
|
|
167
|
+
}
|
|
153
168
|
function toManifest(handle, body) {
|
|
154
169
|
const data = JSON.parse(JSON.stringify(handle));
|
|
155
170
|
return matter2.stringify(`
|
|
@@ -157,6 +172,52 @@ ${body}
|
|
|
157
172
|
`, data);
|
|
158
173
|
}
|
|
159
174
|
|
|
175
|
+
// src/version-range.ts
|
|
176
|
+
var VERSION_RE = /^(\d+)\.(\d+)\.(\d+)(?:[-+][\w.\-]+)?$/;
|
|
177
|
+
function parseVersion(v) {
|
|
178
|
+
const m = VERSION_RE.exec(v);
|
|
179
|
+
if (!m) {
|
|
180
|
+
throw new Error(`invalid version "${v}" \u2014 expected major.minor.patch (e.g. "1.2.3").`);
|
|
181
|
+
}
|
|
182
|
+
return [Number(m[1]), Number(m[2]), Number(m[3])];
|
|
183
|
+
}
|
|
184
|
+
function compare(a, b) {
|
|
185
|
+
return a[0] - b[0] || a[1] - b[1] || a[2] - b[2];
|
|
186
|
+
}
|
|
187
|
+
function parseVersionRange(range) {
|
|
188
|
+
let m = /^\^(\d+)(?:\.(\d+))?(?:\.(\d+))?$/.exec(range);
|
|
189
|
+
if (m !== null) {
|
|
190
|
+
return {
|
|
191
|
+
kind: "caret",
|
|
192
|
+
version: [Number(m[1]), m[2] !== void 0 ? Number(m[2]) : 0, m[3] !== void 0 ? Number(m[3]) : 0]
|
|
193
|
+
};
|
|
194
|
+
}
|
|
195
|
+
m = /^~(\d+)(?:\.(\d+))?(?:\.(\d+))?$/.exec(range);
|
|
196
|
+
if (m !== null) {
|
|
197
|
+
return {
|
|
198
|
+
kind: "tilde",
|
|
199
|
+
version: [Number(m[1]), m[2] !== void 0 ? Number(m[2]) : 0, m[3] !== void 0 ? Number(m[3]) : 0],
|
|
200
|
+
minorGiven: m[2] !== void 0
|
|
201
|
+
};
|
|
202
|
+
}
|
|
203
|
+
if (VERSION_RE.test(range)) return { kind: "exact", version: parseVersion(range) };
|
|
204
|
+
throw new Error(
|
|
205
|
+
`invalid version range "${range}" \u2014 expected an exact version ("1.2.3"), a caret ("^1", "^1.2", "^1.2.3"), or a tilde ("~1", "~1.2", "~1.2.3").`
|
|
206
|
+
);
|
|
207
|
+
}
|
|
208
|
+
function versionSatisfies(version, range) {
|
|
209
|
+
const v = parseVersion(version);
|
|
210
|
+
const r = parseVersionRange(range);
|
|
211
|
+
if (r.kind === "exact") return compare(v, r.version) === 0;
|
|
212
|
+
if (compare(v, r.version) < 0) return false;
|
|
213
|
+
if (r.kind === "caret") {
|
|
214
|
+
if (r.version[0] > 0) return v[0] === r.version[0];
|
|
215
|
+
if (r.version[1] > 0) return v[0] === 0 && v[1] === r.version[1];
|
|
216
|
+
return v[0] === 0 && v[1] === 0 && v[2] === r.version[2];
|
|
217
|
+
}
|
|
218
|
+
return v[0] === r.version[0] && (!r.minorGiven || v[1] === r.version[1]);
|
|
219
|
+
}
|
|
220
|
+
|
|
160
221
|
// src/manifest-fields.ts
|
|
161
222
|
var APP_PLACEMENTS = ["local", "box", "any", "split"];
|
|
162
223
|
function isRecord(v) {
|
|
@@ -174,6 +235,52 @@ function bool(v, key, fail) {
|
|
|
174
235
|
if (typeof v !== "boolean") throw fail(`'${key}' must be a boolean.`);
|
|
175
236
|
return v;
|
|
176
237
|
}
|
|
238
|
+
function appRequirementEntry(entry, key, fail) {
|
|
239
|
+
if (typeof entry === "string") {
|
|
240
|
+
if (entry.trim() === "") throw fail(`'${key}' entries must be non-empty strings or objects.`);
|
|
241
|
+
return { id: entry };
|
|
242
|
+
}
|
|
243
|
+
if (!isRecord(entry)) {
|
|
244
|
+
throw fail(`'${key}' entries must be non-empty strings or objects, got ${JSON.stringify(entry)}.`);
|
|
245
|
+
}
|
|
246
|
+
const id = entry.id;
|
|
247
|
+
if (typeof id !== "string" || id.trim() === "") {
|
|
248
|
+
throw fail(`'${key}.id' must be a non-empty string.`);
|
|
249
|
+
}
|
|
250
|
+
const version = entry.version;
|
|
251
|
+
if (version !== void 0) {
|
|
252
|
+
if (typeof version !== "string" || version.trim() === "") {
|
|
253
|
+
throw fail(`'${key}.version' must be a non-empty string.`);
|
|
254
|
+
}
|
|
255
|
+
try {
|
|
256
|
+
parseVersionRange(version);
|
|
257
|
+
} catch (err) {
|
|
258
|
+
throw fail(`'${key}.version' ${err instanceof Error ? err.message : String(err)}`);
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
const workflows = entry.workflows;
|
|
262
|
+
if (workflows !== void 0) {
|
|
263
|
+
if (!Array.isArray(workflows) || !workflows.every((w) => typeof w === "string" && w.trim() !== "")) {
|
|
264
|
+
throw fail(`'${key}.workflows' must be an array of non-empty strings.`);
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
const extra = Object.keys(entry).filter((k) => k !== "id" && k !== "version" && k !== "workflows");
|
|
268
|
+
if (extra.length > 0) {
|
|
269
|
+
throw fail(`'${key}.${extra[0]}' is not a supported requires.apps entry field (expected id, version, workflows).`);
|
|
270
|
+
}
|
|
271
|
+
return {
|
|
272
|
+
id,
|
|
273
|
+
...version !== void 0 ? { version } : {},
|
|
274
|
+
...workflows !== void 0 ? { workflows: [...workflows] } : {}
|
|
275
|
+
};
|
|
276
|
+
}
|
|
277
|
+
function appRequirementList(v, key, fail) {
|
|
278
|
+
if (v === void 0) return [];
|
|
279
|
+
if (!Array.isArray(v)) {
|
|
280
|
+
throw fail(`'${key}' must be an array of non-empty strings or { id, version?, workflows? } objects.`);
|
|
281
|
+
}
|
|
282
|
+
return v.map((e, i) => appRequirementEntry(e, `${key}[${i}]`, fail));
|
|
283
|
+
}
|
|
177
284
|
function normalizeManifestFields(input, declared, fail) {
|
|
178
285
|
let placement = "any";
|
|
179
286
|
if (input.placement !== void 0) {
|
|
@@ -186,6 +293,7 @@ function normalizeManifestFields(input, declared, fail) {
|
|
|
186
293
|
}
|
|
187
294
|
let requires;
|
|
188
295
|
let requirements = { browser: false, fs: false, gpu: false, secrets: [], apps: [] };
|
|
296
|
+
let appRequirements = [];
|
|
189
297
|
const r = input.requires;
|
|
190
298
|
if (r !== void 0) {
|
|
191
299
|
if (Array.isArray(r)) {
|
|
@@ -194,16 +302,18 @@ function normalizeManifestFields(input, declared, fail) {
|
|
|
194
302
|
}
|
|
195
303
|
requires = [...r];
|
|
196
304
|
requirements = { ...requirements, apps: requires };
|
|
305
|
+
appRequirements = appRequirementList(r, "requires", fail);
|
|
197
306
|
} else if (isRecord(r)) {
|
|
198
|
-
const apps =
|
|
307
|
+
const apps = appRequirementList(r.apps, "requires.apps", fail);
|
|
199
308
|
requirements = {
|
|
200
309
|
browser: bool(r.browser, "requires.browser", fail),
|
|
201
310
|
fs: bool(r.fs, "requires.fs", fail),
|
|
202
311
|
gpu: bool(r.gpu, "requires.gpu", fail),
|
|
203
312
|
secrets: stringList(r.secrets, "requires.secrets", fail),
|
|
204
|
-
apps
|
|
313
|
+
apps: apps.map((e) => e.id)
|
|
205
314
|
};
|
|
206
|
-
|
|
315
|
+
appRequirements = apps;
|
|
316
|
+
if (apps.length > 0) requires = apps.map((e) => e.id);
|
|
207
317
|
} else {
|
|
208
318
|
throw fail("'requires' must be an array of strings or an object { browser, fs, gpu, secrets, apps }.");
|
|
209
319
|
}
|
|
@@ -234,7 +344,7 @@ function normalizeManifestFields(input, declared, fail) {
|
|
|
234
344
|
if (!isRecord(input.accepts)) throw fail("'accepts' must be an object { tasks }.");
|
|
235
345
|
accepts = { tasks: bool(input.accepts.tasks, "accepts.tasks", fail) };
|
|
236
346
|
}
|
|
237
|
-
return { placement, requires, requirements, exposes, accepts };
|
|
347
|
+
return { placement, requires, requirements, appRequirements, exposes, accepts };
|
|
238
348
|
}
|
|
239
349
|
|
|
240
350
|
// src/define-app.ts
|
|
@@ -302,6 +412,9 @@ function defineApp(def) {
|
|
|
302
412
|
secrets: Object.freeze([...fields.requirements.secrets]),
|
|
303
413
|
apps: Object.freeze([...fields.requirements.apps])
|
|
304
414
|
});
|
|
415
|
+
const appRequirements = Object.freeze(
|
|
416
|
+
fields.appRequirements.map((e) => Object.freeze({ ...e, ...e.workflows !== void 0 ? { workflows: Object.freeze([...e.workflows]) } : {} }))
|
|
417
|
+
);
|
|
305
418
|
const placement = fields.placement;
|
|
306
419
|
const exposes = Object.freeze({
|
|
307
420
|
agents: Object.freeze([...fields.exposes.agents]),
|
|
@@ -350,6 +463,7 @@ function defineApp(def) {
|
|
|
350
463
|
...description !== void 0 ? { description } : {},
|
|
351
464
|
...requires !== void 0 ? { requires } : {},
|
|
352
465
|
requirements,
|
|
466
|
+
appRequirements,
|
|
353
467
|
placement,
|
|
354
468
|
exposes,
|
|
355
469
|
accepts,
|
|
@@ -393,6 +507,7 @@ function defineApp(def) {
|
|
|
393
507
|
...description !== void 0 ? { description } : {},
|
|
394
508
|
...requires !== void 0 ? { requires } : {},
|
|
395
509
|
requirements,
|
|
510
|
+
appRequirements,
|
|
396
511
|
placement,
|
|
397
512
|
exposes,
|
|
398
513
|
accepts,
|
|
@@ -1227,8 +1342,92 @@ function extractMeta(front) {
|
|
|
1227
1342
|
...ui !== void 0 ? { ui } : {}
|
|
1228
1343
|
};
|
|
1229
1344
|
}
|
|
1345
|
+
var RELEASE_DEFAULT_EXCLUDE = [
|
|
1346
|
+
"ui/**",
|
|
1347
|
+
"docs/**",
|
|
1348
|
+
"data/**",
|
|
1349
|
+
"scripts/**",
|
|
1350
|
+
// Root-level only: `**/dev/**` would also drop a shipped agent named
|
|
1351
|
+
// `dev` (`.agentproto/agents/dev/`); `ui/dev/` is covered by `ui/**`.
|
|
1352
|
+
"dev/**",
|
|
1353
|
+
"**/*.log",
|
|
1354
|
+
"**/*.map",
|
|
1355
|
+
"**/.DS_Store",
|
|
1356
|
+
"**/.env",
|
|
1357
|
+
"**/.env.*"
|
|
1358
|
+
];
|
|
1359
|
+
function globToRegExp(glob) {
|
|
1360
|
+
const g = glob.replace(/^\.\//, "");
|
|
1361
|
+
let re = "";
|
|
1362
|
+
for (let i = 0; i < g.length; i++) {
|
|
1363
|
+
const c = g[i];
|
|
1364
|
+
if (c === "*") {
|
|
1365
|
+
if (g[i + 1] === "*") {
|
|
1366
|
+
i++;
|
|
1367
|
+
if (g[i + 1] === "/") {
|
|
1368
|
+
i++;
|
|
1369
|
+
re += "(?:.*/)?";
|
|
1370
|
+
} else {
|
|
1371
|
+
re += ".*";
|
|
1372
|
+
}
|
|
1373
|
+
} else {
|
|
1374
|
+
re += "[^/]*";
|
|
1375
|
+
}
|
|
1376
|
+
} else if ("\\^$+?.()|{}[]".includes(c)) {
|
|
1377
|
+
re += "\\" + c;
|
|
1378
|
+
} else {
|
|
1379
|
+
re += c;
|
|
1380
|
+
}
|
|
1381
|
+
}
|
|
1382
|
+
return new RegExp(`^${re}$`);
|
|
1383
|
+
}
|
|
1384
|
+
function toPosix(p) {
|
|
1385
|
+
return p.replace(/\\/g, "/");
|
|
1386
|
+
}
|
|
1387
|
+
function matchesAny(path, globs) {
|
|
1388
|
+
const p = toPosix(path);
|
|
1389
|
+
return globs.some((re) => re.test(p));
|
|
1390
|
+
}
|
|
1391
|
+
function readPackageRules(front) {
|
|
1392
|
+
const raw = front.package;
|
|
1393
|
+
if (raw === void 0 || raw === null) return {};
|
|
1394
|
+
if (typeof raw !== "object" || Array.isArray(raw)) {
|
|
1395
|
+
throw new AgentAppPackError("invalid-package", "APP.md `package` must be an object.");
|
|
1396
|
+
}
|
|
1397
|
+
const r = raw;
|
|
1398
|
+
const list = (key) => {
|
|
1399
|
+
const v = r[key];
|
|
1400
|
+
if (v === void 0) return void 0;
|
|
1401
|
+
if (!Array.isArray(v) || v.some((s) => typeof s !== "string" || s.trim() === "")) {
|
|
1402
|
+
throw new AgentAppPackError(
|
|
1403
|
+
"invalid-package",
|
|
1404
|
+
`APP.md \`package.${key}\` must be an array of non-empty glob strings.`
|
|
1405
|
+
);
|
|
1406
|
+
}
|
|
1407
|
+
return v;
|
|
1408
|
+
};
|
|
1409
|
+
if (r.stripBuild !== void 0 && typeof r.stripBuild !== "boolean") {
|
|
1410
|
+
throw new AgentAppPackError("invalid-package", "APP.md `package.stripBuild` must be a boolean.");
|
|
1411
|
+
}
|
|
1412
|
+
const include = list("include");
|
|
1413
|
+
const exclude = list("exclude");
|
|
1414
|
+
return {
|
|
1415
|
+
...include !== void 0 ? { include } : {},
|
|
1416
|
+
...exclude !== void 0 ? { exclude } : {},
|
|
1417
|
+
...typeof r.stripBuild === "boolean" ? { stripBuild: r.stripBuild } : {}
|
|
1418
|
+
};
|
|
1419
|
+
}
|
|
1420
|
+
function uiRelPath(front) {
|
|
1421
|
+
const ui = front.ui;
|
|
1422
|
+
const raw = typeof ui === "string" ? ui : ui && typeof ui === "object" && !Array.isArray(ui) && typeof ui.path === "string" ? ui.path : void 0;
|
|
1423
|
+
if (raw === void 0 || raw === "" || isAbsolute(raw)) return void 0;
|
|
1424
|
+
const rel = posix.normalize(toPosix(raw)).replace(/^\.\//, "");
|
|
1425
|
+
if (rel.startsWith("../") || rel === "..") return void 0;
|
|
1426
|
+
return rel;
|
|
1427
|
+
}
|
|
1230
1428
|
async function packApp(input) {
|
|
1231
1429
|
const appDirAbs = resolve(input.appDir);
|
|
1430
|
+
const release = input.release === true;
|
|
1232
1431
|
const appMdPath = join(appDirAbs, ".agentproto", "APP.md");
|
|
1233
1432
|
if (!await pathExists(appMdPath)) {
|
|
1234
1433
|
throw new AgentAppPackError(
|
|
@@ -1237,49 +1436,82 @@ async function packApp(input) {
|
|
|
1237
1436
|
);
|
|
1238
1437
|
}
|
|
1239
1438
|
const raw = await readFile(appMdPath, "utf8");
|
|
1240
|
-
const
|
|
1439
|
+
const parsedAppMd = matter2(raw);
|
|
1440
|
+
const front = parsedAppMd.data;
|
|
1241
1441
|
const meta = extractMeta(front);
|
|
1442
|
+
const rules = readPackageRules(front);
|
|
1242
1443
|
const outAbs = input.out !== void 0 ? resolve(input.out) : resolve(process.cwd(), `${safeId(meta.id)}-${meta.version}.agentapp`);
|
|
1243
1444
|
await mkdir(dirname(outAbs), { recursive: true });
|
|
1244
|
-
const
|
|
1245
|
-
const
|
|
1246
|
-
const
|
|
1247
|
-
const
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
)
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
sha256,
|
|
1264
|
-
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1265
|
-
agentprotoVersion: ">=0.1.0"
|
|
1266
|
-
};
|
|
1445
|
+
const appMdRel = ".agentproto/APP.md";
|
|
1446
|
+
const uiRel = uiRelPath(front);
|
|
1447
|
+
const uiAssetsPrefix = uiRel !== void 0 ? `${posix.dirname(uiRel)}/assets/`.replace(/^\.\//, "") : void 0;
|
|
1448
|
+
const includeRes = rules.include?.map(globToRegExp);
|
|
1449
|
+
const excludeRes = [...release ? RELEASE_DEFAULT_EXCLUDE : [], ...rules.exclude ?? []].map(globToRegExp);
|
|
1450
|
+
const alwaysShip = (p) => p === appMdRel || p === uiRel || uiAssetsPrefix !== void 0 && p.startsWith(uiAssetsPrefix);
|
|
1451
|
+
const selected = (await collectFiles(appDirAbs)).filter((f) => f.path !== "manifest.json").filter((f) => join(appDirAbs, f.path) !== outAbs).filter((f) => {
|
|
1452
|
+
const p = toPosix(f.path);
|
|
1453
|
+
if (alwaysShip(p)) return true;
|
|
1454
|
+
if (includeRes !== void 0 && !matchesAny(p, includeRes)) return false;
|
|
1455
|
+
return !matchesAny(p, excludeRes);
|
|
1456
|
+
}).sort((a, b) => a.path < b.path ? -1 : a.path > b.path ? 1 : 0);
|
|
1457
|
+
if (release && uiRel !== void 0 && !selected.some((f) => toPosix(f.path) === uiRel)) {
|
|
1458
|
+
throw new AgentAppPackError(
|
|
1459
|
+
"missing-ui",
|
|
1460
|
+
`ui.path "${uiRel}" does not exist in ${appDirAbs} \u2014 build the UI first (\`agentproto app build <appDir>\`, or \`agentproto app pack --release\`, which runs \`ui.build\`).`
|
|
1461
|
+
);
|
|
1462
|
+
}
|
|
1463
|
+
const stripBuild = rules.stripBuild ?? release;
|
|
1267
1464
|
const staging = await mkdtemp(join(tmpdir(), "agentapp-"));
|
|
1268
1465
|
try {
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1466
|
+
for (const f of selected) {
|
|
1467
|
+
const dest = join(staging, f.path);
|
|
1468
|
+
await mkdir(dirname(dest), { recursive: true });
|
|
1469
|
+
await copyFile(join(appDirAbs, f.path), dest);
|
|
1470
|
+
}
|
|
1471
|
+
if (stripBuild) {
|
|
1472
|
+
const ui = front.ui;
|
|
1473
|
+
if (ui && typeof ui === "object" && !Array.isArray(ui) && "build" in ui) {
|
|
1474
|
+
const data = structuredClone(front);
|
|
1475
|
+
delete data.ui.build;
|
|
1476
|
+
await writeFile(join(staging, appMdRel), matter2.stringify(parsedAppMd.content, data), "utf8");
|
|
1477
|
+
}
|
|
1478
|
+
}
|
|
1479
|
+
const files = [];
|
|
1480
|
+
for (const f of selected) {
|
|
1481
|
+
files.push({ path: f.path, size: (await stat(join(staging, f.path))).size });
|
|
1482
|
+
}
|
|
1483
|
+
const fileCount = files.length;
|
|
1484
|
+
const totalSize = files.reduce((sum, f) => sum + f.size, 0);
|
|
1485
|
+
const sha256 = await aggregateSha256(
|
|
1486
|
+
staging,
|
|
1487
|
+
files.map((f) => f.path)
|
|
1488
|
+
);
|
|
1489
|
+
const manifest = {
|
|
1490
|
+
format: AGENTAPP_FORMAT,
|
|
1491
|
+
id: meta.id,
|
|
1492
|
+
...meta.name !== void 0 ? { name: meta.name } : {},
|
|
1493
|
+
version: meta.version,
|
|
1494
|
+
...meta.description !== void 0 ? { description: meta.description } : {},
|
|
1495
|
+
agents: meta.agents,
|
|
1496
|
+
workflows: meta.workflows,
|
|
1497
|
+
...meta.ui !== void 0 ? { ui: meta.ui } : {},
|
|
1498
|
+
files: files.map((f) => f.path),
|
|
1499
|
+
fileCount,
|
|
1500
|
+
totalSize,
|
|
1501
|
+
sha256,
|
|
1502
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1503
|
+
agentprotoVersion: ">=0.1.0"
|
|
1504
|
+
};
|
|
1273
1505
|
await writeFile(join(staging, "manifest.json"), JSON.stringify(manifest, null, 2) + "\n", "utf8");
|
|
1274
1506
|
const entries = (await readdir(staging)).sort();
|
|
1275
1507
|
const packCode = await runTar(["-czf", outAbs, ...entries], { cwd: staging });
|
|
1276
1508
|
if (packCode !== 0) {
|
|
1277
1509
|
throw new AgentAppPackError("tar-failed", `tar failed with exit code ${packCode}`);
|
|
1278
1510
|
}
|
|
1511
|
+
return { file: outAbs, manifest };
|
|
1279
1512
|
} finally {
|
|
1280
1513
|
await rm(staging, { recursive: true, force: true });
|
|
1281
1514
|
}
|
|
1282
|
-
return { file: outAbs, manifest };
|
|
1283
1515
|
}
|
|
1284
1516
|
function isUnsafeBundlePath(p) {
|
|
1285
1517
|
if (p === "" || isAbsolute(p)) return true;
|
|
@@ -1343,6 +1575,6 @@ async function unpackApp(input) {
|
|
|
1343
1575
|
}
|
|
1344
1576
|
}
|
|
1345
1577
|
|
|
1346
|
-
export { AGENTAPP_FORMAT, AgentAppPackError, AppDefinitionError, AppLoadError, aggregateSha256, collectFiles, defineApp, emitApp, isManifest, loadAppBundledTools, loadAppHandle, packApp, peekAppUi, refKey, resolveAppUIRoot, safeId, stripOwner, unpackApp };
|
|
1578
|
+
export { AGENTAPP_FORMAT, AgentAppPackError, AppDefinitionError, AppLoadError, RELEASE_DEFAULT_EXCLUDE, aggregateSha256, collectFiles, defineApp, emitApp, globToRegExp, isManifest, loadAppBundledTools, loadAppHandle, packApp, peekAppUi, readPackageRules, refKey, resolveAppUIRoot, safeId, stripOwner, unpackApp, versionSatisfies };
|
|
1347
1579
|
//# sourceMappingURL=index.mjs.map
|
|
1348
1580
|
//# sourceMappingURL=index.mjs.map
|