@marifold/core 0.60.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 +674 -0
- package/dist/agent/AgentEvents.d.ts +106 -0
- package/dist/agent/AgentEvents.d.ts.map +1 -0
- package/dist/agent/AgentEvents.js +3 -0
- package/dist/agent/AgentEvents.js.map +1 -0
- package/dist/agent/AgentHistory.d.ts +27 -0
- package/dist/agent/AgentHistory.d.ts.map +1 -0
- package/dist/agent/AgentHistory.js +42 -0
- package/dist/agent/AgentHistory.js.map +1 -0
- package/dist/agent/AgentRunner.d.ts +149 -0
- package/dist/agent/AgentRunner.d.ts.map +1 -0
- package/dist/agent/AgentRunner.js +727 -0
- package/dist/agent/AgentRunner.js.map +1 -0
- package/dist/agent/ApprovalPolicy.d.ts +71 -0
- package/dist/agent/ApprovalPolicy.d.ts.map +1 -0
- package/dist/agent/ApprovalPolicy.js +29 -0
- package/dist/agent/ApprovalPolicy.js.map +1 -0
- package/dist/agent/ControlBlockTools.d.ts +9 -0
- package/dist/agent/ControlBlockTools.d.ts.map +1 -0
- package/dist/agent/ControlBlockTools.js +49 -0
- package/dist/agent/ControlBlockTools.js.map +1 -0
- package/dist/agent/RunWorkspace.d.ts +92 -0
- package/dist/agent/RunWorkspace.d.ts.map +1 -0
- package/dist/agent/RunWorkspace.js +328 -0
- package/dist/agent/RunWorkspace.js.map +1 -0
- package/dist/agent/ScopedProcess.d.ts +35 -0
- package/dist/agent/ScopedProcess.d.ts.map +1 -0
- package/dist/agent/ScopedProcess.js +280 -0
- package/dist/agent/ScopedProcess.js.map +1 -0
- package/dist/agent/ToolRegistry.d.ts +80 -0
- package/dist/agent/ToolRegistry.d.ts.map +1 -0
- package/dist/agent/ToolRegistry.js +45 -0
- package/dist/agent/ToolRegistry.js.map +1 -0
- package/dist/agent/UserInput.d.ts +59 -0
- package/dist/agent/UserInput.d.ts.map +1 -0
- package/dist/agent/UserInput.js +203 -0
- package/dist/agent/UserInput.js.map +1 -0
- package/dist/agent/tools/AskUserTool.d.ts +71 -0
- package/dist/agent/tools/AskUserTool.d.ts.map +1 -0
- package/dist/agent/tools/AskUserTool.js +70 -0
- package/dist/agent/tools/AskUserTool.js.map +1 -0
- package/dist/agent/tools/DelegateTool.d.ts +49 -0
- package/dist/agent/tools/DelegateTool.d.ts.map +1 -0
- package/dist/agent/tools/DelegateTool.js +62 -0
- package/dist/agent/tools/DelegateTool.js.map +1 -0
- package/dist/agent/tools/InspectAttachmentTool.d.ts +25 -0
- package/dist/agent/tools/InspectAttachmentTool.d.ts.map +1 -0
- package/dist/agent/tools/InspectAttachmentTool.js +129 -0
- package/dist/agent/tools/InspectAttachmentTool.js.map +1 -0
- package/dist/agent/tools/PythonPackageTool.d.ts +26 -0
- package/dist/agent/tools/PythonPackageTool.d.ts.map +1 -0
- package/dist/agent/tools/PythonPackageTool.js +105 -0
- package/dist/agent/tools/PythonPackageTool.js.map +1 -0
- package/dist/agent/tools/ReadFileTool.d.ts +24 -0
- package/dist/agent/tools/ReadFileTool.d.ts.map +1 -0
- package/dist/agent/tools/ReadFileTool.js +112 -0
- package/dist/agent/tools/ReadFileTool.js.map +1 -0
- package/dist/agent/tools/ShellExecTool.d.ts +23 -0
- package/dist/agent/tools/ShellExecTool.d.ts.map +1 -0
- package/dist/agent/tools/ShellExecTool.js +75 -0
- package/dist/agent/tools/ShellExecTool.js.map +1 -0
- package/dist/agent/tools/WebSearchTool.d.ts +26 -0
- package/dist/agent/tools/WebSearchTool.d.ts.map +1 -0
- package/dist/agent/tools/WebSearchTool.js +52 -0
- package/dist/agent/tools/WebSearchTool.js.map +1 -0
- package/dist/agent/tools/WriteFileTool.d.ts +30 -0
- package/dist/agent/tools/WriteFileTool.d.ts.map +1 -0
- package/dist/agent/tools/WriteFileTool.js +155 -0
- package/dist/agent/tools/WriteFileTool.js.map +1 -0
- package/dist/app/AppActionResolver.d.ts +15 -0
- package/dist/app/AppActionResolver.d.ts.map +1 -0
- package/dist/app/AppActionResolver.js +98 -0
- package/dist/app/AppActionResolver.js.map +1 -0
- package/dist/app/AppSchema.d.ts +83 -0
- package/dist/app/AppSchema.d.ts.map +1 -0
- package/dist/app/AppSchema.js +17 -0
- package/dist/app/AppSchema.js.map +1 -0
- package/dist/app/AppStore.d.ts +14 -0
- package/dist/app/AppStore.d.ts.map +1 -0
- package/dist/app/AppStore.js +146 -0
- package/dist/app/AppStore.js.map +1 -0
- package/dist/app/AppValidator.d.ts +10 -0
- package/dist/app/AppValidator.d.ts.map +1 -0
- package/dist/app/AppValidator.js +503 -0
- package/dist/app/AppValidator.js.map +1 -0
- package/dist/app/SkillAppCompiler.d.ts +5 -0
- package/dist/app/SkillAppCompiler.d.ts.map +1 -0
- package/dist/app/SkillAppCompiler.js +632 -0
- package/dist/app/SkillAppCompiler.js.map +1 -0
- package/dist/app/SkillAppDsl.d.ts +93 -0
- package/dist/app/SkillAppDsl.d.ts.map +1 -0
- package/dist/app/SkillAppDsl.js +72 -0
- package/dist/app/SkillAppDsl.js.map +1 -0
- package/dist/app/SkillAppInstanceRegistry.d.ts +25 -0
- package/dist/app/SkillAppInstanceRegistry.d.ts.map +1 -0
- package/dist/app/SkillAppInstanceRegistry.js +218 -0
- package/dist/app/SkillAppInstanceRegistry.js.map +1 -0
- package/dist/app/SkillAppResolver.d.ts +12 -0
- package/dist/app/SkillAppResolver.d.ts.map +1 -0
- package/dist/app/SkillAppResolver.js +89 -0
- package/dist/app/SkillAppResolver.js.map +1 -0
- package/dist/app/SkillAppSchema.d.ts +116 -0
- package/dist/app/SkillAppSchema.d.ts.map +1 -0
- package/dist/app/SkillAppSchema.js +5 -0
- package/dist/app/SkillAppSchema.js.map +1 -0
- package/dist/channels/TelegramBridge.d.ts +103 -0
- package/dist/channels/TelegramBridge.d.ts.map +1 -0
- package/dist/channels/TelegramBridge.js +565 -0
- package/dist/channels/TelegramBridge.js.map +1 -0
- package/dist/channels/respond.d.ts +46 -0
- package/dist/channels/respond.d.ts.map +1 -0
- package/dist/channels/respond.js +41 -0
- package/dist/channels/respond.js.map +1 -0
- package/dist/config/ChatGptTokenRefresh.d.ts +18 -0
- package/dist/config/ChatGptTokenRefresh.d.ts.map +1 -0
- package/dist/config/ChatGptTokenRefresh.js +63 -0
- package/dist/config/ChatGptTokenRefresh.js.map +1 -0
- package/dist/config/ConfigBackup.d.ts +20 -0
- package/dist/config/ConfigBackup.d.ts.map +1 -0
- package/dist/config/ConfigBackup.js +197 -0
- package/dist/config/ConfigBackup.js.map +1 -0
- package/dist/config/ConfigLoader.d.ts +28 -0
- package/dist/config/ConfigLoader.d.ts.map +1 -0
- package/dist/config/ConfigLoader.js +335 -0
- package/dist/config/ConfigLoader.js.map +1 -0
- package/dist/config/ConfigManager.d.ts +55 -0
- package/dist/config/ConfigManager.d.ts.map +1 -0
- package/dist/config/ConfigManager.js +707 -0
- package/dist/config/ConfigManager.js.map +1 -0
- package/dist/config/ConfigSchema.d.ts +231 -0
- package/dist/config/ConfigSchema.d.ts.map +1 -0
- package/dist/config/ConfigSchema.js +15 -0
- package/dist/config/ConfigSchema.js.map +1 -0
- package/dist/config/GitHubCopilotAuth.d.ts +7 -0
- package/dist/config/GitHubCopilotAuth.d.ts.map +1 -0
- package/dist/config/GitHubCopilotAuth.js +40 -0
- package/dist/config/GitHubCopilotAuth.js.map +1 -0
- package/dist/config/MarifoldOpenAICompatProvider.d.ts +39 -0
- package/dist/config/MarifoldOpenAICompatProvider.d.ts.map +1 -0
- package/dist/config/MarifoldOpenAICompatProvider.js +158 -0
- package/dist/config/MarifoldOpenAICompatProvider.js.map +1 -0
- package/dist/config/OpenAICompatUrls.d.ts +7 -0
- package/dist/config/OpenAICompatUrls.d.ts.map +1 -0
- package/dist/config/OpenAICompatUrls.js +47 -0
- package/dist/config/OpenAICompatUrls.js.map +1 -0
- package/dist/config/ProviderFactory.d.ts +12 -0
- package/dist/config/ProviderFactory.d.ts.map +1 -0
- package/dist/config/ProviderFactory.js +61 -0
- package/dist/config/ProviderFactory.js.map +1 -0
- package/dist/config/ProviderInspector.d.ts +46 -0
- package/dist/config/ProviderInspector.d.ts.map +1 -0
- package/dist/config/ProviderInspector.js +356 -0
- package/dist/config/ProviderInspector.js.map +1 -0
- package/dist/config/ProviderRegistry.d.ts +19 -0
- package/dist/config/ProviderRegistry.d.ts.map +1 -0
- package/dist/config/ProviderRegistry.js +301 -0
- package/dist/config/ProviderRegistry.js.map +1 -0
- package/dist/config/XaiTokenRefresh.d.ts +15 -0
- package/dist/config/XaiTokenRefresh.d.ts.map +1 -0
- package/dist/config/XaiTokenRefresh.js +73 -0
- package/dist/config/XaiTokenRefresh.js.map +1 -0
- package/dist/errors/MarifoldError.d.ts +34 -0
- package/dist/errors/MarifoldError.d.ts.map +1 -0
- package/dist/errors/MarifoldError.js +100 -0
- package/dist/errors/MarifoldError.js.map +1 -0
- package/dist/images/ImageOptimizer.d.ts +34 -0
- package/dist/images/ImageOptimizer.d.ts.map +1 -0
- package/dist/images/ImageOptimizer.js +225 -0
- package/dist/images/ImageOptimizer.js.map +1 -0
- package/dist/index.d.ts +96 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +193 -0
- package/dist/index.js.map +1 -0
- package/dist/memory/MemoryControls.d.ts +26 -0
- package/dist/memory/MemoryControls.d.ts.map +1 -0
- package/dist/memory/MemoryControls.js +388 -0
- package/dist/memory/MemoryControls.js.map +1 -0
- package/dist/memory/MemoryStore.d.ts +122 -0
- package/dist/memory/MemoryStore.d.ts.map +1 -0
- package/dist/memory/MemoryStore.js +1096 -0
- package/dist/memory/MemoryStore.js.map +1 -0
- package/dist/profiles/ProfileManager.d.ts +139 -0
- package/dist/profiles/ProfileManager.d.ts.map +1 -0
- package/dist/profiles/ProfileManager.js +475 -0
- package/dist/profiles/ProfileManager.js.map +1 -0
- package/dist/profiles/ProfileResolver.d.ts +18 -0
- package/dist/profiles/ProfileResolver.d.ts.map +1 -0
- package/dist/profiles/ProfileResolver.js +280 -0
- package/dist/profiles/ProfileResolver.js.map +1 -0
- package/dist/runs/RunRegistry.d.ts +140 -0
- package/dist/runs/RunRegistry.d.ts.map +1 -0
- package/dist/runs/RunRegistry.js +432 -0
- package/dist/runs/RunRegistry.js.map +1 -0
- package/dist/runtime/MarifoldRuntime.d.ts +244 -0
- package/dist/runtime/MarifoldRuntime.d.ts.map +1 -0
- package/dist/runtime/MarifoldRuntime.js +1099 -0
- package/dist/runtime/MarifoldRuntime.js.map +1 -0
- package/dist/runtime/MarifoldTypes.d.ts +70 -0
- package/dist/runtime/MarifoldTypes.d.ts.map +1 -0
- package/dist/runtime/MarifoldTypes.js +3 -0
- package/dist/runtime/MarifoldTypes.js.map +1 -0
- package/dist/schedule/ScheduleStore.d.ts +60 -0
- package/dist/schedule/ScheduleStore.d.ts.map +1 -0
- package/dist/schedule/ScheduleStore.js +212 -0
- package/dist/schedule/ScheduleStore.js.map +1 -0
- package/dist/schedule/Scheduler.d.ts +28 -0
- package/dist/schedule/Scheduler.d.ts.map +1 -0
- package/dist/schedule/Scheduler.js +65 -0
- package/dist/schedule/Scheduler.js.map +1 -0
- package/dist/search/DuckDuckGoBackend.d.ts +18 -0
- package/dist/search/DuckDuckGoBackend.d.ts.map +1 -0
- package/dist/search/DuckDuckGoBackend.js +37 -0
- package/dist/search/DuckDuckGoBackend.js.map +1 -0
- package/dist/search/FirecrawlBackend.d.ts +28 -0
- package/dist/search/FirecrawlBackend.d.ts.map +1 -0
- package/dist/search/FirecrawlBackend.js +76 -0
- package/dist/search/FirecrawlBackend.js.map +1 -0
- package/dist/search/SearchBackend.d.ts +18 -0
- package/dist/search/SearchBackend.d.ts.map +1 -0
- package/dist/search/SearchBackend.js +24 -0
- package/dist/search/SearchBackend.js.map +1 -0
- package/dist/search/createSearchBackend.d.ts +16 -0
- package/dist/search/createSearchBackend.d.ts.map +1 -0
- package/dist/search/createSearchBackend.js +30 -0
- package/dist/search/createSearchBackend.js.map +1 -0
- package/dist/sessions/ResponseMetrics.d.ts +17 -0
- package/dist/sessions/ResponseMetrics.d.ts.map +1 -0
- package/dist/sessions/ResponseMetrics.js +3 -0
- package/dist/sessions/ResponseMetrics.js.map +1 -0
- package/dist/sessions/SessionResolver.d.ts +135 -0
- package/dist/sessions/SessionResolver.d.ts.map +1 -0
- package/dist/sessions/SessionResolver.js +1173 -0
- package/dist/sessions/SessionResolver.js.map +1 -0
- package/dist/skill/BuiltInSkillManager.d.ts +11 -0
- package/dist/skill/BuiltInSkillManager.d.ts.map +1 -0
- package/dist/skill/BuiltInSkillManager.js +98 -0
- package/dist/skill/BuiltInSkillManager.js.map +1 -0
- package/dist/skill/SkillInvocation.d.ts +30 -0
- package/dist/skill/SkillInvocation.d.ts.map +1 -0
- package/dist/skill/SkillInvocation.js +135 -0
- package/dist/skill/SkillInvocation.js.map +1 -0
- package/dist/skill/SkillSchema.d.ts +37 -0
- package/dist/skill/SkillSchema.d.ts.map +1 -0
- package/dist/skill/SkillSchema.js +26 -0
- package/dist/skill/SkillSchema.js.map +1 -0
- package/dist/skill/SkillStore.d.ts +41 -0
- package/dist/skill/SkillStore.d.ts.map +1 -0
- package/dist/skill/SkillStore.js +184 -0
- package/dist/skill/SkillStore.js.map +1 -0
- package/dist/skill/SkillTemplater.d.ts +19 -0
- package/dist/skill/SkillTemplater.d.ts.map +1 -0
- package/dist/skill/SkillTemplater.js +36 -0
- package/dist/skill/SkillTemplater.js.map +1 -0
- package/dist/skill/SkillValidator.d.ts +10 -0
- package/dist/skill/SkillValidator.d.ts.map +1 -0
- package/dist/skill/SkillValidator.js +131 -0
- package/dist/skill/SkillValidator.js.map +1 -0
- package/dist/skill/SkillVars.d.ts +10 -0
- package/dist/skill/SkillVars.d.ts.map +1 -0
- package/dist/skill/SkillVars.js +65 -0
- package/dist/skill/SkillVars.js.map +1 -0
- package/dist/skill/index.d.ts +10 -0
- package/dist/skill/index.d.ts.map +1 -0
- package/dist/skill/index.js +22 -0
- package/dist/skill/index.js.map +1 -0
- package/dist/skillapp/SkillAppActionResolver.d.ts +13 -0
- package/dist/skillapp/SkillAppActionResolver.d.ts.map +1 -0
- package/dist/skillapp/SkillAppActionResolver.js +95 -0
- package/dist/skillapp/SkillAppActionResolver.js.map +1 -0
- package/dist/skillapp/SkillAppSchema.d.ts +79 -0
- package/dist/skillapp/SkillAppSchema.d.ts.map +1 -0
- package/dist/skillapp/SkillAppSchema.js +20 -0
- package/dist/skillapp/SkillAppSchema.js.map +1 -0
- package/dist/skillapp/SkillAppStore.d.ts +11 -0
- package/dist/skillapp/SkillAppStore.d.ts.map +1 -0
- package/dist/skillapp/SkillAppStore.js +98 -0
- package/dist/skillapp/SkillAppStore.js.map +1 -0
- package/dist/skillapp/SkillAppValidator.d.ts +10 -0
- package/dist/skillapp/SkillAppValidator.d.ts.map +1 -0
- package/dist/skillapp/SkillAppValidator.js +522 -0
- package/dist/skillapp/SkillAppValidator.js.map +1 -0
- package/dist/tasks/TaskStore.d.ts +110 -0
- package/dist/tasks/TaskStore.d.ts.map +1 -0
- package/dist/tasks/TaskStore.js +371 -0
- package/dist/tasks/TaskStore.js.map +1 -0
- package/dist/util/fetchRetry.d.ts +11 -0
- package/dist/util/fetchRetry.d.ts.map +1 -0
- package/dist/util/fetchRetry.js +48 -0
- package/dist/util/fetchRetry.js.map +1 -0
- package/dist/util/idToken.d.ts +12 -0
- package/dist/util/idToken.d.ts.map +1 -0
- package/dist/util/idToken.js +32 -0
- package/dist/util/idToken.js.map +1 -0
- package/dist/util/proxy.d.ts +18 -0
- package/dist/util/proxy.d.ts.map +1 -0
- package/dist/util/proxy.js +28 -0
- package/dist/util/proxy.js.map +1 -0
- package/dist/workspace/Workspace.d.ts +9 -0
- package/dist/workspace/Workspace.d.ts.map +1 -0
- package/dist/workspace/Workspace.js +55 -0
- package/dist/workspace/Workspace.js.map +1 -0
- package/dist/workspace/WorkspaceInitializer.d.ts +40 -0
- package/dist/workspace/WorkspaceInitializer.d.ts.map +1 -0
- package/dist/workspace/WorkspaceInitializer.js +212 -0
- package/dist/workspace/WorkspaceInitializer.js.map +1 -0
- package/dist/workspace/WorkspacePaths.d.ts +11 -0
- package/dist/workspace/WorkspacePaths.d.ts.map +1 -0
- package/dist/workspace/WorkspacePaths.js +82 -0
- package/dist/workspace/WorkspacePaths.js.map +1 -0
- package/package.json +36 -0
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.AppStore = void 0;
|
|
37
|
+
const fs = __importStar(require("fs"));
|
|
38
|
+
const path = __importStar(require("path"));
|
|
39
|
+
const MarifoldError_1 = require("../errors/MarifoldError");
|
|
40
|
+
const SkillValidator_1 = require("../skill/SkillValidator");
|
|
41
|
+
const SkillAppCompiler_1 = require("./SkillAppCompiler");
|
|
42
|
+
const SAFE_APP_NAME = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
|
|
43
|
+
const SKILL_APP_DEFINITION_FILE = 'skillapp.ts';
|
|
44
|
+
/** Global App bundles under `<appsDir>/<name>/skillapp.ts`. Invalid bundles
|
|
45
|
+
* are skipped by list(); get() reports their exact validation failure. */
|
|
46
|
+
class AppStore {
|
|
47
|
+
directory;
|
|
48
|
+
constructor(directory) {
|
|
49
|
+
this.directory = directory;
|
|
50
|
+
}
|
|
51
|
+
list() {
|
|
52
|
+
if (!fs.existsSync(this.directory))
|
|
53
|
+
return [];
|
|
54
|
+
const apps = [];
|
|
55
|
+
for (const entry of fs.readdirSync(this.directory, { withFileTypes: true })) {
|
|
56
|
+
if (!entry.isDirectory() || !SAFE_APP_NAME.test(entry.name))
|
|
57
|
+
continue;
|
|
58
|
+
try {
|
|
59
|
+
const app = this.get(entry.name);
|
|
60
|
+
if (app)
|
|
61
|
+
apps.push(app);
|
|
62
|
+
}
|
|
63
|
+
catch {
|
|
64
|
+
// A catalog stays usable when one local definition is malformed.
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
return apps.sort((a, b) => a.app.title.localeCompare(b.app.title));
|
|
68
|
+
}
|
|
69
|
+
get(name) {
|
|
70
|
+
assertSafeAppName(name);
|
|
71
|
+
const bundle = path.join(this.directory, name);
|
|
72
|
+
const skillAppSource = path.join(bundle, SKILL_APP_DEFINITION_FILE);
|
|
73
|
+
if (!fs.existsSync(skillAppSource))
|
|
74
|
+
return undefined;
|
|
75
|
+
const realSource = requireConfinedFile(bundle, skillAppSource, 'SkillApp definition');
|
|
76
|
+
const definition = (0, SkillAppCompiler_1.compileSkillApp)(fs.readFileSync(realSource, 'utf-8'), realSource);
|
|
77
|
+
if (definition.app.name !== name) {
|
|
78
|
+
throw MarifoldError_1.MarifoldError.appInvalid(`App app.name '${definition.app.name}' must match bundle directory '${name}'.`, realSource);
|
|
79
|
+
}
|
|
80
|
+
this.validateLocalSkills(name, definition);
|
|
81
|
+
return definition;
|
|
82
|
+
}
|
|
83
|
+
require(name) {
|
|
84
|
+
const app = this.get(name);
|
|
85
|
+
if (!app)
|
|
86
|
+
throw MarifoldError_1.MarifoldError.appNotFound(name);
|
|
87
|
+
return app;
|
|
88
|
+
}
|
|
89
|
+
/** Resolve one v1 app-local Skill without profile/global fallback. */
|
|
90
|
+
requireLocalSkillSource(appName, skillName) {
|
|
91
|
+
assertSafeAppName(appName);
|
|
92
|
+
if (!/^[a-z0-9][a-z0-9_-]*$/.test(skillName)) {
|
|
93
|
+
throw MarifoldError_1.MarifoldError.appInvalid(`Invalid app-local skill name '${skillName}'.`);
|
|
94
|
+
}
|
|
95
|
+
const bundle = path.join(this.directory, appName);
|
|
96
|
+
const source = path.join(bundle, 'skills', skillName, 'SKILL.md');
|
|
97
|
+
if (!fs.existsSync(source))
|
|
98
|
+
throw MarifoldError_1.MarifoldError.skillNotFound(skillName);
|
|
99
|
+
return requireConfinedFile(bundle, source, `App-local skill '${skillName}'`);
|
|
100
|
+
}
|
|
101
|
+
validateLocalSkills(appName, definition) {
|
|
102
|
+
for (const registered of definition.skills) {
|
|
103
|
+
const source = this.requireLocalSkillSource(appName, registered.name);
|
|
104
|
+
const skill = (0, SkillValidator_1.parseSkill)(fs.readFileSync(source, 'utf-8'), source);
|
|
105
|
+
if (skill.name !== registered.name) {
|
|
106
|
+
throw MarifoldError_1.MarifoldError.appInvalid(`App-local Skill folder '${registered.name}' contains Skill '${skill.name}'. Names must match.`, source);
|
|
107
|
+
}
|
|
108
|
+
if (skill.mode && skill.mode !== 'chat') {
|
|
109
|
+
throw MarifoldError_1.MarifoldError.appInvalid(`SkillApp v1 only supports chat-mode Skills; '${skill.name}' uses '${skill.mode}'.`, source);
|
|
110
|
+
}
|
|
111
|
+
const variables = new Set(skill.variables.map(variable => variable.name));
|
|
112
|
+
for (const operation of definition.operations.filter(candidate => candidate.skill === registered.name)) {
|
|
113
|
+
const parameters = new Set(Object.keys(operation.parameters));
|
|
114
|
+
const unknown = [...parameters].filter(name => !variables.has(name));
|
|
115
|
+
if (unknown.length > 0) {
|
|
116
|
+
throw MarifoldError_1.MarifoldError.appInvalid(`SkillApp operation '${operation.name}' supplies unknown Skill parameter(s): ${unknown.join(', ')}.`, source);
|
|
117
|
+
}
|
|
118
|
+
const missing = skill.variables
|
|
119
|
+
.filter(variable => variable.required && variable.default === undefined && !parameters.has(variable.name))
|
|
120
|
+
.map(variable => variable.name);
|
|
121
|
+
if (missing.length > 0) {
|
|
122
|
+
throw MarifoldError_1.MarifoldError.appInvalid(`SkillApp operation '${operation.name}' does not bind required Skill parameter(s): ${missing.join(', ')}.`, source);
|
|
123
|
+
}
|
|
124
|
+
operation.requiredInputs = [...new Set(skill.variables
|
|
125
|
+
.filter(variable => variable.required && variable.default === undefined)
|
|
126
|
+
.map(variable => operation.parameters[variable.name]))];
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
exports.AppStore = AppStore;
|
|
132
|
+
function requireConfinedFile(bundle, source, label) {
|
|
133
|
+
const bundleRoot = fs.realpathSync(bundle);
|
|
134
|
+
const realSource = fs.realpathSync(source);
|
|
135
|
+
const relative = path.relative(bundleRoot, realSource);
|
|
136
|
+
if (relative === '..' || relative.startsWith(`..${path.sep}`) || path.isAbsolute(relative)) {
|
|
137
|
+
throw MarifoldError_1.MarifoldError.appInvalid(`${label} escapes bundle confinement.`, source);
|
|
138
|
+
}
|
|
139
|
+
return realSource;
|
|
140
|
+
}
|
|
141
|
+
function assertSafeAppName(name) {
|
|
142
|
+
if (!SAFE_APP_NAME.test(name)) {
|
|
143
|
+
throw MarifoldError_1.MarifoldError.appInvalid(`Invalid App name '${name}'.`);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
//# sourceMappingURL=AppStore.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AppStore.js","sourceRoot":"","sources":["../../src/app/AppStore.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { AppDefinition } from './AppSchema';
|
|
2
|
+
export interface AppValidationResult {
|
|
3
|
+
ok: boolean;
|
|
4
|
+
definition?: AppDefinition;
|
|
5
|
+
errors: string[];
|
|
6
|
+
}
|
|
7
|
+
/** Parse and validate an App TOML document (docs/app.md, v0 rules). */
|
|
8
|
+
export declare function validateAppToml(source: string): AppValidationResult;
|
|
9
|
+
export declare function validateApp(raw: Record<string, unknown>): AppValidationResult;
|
|
10
|
+
//# sourceMappingURL=AppValidator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AppValidator.d.ts","sourceRoot":"","sources":["../../src/app/AppValidator.ts"],"names":[],"mappings":"AACA,OAAO,EAQL,aAAa,EAWd,MAAM,aAAa,CAAC;AAqBrB,MAAM,WAAW,mBAAmB;IAClC,EAAE,EAAE,OAAO,CAAC;IACZ,UAAU,CAAC,EAAE,aAAa,CAAC;IAC3B,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB;AAED,uEAAuE;AACvE,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,mBAAmB,CAQnE;AAED,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,mBAAmB,CA0B7E"}
|
|
@@ -0,0 +1,503 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.validateAppToml = validateAppToml;
|
|
4
|
+
exports.validateApp = validateApp;
|
|
5
|
+
const smol_toml_1 = require("smol-toml");
|
|
6
|
+
const AppSchema_1 = require("./AppSchema");
|
|
7
|
+
const KEBAB_CASE = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
|
|
8
|
+
const SNAKE_CASE = /^[a-z0-9]+(?:_[a-z0-9]+)*$/;
|
|
9
|
+
const SKILL_NAME = /^[a-z0-9][a-z0-9_-]*$/;
|
|
10
|
+
const PROFILE_NAME = /^[A-Za-z0-9_-]+$/;
|
|
11
|
+
const SEMVER = /^(?:0|[1-9]\d*)\.(?:0|[1-9]\d*)\.(?:0|[1-9]\d*)(?:-[0-9A-Za-z.-]+)?$/;
|
|
12
|
+
const TEMPLATE_PLACEHOLDER = /\{\{\s*([a-z0-9_]+)\s*\}\}/g;
|
|
13
|
+
const VARIABLE_TYPES = new Set(['string', 'number', 'boolean', 'enum']);
|
|
14
|
+
const VARIABLE_ROLES = new Set(['input', 'output', 'state']);
|
|
15
|
+
const COMPONENTS = new Set([
|
|
16
|
+
'row', 'column', 'spacer', 'text', 'text_input', 'textarea', 'select', 'preview', 'tabs', 'file_picker', 'button',
|
|
17
|
+
'download_button',
|
|
18
|
+
]);
|
|
19
|
+
const ACTION_KINDS = new Set(['skill']);
|
|
20
|
+
const FILES_PERMISSIONS = new Set(['none', 'read', 'write']);
|
|
21
|
+
const LAYOUT_GAPS = new Set(['none', 'small', 'medium', 'large']);
|
|
22
|
+
const RESPONSIVE_BEHAVIORS = new Set(['stack']);
|
|
23
|
+
const MAX_LAYOUT_DEPTH = 4;
|
|
24
|
+
const MAX_LAYOUT_ITEMS = 100;
|
|
25
|
+
/** Parse and validate an App TOML document (docs/app.md, v0 rules). */
|
|
26
|
+
function validateAppToml(source) {
|
|
27
|
+
let raw;
|
|
28
|
+
try {
|
|
29
|
+
raw = (0, smol_toml_1.parse)(source);
|
|
30
|
+
}
|
|
31
|
+
catch (error) {
|
|
32
|
+
return { ok: false, errors: [`Invalid TOML: ${error instanceof Error ? error.message : String(error)}`] };
|
|
33
|
+
}
|
|
34
|
+
return validateApp(raw);
|
|
35
|
+
}
|
|
36
|
+
function validateApp(raw) {
|
|
37
|
+
const errors = [];
|
|
38
|
+
if (raw.schema !== AppSchema_1.APP_SCHEMA) {
|
|
39
|
+
errors.push(`schema must be "${AppSchema_1.APP_SCHEMA}".`);
|
|
40
|
+
}
|
|
41
|
+
const app = readApp(raw.app, errors);
|
|
42
|
+
const actors = readActors(raw.actors, errors);
|
|
43
|
+
const variables = readVariables(raw.variables, errors);
|
|
44
|
+
const execution = readExecution(raw.execution, errors);
|
|
45
|
+
const permissions = readPermissions(raw.permissions, errors);
|
|
46
|
+
const actions = readActions(raw.actions, actors, variables, permissions, errors);
|
|
47
|
+
const layout = readLayout(raw.layout, variables, actions, permissions, errors, {
|
|
48
|
+
depth: 0,
|
|
49
|
+
insideTabs: false,
|
|
50
|
+
count: { value: 0 },
|
|
51
|
+
path: 'layout',
|
|
52
|
+
});
|
|
53
|
+
if (errors.length > 0)
|
|
54
|
+
return { ok: false, errors };
|
|
55
|
+
return {
|
|
56
|
+
ok: true,
|
|
57
|
+
errors: [],
|
|
58
|
+
definition: { schema: AppSchema_1.APP_SCHEMA, app: app, actors, variables, layout, actions, execution, permissions },
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
function readApp(value, errors) {
|
|
62
|
+
const app = asTable(value);
|
|
63
|
+
if (!app) {
|
|
64
|
+
errors.push('[app] table is required.');
|
|
65
|
+
return undefined;
|
|
66
|
+
}
|
|
67
|
+
const name = asString(app.name);
|
|
68
|
+
const title = asString(app.title);
|
|
69
|
+
if (!name || !KEBAB_CASE.test(name))
|
|
70
|
+
errors.push('app.name is required and must be kebab-case.');
|
|
71
|
+
if (!title)
|
|
72
|
+
errors.push('app.title is required.');
|
|
73
|
+
const version = asString(app.version);
|
|
74
|
+
if (version && !SEMVER.test(version))
|
|
75
|
+
errors.push('app.version must use Semantic Versioning without a "v" prefix.');
|
|
76
|
+
const description = asString(app.description);
|
|
77
|
+
if (!name || !title)
|
|
78
|
+
return undefined;
|
|
79
|
+
return {
|
|
80
|
+
name,
|
|
81
|
+
title,
|
|
82
|
+
...(version ? { version } : {}),
|
|
83
|
+
...(description ? { description } : {}),
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
function readActors(value, errors) {
|
|
87
|
+
const items = asArrayOfTables(value);
|
|
88
|
+
if (!items)
|
|
89
|
+
return [];
|
|
90
|
+
const seen = new Set();
|
|
91
|
+
const actors = [];
|
|
92
|
+
items.forEach((item, index) => {
|
|
93
|
+
const label = `actors[${index}]`;
|
|
94
|
+
const name = asString(item.name);
|
|
95
|
+
if (!name || !SNAKE_CASE.test(name)) {
|
|
96
|
+
errors.push(`${label}.name is required and must be snake_case.`);
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
if (seen.has(name)) {
|
|
100
|
+
errors.push(`Duplicate actor name '${name}'.`);
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
seen.add(name);
|
|
104
|
+
const profile = asString(item.profile);
|
|
105
|
+
if (!profile || !PROFILE_NAME.test(profile)) {
|
|
106
|
+
errors.push(`${label}.profile is required and must be a valid profile name.`);
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
actors.push({
|
|
110
|
+
name,
|
|
111
|
+
profile,
|
|
112
|
+
...(asString(item.label) ? { label: asString(item.label) } : {}),
|
|
113
|
+
});
|
|
114
|
+
});
|
|
115
|
+
return actors;
|
|
116
|
+
}
|
|
117
|
+
function readVariables(value, errors) {
|
|
118
|
+
const items = asArrayOfTables(value);
|
|
119
|
+
if (!items || items.length === 0) {
|
|
120
|
+
errors.push('At least one [[variables]] entry is required.');
|
|
121
|
+
return [];
|
|
122
|
+
}
|
|
123
|
+
const seen = new Set();
|
|
124
|
+
const variables = [];
|
|
125
|
+
items.forEach((item, index) => {
|
|
126
|
+
const label = `variables[${index}]`;
|
|
127
|
+
const name = asString(item.name);
|
|
128
|
+
if (!name || !SNAKE_CASE.test(name)) {
|
|
129
|
+
errors.push(`${label}.name is required and must be snake_case.`);
|
|
130
|
+
return;
|
|
131
|
+
}
|
|
132
|
+
if (seen.has(name)) {
|
|
133
|
+
errors.push(`Duplicate variable name '${name}'.`);
|
|
134
|
+
return;
|
|
135
|
+
}
|
|
136
|
+
seen.add(name);
|
|
137
|
+
const type = asString(item.type);
|
|
138
|
+
if (!type || !VARIABLE_TYPES.has(type)) {
|
|
139
|
+
errors.push(`${label}.type must be string, number, boolean, or enum.`);
|
|
140
|
+
return;
|
|
141
|
+
}
|
|
142
|
+
const role = asString(item.role);
|
|
143
|
+
if (!role || !VARIABLE_ROLES.has(role)) {
|
|
144
|
+
errors.push(`${label}.role must be input, output, or state.`);
|
|
145
|
+
return;
|
|
146
|
+
}
|
|
147
|
+
const options = item.options;
|
|
148
|
+
if (type === 'enum') {
|
|
149
|
+
if (!Array.isArray(options) || options.length === 0 || !options.every(o => typeof o === 'string')) {
|
|
150
|
+
errors.push(`${label}.options must be a non-empty string array for enum variables.`);
|
|
151
|
+
return;
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
else if (options !== undefined) {
|
|
155
|
+
errors.push(`${label}.options is only allowed for enum variables.`);
|
|
156
|
+
return;
|
|
157
|
+
}
|
|
158
|
+
const variable = {
|
|
159
|
+
name,
|
|
160
|
+
type,
|
|
161
|
+
role,
|
|
162
|
+
...(asString(item.label) ? { label: asString(item.label) } : {}),
|
|
163
|
+
...(typeof item.required === 'boolean' ? { required: item.required } : {}),
|
|
164
|
+
...(item.default !== undefined ? { default: item.default } : {}),
|
|
165
|
+
...(type === 'enum' ? { options: options } : {}),
|
|
166
|
+
};
|
|
167
|
+
if (item.required !== undefined && typeof item.required !== 'boolean') {
|
|
168
|
+
errors.push(`${label}.required must be a boolean.`);
|
|
169
|
+
return;
|
|
170
|
+
}
|
|
171
|
+
if (variable.default !== undefined && !defaultMatchesType(variable)) {
|
|
172
|
+
errors.push(`${label}.default does not match type '${type}'.`);
|
|
173
|
+
return;
|
|
174
|
+
}
|
|
175
|
+
variables.push(variable);
|
|
176
|
+
});
|
|
177
|
+
return variables;
|
|
178
|
+
}
|
|
179
|
+
function defaultMatchesType(variable) {
|
|
180
|
+
const value = variable.default;
|
|
181
|
+
switch (variable.type) {
|
|
182
|
+
case 'string': return typeof value === 'string';
|
|
183
|
+
case 'number': return typeof value === 'number';
|
|
184
|
+
case 'boolean': return typeof value === 'boolean';
|
|
185
|
+
case 'enum': return typeof value === 'string' && (variable.options ?? []).includes(value);
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
function readExecution(value, errors) {
|
|
189
|
+
const table = asTable(value);
|
|
190
|
+
if (!table)
|
|
191
|
+
return { ...AppSchema_1.DEFAULT_APP_EXECUTION };
|
|
192
|
+
const readBool = (key, fallback) => {
|
|
193
|
+
const raw = table[key];
|
|
194
|
+
if (raw === undefined)
|
|
195
|
+
return fallback;
|
|
196
|
+
if (typeof raw !== 'boolean') {
|
|
197
|
+
errors.push(`execution.${key} must be a boolean.`);
|
|
198
|
+
return fallback;
|
|
199
|
+
}
|
|
200
|
+
return raw;
|
|
201
|
+
};
|
|
202
|
+
if (table.history !== undefined) {
|
|
203
|
+
errors.push('execution.history is not supported; App actions never use Agent transcripts.');
|
|
204
|
+
}
|
|
205
|
+
return {
|
|
206
|
+
think: readBool('think', AppSchema_1.DEFAULT_APP_EXECUTION.think),
|
|
207
|
+
memory: readBool('memory', AppSchema_1.DEFAULT_APP_EXECUTION.memory),
|
|
208
|
+
profileContext: readBool('profile_context', AppSchema_1.DEFAULT_APP_EXECUTION.profileContext),
|
|
209
|
+
};
|
|
210
|
+
}
|
|
211
|
+
function readPermissions(value, errors) {
|
|
212
|
+
const table = asTable(value);
|
|
213
|
+
if (!table)
|
|
214
|
+
return { ...AppSchema_1.DEFAULT_APP_PERMISSIONS };
|
|
215
|
+
const files = table.files === undefined ? AppSchema_1.DEFAULT_APP_PERMISSIONS.files : asString(table.files);
|
|
216
|
+
if (!FILES_PERMISSIONS.has(files)) {
|
|
217
|
+
errors.push('permissions.files must be "none", "read", or "write".');
|
|
218
|
+
}
|
|
219
|
+
const readBool = (key, fallback) => {
|
|
220
|
+
const raw = table[key];
|
|
221
|
+
if (raw === undefined)
|
|
222
|
+
return fallback;
|
|
223
|
+
if (typeof raw !== 'boolean') {
|
|
224
|
+
errors.push(`permissions.${key} must be a boolean.`);
|
|
225
|
+
return fallback;
|
|
226
|
+
}
|
|
227
|
+
return raw;
|
|
228
|
+
};
|
|
229
|
+
return {
|
|
230
|
+
providerCalls: readBool('provider_calls', AppSchema_1.DEFAULT_APP_PERMISSIONS.providerCalls),
|
|
231
|
+
files: FILES_PERMISSIONS.has(files) ? files : AppSchema_1.DEFAULT_APP_PERMISSIONS.files,
|
|
232
|
+
shell: readBool('shell', AppSchema_1.DEFAULT_APP_PERMISSIONS.shell),
|
|
233
|
+
network: readBool('network', AppSchema_1.DEFAULT_APP_PERMISSIONS.network),
|
|
234
|
+
export: readBool('export', AppSchema_1.DEFAULT_APP_PERMISSIONS.export),
|
|
235
|
+
};
|
|
236
|
+
}
|
|
237
|
+
function readActions(value, actors, variables, permissions, errors) {
|
|
238
|
+
const items = asArrayOfTables(value);
|
|
239
|
+
if (!items)
|
|
240
|
+
return [];
|
|
241
|
+
const actorNames = new Set(actors.map(actor => actor.name));
|
|
242
|
+
const variableNames = new Set(variables.map(v => v.name));
|
|
243
|
+
const writableNames = new Set(variables.filter(v => v.role !== 'input').map(v => v.name));
|
|
244
|
+
const seen = new Set();
|
|
245
|
+
const actions = [];
|
|
246
|
+
items.forEach((item, index) => {
|
|
247
|
+
const label = `actions[${index}]`;
|
|
248
|
+
const name = asString(item.name);
|
|
249
|
+
if (!name || !SNAKE_CASE.test(name)) {
|
|
250
|
+
errors.push(`${label}.name is required and must be snake_case.`);
|
|
251
|
+
return;
|
|
252
|
+
}
|
|
253
|
+
if (seen.has(name)) {
|
|
254
|
+
errors.push(`Duplicate action name '${name}'.`);
|
|
255
|
+
return;
|
|
256
|
+
}
|
|
257
|
+
seen.add(name);
|
|
258
|
+
const kind = asString(item.kind);
|
|
259
|
+
if (!kind || !ACTION_KINDS.has(kind)) {
|
|
260
|
+
errors.push(`${label}.kind must be skill.`);
|
|
261
|
+
return;
|
|
262
|
+
}
|
|
263
|
+
const output = asString(item.output);
|
|
264
|
+
if (!output || !variableNames.has(output)) {
|
|
265
|
+
errors.push(`${label}.output must reference a declared variable.`);
|
|
266
|
+
return;
|
|
267
|
+
}
|
|
268
|
+
if (!writableNames.has(output)) {
|
|
269
|
+
errors.push(`${label}.output must reference an output or state variable, not an input.`);
|
|
270
|
+
return;
|
|
271
|
+
}
|
|
272
|
+
if (!permissions.providerCalls) {
|
|
273
|
+
errors.push(`${label} requires permissions.provider_calls = true.`);
|
|
274
|
+
return;
|
|
275
|
+
}
|
|
276
|
+
const actor = asString(item.actor);
|
|
277
|
+
if (!actor || !actorNames.has(actor)) {
|
|
278
|
+
errors.push(`${label}.actor must reference a declared actor.`);
|
|
279
|
+
return;
|
|
280
|
+
}
|
|
281
|
+
const skill = asString(item.skill);
|
|
282
|
+
if (!skill || !SKILL_NAME.test(skill)) {
|
|
283
|
+
errors.push(`${label}.skill is required and must be a valid skill name.`);
|
|
284
|
+
return;
|
|
285
|
+
}
|
|
286
|
+
const argumentsTable = asTable(item.arguments);
|
|
287
|
+
if (!argumentsTable) {
|
|
288
|
+
errors.push(`${label}.arguments is required for skill actions.`);
|
|
289
|
+
return;
|
|
290
|
+
}
|
|
291
|
+
const actionArguments = {};
|
|
292
|
+
for (const [key, argumentValue] of Object.entries(argumentsTable)) {
|
|
293
|
+
if (!SNAKE_CASE.test(key)) {
|
|
294
|
+
errors.push(`${label}.arguments key '${key}' must be snake_case.`);
|
|
295
|
+
continue;
|
|
296
|
+
}
|
|
297
|
+
if (!isVariableValue(argumentValue)) {
|
|
298
|
+
errors.push(`${label}.arguments.${key} must be a string, number, or boolean.`);
|
|
299
|
+
continue;
|
|
300
|
+
}
|
|
301
|
+
if (typeof argumentValue === 'string') {
|
|
302
|
+
checkTemplate(argumentValue, variableNames, `${label}.arguments.${key}`, errors);
|
|
303
|
+
}
|
|
304
|
+
actionArguments[key] = argumentValue;
|
|
305
|
+
}
|
|
306
|
+
actions.push({ name, kind, actor, skill, arguments: actionArguments, output });
|
|
307
|
+
});
|
|
308
|
+
return actions;
|
|
309
|
+
}
|
|
310
|
+
function readLayout(value, variables, actions, permissions, errors, context) {
|
|
311
|
+
if (context.depth > MAX_LAYOUT_DEPTH) {
|
|
312
|
+
errors.push(`${context.path} exceeds the maximum layout depth of ${MAX_LAYOUT_DEPTH}.`);
|
|
313
|
+
return [];
|
|
314
|
+
}
|
|
315
|
+
const items = asArrayOfTables(value);
|
|
316
|
+
if (!items || items.length === 0) {
|
|
317
|
+
errors.push(`${context.path} must contain at least one layout item.`);
|
|
318
|
+
return [];
|
|
319
|
+
}
|
|
320
|
+
const variableByName = new Map(variables.map(v => [v.name, v]));
|
|
321
|
+
const actionNames = new Set(actions.map(a => a.name));
|
|
322
|
+
const layout = [];
|
|
323
|
+
items.forEach((item, index) => {
|
|
324
|
+
const label = `${context.path}[${index}]`;
|
|
325
|
+
context.count.value += 1;
|
|
326
|
+
if (context.count.value > MAX_LAYOUT_ITEMS) {
|
|
327
|
+
if (context.count.value === MAX_LAYOUT_ITEMS + 1) {
|
|
328
|
+
errors.push(`Layout exceeds the maximum of ${MAX_LAYOUT_ITEMS} items.`);
|
|
329
|
+
}
|
|
330
|
+
return;
|
|
331
|
+
}
|
|
332
|
+
const component = asString(item.component);
|
|
333
|
+
if (!component || !COMPONENTS.has(component)) {
|
|
334
|
+
errors.push(`${label}.component must be one of: ${[...COMPONENTS].join(', ')}.`);
|
|
335
|
+
return;
|
|
336
|
+
}
|
|
337
|
+
const gap = asString(item.gap);
|
|
338
|
+
if (gap && !LAYOUT_GAPS.has(gap))
|
|
339
|
+
errors.push(`${label}.gap must be none, small, medium, or large.`);
|
|
340
|
+
const responsive = asString(item.responsive);
|
|
341
|
+
if (responsive && !RESPONSIVE_BEHAVIORS.has(responsive)) {
|
|
342
|
+
errors.push(`${label}.responsive must be stack.`);
|
|
343
|
+
}
|
|
344
|
+
if (item.grow !== undefined && typeof item.grow !== 'boolean') {
|
|
345
|
+
errors.push(`${label}.grow must be a boolean.`);
|
|
346
|
+
}
|
|
347
|
+
if (item.show_label !== undefined && typeof item.show_label !== 'boolean') {
|
|
348
|
+
errors.push(`${label}.show_label must be a boolean.`);
|
|
349
|
+
}
|
|
350
|
+
const labelControl = component === 'text_input' || component === 'textarea' || component === 'select';
|
|
351
|
+
if (item.show_label !== undefined && !labelControl) {
|
|
352
|
+
errors.push(`${label}.show_label is only allowed on text_input, textarea, or select.`);
|
|
353
|
+
}
|
|
354
|
+
const entry = {
|
|
355
|
+
component,
|
|
356
|
+
...(asString(item.bind) ? { bind: asString(item.bind) } : {}),
|
|
357
|
+
...(asString(item.label) ? { label: asString(item.label) } : {}),
|
|
358
|
+
...(asString(item.action) ? { action: asString(item.action) } : {}),
|
|
359
|
+
...(asString(item.content) ? { content: asString(item.content) } : {}),
|
|
360
|
+
...(asString(item.format) ? { format: asString(item.format) } : {}),
|
|
361
|
+
...(typeof item.show_label === 'boolean' ? { showLabel: item.show_label } : {}),
|
|
362
|
+
...(gap && LAYOUT_GAPS.has(gap) ? { gap } : {}),
|
|
363
|
+
...(responsive && RESPONSIVE_BEHAVIORS.has(responsive) ? { responsive } : {}),
|
|
364
|
+
...(typeof item.grow === 'boolean' ? { grow: item.grow } : {}),
|
|
365
|
+
};
|
|
366
|
+
switch (component) {
|
|
367
|
+
case 'row':
|
|
368
|
+
case 'column': {
|
|
369
|
+
const children = asArrayOfTables(item.children);
|
|
370
|
+
if (!children || children.length === 0) {
|
|
371
|
+
errors.push(`${label} (${component}) requires a non-empty children array.`);
|
|
372
|
+
break;
|
|
373
|
+
}
|
|
374
|
+
entry.children = readLayout(children, variables, actions, permissions, errors, {
|
|
375
|
+
...context,
|
|
376
|
+
depth: context.depth + 1,
|
|
377
|
+
path: `${label}.children`,
|
|
378
|
+
});
|
|
379
|
+
break;
|
|
380
|
+
}
|
|
381
|
+
case 'spacer':
|
|
382
|
+
break;
|
|
383
|
+
case 'text':
|
|
384
|
+
if (!entry.content)
|
|
385
|
+
errors.push(`${label} (text) requires content.`);
|
|
386
|
+
break;
|
|
387
|
+
case 'button':
|
|
388
|
+
if (!entry.action || !actionNames.has(entry.action)) {
|
|
389
|
+
errors.push(`${label} (button) requires action referencing a declared action.`);
|
|
390
|
+
}
|
|
391
|
+
break;
|
|
392
|
+
case 'tabs': {
|
|
393
|
+
if (context.insideTabs) {
|
|
394
|
+
errors.push(`${label}: tabs cannot be nested.`);
|
|
395
|
+
break;
|
|
396
|
+
}
|
|
397
|
+
if (!Array.isArray(item.tabs) || item.tabs.length === 0) {
|
|
398
|
+
errors.push(`${label} (tabs) requires a non-empty tabs array.`);
|
|
399
|
+
break;
|
|
400
|
+
}
|
|
401
|
+
entry.tabs = item.tabs.map((tab, tabIndex) => readLayout(tab, variables, actions, permissions, errors, {
|
|
402
|
+
...context,
|
|
403
|
+
depth: context.depth + 1,
|
|
404
|
+
insideTabs: true,
|
|
405
|
+
path: `${label}.tabs[${tabIndex}]`,
|
|
406
|
+
}));
|
|
407
|
+
break;
|
|
408
|
+
}
|
|
409
|
+
case 'file_picker': {
|
|
410
|
+
if (permissions.files === 'none')
|
|
411
|
+
errors.push(`${label} (file_picker) requires permissions.files of read or write.`);
|
|
412
|
+
const variable = requireBind(entry, variableByName, label, errors);
|
|
413
|
+
requireWritableVariable(variable, label, errors);
|
|
414
|
+
break;
|
|
415
|
+
}
|
|
416
|
+
case 'download_button':
|
|
417
|
+
if (!permissions.export)
|
|
418
|
+
errors.push(`${label} (download_button) requires permissions.export = true.`);
|
|
419
|
+
requireBind(entry, variableByName, label, errors);
|
|
420
|
+
break;
|
|
421
|
+
case 'select': {
|
|
422
|
+
const variable = requireBind(entry, variableByName, label, errors);
|
|
423
|
+
if (variable && variable.type !== 'enum')
|
|
424
|
+
errors.push(`${label} (select) must bind an enum variable.`);
|
|
425
|
+
requireWritableVariable(variable, label, errors);
|
|
426
|
+
break;
|
|
427
|
+
}
|
|
428
|
+
case 'textarea': {
|
|
429
|
+
const variable = requireBind(entry, variableByName, label, errors);
|
|
430
|
+
if (variable && variable.type !== 'string')
|
|
431
|
+
errors.push(`${label} (textarea) must bind a string variable.`);
|
|
432
|
+
requireWritableVariable(variable, label, errors);
|
|
433
|
+
break;
|
|
434
|
+
}
|
|
435
|
+
case 'text_input': {
|
|
436
|
+
const variable = requireBind(entry, variableByName, label, errors);
|
|
437
|
+
if (variable && variable.type !== 'string' && variable.type !== 'number') {
|
|
438
|
+
errors.push(`${label} (text_input) must bind a string or number variable.`);
|
|
439
|
+
}
|
|
440
|
+
requireWritableVariable(variable, label, errors);
|
|
441
|
+
break;
|
|
442
|
+
}
|
|
443
|
+
case 'preview':
|
|
444
|
+
if (entry.format && entry.format !== 'text' && entry.format !== 'markdown') {
|
|
445
|
+
errors.push(`${label} (preview) format must be text or markdown.`);
|
|
446
|
+
}
|
|
447
|
+
requireBind(entry, variableByName, label, errors);
|
|
448
|
+
break;
|
|
449
|
+
}
|
|
450
|
+
layout.push(entry);
|
|
451
|
+
});
|
|
452
|
+
return layout;
|
|
453
|
+
}
|
|
454
|
+
function requireWritableVariable(variable, label, errors) {
|
|
455
|
+
if (variable?.role === 'output') {
|
|
456
|
+
errors.push(`${label} cannot edit output variable '${variable.name}'. Use preview instead.`);
|
|
457
|
+
}
|
|
458
|
+
}
|
|
459
|
+
function requireBind(entry, variables, label, errors) {
|
|
460
|
+
if (!entry.bind) {
|
|
461
|
+
errors.push(`${label} (${entry.component}) requires bind.`);
|
|
462
|
+
return undefined;
|
|
463
|
+
}
|
|
464
|
+
const variable = variables.get(entry.bind);
|
|
465
|
+
if (!variable) {
|
|
466
|
+
errors.push(`${label}.bind references unknown variable '${entry.bind}'.`);
|
|
467
|
+
return undefined;
|
|
468
|
+
}
|
|
469
|
+
return variable;
|
|
470
|
+
}
|
|
471
|
+
function checkTemplate(template, variableNames, label, errors) {
|
|
472
|
+
for (const match of template.matchAll(TEMPLATE_PLACEHOLDER)) {
|
|
473
|
+
if (!variableNames.has(match[1])) {
|
|
474
|
+
errors.push(`${label} references unknown variable '{{${match[1]}}}'.`);
|
|
475
|
+
}
|
|
476
|
+
}
|
|
477
|
+
}
|
|
478
|
+
function isVariableValue(value) {
|
|
479
|
+
return typeof value === 'string'
|
|
480
|
+
|| typeof value === 'boolean'
|
|
481
|
+
|| (typeof value === 'number' && Number.isFinite(value));
|
|
482
|
+
}
|
|
483
|
+
function asTable(value) {
|
|
484
|
+
if (typeof value === 'object' && value !== null && !Array.isArray(value))
|
|
485
|
+
return value;
|
|
486
|
+
return undefined;
|
|
487
|
+
}
|
|
488
|
+
function asArrayOfTables(value) {
|
|
489
|
+
if (!Array.isArray(value))
|
|
490
|
+
return undefined;
|
|
491
|
+
const tables = [];
|
|
492
|
+
for (const item of value) {
|
|
493
|
+
const table = asTable(item);
|
|
494
|
+
if (!table)
|
|
495
|
+
return undefined;
|
|
496
|
+
tables.push(table);
|
|
497
|
+
}
|
|
498
|
+
return tables;
|
|
499
|
+
}
|
|
500
|
+
function asString(value) {
|
|
501
|
+
return typeof value === 'string' && value.trim() ? value : undefined;
|
|
502
|
+
}
|
|
503
|
+
//# sourceMappingURL=AppValidator.js.map
|