@unoverse-platform/studio 0.1.90 → 0.1.91
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/local/plugin.ts +20 -12
- package/package.json +13 -3
- package/vendor/base/src/agent-mcp/discovery.ts +203 -0
- package/vendor/base/src/agent-mcp/handoff.ts +56 -0
- package/vendor/base/src/agent-mcp/index.ts +44 -0
- package/vendor/base/src/agent-mcp/invoke.ts +140 -0
- package/vendor/base/src/agent-mcp/lean.ts +111 -0
- package/vendor/base/src/agent-mcp/memoryContext.ts +104 -0
- package/vendor/base/src/agent-mcp/memoryIngest.ts +88 -0
- package/vendor/base/src/agent-mcp/rowComponents.ts +172 -0
- package/vendor/base/src/agent-mcp/tools.ts +134 -0
- package/vendor/base/src/agent-mcp/types.ts +130 -0
- package/vendor/base/src/auth/auth.ts +278 -0
- package/vendor/base/src/auth/authConfig.ts +73 -0
- package/vendor/base/src/boot.ts +245 -0
- package/vendor/base/src/definitions/definitions.ts +18 -0
- package/vendor/base/src/definitions/dsPackage.ts +45 -0
- package/vendor/base/src/definitions/fsCache.ts +128 -0
- package/vendor/base/src/definitions/index.ts +19 -0
- package/vendor/base/src/definitions/inputs.ts +30 -0
- package/vendor/base/src/definitions/load/compile/component.ts +80 -0
- package/vendor/base/src/definitions/load/compile/index.ts +12 -0
- package/vendor/base/src/definitions/load/compile/sections.ts +132 -0
- package/vendor/base/src/definitions/load/compile/template.ts +153 -0
- package/vendor/base/src/definitions/load/expand/includes.ts +27 -0
- package/vendor/base/src/definitions/load/expand/index.ts +17 -0
- package/vendor/base/src/definitions/load/expand/inherit.ts +169 -0
- package/vendor/base/src/definitions/load/expand/referenced.ts +164 -0
- package/vendor/base/src/definitions/load/expand/refs.ts +106 -0
- package/vendor/base/src/definitions/load/expand/walk.ts +91 -0
- package/vendor/base/src/definitions/load/load.ts +487 -0
- package/vendor/base/src/definitions/model.ts +238 -0
- package/vendor/base/src/definitions/registry/catalog.ts +643 -0
- package/vendor/base/src/definitions/registry/homes.ts +252 -0
- package/vendor/base/src/definitions/theme.ts +383 -0
- package/vendor/base/src/executor.ts +284 -0
- package/vendor/base/src/http/uwsFetchAdapter.ts +260 -0
- package/vendor/base/src/items/baseVersion.ts +96 -0
- package/vendor/base/src/items/collect.ts +199 -0
- package/vendor/base/src/items/fingerprint.ts +34 -0
- package/vendor/base/src/items/publish.ts +198 -0
- package/vendor/base/src/lint/context.mjs +56 -0
- package/vendor/base/src/lint/design/defs.mjs +46 -0
- package/vendor/base/src/lint/design/file.mjs +737 -0
- package/vendor/base/src/lint/design/index.d.mts +30 -0
- package/vendor/base/src/lint/design/index.mjs +996 -0
- package/vendor/base/src/lint/design/tokens.mjs +128 -0
- package/vendor/base/src/lint/design/vocabulary.mjs +181 -0
- package/vendor/base/src/lint/design/walk.mjs +444 -0
- package/vendor/base/src/lint/index.mjs +28 -0
- package/vendor/base/src/lint/nodes/blocks.mjs +63 -0
- package/vendor/base/src/lint/nodes/index.mjs +64 -0
- package/vendor/base/src/lint/nodes/load.mjs +126 -0
- package/vendor/base/src/lint/nodes/node.mjs +764 -0
- package/vendor/base/src/lint/nodes/package.mjs +112 -0
- package/vendor/base/src/lint/nodes/schema.mjs +75 -0
- package/vendor/base/src/logger.ts +33 -0
- package/vendor/base/src/manifests/compose.ts +539 -0
- package/vendor/base/src/manifests/executor/callback.ts +107 -0
- package/vendor/base/src/manifests/executor/context.ts +107 -0
- package/vendor/base/src/manifests/executor/index.ts +47 -0
- package/vendor/base/src/manifests/executor/lookup.ts +21 -0
- package/vendor/base/src/manifests/executor/memory.ts +62 -0
- package/vendor/base/src/manifests/executor/promise.ts +71 -0
- package/vendor/base/src/manifests/executor/refire.ts +34 -0
- package/vendor/base/src/manifests/executor/send.ts +65 -0
- package/vendor/base/src/manifests/executor/session.ts +46 -0
- package/vendor/base/src/manifests/executor/toolBridge.ts +266 -0
- package/vendor/base/src/manifests/index.ts +280 -0
- package/vendor/base/src/manifests/integrity.ts +93 -0
- package/vendor/base/src/manifests/rows.ts +33 -0
- package/vendor/base/src/manifests/runtime/auth/aws.ts +240 -0
- package/vendor/base/src/manifests/runtime/auth/oauth.ts +76 -0
- package/vendor/base/src/manifests/runtime/authorize.ts +159 -0
- package/vendor/base/src/manifests/runtime/channels/final.ts +171 -0
- package/vendor/base/src/manifests/runtime/channels/service.ts +125 -0
- package/vendor/base/src/manifests/runtime/channels/workflow.ts +310 -0
- package/vendor/base/src/manifests/runtime/context.ts +150 -0
- package/vendor/base/src/manifests/runtime/docstore/handlers.ts +547 -0
- package/vendor/base/src/manifests/runtime/docstore/index.ts +135 -0
- package/vendor/base/src/manifests/runtime/docstore/sectionizer.ts +184 -0
- package/vendor/base/src/manifests/runtime/docstore/store.ts +172 -0
- package/vendor/base/src/manifests/runtime/docstore/types.ts +60 -0
- package/vendor/base/src/manifests/runtime/duplex/audioLane.ts +165 -0
- package/vendor/base/src/manifests/runtime/duplex/session.ts +511 -0
- package/vendor/base/src/manifests/runtime/events.ts +223 -0
- package/vendor/base/src/manifests/runtime/helpers.ts +53 -0
- package/vendor/base/src/manifests/runtime/http/allowedHosts.ts +118 -0
- package/vendor/base/src/manifests/runtime/http/request.ts +637 -0
- package/vendor/base/src/manifests/runtime/http/response.ts +162 -0
- package/vendor/base/src/manifests/runtime/index.ts +57 -0
- package/vendor/base/src/manifests/runtime/loops/chunk.ts +98 -0
- package/vendor/base/src/manifests/runtime/loops/loop.ts +191 -0
- package/vendor/base/src/manifests/runtime/loops/paginate.ts +143 -0
- package/vendor/base/src/manifests/runtime/loops/poll.ts +169 -0
- package/vendor/base/src/manifests/runtime/narrate.ts +53 -0
- package/vendor/base/src/manifests/runtime/state.ts +171 -0
- package/vendor/base/src/manifests/runtime/templating.ts +110 -0
- package/vendor/base/src/manifests/runtime/tools/regionSkills.ts +125 -0
- package/vendor/base/src/manifests/runtime/tools/toolloop.ts +542 -0
- package/vendor/base/src/manifests/runtime/usage.ts +87 -0
- package/vendor/base/src/manifests/source.ts +187 -0
- package/vendor/base/src/manifests/watch.ts +67 -0
- package/vendor/base/src/markdown/document.ts +141 -0
- package/vendor/base/src/paths.ts +180 -0
- package/vendor/base/src/platform/audioManager.ts +100 -0
- package/vendor/base/src/platform/clientTransport.ts +65 -0
- package/vendor/base/src/platform/executionContext.ts +154 -0
- package/vendor/base/src/platform/index.ts +10 -0
- package/vendor/base/src/platform/pluginAPI.ts +146 -0
- package/vendor/base/src/platform/redis.ts +54 -0
- package/vendor/base/src/platform/serviceCalls.ts +222 -0
- package/vendor/base/src/pluginBase.ts +248 -0
- package/vendor/base/src/plugins/README.md +57 -0
- package/vendor/base/src/plugins/discovery.ts +87 -0
- package/vendor/base/src/plugins/index.ts +16 -0
- package/vendor/base/src/plugins/loader.ts +179 -0
- package/vendor/base/src/plugins/redis.ts +36 -0
- package/vendor/base/src/plugins/state.ts +53 -0
- package/vendor/base/src/registry.ts +95 -0
- package/vendor/base/src/security/permissions.ts +93 -0
- package/vendor/base/src/security/rules.ts +73 -0
- package/vendor/base/src/template/SafeExpression.ts +556 -0
- package/vendor/base/src/template/StringTemplateResolver.ts +75 -0
- package/vendor/base/src/template/index.ts +22 -0
- package/vendor/base/src/types.ts +50 -0
- package/vendor/base/src/workflow/GetMemoryService.ts +158 -0
- package/vendor/base/src/workflow/PlatformMemoryCore.ts +438 -0
- package/vendor/base/src/workflow/routing.ts +122 -0
- package/vendor/sdk/lib/core/store.ts +26 -6
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Rules about a PACKAGE rather than a node: allowedHosts covering every host its nodes
|
|
3
|
+
* call, credentials declared once, node types unique across the whole tree, and shared/
|
|
4
|
+
* fragments earning their place.
|
|
5
|
+
*/
|
|
6
|
+
import { readdirSync, readFileSync, existsSync, statSync } from "node:fs";
|
|
7
|
+
import { join, relative, resolve, dirname } from "node:path";
|
|
8
|
+
import { report, rel, refCounts, derivedKinds, allCredentials, state } from "../context.mjs";
|
|
9
|
+
import { SCHEMA_ID, SECTIONS, validateAgainst } from "./schema.mjs";
|
|
10
|
+
import { readYaml, resolveRefs, sharedDirFor } from "./load.mjs";
|
|
11
|
+
import { lintNode } from "./node.mjs";
|
|
12
|
+
|
|
13
|
+
// ── one package ───────────────────────────────────────────────────────────────
|
|
14
|
+
export function lintPackage(dir) {
|
|
15
|
+
const pkgFile = join(dir, "package.yaml");
|
|
16
|
+
const pkg = { file: pkgFile, credentials: new Set(), requires: null, allowedHosts: [] };
|
|
17
|
+
|
|
18
|
+
if (existsSync(pkgFile)) {
|
|
19
|
+
const doc = readYaml(pkgFile);
|
|
20
|
+
if (doc) {
|
|
21
|
+
validateAgainst(SCHEMA_ID.package, doc, rel(pkgFile), "package.schema.json");
|
|
22
|
+
pkg.requires = doc.requires ?? null;
|
|
23
|
+
pkg.allowedHosts = (doc.allowedHosts ?? []).map((h) => String(h).toLowerCase());
|
|
24
|
+
if (doc.name && doc.name !== dir.split("/").pop())
|
|
25
|
+
report("warn", rel(pkgFile), `name "${doc.name}" does not match the folder name "${dir.split("/").pop()}"`);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const credDir = join(dir, "credentials");
|
|
30
|
+
if (existsSync(credDir))
|
|
31
|
+
for (const f of readdirSync(credDir).filter((f) => /\.ya?ml$/.test(f))) {
|
|
32
|
+
const doc = readYaml(join(credDir, f));
|
|
33
|
+
if (!doc) continue;
|
|
34
|
+
validateAgainst(SCHEMA_ID.credential, doc, rel(join(credDir, f)), "credential.schema.json");
|
|
35
|
+
if (doc.name) pkg.credentials.add(doc.name);
|
|
36
|
+
if (doc.name && doc.name !== f.replace(/\.ya?ml$/, ""))
|
|
37
|
+
report("warn", rel(join(credDir, f)), `declares name "${doc.name}" but the file is ${f}. Nodes reference the NAME, so keep them the same`);
|
|
38
|
+
|
|
39
|
+
// Two packages may both declare a credential, but they must agree on it:
|
|
40
|
+
// context.credentials is ONE flat bag keyed by name, so a disagreement means
|
|
41
|
+
// whichever package loses the race describes a credential it cannot read.
|
|
42
|
+
if (doc.name) {
|
|
43
|
+
const fields = (doc.properties ?? []).map((p) => p.name).sort().join(",");
|
|
44
|
+
const prior = allCredentials.get(doc.name);
|
|
45
|
+
if (prior && prior.fields !== fields)
|
|
46
|
+
report(
|
|
47
|
+
"error",
|
|
48
|
+
rel(join(credDir, f)),
|
|
49
|
+
`credential "${doc.name}" is also declared in ${prior.file} with different fields (${prior.fields} vs ${fields}). They share one entry in context.credentials and must agree (04-credentials.md)`,
|
|
50
|
+
);
|
|
51
|
+
else if (!prior) allCredentials.set(doc.name, { file: rel(join(credDir, f)), fields });
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// MIGRATION HAZARD, checked per package because the credential's NAME often is not
|
|
56
|
+
// in this package's source at all (openai re-exports OpenAICredential from
|
|
57
|
+
// plugin-base, so only the identifier appears here).
|
|
58
|
+
//
|
|
59
|
+
// registerCredentialType is first-wins-and-SILENT: it logs "already registered,
|
|
60
|
+
// skipping" and returns. With a credentials/*.yaml AND a live api.registerCredential
|
|
61
|
+
// call, whichever loads first takes the slot and the other vanishes. A wrong
|
|
62
|
+
// credential type then makes getDecryptedCredential quietly skip decryption, which
|
|
63
|
+
// surfaces as an auth failure with the right credential visibly selected.
|
|
64
|
+
if (pkg.credentials.size) {
|
|
65
|
+
const entry = join(dir, "src/index.ts");
|
|
66
|
+
if (existsSync(entry) && /api\.registerCredential\s*\(/.test(readFileSync(entry, "utf8")))
|
|
67
|
+
report(
|
|
68
|
+
"error",
|
|
69
|
+
rel(entry),
|
|
70
|
+
`still calls api.registerCredential() while this package also declares credentials/ manifests. Registration is first-wins and silent, so one of them is dropped at random. Move the declaration, do not copy it (04-credentials.md)`,
|
|
71
|
+
);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
const nodesDir = join(dir, "nodes");
|
|
75
|
+
if (!existsSync(nodesDir)) return 0;
|
|
76
|
+
|
|
77
|
+
let count = 0;
|
|
78
|
+
const types = new Map();
|
|
79
|
+
for (const entry of readdirSync(nodesDir)) {
|
|
80
|
+
const nd = join(nodesDir, entry);
|
|
81
|
+
if (!statSync(nd).isDirectory()) continue;
|
|
82
|
+
const node = lintNode(nd, pkg);
|
|
83
|
+
count++;
|
|
84
|
+
if (node?.type) {
|
|
85
|
+
if (types.has(node.type))
|
|
86
|
+
report("error", rel(nd), `type "${node.type}" is already used by ${types.get(node.type)}. A node type is a stable global identity`);
|
|
87
|
+
else types.set(node.type, entry);
|
|
88
|
+
if (node.type !== entry)
|
|
89
|
+
report("warn", rel(nd), `folder is "${entry}" but type is "${node.type}". Keep them the same so a type is findable by path`);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// A shared/ fragment with one consumer should be inlined; shared/ is for DATA
|
|
94
|
+
// several nodes genuinely share, and it silts up if nothing prunes it.
|
|
95
|
+
const sharedDir = join(dir, "shared");
|
|
96
|
+
if (existsSync(sharedDir))
|
|
97
|
+
for (const f of readdirSync(sharedDir).filter((f) => /\.ya?ml$/.test(f))) {
|
|
98
|
+
const n = refCounts.get(join(sharedDir, f))?.size ?? 0;
|
|
99
|
+
/**
|
|
100
|
+
* A HELPERS FILE IS REACHED BY NAME, not by $ref: `helpers:` declarations are collected
|
|
101
|
+
* from every shared file and called as `helpers.someName(...)` from inside an
|
|
102
|
+
* expression. Counting $refs alone reads that as dead and tells the author to delete
|
|
103
|
+
* the file their node depends on — the worst possible advice, delivered confidently.
|
|
104
|
+
*/
|
|
105
|
+
const declaresHelpers = /^helpers\s*:/m.test(readFileSync(join(sharedDir, f), "utf8"));
|
|
106
|
+
if (declaresHelpers) continue;
|
|
107
|
+
if (n === 0) report("warn", rel(join(sharedDir, f)), `is referenced by nothing. Delete it or $ref it`);
|
|
108
|
+
else if (n === 1) report("hint", rel(join(sharedDir, f)), `has a single consumer. A fragment earns shared/ at the SECOND one, otherwise inline it`);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
return count;
|
|
112
|
+
}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tier 2: structural validation against nodes/_schema/*.json.
|
|
3
|
+
*
|
|
4
|
+
* A JSON Schema catches shape. Everything a schema CANNOT express (cross-file agreement,
|
|
5
|
+
* ordering, reachability) is tier 3 and lives in the rule modules.
|
|
6
|
+
*/
|
|
7
|
+
import { readdirSync, readFileSync, existsSync } from "node:fs";
|
|
8
|
+
import { join } from "node:path";
|
|
9
|
+
import { createRequire } from "node:module";
|
|
10
|
+
import { report, state } from "../context.mjs";
|
|
11
|
+
|
|
12
|
+
const require_ = createRequire(import.meta.url);
|
|
13
|
+
/**
|
|
14
|
+
* EXPORTED, because `node.mjs` validates a fixture against a RELAXED copy of the node's own
|
|
15
|
+
* configSchema — an ad-hoc schema built at run time, not one of the files loaded above. It needs the
|
|
16
|
+
* same validator, and this module is where the dependency is resolved and its absence explained, so
|
|
17
|
+
* re-requiring it there would mean two places to change and two error messages for one missing
|
|
18
|
+
* package.
|
|
19
|
+
*/
|
|
20
|
+
export let Validator;
|
|
21
|
+
try {
|
|
22
|
+
({ Validator } = require_("@cfworker/json-schema"));
|
|
23
|
+
} catch {
|
|
24
|
+
throw new Error("the node linter needs @cfworker/json-schema (npm install -D @cfworker/json-schema)");
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export const SCHEMA_ID = {
|
|
28
|
+
node: "https://unoverse/nodes/node.schema.json",
|
|
29
|
+
interface: "https://unoverse/nodes/interface.schema.json",
|
|
30
|
+
config: "https://unoverse/nodes/config.schema.json",
|
|
31
|
+
api: "https://unoverse/nodes/api.schema.json",
|
|
32
|
+
test: "https://unoverse/nodes/test.schema.json",
|
|
33
|
+
package: "https://unoverse/nodes/package.schema.json",
|
|
34
|
+
credential: "https://unoverse/nodes/credential.schema.json",
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
/** The four sections that may live in their own file OR inline in node.yaml. */
|
|
38
|
+
export const SECTIONS = ["interface", "config", "api", "test"];
|
|
39
|
+
|
|
40
|
+
/** Read _schema/*.json into the run. A malformed schema is REPORTED, never thrown: the
|
|
41
|
+
* caller gets one shape of answer whatever went wrong. */
|
|
42
|
+
export function loadSchemas() {
|
|
43
|
+
if (!existsSync(state.schemaDir)) return;
|
|
44
|
+
for (const f of readdirSync(state.schemaDir).filter((f) => f.endsWith(".json")))
|
|
45
|
+
try {
|
|
46
|
+
const s = JSON.parse(readFileSync(join(state.schemaDir, f), "utf8"));
|
|
47
|
+
state.schemas[s.$id] = s;
|
|
48
|
+
} catch (e) {
|
|
49
|
+
report("error", `_schema/${f}`, `is not valid JSON: ${e.message}`);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export function validateAgainst(schemaId, doc, file, label) {
|
|
54
|
+
const schema = state.schemas[schemaId];
|
|
55
|
+
if (!schema) {
|
|
56
|
+
report("warn", file, `no schema found for ${label}. Is nodes/_schema/ present?`);
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
const v = new Validator(schema, "7", false);
|
|
60
|
+
for (const [id, s] of Object.entries(state.schemas)) if (id !== schemaId) v.addSchema(s, id);
|
|
61
|
+
const r = v.validate(doc);
|
|
62
|
+
if (r.valid) return;
|
|
63
|
+
// A single bad value produces one error per schema level plus internal artefacts.
|
|
64
|
+
// Keep only the DEEPEST error per location: that is the one naming the real problem.
|
|
65
|
+
const useful = r.errors.filter(
|
|
66
|
+
(e) => !/False boolean schema|does not match additional properties|A subschema had errors|does not match schema\.$/.test(e.error),
|
|
67
|
+
);
|
|
68
|
+
const deepest = new Map();
|
|
69
|
+
for (const e of useful.length ? useful : r.errors) {
|
|
70
|
+
const at = e.instanceLocation.replace(/^#/, "") || "(root)";
|
|
71
|
+
if (!deepest.has(at)) deepest.set(at, e.error);
|
|
72
|
+
}
|
|
73
|
+
for (const [at, err] of [...deepest].slice(0, 6)) report("error", file, `${at} ${err} (${label})`);
|
|
74
|
+
}
|
|
75
|
+
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Structured logger for base runtime modules — JSON lines to stdout, same shape the
|
|
3
|
+
* platform's pino logs settle into, so compiled and interpreted runs look identical
|
|
4
|
+
* to any log ingestion. No pino dependency: base stays lean, and a line is a line.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
export interface Logger {
|
|
8
|
+
error: (message: string, data?: any) => void;
|
|
9
|
+
warn: (message: string, data?: any) => void;
|
|
10
|
+
info: (message: string, data?: any) => void;
|
|
11
|
+
debug: (message: string, data?: any) => void;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
const LEVELS: Record<string, number> = { debug: 10, info: 20, warn: 30, error: 40 };
|
|
15
|
+
|
|
16
|
+
function threshold(): number {
|
|
17
|
+
return LEVELS[process.env.LOG_LEVEL?.toLowerCase() ?? "info"] ?? LEVELS.info;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export function createLogger(context: string): Logger {
|
|
21
|
+
const log = (level: string, message: string, data?: any) => {
|
|
22
|
+
if ((LEVELS[level] ?? LEVELS.info) < threshold()) return;
|
|
23
|
+
const line: Record<string, unknown> = { level, context, msg: message, time: new Date().toISOString() };
|
|
24
|
+
if (data !== undefined) line.data = data;
|
|
25
|
+
console.log(JSON.stringify(line));
|
|
26
|
+
};
|
|
27
|
+
return {
|
|
28
|
+
error: (message, data) => log("error", message, data),
|
|
29
|
+
warn: (message, data) => log("warn", message, data),
|
|
30
|
+
info: (message, data) => log("info", message, data),
|
|
31
|
+
debug: (message, data) => log("debug", message, data),
|
|
32
|
+
};
|
|
33
|
+
}
|