@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,1099 @@
|
|
|
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.MarifoldRuntime = void 0;
|
|
37
|
+
const core_1 = require("@priest-ai/core");
|
|
38
|
+
const path = __importStar(require("path"));
|
|
39
|
+
const AgentRunner_1 = require("../agent/AgentRunner");
|
|
40
|
+
const AgentHistory_1 = require("../agent/AgentHistory");
|
|
41
|
+
const ApprovalPolicy_1 = require("../agent/ApprovalPolicy");
|
|
42
|
+
const DelegateTool_1 = require("../agent/tools/DelegateTool");
|
|
43
|
+
const PythonPackageTool_1 = require("../agent/tools/PythonPackageTool");
|
|
44
|
+
const ReadFileTool_1 = require("../agent/tools/ReadFileTool");
|
|
45
|
+
const ShellExecTool_1 = require("../agent/tools/ShellExecTool");
|
|
46
|
+
const WebSearchTool_1 = require("../agent/tools/WebSearchTool");
|
|
47
|
+
const AskUserTool_1 = require("../agent/tools/AskUserTool");
|
|
48
|
+
const InspectAttachmentTool_1 = require("../agent/tools/InspectAttachmentTool");
|
|
49
|
+
const WriteFileTool_1 = require("../agent/tools/WriteFileTool");
|
|
50
|
+
const ToolRegistry_1 = require("../agent/ToolRegistry");
|
|
51
|
+
const ChatGptTokenRefresh_1 = require("../config/ChatGptTokenRefresh");
|
|
52
|
+
const XaiTokenRefresh_1 = require("../config/XaiTokenRefresh");
|
|
53
|
+
const ConfigManager_1 = require("../config/ConfigManager");
|
|
54
|
+
const ConfigSchema_1 = require("../config/ConfigSchema");
|
|
55
|
+
const ProviderInspector_1 = require("../config/ProviderInspector");
|
|
56
|
+
const GitHubCopilotAuth_1 = require("../config/GitHubCopilotAuth");
|
|
57
|
+
const createSearchBackend_1 = require("../search/createSearchBackend");
|
|
58
|
+
const SearchBackend_1 = require("../search/SearchBackend");
|
|
59
|
+
const ProviderFactory_1 = require("../config/ProviderFactory");
|
|
60
|
+
const ProviderRegistry_1 = require("../config/ProviderRegistry");
|
|
61
|
+
const MarifoldError_1 = require("../errors/MarifoldError");
|
|
62
|
+
const ImageOptimizer_1 = require("../images/ImageOptimizer");
|
|
63
|
+
const MemoryStore_1 = require("../memory/MemoryStore");
|
|
64
|
+
const MemoryControls_1 = require("../memory/MemoryControls");
|
|
65
|
+
const ProfileResolver_1 = require("../profiles/ProfileResolver");
|
|
66
|
+
const ProfileManager_1 = require("../profiles/ProfileManager");
|
|
67
|
+
const Scheduler_1 = require("../schedule/Scheduler");
|
|
68
|
+
const RunRegistry_1 = require("../runs/RunRegistry");
|
|
69
|
+
const TelegramBridge_1 = require("../channels/TelegramBridge");
|
|
70
|
+
const ScheduleStore_1 = require("../schedule/ScheduleStore");
|
|
71
|
+
const SessionResolver_1 = require("../sessions/SessionResolver");
|
|
72
|
+
const SkillStore_1 = require("../skill/SkillStore");
|
|
73
|
+
const SkillInvocation_1 = require("../skill/SkillInvocation");
|
|
74
|
+
const BuiltInSkillManager_1 = require("../skill/BuiltInSkillManager");
|
|
75
|
+
const AppStore_1 = require("../app/AppStore");
|
|
76
|
+
const SkillAppResolver_1 = require("../app/SkillAppResolver");
|
|
77
|
+
const SkillAppInstanceRegistry_1 = require("../app/SkillAppInstanceRegistry");
|
|
78
|
+
const TaskStore_1 = require("../tasks/TaskStore");
|
|
79
|
+
const WorkspacePaths_1 = require("../workspace/WorkspacePaths");
|
|
80
|
+
// Older OpenAI-compatible gateways still take a raw `{think}` body option.
|
|
81
|
+
// Priest 2.8 owns neutral reasoning for Ollama, Anthropic, and Responses.
|
|
82
|
+
const LEGACY_THINK_PROVIDER_NAMES = new Set(['bailian', 'alibaba_cloud']);
|
|
83
|
+
const CHAT_TOOL_MAX_ITERATIONS = 3;
|
|
84
|
+
const EDIT_HISTORY_BUDGET_DEFAULT_CHARS = 16_000;
|
|
85
|
+
class MarifoldRuntime {
|
|
86
|
+
options;
|
|
87
|
+
profileResolver;
|
|
88
|
+
profileManager;
|
|
89
|
+
sessionResolver;
|
|
90
|
+
providerFactory;
|
|
91
|
+
memoryStore;
|
|
92
|
+
taskStore;
|
|
93
|
+
searchBackend;
|
|
94
|
+
scheduleStore;
|
|
95
|
+
constructor(options) {
|
|
96
|
+
this.options = options;
|
|
97
|
+
const { config, configPath } = options.loadedConfig;
|
|
98
|
+
this.profileResolver = new ProfileResolver_1.ProfileResolver(config.paths.profilesDir);
|
|
99
|
+
this.profileManager = new ProfileManager_1.ProfileManager(config.paths.profilesDir);
|
|
100
|
+
this.sessionResolver = new SessionResolver_1.SessionResolver(config.paths.sessionsDb);
|
|
101
|
+
this.providerFactory = new ProviderFactory_1.ProviderFactory(config, configPath);
|
|
102
|
+
this.memoryStore = new MemoryStore_1.MemoryStore(config.paths.profilesDir);
|
|
103
|
+
this.taskStore = new TaskStore_1.TaskStore(config.paths.tasksDir);
|
|
104
|
+
this.searchBackend = options.searchBackend
|
|
105
|
+
?? (0, createSearchBackend_1.createSearchBackend)((0, ConfigSchema_1.resolveWebSearchConfig)(config.webSearch));
|
|
106
|
+
this.scheduleStore = new ScheduleStore_1.ScheduleStore(config.paths.schedulesDir ?? (0, WorkspacePaths_1.defaultSchedulesDir)());
|
|
107
|
+
}
|
|
108
|
+
resolveSettings(request) {
|
|
109
|
+
const { config, configPath } = this.options.loadedConfig;
|
|
110
|
+
const profile = request.profile ?? config.default.profile;
|
|
111
|
+
const profileSettings = this.profileResolver.loadSettings(profile);
|
|
112
|
+
const provider = request.provider ?? profileSettings.provider ?? config.default.provider;
|
|
113
|
+
const model = request.model ?? profileSettings.model ?? config.default.model;
|
|
114
|
+
const think = request.think ?? profileSettings.think ?? config.default.think;
|
|
115
|
+
const mode = profileSettings.mode ?? 'agent';
|
|
116
|
+
if (!provider || !model)
|
|
117
|
+
throw MarifoldError_1.MarifoldError.missingProviderModel(configPath);
|
|
118
|
+
return {
|
|
119
|
+
profile, provider, model, think, mode,
|
|
120
|
+
maxContextTokens: request.maxContextTokens ?? profileSettings.maxContextTokens,
|
|
121
|
+
sessionContextTurns: profileSettings.sessionContextTurns,
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
async ask(request) {
|
|
125
|
+
const startedAtMs = Date.now();
|
|
126
|
+
const startedAt = new Date(startedAtMs).toISOString();
|
|
127
|
+
const settings = this.resolveSettings(request);
|
|
128
|
+
const preparedImages = await (0, ImageOptimizer_1.prepareImageInputs)(request.images, { optimize: request.originalImages !== true });
|
|
129
|
+
await this.refreshProviderCredentialsIfNeeded(settings.provider);
|
|
130
|
+
const replacing = request.replaceUserTurnIndex !== undefined;
|
|
131
|
+
const isolated = request.isolated === true;
|
|
132
|
+
const engine = this.createEngine(settings.provider, Boolean(request.sessionId) && !replacing && !isolated, request.profileContext !== false);
|
|
133
|
+
const memoryOn = this.memoryEnabled(settings.profile, request.memories);
|
|
134
|
+
const memory = this.memoryForRequest(settings.profile, request.memories, request.prompt, settings.think);
|
|
135
|
+
const response = await engine.run({
|
|
136
|
+
config: this.toPriestConfig(settings),
|
|
137
|
+
profile: settings.profile,
|
|
138
|
+
prompt: request.prompt,
|
|
139
|
+
session: request.sessionId && !replacing && !isolated
|
|
140
|
+
? { id: request.sessionId, createIfMissing: true }
|
|
141
|
+
: undefined,
|
|
142
|
+
context: [
|
|
143
|
+
...this.runtimeContext(memory, request.prompt, memoryOn),
|
|
144
|
+
...this.editHistoryContext(request, settings),
|
|
145
|
+
...(request.instructions ?? []),
|
|
146
|
+
],
|
|
147
|
+
memory,
|
|
148
|
+
images: preparedImages.images.length > 0 ? preparedImages.images : undefined,
|
|
149
|
+
userContext: request.userContext,
|
|
150
|
+
});
|
|
151
|
+
const stripped = (0, MemoryControls_1.stripMemoryControls)(response.text ?? '');
|
|
152
|
+
const userTurn = request.userTurn ?? request.prompt;
|
|
153
|
+
const responseMetrics = completedResponseMetrics('chat', settings, startedAt, startedAtMs, response.usage);
|
|
154
|
+
if (response.ok && request.sessionId) {
|
|
155
|
+
if (request.replaceUserTurnIndex !== undefined) {
|
|
156
|
+
this.replaceEditedExchange(request.sessionId, request.replaceUserTurnIndex, userTurn, stripped.text, preparedImages.images, responseMetrics);
|
|
157
|
+
}
|
|
158
|
+
else if (isolated) {
|
|
159
|
+
await this.sessionResolver.appendExchange(request.sessionId, settings.profile, userTurn, stripped.text, preparedImages.images, responseMetrics);
|
|
160
|
+
}
|
|
161
|
+
else {
|
|
162
|
+
if (request.userTurn)
|
|
163
|
+
this.sessionResolver.replaceLastUserTurn(request.sessionId, request.userTurn);
|
|
164
|
+
this.sessionResolver.replaceLastAssistantTurn(request.sessionId, stripped.text);
|
|
165
|
+
this.sessionResolver.saveLastUserTurnAttachments(request.sessionId, preparedImages.images);
|
|
166
|
+
this.sessionResolver.saveLastResponseMetrics(request.sessionId, responseMetrics);
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
if (response.ok && memoryOn) {
|
|
170
|
+
this.applyTurnMemory(settings.profile, request.prompt, stripped, request.sessionId);
|
|
171
|
+
}
|
|
172
|
+
return {
|
|
173
|
+
ok: response.ok,
|
|
174
|
+
text: stripped.text,
|
|
175
|
+
settings,
|
|
176
|
+
latencyMs: response.ok ? responseMetrics.latencyMs : response.execution.latencyMs,
|
|
177
|
+
session: response.session,
|
|
178
|
+
error: response.error ? { code: response.error.code, message: response.error.message } : undefined,
|
|
179
|
+
};
|
|
180
|
+
}
|
|
181
|
+
async *stream(request, onComplete, onReasoningSummary) {
|
|
182
|
+
const startedAtMs = Date.now();
|
|
183
|
+
const startedAt = new Date(startedAtMs).toISOString();
|
|
184
|
+
const settings = this.resolveSettings(request);
|
|
185
|
+
const preparedImages = await (0, ImageOptimizer_1.prepareImageInputs)(request.images, { optimize: request.originalImages !== true });
|
|
186
|
+
await this.refreshProviderCredentialsIfNeeded(settings.provider);
|
|
187
|
+
let aggregateUsage;
|
|
188
|
+
const replacing = request.replaceUserTurnIndex !== undefined;
|
|
189
|
+
const isolated = request.isolated === true;
|
|
190
|
+
const enginePersistsSession = Boolean(request.sessionId) && !replacing && !isolated;
|
|
191
|
+
const sessionWasMissing = enginePersistsSession
|
|
192
|
+
? this.sessionResolver.get(request.sessionId) === undefined
|
|
193
|
+
: false;
|
|
194
|
+
const engine = this.createEngine(settings.provider, enginePersistsSession, request.profileContext !== false);
|
|
195
|
+
const memoryOn = this.memoryEnabled(settings.profile, request.memories);
|
|
196
|
+
const memory = this.memoryForRequest(settings.profile, request.memories, request.prompt, settings.think);
|
|
197
|
+
const chatTools = this.chatTools(request);
|
|
198
|
+
const baseRequest = {
|
|
199
|
+
config: this.toPriestConfig(settings),
|
|
200
|
+
profile: settings.profile,
|
|
201
|
+
prompt: request.prompt,
|
|
202
|
+
session: request.sessionId && !replacing && !isolated
|
|
203
|
+
? { id: request.sessionId, createIfMissing: true }
|
|
204
|
+
: undefined,
|
|
205
|
+
context: [
|
|
206
|
+
...this.runtimeContext(memory, request.prompt, memoryOn),
|
|
207
|
+
...this.editHistoryContext(request, settings),
|
|
208
|
+
...(request.instructions ?? []),
|
|
209
|
+
],
|
|
210
|
+
memory,
|
|
211
|
+
images: preparedImages.images.length > 0 ? preparedImages.images : undefined,
|
|
212
|
+
userContext: request.userContext,
|
|
213
|
+
};
|
|
214
|
+
// Model-initiated tool loop (web_search/read_file) when [web_search].enabled.
|
|
215
|
+
// Intermediate tool-call turns are turn-local; the engine persists the
|
|
216
|
+
// session only on the loop's final response, and memory payloads are
|
|
217
|
+
// applied only from that final response.
|
|
218
|
+
const exchange = [];
|
|
219
|
+
const maxIterations = chatTools ? CHAT_TOOL_MAX_ITERATIONS : 1;
|
|
220
|
+
for (let iteration = 0; iteration < maxIterations; iteration += 1) {
|
|
221
|
+
const stripper = new MemoryControls_1.MemoryControlStripper();
|
|
222
|
+
const visibleParts = [];
|
|
223
|
+
let done;
|
|
224
|
+
const lastIteration = iteration === maxIterations - 1;
|
|
225
|
+
for await (const event of engine.streamEvents({
|
|
226
|
+
...baseRequest,
|
|
227
|
+
...(chatTools && !lastIteration ? { tools: chatTools.definitions } : {}),
|
|
228
|
+
...(exchange.length > 0 ? { toolExchange: exchange } : {}),
|
|
229
|
+
}, request.signal ? { signal: request.signal } : undefined)) {
|
|
230
|
+
if (event.type === 'text_delta') {
|
|
231
|
+
const visible = stripper.feed(event.text);
|
|
232
|
+
if (visible) {
|
|
233
|
+
visibleParts.push(visible);
|
|
234
|
+
yield visible;
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
else if (event.type === 'reasoning_summary_delta') {
|
|
238
|
+
onReasoningSummary?.(event.text);
|
|
239
|
+
}
|
|
240
|
+
else if (event.type === 'done') {
|
|
241
|
+
done = event.response;
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
const tail = stripper.flush();
|
|
245
|
+
if (tail) {
|
|
246
|
+
visibleParts.push(tail);
|
|
247
|
+
yield tail;
|
|
248
|
+
}
|
|
249
|
+
aggregateUsage = sumUsage(aggregateUsage, done?.usage);
|
|
250
|
+
if (done?.error) {
|
|
251
|
+
this.discardFailedNewSession(request.sessionId, sessionWasMissing);
|
|
252
|
+
throw MarifoldError_1.MarifoldError.providerError(done.error.message, settings.provider, settings.model, done.error.code);
|
|
253
|
+
}
|
|
254
|
+
const toolCalls = done?.toolCalls ?? [];
|
|
255
|
+
if (!chatTools || toolCalls.length === 0) {
|
|
256
|
+
const streamedText = visibleParts.join('');
|
|
257
|
+
const fallbackControls = streamedText.length === 0
|
|
258
|
+
? (0, MemoryControls_1.stripMemoryControls)(done?.text ?? '')
|
|
259
|
+
: undefined;
|
|
260
|
+
const finalText = streamedText || fallbackControls?.text || '';
|
|
261
|
+
if (done?.text === undefined && finalText.length === 0) {
|
|
262
|
+
this.discardFailedNewSession(request.sessionId, sessionWasMissing);
|
|
263
|
+
throw MarifoldError_1.MarifoldError.providerError(`Provider '${settings.provider}' returned no text for model '${settings.model}'.`, settings.provider, settings.model, 'EMPTY_RESPONSE');
|
|
264
|
+
}
|
|
265
|
+
if (streamedText.length === 0 && finalText)
|
|
266
|
+
yield finalText;
|
|
267
|
+
const userTurn = request.userTurn ?? request.prompt;
|
|
268
|
+
const responseMetrics = completedResponseMetrics('chat', settings, startedAt, startedAtMs, aggregateUsage);
|
|
269
|
+
if (request.sessionId) {
|
|
270
|
+
if (request.replaceUserTurnIndex !== undefined) {
|
|
271
|
+
this.replaceEditedExchange(request.sessionId, request.replaceUserTurnIndex, userTurn, finalText, preparedImages.images, responseMetrics);
|
|
272
|
+
}
|
|
273
|
+
else if (isolated) {
|
|
274
|
+
await this.sessionResolver.appendExchange(request.sessionId, settings.profile, userTurn, finalText, preparedImages.images, responseMetrics);
|
|
275
|
+
}
|
|
276
|
+
else {
|
|
277
|
+
if (request.userTurn)
|
|
278
|
+
this.sessionResolver.replaceLastUserTurn(request.sessionId, request.userTurn);
|
|
279
|
+
this.sessionResolver.replaceLastAssistantTurn(request.sessionId, finalText);
|
|
280
|
+
this.sessionResolver.saveLastUserTurnAttachments(request.sessionId, preparedImages.images);
|
|
281
|
+
this.sessionResolver.saveLastResponseMetrics(request.sessionId, responseMetrics);
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
if (memoryOn) {
|
|
285
|
+
this.applyTurnMemory(settings.profile, request.prompt, fallbackControls ?? stripper, request.sessionId);
|
|
286
|
+
}
|
|
287
|
+
onComplete?.({ usage: aggregateUsage, latencyMs: responseMetrics.latencyMs });
|
|
288
|
+
return;
|
|
289
|
+
}
|
|
290
|
+
exchange.push({
|
|
291
|
+
kind: 'assistant',
|
|
292
|
+
text: done?.text,
|
|
293
|
+
toolCalls,
|
|
294
|
+
...(done?.reasoning ? { reasoning: done.reasoning } : {}),
|
|
295
|
+
});
|
|
296
|
+
for (const call of toolCalls) {
|
|
297
|
+
const result = await chatTools.execute(call.name, call.arguments);
|
|
298
|
+
exchange.push({
|
|
299
|
+
kind: 'tool_result',
|
|
300
|
+
toolCallId: call.id,
|
|
301
|
+
name: call.name,
|
|
302
|
+
content: result.content,
|
|
303
|
+
isError: result.isError,
|
|
304
|
+
});
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
/** Run the web search backend directly (the /search chat command). */
|
|
309
|
+
async searchWeb(query, maxResults) {
|
|
310
|
+
const config = (0, ConfigSchema_1.resolveWebSearchConfig)(this.options.loadedConfig.config.webSearch);
|
|
311
|
+
const results = await this.searchBackend.search(query, maxResults ?? config.maxResults);
|
|
312
|
+
return (0, SearchBackend_1.formatSearchResults)(query, results);
|
|
313
|
+
}
|
|
314
|
+
rememberMemory(profile, kind, text, sessionId) {
|
|
315
|
+
return this.memoryStore.remember(profile, kind, text, { sessionId });
|
|
316
|
+
}
|
|
317
|
+
forgetMemories(profile, query) {
|
|
318
|
+
return this.memoryStore.forget(profile, query);
|
|
319
|
+
}
|
|
320
|
+
deleteMemories(profile, query) {
|
|
321
|
+
return this.memoryStore.delete(profile, query);
|
|
322
|
+
}
|
|
323
|
+
listMemories(profile, includeSuperseded = false) {
|
|
324
|
+
const entries = this.memoryStore.listEntries(profile);
|
|
325
|
+
return includeSuperseded ? entries : entries.filter(entry => entry.status === 'active');
|
|
326
|
+
}
|
|
327
|
+
ensureProfileMemoryFiles(profile) {
|
|
328
|
+
this.profileResolver.load(profile);
|
|
329
|
+
return this.memoryStore.ensureProfile(profile);
|
|
330
|
+
}
|
|
331
|
+
memoryEnabled(profile, requestMemories = true) {
|
|
332
|
+
return requestMemories && this.profileResolver.loadSettings(profile).memories;
|
|
333
|
+
}
|
|
334
|
+
listProfiles() {
|
|
335
|
+
const activity = new Map(this.sessionResolver.profileActivity().map(item => [item.profileName, item]));
|
|
336
|
+
return this.profileResolver.list()
|
|
337
|
+
.map(profile => {
|
|
338
|
+
const recent = activity.get(profile.name);
|
|
339
|
+
return recent ? {
|
|
340
|
+
...profile,
|
|
341
|
+
...(recent.pinned ? { pinned: true } : {}),
|
|
342
|
+
...(recent.updatedAt ? { updatedAt: recent.updatedAt } : {}),
|
|
343
|
+
...(recent.preview ? { preview: recent.preview } : {}),
|
|
344
|
+
} : profile;
|
|
345
|
+
})
|
|
346
|
+
.sort((a, b) => {
|
|
347
|
+
const pinOrder = Number(Boolean(b.pinned)) - Number(Boolean(a.pinned));
|
|
348
|
+
if (pinOrder !== 0)
|
|
349
|
+
return pinOrder;
|
|
350
|
+
const activityOrder = (b.updatedAt ?? '').localeCompare(a.updatedAt ?? '');
|
|
351
|
+
return activityOrder !== 0 ? activityOrder : a.name.localeCompare(b.name);
|
|
352
|
+
});
|
|
353
|
+
}
|
|
354
|
+
getProfile(name) {
|
|
355
|
+
return this.profileResolver.detail(name);
|
|
356
|
+
}
|
|
357
|
+
setProfilePinned(name, pinned) {
|
|
358
|
+
this.getProfile(name);
|
|
359
|
+
this.sessionResolver.setProfilePinned(name, pinned);
|
|
360
|
+
return this.listProfiles();
|
|
361
|
+
}
|
|
362
|
+
/** Persist (or clear) a profile's human-readable label. */
|
|
363
|
+
setProfileDisplayName(name, displayName) {
|
|
364
|
+
this.profileManager.setDisplayName(name, displayName);
|
|
365
|
+
}
|
|
366
|
+
/** Persist a profile's default TUI mode to its profile.toml. Returns the
|
|
367
|
+
* mode that was written. */
|
|
368
|
+
setProfileMode(name, mode) {
|
|
369
|
+
return this.profileManager.setMode(name, mode).mode;
|
|
370
|
+
}
|
|
371
|
+
/** Persist (or clear) a profile's conversation-context budget in profile.toml. */
|
|
372
|
+
setProfileMaxContextTokens(name, tokens) {
|
|
373
|
+
return this.profileManager.setMaxContextTokens(name, tokens).maxContextTokens;
|
|
374
|
+
}
|
|
375
|
+
/** Persist a per-profile approval decision into the profile's profile.toml
|
|
376
|
+
* `[agent.approval]` (e.g. the TUI's "always allow"). `undefined` clears the
|
|
377
|
+
* override so the kind inherits the global default again. */
|
|
378
|
+
setProfileAgentApproval(name, kind, mode) {
|
|
379
|
+
this.profileManager.setAgentApproval(name, kind, mode);
|
|
380
|
+
}
|
|
381
|
+
/** Add a trusted folder capability to a profile. External folders still
|
|
382
|
+
* require approval per action. Returns the resolved absolute folder. */
|
|
383
|
+
addProfileTrustedFolder(name, folder) {
|
|
384
|
+
return this.profileManager.addTrustedFolder(name, folder).folder;
|
|
385
|
+
}
|
|
386
|
+
/** Remove a trusted folder from a profile. Returns whether it was present. */
|
|
387
|
+
removeProfileTrustedFolder(name, folder) {
|
|
388
|
+
return this.profileManager.removeTrustedFolder(name, folder).removed;
|
|
389
|
+
}
|
|
390
|
+
/** Set (or clear with both undefined) a profile's provider/model override. */
|
|
391
|
+
setProfileModelOverride(name, provider, model) {
|
|
392
|
+
if (provider === undefined && model === undefined) {
|
|
393
|
+
this.profileManager.clearModelOverride(name);
|
|
394
|
+
return;
|
|
395
|
+
}
|
|
396
|
+
if (!provider || !model) {
|
|
397
|
+
throw MarifoldError_1.MarifoldError.profileInvalid('Profile model overrides require both provider and model (or neither to clear).', name);
|
|
398
|
+
}
|
|
399
|
+
this.profileManager.setModelOverride(name, provider, model);
|
|
400
|
+
}
|
|
401
|
+
/** Persist (or clear) whether a profile loads its memory. */
|
|
402
|
+
setProfileMemories(name, memories) {
|
|
403
|
+
this.profileManager.setMemories(name, memories);
|
|
404
|
+
}
|
|
405
|
+
/** Persist (or clear) a profile's thinking-mode default. */
|
|
406
|
+
setProfileThink(name, think) {
|
|
407
|
+
this.profileManager.setThink(name, think);
|
|
408
|
+
}
|
|
409
|
+
/** Persist a profile's recent-turn window ('all'/undefined clears the key). */
|
|
410
|
+
setProfileSessionContextTurns(name, turns) {
|
|
411
|
+
this.profileManager.setSessionContextTurns(name, turns);
|
|
412
|
+
}
|
|
413
|
+
/** Overwrite one of a profile's markdown files (PROFILE/RULES/CUSTOM.md). */
|
|
414
|
+
writeProfileFile(name, file, content) {
|
|
415
|
+
this.profileManager.writeProfileFile(name, file, content);
|
|
416
|
+
}
|
|
417
|
+
/** Scaffold a new profile directory (same layout as `profile init`) and
|
|
418
|
+
* return its detail. Duplicate or invalid names throw PROFILE_INVALID. */
|
|
419
|
+
initProfile(name) {
|
|
420
|
+
this.profileManager.init(name);
|
|
421
|
+
return this.getProfile(name);
|
|
422
|
+
}
|
|
423
|
+
/** Delete stored profile files while retaining session history. The current
|
|
424
|
+
* configured default must be changed first, matching the CLI guard. */
|
|
425
|
+
deleteProfile(name) {
|
|
426
|
+
if (this.options.loadedConfig.config.default.profile === name) {
|
|
427
|
+
throw MarifoldError_1.MarifoldError.profileInvalid(`Cannot delete the current default profile '${name}'. Set another default profile first.`, name);
|
|
428
|
+
}
|
|
429
|
+
this.profileManager.delete(name);
|
|
430
|
+
this.sessionResolver.deleteProfileDisplay(name);
|
|
431
|
+
}
|
|
432
|
+
/** The profile's stored avatar image (path + media type), if any. */
|
|
433
|
+
getProfileAvatar(name) {
|
|
434
|
+
return this.profileManager.avatar(name);
|
|
435
|
+
}
|
|
436
|
+
/** Store a profile's avatar (PNG/JPEG/WebP, ≤1 MB), replacing any previous one. */
|
|
437
|
+
setProfileAvatar(name, image, mediaType) {
|
|
438
|
+
this.profileManager.setAvatar(name, image, mediaType);
|
|
439
|
+
}
|
|
440
|
+
/** Remove a profile's avatar. Returns whether one existed. */
|
|
441
|
+
deleteProfileAvatar(name) {
|
|
442
|
+
return this.profileManager.deleteAvatar(name).removed;
|
|
443
|
+
}
|
|
444
|
+
/** Set a config value by dotted key and persist — the same routing and
|
|
445
|
+
* validation as the CLI's `config set` (see ConfigManager.setValue). */
|
|
446
|
+
setConfigValue(key, value) {
|
|
447
|
+
new ConfigManager_1.ConfigManager(this.options.loadedConfig).setValue(key, value);
|
|
448
|
+
}
|
|
449
|
+
/** Read a config value by dotted key (CLI `config get`). */
|
|
450
|
+
getConfigValue(key) {
|
|
451
|
+
return new ConfigManager_1.ConfigManager(this.options.loadedConfig).getValue(key);
|
|
452
|
+
}
|
|
453
|
+
/** Reachability + sanitized config for every provider (CLI `provider status`). */
|
|
454
|
+
providerStatus() {
|
|
455
|
+
return new ProviderInspector_1.ProviderInspector(this.options.loadedConfig).status();
|
|
456
|
+
}
|
|
457
|
+
/** Models a provider actually serves right now (CLI `model list --live`). */
|
|
458
|
+
listProviderModels(provider) {
|
|
459
|
+
return new ProviderInspector_1.ProviderInspector(this.options.loadedConfig).listModels(provider);
|
|
460
|
+
}
|
|
461
|
+
/** Add a saved provider/model option (creating/updating the provider entry;
|
|
462
|
+
* secrets are not part of this surface — CLI/file only). */
|
|
463
|
+
addModelOption(provider, model, options = {}) {
|
|
464
|
+
new ConfigManager_1.ConfigManager(this.options.loadedConfig).addModel(provider, model, options);
|
|
465
|
+
}
|
|
466
|
+
/** Remove a saved provider/model option. Returns whether it was present and
|
|
467
|
+
* whether it was the current default (left untouched either way). */
|
|
468
|
+
removeModelOption(provider, model) {
|
|
469
|
+
const result = new ConfigManager_1.ConfigManager(this.options.loadedConfig).removeModel(provider, model);
|
|
470
|
+
return { removed: result.removed, wasDefault: result.wasDefault };
|
|
471
|
+
}
|
|
472
|
+
/** Remove local provider configuration and model options. Profile overrides
|
|
473
|
+
* are guarded here because they live outside the global config file. */
|
|
474
|
+
removeProvider(provider) {
|
|
475
|
+
const profileNames = this.listProfiles()
|
|
476
|
+
.filter(profile => this.getProfile(profile.name).settings.provider === provider)
|
|
477
|
+
.map(profile => profile.name);
|
|
478
|
+
if (profileNames.length > 0) {
|
|
479
|
+
throw MarifoldError_1.MarifoldError.configInvalid(`Cannot remove provider '${provider}' because ${profileNames.length === 1 ? 'profile' : 'profiles'} `
|
|
480
|
+
+ `${profileNames.map(name => `'${name}'`).join(', ')} use it. Clear those model overrides first.`);
|
|
481
|
+
}
|
|
482
|
+
const result = new ConfigManager_1.ConfigManager(this.options.loadedConfig).removeProvider(provider);
|
|
483
|
+
return { removed: result.removed, removedModels: result.removedModels };
|
|
484
|
+
}
|
|
485
|
+
/** Set the global default provider/model (also registers the option). */
|
|
486
|
+
setDefaultModel(provider, model) {
|
|
487
|
+
new ConfigManager_1.ConfigManager(this.options.loadedConfig).setDefaultModel(model, provider);
|
|
488
|
+
}
|
|
489
|
+
/** Supersede exactly one memory entry by id (per-row Forget — recoverable). */
|
|
490
|
+
forgetMemoryById(profile, id) {
|
|
491
|
+
return this.memoryStore.forgetById(profile, id);
|
|
492
|
+
}
|
|
493
|
+
/** Permanently remove exactly one memory entry by id (per-row Delete). */
|
|
494
|
+
deleteMemoryById(profile, id) {
|
|
495
|
+
return this.memoryStore.deleteById(profile, id);
|
|
496
|
+
}
|
|
497
|
+
/** Manually compact a session now (the /compact command). Returns whether anything was folded. */
|
|
498
|
+
async compactSession(sessionId, request) {
|
|
499
|
+
const settings = this.resolveSettings(request);
|
|
500
|
+
await this.refreshProviderCredentialsIfNeeded(settings.provider);
|
|
501
|
+
const engine = this.createEngine(settings.provider, true);
|
|
502
|
+
const result = await engine.compactSession(sessionId, this.toPriestConfig(settings));
|
|
503
|
+
return { compacted: result.compacted };
|
|
504
|
+
}
|
|
505
|
+
listSessions(limit, profileName, options) {
|
|
506
|
+
return this.sessionResolver.list(limit, profileName, options);
|
|
507
|
+
}
|
|
508
|
+
/** Read-only integrity check of the session DB (for `marifold doctor`). Never throws. */
|
|
509
|
+
checkSessionDb() {
|
|
510
|
+
return this.sessionResolver.checkIntegrity();
|
|
511
|
+
}
|
|
512
|
+
/** Filesystem path of the session DB, for diagnostics. */
|
|
513
|
+
get sessionDbPath() {
|
|
514
|
+
return this.options.loadedConfig.config.paths.sessionsDb;
|
|
515
|
+
}
|
|
516
|
+
latestSession(profileName) {
|
|
517
|
+
return this.sessionResolver.latest(profileName);
|
|
518
|
+
}
|
|
519
|
+
getSession(sessionId) {
|
|
520
|
+
return this.sessionResolver.get(sessionId);
|
|
521
|
+
}
|
|
522
|
+
getSessionAttachment(sessionId, userTurnIndex, attachmentIndex) {
|
|
523
|
+
return this.sessionResolver.getAttachment(sessionId, userTurnIndex, attachmentIndex);
|
|
524
|
+
}
|
|
525
|
+
deleteSession(sessionId) {
|
|
526
|
+
return this.sessionResolver.delete(sessionId);
|
|
527
|
+
}
|
|
528
|
+
updateSessionDisplay(sessionId, update) {
|
|
529
|
+
return this.sessionResolver.updateDisplay(sessionId, update);
|
|
530
|
+
}
|
|
531
|
+
truncateSessionFromUserTurn(sessionId, userTurnIndex) {
|
|
532
|
+
return this.sessionResolver.truncateFromUserTurn(sessionId, userTurnIndex);
|
|
533
|
+
}
|
|
534
|
+
clearSessions(options = {}) {
|
|
535
|
+
return this.sessionResolver.clear(options);
|
|
536
|
+
}
|
|
537
|
+
renameSession(fromSessionId, toSessionId) {
|
|
538
|
+
return this.sessionResolver.rename(fromSessionId, toSessionId);
|
|
539
|
+
}
|
|
540
|
+
/**
|
|
541
|
+
* Build an approval-aware agent runner over this runtime's engine wiring,
|
|
542
|
+
* TaskStore, and config policy. Pass a custom registry to replace the
|
|
543
|
+
* default file/shell/delegate tool set.
|
|
544
|
+
*/
|
|
545
|
+
/**
|
|
546
|
+
* Effective agent config for a profile: the global `[agent]` with the
|
|
547
|
+
* profile's `[agent]` overrides (profile.toml) merged on top. Unset profile
|
|
548
|
+
* keys inherit global/defaults; `undefined` profile → global only.
|
|
549
|
+
*/
|
|
550
|
+
resolveAgentConfigForProfile(profile) {
|
|
551
|
+
const global = (0, ApprovalPolicy_1.resolveAgentConfig)(this.options.loadedConfig.config.agent);
|
|
552
|
+
const name = profile ?? this.options.loadedConfig.config.default.profile;
|
|
553
|
+
const override = this.profileResolver.loadSettings(name).agent;
|
|
554
|
+
if (!override)
|
|
555
|
+
return global;
|
|
556
|
+
const unattended = { ...(global.unattended ?? {}), ...(override.unattended ?? {}) };
|
|
557
|
+
return {
|
|
558
|
+
approval: { ...global.approval, ...(override.approval ?? {}) },
|
|
559
|
+
...(Object.keys(unattended).length > 0 ? { unattended } : {}),
|
|
560
|
+
// Trusted folders are additive: a profile adds to any global ones.
|
|
561
|
+
trustedFolders: [...new Set([...global.trustedFolders, ...(override.trustedFolders ?? [])])],
|
|
562
|
+
maxIterations: override.maxIterations ?? global.maxIterations,
|
|
563
|
+
toolOutputLimit: override.toolOutputLimit ?? global.toolOutputLimit,
|
|
564
|
+
toolMode: override.toolMode ?? global.toolMode,
|
|
565
|
+
};
|
|
566
|
+
}
|
|
567
|
+
createAgentRunner(profile, registry) {
|
|
568
|
+
return new AgentRunner_1.AgentRunner({
|
|
569
|
+
taskStore: this.taskStore,
|
|
570
|
+
registry: registry ?? this.createDefaultToolRegistry(profile),
|
|
571
|
+
agentConfig: this.resolveAgentConfigForProfile(profile),
|
|
572
|
+
resolveSettings: request => this.resolveSettings(request),
|
|
573
|
+
prepareEngine: async (settings) => {
|
|
574
|
+
await this.refreshProviderCredentialsIfNeeded(settings.provider);
|
|
575
|
+
return {
|
|
576
|
+
// No engine-level session store: priest would otherwise persist the
|
|
577
|
+
// raw per-iteration `Objective:`/tool framing (and duplicates). The
|
|
578
|
+
// runner instead persists one clean turn pair via `persistTurn` below.
|
|
579
|
+
engine: this.createEngine(settings.provider, false),
|
|
580
|
+
config: this.toPriestConfig(settings),
|
|
581
|
+
};
|
|
582
|
+
},
|
|
583
|
+
prepareImages: async (images, optimize) => (await (0, ImageOptimizer_1.prepareImageInputs)(images, { optimize })).images,
|
|
584
|
+
// Record the run as a single tidy user→assistant exchange so resuming the
|
|
585
|
+
// session shows the result, not the agent's internal framing.
|
|
586
|
+
persistTurn: async (sessionId, profile, userText, assistantText, images, replaceUserTurnIndex, responseMetrics) => {
|
|
587
|
+
if (replaceUserTurnIndex !== undefined) {
|
|
588
|
+
this.replaceEditedExchange(sessionId, replaceUserTurnIndex, userText, assistantText, images, responseMetrics);
|
|
589
|
+
return;
|
|
590
|
+
}
|
|
591
|
+
await this.sessionResolver.appendExchange(sessionId, profile, userText, assistantText, images, responseMetrics);
|
|
592
|
+
},
|
|
593
|
+
// Bounded cross-objective memory for non-lean tasks: replay the clean
|
|
594
|
+
// pairs (objective → answer) that persistTurn wrote, never raw framing.
|
|
595
|
+
loadRecentTurns: (sessionId, beforeUserTurnIndex) => (beforeUserTurnIndex === undefined
|
|
596
|
+
? (this.sessionResolver.get(sessionId)?.turns ?? [])
|
|
597
|
+
: (this.sessionResolver.turnsBeforeUserTurn(sessionId, beforeUserTurnIndex)
|
|
598
|
+
?? this.missingEditedTurn(sessionId, beforeUserTurnIndex)))
|
|
599
|
+
.filter(t => t.role === 'user' || t.role === 'assistant')
|
|
600
|
+
.map(t => ({ role: t.role, content: t.content })),
|
|
601
|
+
resolveBuiltInInstructions: (objective, resolvedProfile) => {
|
|
602
|
+
if (!(0, BuiltInSkillManager_1.mentionsSkills)(objective))
|
|
603
|
+
return [];
|
|
604
|
+
const { config } = this.options.loadedConfig;
|
|
605
|
+
return [(0, BuiltInSkillManager_1.buildSkillManagerGuide)({
|
|
606
|
+
profile: resolvedProfile,
|
|
607
|
+
profilesDir: config.paths.profilesDir,
|
|
608
|
+
globalSkillsDir: config.paths.skillsDir ?? (0, WorkspacePaths_1.defaultSkillsDir)(),
|
|
609
|
+
})];
|
|
610
|
+
},
|
|
611
|
+
resolveReadOnlyFolders: resolvedProfile => {
|
|
612
|
+
const { config } = this.options.loadedConfig;
|
|
613
|
+
return [
|
|
614
|
+
path.join(config.paths.profilesDir, resolvedProfile, 'skills'),
|
|
615
|
+
config.paths.skillsDir ?? (0, WorkspacePaths_1.defaultSkillsDir)(),
|
|
616
|
+
];
|
|
617
|
+
},
|
|
618
|
+
});
|
|
619
|
+
}
|
|
620
|
+
createDefaultToolRegistry(profile) {
|
|
621
|
+
const registry = new ToolRegistry_1.ToolRegistry();
|
|
622
|
+
registry.register(new AskUserTool_1.AskUserTool());
|
|
623
|
+
registry.register(new InspectAttachmentTool_1.InspectAttachmentTool());
|
|
624
|
+
registry.register(new ReadFileTool_1.ReadFileTool());
|
|
625
|
+
registry.register(new WriteFileTool_1.WriteFileTool());
|
|
626
|
+
registry.register(new ShellExecTool_1.ShellExecTool());
|
|
627
|
+
registry.register(new PythonPackageTool_1.PythonPackageTool());
|
|
628
|
+
// web_search joins the agent's toolset when search is enabled and the
|
|
629
|
+
// network isn't denied — so the model can look things up on its own.
|
|
630
|
+
const webSearch = (0, ConfigSchema_1.resolveWebSearchConfig)(this.options.loadedConfig.config.webSearch);
|
|
631
|
+
const approval = this.resolveAgentConfigForProfile(profile).approval;
|
|
632
|
+
if (webSearch.enabled && approval.network !== 'deny') {
|
|
633
|
+
registry.register(new WebSearchTool_1.WebSearchTool(this.searchBackend, webSearch.maxResults));
|
|
634
|
+
}
|
|
635
|
+
registry.register(new DelegateTool_1.DelegateTool({
|
|
636
|
+
ask: async (request) => {
|
|
637
|
+
const response = await this.ask({ prompt: request.prompt, profile: request.profile });
|
|
638
|
+
return { ok: response.ok, text: response.text, error: response.error };
|
|
639
|
+
},
|
|
640
|
+
listProfileNames: () => this.profileResolver.list().map(profile => profile.name),
|
|
641
|
+
}));
|
|
642
|
+
return registry;
|
|
643
|
+
}
|
|
644
|
+
/**
|
|
645
|
+
* Skill store over the shared skills dir ([paths].skills_dir) and the given
|
|
646
|
+
* profile's skills/ dir (profile skills shadow global ones). Defaults to the
|
|
647
|
+
* configured default profile.
|
|
648
|
+
*/
|
|
649
|
+
createSkillStore(profile) {
|
|
650
|
+
const { config } = this.options.loadedConfig;
|
|
651
|
+
const resolvedProfile = profile ?? config.default.profile;
|
|
652
|
+
return new SkillStore_1.SkillStore({
|
|
653
|
+
globalDir: config.paths.skillsDir ?? (0, WorkspacePaths_1.defaultSkillsDir)(),
|
|
654
|
+
profileDir: path.join(config.paths.profilesDir, resolvedProfile, 'skills'),
|
|
655
|
+
});
|
|
656
|
+
}
|
|
657
|
+
listSkills(profile, scope) {
|
|
658
|
+
return this.createSkillStore(profile).list(scope);
|
|
659
|
+
}
|
|
660
|
+
getSkill(name, profile) {
|
|
661
|
+
return this.createSkillStore(profile).get(name);
|
|
662
|
+
}
|
|
663
|
+
resolveSkillInvocation(input, profile) {
|
|
664
|
+
const parsed = (0, SkillInvocation_1.parseSkillInvocation)(input);
|
|
665
|
+
if (!parsed)
|
|
666
|
+
throw MarifoldError_1.MarifoldError.skillInvalid('Expected an invocation beginning with $.');
|
|
667
|
+
const resolvedProfile = profile ?? this.options.loadedConfig.config.default.profile;
|
|
668
|
+
this.profileResolver.loadSettings(resolvedProfile);
|
|
669
|
+
const skill = this.createSkillStore(resolvedProfile).require(parsed.name);
|
|
670
|
+
return (0, SkillInvocation_1.resolveSkillInvocation)(skill, parsed);
|
|
671
|
+
}
|
|
672
|
+
installSkillFromText(text, scope = 'global', profile) {
|
|
673
|
+
return this.createSkillStore(profile).installFromText(text, scope);
|
|
674
|
+
}
|
|
675
|
+
installSkillFromFile(filePath, scope = 'global', profile) {
|
|
676
|
+
return this.createSkillStore(profile).installFromFile(filePath, scope);
|
|
677
|
+
}
|
|
678
|
+
removeSkill(name, profile, scope) {
|
|
679
|
+
return this.createSkillStore(profile).remove(name, scope);
|
|
680
|
+
}
|
|
681
|
+
createAppStore() {
|
|
682
|
+
const { config } = this.options.loadedConfig;
|
|
683
|
+
return new AppStore_1.AppStore(config.paths.appsDir ?? (0, WorkspacePaths_1.defaultAppsDir)());
|
|
684
|
+
}
|
|
685
|
+
listApps() {
|
|
686
|
+
return this.createAppStore().list();
|
|
687
|
+
}
|
|
688
|
+
getApp(name) {
|
|
689
|
+
return this.createAppStore().get(name);
|
|
690
|
+
}
|
|
691
|
+
/** Execute one profile-free v1 operation and normalize provider output to
|
|
692
|
+
* the Skill's declared result contract. No session, memory, tools, profile
|
|
693
|
+
* context, or transcript is created. */
|
|
694
|
+
async runSkillAppOperation(appName, operationName, state, signal) {
|
|
695
|
+
const startedAt = Date.now();
|
|
696
|
+
try {
|
|
697
|
+
const store = this.createAppStore();
|
|
698
|
+
const definition = store.require(appName);
|
|
699
|
+
const operation = (0, SkillAppResolver_1.resolveSkillAppOperation)(store, definition, operationName, state);
|
|
700
|
+
await this.refreshProviderCredentialsIfNeeded(operation.model.provider);
|
|
701
|
+
const settings = {
|
|
702
|
+
profile: `skillapp-${appName}`,
|
|
703
|
+
provider: operation.model.provider,
|
|
704
|
+
model: operation.model.model,
|
|
705
|
+
think: operation.model.think,
|
|
706
|
+
mode: 'chat',
|
|
707
|
+
};
|
|
708
|
+
const response = await this.createEngine(settings.provider, false, false).run({
|
|
709
|
+
config: this.toPriestConfig(settings),
|
|
710
|
+
profile: settings.profile,
|
|
711
|
+
prompt: operation.prompt,
|
|
712
|
+
context: operation.instructions,
|
|
713
|
+
}, signal ? { signal } : undefined);
|
|
714
|
+
if (response.error) {
|
|
715
|
+
throw MarifoldError_1.MarifoldError.providerError(response.error.message, settings.provider, settings.model, response.error.code);
|
|
716
|
+
}
|
|
717
|
+
if (response.text === undefined) {
|
|
718
|
+
throw MarifoldError_1.MarifoldError.providerError(`Provider '${settings.provider}' returned no text for model '${settings.model}'.`, settings.provider, settings.model, 'EMPTY_RESPONSE');
|
|
719
|
+
}
|
|
720
|
+
const text = operation.result.trim ? response.text.trim() : response.text;
|
|
721
|
+
return {
|
|
722
|
+
status: 'ok',
|
|
723
|
+
data: { text },
|
|
724
|
+
meta: {
|
|
725
|
+
engine: settings.provider,
|
|
726
|
+
model: settings.model,
|
|
727
|
+
durationMs: Date.now() - startedAt,
|
|
728
|
+
...(response.usage ? { usage: response.usage } : {}),
|
|
729
|
+
},
|
|
730
|
+
};
|
|
731
|
+
}
|
|
732
|
+
catch (error) {
|
|
733
|
+
if (signal?.aborted)
|
|
734
|
+
throw error;
|
|
735
|
+
return {
|
|
736
|
+
status: 'error',
|
|
737
|
+
error: {
|
|
738
|
+
code: error instanceof MarifoldError_1.MarifoldError ? error.code : 'APP_INVALID',
|
|
739
|
+
message: error instanceof Error ? error.message : String(error),
|
|
740
|
+
},
|
|
741
|
+
};
|
|
742
|
+
}
|
|
743
|
+
}
|
|
744
|
+
createSkillAppInstanceRegistry() {
|
|
745
|
+
return new SkillAppInstanceRegistry_1.SkillAppInstanceRegistry(this);
|
|
746
|
+
}
|
|
747
|
+
createSchedule(input) {
|
|
748
|
+
return this.scheduleStore.create(input);
|
|
749
|
+
}
|
|
750
|
+
listSchedules() {
|
|
751
|
+
return this.scheduleStore.list();
|
|
752
|
+
}
|
|
753
|
+
getSchedule(scheduleId) {
|
|
754
|
+
return this.scheduleStore.get(scheduleId);
|
|
755
|
+
}
|
|
756
|
+
updateSchedule(scheduleId, input) {
|
|
757
|
+
return this.scheduleStore.update(scheduleId, input);
|
|
758
|
+
}
|
|
759
|
+
deleteSchedule(scheduleId) {
|
|
760
|
+
return this.scheduleStore.delete(scheduleId);
|
|
761
|
+
}
|
|
762
|
+
/**
|
|
763
|
+
* Execute one schedule unattended: [agent.unattended] approval overrides
|
|
764
|
+
* apply and 'ask' degrades to deny. Records lastRunAt/lastTaskId.
|
|
765
|
+
*/
|
|
766
|
+
async runScheduleUnattended(scheduleId) {
|
|
767
|
+
const schedule = this.scheduleStore.require(scheduleId);
|
|
768
|
+
const result = await this.runScheduledAgent(schedule);
|
|
769
|
+
this.scheduleStore.update(schedule.id, {
|
|
770
|
+
lastRunAt: new Date().toISOString(),
|
|
771
|
+
...(result.taskId ? { lastTaskId: result.taskId } : {}),
|
|
772
|
+
lastResultSeen: false,
|
|
773
|
+
});
|
|
774
|
+
return result;
|
|
775
|
+
}
|
|
776
|
+
/** Scheduler for the long-running service process. Call start()/stop(). */
|
|
777
|
+
createScheduler(log) {
|
|
778
|
+
return new Scheduler_1.Scheduler({
|
|
779
|
+
store: this.scheduleStore,
|
|
780
|
+
runSchedule: schedule => this.runScheduledAgent(schedule),
|
|
781
|
+
log,
|
|
782
|
+
});
|
|
783
|
+
}
|
|
784
|
+
/** Telegram bridge for the service process, or undefined when not configured,
|
|
785
|
+
* disabled, or missing a resolvable token. Call start()/stop(). */
|
|
786
|
+
createTelegramBridge(log) {
|
|
787
|
+
const config = this.options.loadedConfig.config.channels?.telegram;
|
|
788
|
+
if (!config || config.enabled === false)
|
|
789
|
+
return undefined;
|
|
790
|
+
const token = config.botTokenEnv ? process.env[config.botTokenEnv] : config.botToken;
|
|
791
|
+
if (!token) {
|
|
792
|
+
log?.(`Telegram channel configured but no bot token resolved${config.botTokenEnv ? ` (env ${config.botTokenEnv} unset)` : ''} — bridge not started.`);
|
|
793
|
+
return undefined;
|
|
794
|
+
}
|
|
795
|
+
return new TelegramBridge_1.TelegramBridge({
|
|
796
|
+
runtime: this,
|
|
797
|
+
token,
|
|
798
|
+
config,
|
|
799
|
+
log,
|
|
800
|
+
profilesDir: this.options.loadedConfig.config.paths.profilesDir,
|
|
801
|
+
});
|
|
802
|
+
}
|
|
803
|
+
/** Live run-session registry for the service process: start/attach/approve/
|
|
804
|
+
* steer/cancel agent runs across separate requests. Call close() on shutdown. */
|
|
805
|
+
createRunRegistry(log) {
|
|
806
|
+
return new RunRegistry_1.RunRegistry({
|
|
807
|
+
runtime: {
|
|
808
|
+
createAgentRunner: profile => this.createAgentRunner(profile),
|
|
809
|
+
setProfileAgentApproval: (profile, kind, mode) => {
|
|
810
|
+
this.setProfileAgentApproval(profile, kind, mode);
|
|
811
|
+
},
|
|
812
|
+
addProfileTrustedFolder: (profile, folder) => this.addProfileTrustedFolder(profile, folder),
|
|
813
|
+
defaultProfile: () => this.options.loadedConfig.config.default.profile,
|
|
814
|
+
},
|
|
815
|
+
log,
|
|
816
|
+
});
|
|
817
|
+
}
|
|
818
|
+
async runScheduledAgent(schedule) {
|
|
819
|
+
const runner = this.createAgentRunner(schedule.profile);
|
|
820
|
+
let taskId;
|
|
821
|
+
let status = 'failed';
|
|
822
|
+
for await (const event of runner.run({
|
|
823
|
+
objective: schedule.objective,
|
|
824
|
+
profile: schedule.profile,
|
|
825
|
+
tags: ['scheduled'],
|
|
826
|
+
unattended: true,
|
|
827
|
+
})) {
|
|
828
|
+
if (event.type === 'done') {
|
|
829
|
+
taskId = event.taskId;
|
|
830
|
+
status = event.status;
|
|
831
|
+
}
|
|
832
|
+
}
|
|
833
|
+
return { taskId, status };
|
|
834
|
+
}
|
|
835
|
+
createTask(input) {
|
|
836
|
+
return this.taskStore.create(input);
|
|
837
|
+
}
|
|
838
|
+
listTasks(options = {}) {
|
|
839
|
+
return this.taskStore.list(options);
|
|
840
|
+
}
|
|
841
|
+
getTask(taskId) {
|
|
842
|
+
return this.taskStore.get(taskId);
|
|
843
|
+
}
|
|
844
|
+
updateTask(taskId, input) {
|
|
845
|
+
return this.taskStore.update(taskId, input);
|
|
846
|
+
}
|
|
847
|
+
appendTaskEvent(taskId, input) {
|
|
848
|
+
return this.taskStore.appendEvent(taskId, input);
|
|
849
|
+
}
|
|
850
|
+
deleteTask(taskId) {
|
|
851
|
+
return this.taskStore.delete(taskId);
|
|
852
|
+
}
|
|
853
|
+
close() {
|
|
854
|
+
this.sessionResolver.close();
|
|
855
|
+
}
|
|
856
|
+
discardFailedNewSession(sessionId, sessionWasMissing) {
|
|
857
|
+
if (!sessionId || !sessionWasMissing)
|
|
858
|
+
return;
|
|
859
|
+
const session = this.sessionResolver.get(sessionId);
|
|
860
|
+
if (session?.turnCount === 0)
|
|
861
|
+
this.sessionResolver.delete(sessionId);
|
|
862
|
+
}
|
|
863
|
+
createEngine(providerName, useSession, profileContext = true) {
|
|
864
|
+
const adapter = this.providerFactory.create(providerName);
|
|
865
|
+
const profileLoader = profileContext
|
|
866
|
+
? this.profileResolver
|
|
867
|
+
: {
|
|
868
|
+
load: (name) => ({
|
|
869
|
+
name,
|
|
870
|
+
identity: '',
|
|
871
|
+
rules: '',
|
|
872
|
+
custom: '',
|
|
873
|
+
memories: [],
|
|
874
|
+
}),
|
|
875
|
+
};
|
|
876
|
+
return new core_1.PriestEngine(profileLoader, useSession ? this.sessionResolver.openStore() : undefined, { [providerName]: adapter });
|
|
877
|
+
}
|
|
878
|
+
async refreshProviderCredentialsIfNeeded(providerName) {
|
|
879
|
+
if (providerName !== 'github_copilot' && providerName !== 'chatgpt' && providerName !== 'xai')
|
|
880
|
+
return;
|
|
881
|
+
const provider = this.options.loadedConfig.config.providers[providerName];
|
|
882
|
+
if (!provider?.oauthToken)
|
|
883
|
+
return;
|
|
884
|
+
if (provider.apiKeyEnv && process.env[provider.apiKeyEnv])
|
|
885
|
+
return;
|
|
886
|
+
const refreshWindowSeconds = 60;
|
|
887
|
+
const nowSeconds = Math.floor(Date.now() / 1000);
|
|
888
|
+
if (provider.apiKey
|
|
889
|
+
&& provider.apiKeyExpiresAt !== undefined
|
|
890
|
+
&& provider.apiKeyExpiresAt > nowSeconds + refreshWindowSeconds) {
|
|
891
|
+
return;
|
|
892
|
+
}
|
|
893
|
+
if (providerName === 'github_copilot') {
|
|
894
|
+
try {
|
|
895
|
+
const refreshed = await (0, GitHubCopilotAuth_1.exchangeGitHubTokenForCopilotToken)(provider.oauthToken);
|
|
896
|
+
provider.apiKey = refreshed.token;
|
|
897
|
+
provider.baseUrl = refreshed.baseUrl;
|
|
898
|
+
provider.apiKeyExpiresAt = refreshed.expiresAt;
|
|
899
|
+
new ConfigManager_1.ConfigManager(this.options.loadedConfig).save();
|
|
900
|
+
}
|
|
901
|
+
catch (error) {
|
|
902
|
+
throw MarifoldError_1.MarifoldError.configInvalid(`GitHub Copilot authorization could not be refreshed: ${error instanceof Error ? error.message : String(error)}. Run marifold provider reauth github_copilot to authorize again.`);
|
|
903
|
+
}
|
|
904
|
+
return;
|
|
905
|
+
}
|
|
906
|
+
if (providerName === 'xai') {
|
|
907
|
+
try {
|
|
908
|
+
const refreshed = await (0, XaiTokenRefresh_1.refreshXaiAccessToken)(provider.oauthToken, provider.proxy);
|
|
909
|
+
provider.apiKey = refreshed.apiKey;
|
|
910
|
+
provider.oauthToken = refreshed.refreshToken;
|
|
911
|
+
provider.apiKeyExpiresAt = refreshed.expiresAt;
|
|
912
|
+
new ConfigManager_1.ConfigManager(this.options.loadedConfig).save();
|
|
913
|
+
}
|
|
914
|
+
catch (error) {
|
|
915
|
+
throw MarifoldError_1.MarifoldError.configInvalid(`xAI authorization could not be refreshed: ${error instanceof Error ? error.message : String(error)}. Run marifold provider reauth xai to sign in again.`);
|
|
916
|
+
}
|
|
917
|
+
return;
|
|
918
|
+
}
|
|
919
|
+
// chatgpt: refresh the API credential from the stored OAuth refresh token.
|
|
920
|
+
// ChatGPT credentials without an apiKeyExpiresAt were issued before
|
|
921
|
+
// refresh support and may still be valid — only refresh when expiry is
|
|
922
|
+
// known or the key is missing.
|
|
923
|
+
if (provider.apiKey && provider.apiKeyExpiresAt === undefined)
|
|
924
|
+
return;
|
|
925
|
+
try {
|
|
926
|
+
const refreshed = await (0, ChatGptTokenRefresh_1.refreshChatGptAccessToken)(provider.oauthToken);
|
|
927
|
+
provider.apiKey = refreshed.apiKey;
|
|
928
|
+
provider.oauthToken = refreshed.refreshToken;
|
|
929
|
+
provider.apiKeyExpiresAt = refreshed.expiresAt;
|
|
930
|
+
if (refreshed.accountId)
|
|
931
|
+
provider.accountId = refreshed.accountId;
|
|
932
|
+
new ConfigManager_1.ConfigManager(this.options.loadedConfig).save();
|
|
933
|
+
}
|
|
934
|
+
catch (error) {
|
|
935
|
+
throw MarifoldError_1.MarifoldError.configInvalid(`ChatGPT authorization could not be refreshed: ${error instanceof Error ? error.message : String(error)}. Run marifold provider reauth chatgpt to sign in again.`);
|
|
936
|
+
}
|
|
937
|
+
}
|
|
938
|
+
/**
|
|
939
|
+
* Model-initiated tools for chat turns. Opt-in via [web_search].enabled;
|
|
940
|
+
* web_search joins unless network policy is deny, read_file joins only when
|
|
941
|
+
* read policy is allow.
|
|
942
|
+
*/
|
|
943
|
+
chatTools(request) {
|
|
944
|
+
const webSearch = (0, ConfigSchema_1.resolveWebSearchConfig)(this.options.loadedConfig.config.webSearch);
|
|
945
|
+
if (!webSearch.enabled || request.chatTools === false)
|
|
946
|
+
return undefined;
|
|
947
|
+
const agentConfig = this.resolveAgentConfigForProfile(request.profile);
|
|
948
|
+
const approval = agentConfig.approval;
|
|
949
|
+
const tools = [];
|
|
950
|
+
if (approval.network !== 'deny')
|
|
951
|
+
tools.push(new WebSearchTool_1.WebSearchTool(this.searchBackend, webSearch.maxResults));
|
|
952
|
+
if (approval.read === 'allow')
|
|
953
|
+
tools.push(new ReadFileTool_1.ReadFileTool());
|
|
954
|
+
if (tools.length === 0)
|
|
955
|
+
return undefined;
|
|
956
|
+
const outputLimit = agentConfig.toolOutputLimit;
|
|
957
|
+
return {
|
|
958
|
+
definitions: tools.map(tool => tool.definition),
|
|
959
|
+
execute: async (name, args) => {
|
|
960
|
+
const tool = tools.find(t => t.definition.name === name);
|
|
961
|
+
if (!tool)
|
|
962
|
+
return { content: `Unknown tool '${name}'.`, isError: true };
|
|
963
|
+
try {
|
|
964
|
+
const result = await tool.execute(args, { cwd: process.cwd(), outputLimit });
|
|
965
|
+
return { content: result.content, isError: result.isError };
|
|
966
|
+
}
|
|
967
|
+
catch (error) {
|
|
968
|
+
return { content: `Tool '${name}' failed: ${error instanceof Error ? error.message : String(error)}`, isError: true };
|
|
969
|
+
}
|
|
970
|
+
},
|
|
971
|
+
};
|
|
972
|
+
}
|
|
973
|
+
toPriestConfig(settings) {
|
|
974
|
+
const { config } = this.options.loadedConfig;
|
|
975
|
+
const provider = config.providers[settings.provider];
|
|
976
|
+
const neutralReasoning = this.supportsNeutralReasoning(settings.provider, settings.model);
|
|
977
|
+
return {
|
|
978
|
+
provider: settings.provider,
|
|
979
|
+
model: settings.model,
|
|
980
|
+
timeoutSeconds: config.default.timeoutSeconds,
|
|
981
|
+
maxOutputTokens: config.default.maxOutputTokens,
|
|
982
|
+
maxSystemChars: config.default.maxSystemChars,
|
|
983
|
+
maxContextTokens: settings.maxContextTokens ?? config.default.maxContextTokens,
|
|
984
|
+
compactionKeepTurns: config.default.compactionKeepTurns,
|
|
985
|
+
sessionContextTurns: settings.sessionContextTurns ?? config.default.sessionContextTurns,
|
|
986
|
+
reasoning: provider?.type === 'ollama'
|
|
987
|
+
? {
|
|
988
|
+
enabled: settings.think,
|
|
989
|
+
...(settings.think ? { effort: 'high', summary: 'auto' } : {}),
|
|
990
|
+
}
|
|
991
|
+
: neutralReasoning && settings.think
|
|
992
|
+
? { enabled: true, effort: 'high', summary: 'auto' }
|
|
993
|
+
: undefined,
|
|
994
|
+
providerOptions: LEGACY_THINK_PROVIDER_NAMES.has(settings.provider)
|
|
995
|
+
? { think: settings.think }
|
|
996
|
+
: undefined,
|
|
997
|
+
};
|
|
998
|
+
}
|
|
999
|
+
supportsNeutralReasoning(providerName, model) {
|
|
1000
|
+
const provider = this.options.loadedConfig.config.providers[providerName];
|
|
1001
|
+
return provider?.type === 'ollama'
|
|
1002
|
+
|| provider?.type === 'anthropic'
|
|
1003
|
+
|| providerName === 'chatgpt'
|
|
1004
|
+
|| (providerName === 'github_copilot' && (0, ProviderRegistry_1.isGitHubCopilotResponsesModelId)(model));
|
|
1005
|
+
}
|
|
1006
|
+
supportsThink(providerName, model) {
|
|
1007
|
+
return LEGACY_THINK_PROVIDER_NAMES.has(providerName)
|
|
1008
|
+
|| this.supportsNeutralReasoning(providerName, model);
|
|
1009
|
+
}
|
|
1010
|
+
/** Whether the profile's resolved provider honors thinking mode — so a channel
|
|
1011
|
+
* can tell the user when `/think` would have no effect. */
|
|
1012
|
+
profileSupportsThink(profile) {
|
|
1013
|
+
const settings = this.resolveSettings({ profile });
|
|
1014
|
+
return this.supportsThink(settings.provider, settings.model);
|
|
1015
|
+
}
|
|
1016
|
+
memoryForRequest(profile, requestMemories = true, prompt = '', thinking = false) {
|
|
1017
|
+
const { config } = this.options.loadedConfig;
|
|
1018
|
+
if (!this.memoryEnabled(profile, requestMemories))
|
|
1019
|
+
return [];
|
|
1020
|
+
this.ensureProfileMemoryFiles(profile);
|
|
1021
|
+
return this.memoryStore.listPromptMemory(profile, {
|
|
1022
|
+
contextLimit: config.memory.contextLimit,
|
|
1023
|
+
prompt,
|
|
1024
|
+
thinking,
|
|
1025
|
+
});
|
|
1026
|
+
}
|
|
1027
|
+
runtimeContext(memory, prompt, memoryOn) {
|
|
1028
|
+
const context = ['Running inside Marifold.'];
|
|
1029
|
+
if (memoryOn) {
|
|
1030
|
+
context.push('Profile memory is app-owned context. Current user messages and profile rules outrank memory.');
|
|
1031
|
+
if ((0, MemoryControls_1.shouldInjectMemoryInstructions)(prompt))
|
|
1032
|
+
context.push((0, MemoryControls_1.buildMemoryInstructions)());
|
|
1033
|
+
}
|
|
1034
|
+
else if (memory.length > 0) {
|
|
1035
|
+
context.push('Profile memory is app-owned context. Current user messages and profile rules outrank memory.');
|
|
1036
|
+
}
|
|
1037
|
+
return context;
|
|
1038
|
+
}
|
|
1039
|
+
editHistoryContext(request, settings) {
|
|
1040
|
+
if (request.replaceUserTurnIndex === undefined)
|
|
1041
|
+
return [];
|
|
1042
|
+
if (!request.sessionId) {
|
|
1043
|
+
throw MarifoldError_1.MarifoldError.configInvalid('replaceUserTurnIndex requires sessionId.');
|
|
1044
|
+
}
|
|
1045
|
+
const turns = this.sessionResolver.turnsBeforeUserTurn(request.sessionId, request.replaceUserTurnIndex)
|
|
1046
|
+
?? this.missingEditedTurn(request.sessionId, request.replaceUserTurnIndex);
|
|
1047
|
+
const history = (0, AgentHistory_1.buildHistoryContext)(turns.map(turn => ({ role: turn.role, content: turn.content })), settings.maxContextTokens ?? EDIT_HISTORY_BUDGET_DEFAULT_CHARS);
|
|
1048
|
+
return history ? [history] : [];
|
|
1049
|
+
}
|
|
1050
|
+
replaceEditedExchange(sessionId, userTurnIndex, userText, assistantText, images, responseMetrics) {
|
|
1051
|
+
const result = this.sessionResolver.replaceExchange(sessionId, userTurnIndex, userText, assistantText, images, responseMetrics);
|
|
1052
|
+
if (!result.replaced)
|
|
1053
|
+
this.missingEditedTurn(sessionId, userTurnIndex);
|
|
1054
|
+
}
|
|
1055
|
+
missingEditedTurn(sessionId, userTurnIndex) {
|
|
1056
|
+
throw MarifoldError_1.MarifoldError.configInvalid(`Cannot edit user turn ${userTurnIndex} because it is missing from session '${sessionId}'.`);
|
|
1057
|
+
}
|
|
1058
|
+
applyTurnMemory(profile, prompt, controls, sessionId) {
|
|
1059
|
+
this.memoryStore.applySavePayloads(profile, controls.savePayloads, { sessionId });
|
|
1060
|
+
this.memoryStore.applyForgetPayloads(profile, controls.forgetPayloads);
|
|
1061
|
+
for (const query of (0, MemoryControls_1.extractPromptForgetQueries)(prompt)) {
|
|
1062
|
+
this.memoryStore.forget(profile, query);
|
|
1063
|
+
}
|
|
1064
|
+
this.memoryStore.save(profile, (0, MemoryControls_1.extractPromptMemoryInputs)(prompt), { sessionId });
|
|
1065
|
+
this.memoryStore.trimShortTerm(profile, this.options.loadedConfig.config.memory.sizeLimit);
|
|
1066
|
+
}
|
|
1067
|
+
}
|
|
1068
|
+
exports.MarifoldRuntime = MarifoldRuntime;
|
|
1069
|
+
function completedResponseMetrics(mode, settings, startedAt, startedAtMs, usage) {
|
|
1070
|
+
const finishedAtMs = Date.now();
|
|
1071
|
+
return {
|
|
1072
|
+
mode,
|
|
1073
|
+
provider: settings.provider,
|
|
1074
|
+
model: settings.model,
|
|
1075
|
+
think: settings.think,
|
|
1076
|
+
startedAt,
|
|
1077
|
+
finishedAt: new Date(finishedAtMs).toISOString(),
|
|
1078
|
+
latencyMs: Math.max(0, finishedAtMs - startedAtMs),
|
|
1079
|
+
...(usage && Object.values(usage).some(value => value !== undefined) ? { usage: { ...usage } } : {}),
|
|
1080
|
+
};
|
|
1081
|
+
}
|
|
1082
|
+
/** Sum two provider usage reports, preserving undefined when neither side has
|
|
1083
|
+
* a given field (so absent token data stays absent rather than showing 0). */
|
|
1084
|
+
function sumUsage(a, b) {
|
|
1085
|
+
if (!a)
|
|
1086
|
+
return b;
|
|
1087
|
+
if (!b)
|
|
1088
|
+
return a;
|
|
1089
|
+
const add = (x, y) => x == null && y == null ? undefined : (x ?? 0) + (y ?? 0);
|
|
1090
|
+
return {
|
|
1091
|
+
inputTokens: add(a.inputTokens, b.inputTokens),
|
|
1092
|
+
outputTokens: add(a.outputTokens, b.outputTokens),
|
|
1093
|
+
totalTokens: add(a.totalTokens, b.totalTokens),
|
|
1094
|
+
cachedInputTokens: add(a.cachedInputTokens, b.cachedInputTokens),
|
|
1095
|
+
reasoningTokens: add(a.reasoningTokens, b.reasoningTokens),
|
|
1096
|
+
estimatedCostUSD: add(a.estimatedCostUSD, b.estimatedCostUSD),
|
|
1097
|
+
};
|
|
1098
|
+
}
|
|
1099
|
+
//# sourceMappingURL=MarifoldRuntime.js.map
|