@marifold/core 0.64.1 → 0.66.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/dist/agent/AgentRunner.d.ts +7 -0
- package/dist/agent/AgentRunner.d.ts.map +1 -1
- package/dist/agent/AgentRunner.js +27 -1
- package/dist/agent/AgentRunner.js.map +1 -1
- package/dist/agent/RunWorkspace.d.ts +10 -0
- package/dist/agent/RunWorkspace.d.ts.map +1 -1
- package/dist/agent/RunWorkspace.js +19 -1
- package/dist/agent/RunWorkspace.js.map +1 -1
- package/dist/agent/tools/ReadFileTool.d.ts +7 -0
- package/dist/agent/tools/ReadFileTool.d.ts.map +1 -1
- package/dist/agent/tools/ReadFileTool.js +24 -2
- package/dist/agent/tools/ReadFileTool.js.map +1 -1
- package/dist/app/AppStore.d.ts +11 -1
- package/dist/app/AppStore.d.ts.map +1 -1
- package/dist/app/AppStore.js +105 -16
- package/dist/app/AppStore.js.map +1 -1
- package/dist/app/SkillAppCompiler.d.ts.map +1 -1
- package/dist/app/SkillAppCompiler.js +314 -44
- package/dist/app/SkillAppCompiler.js.map +1 -1
- package/dist/app/SkillAppDsl.d.ts +60 -4
- package/dist/app/SkillAppDsl.d.ts.map +1 -1
- package/dist/app/SkillAppDsl.js +44 -0
- package/dist/app/SkillAppDsl.js.map +1 -1
- package/dist/app/SkillAppInstanceRegistry.d.ts +3 -2
- package/dist/app/SkillAppInstanceRegistry.d.ts.map +1 -1
- package/dist/app/SkillAppInstanceRegistry.js +191 -11
- package/dist/app/SkillAppInstanceRegistry.js.map +1 -1
- package/dist/app/SkillAppResolver.d.ts +5 -2
- package/dist/app/SkillAppResolver.d.ts.map +1 -1
- package/dist/app/SkillAppResolver.js +66 -15
- package/dist/app/SkillAppResolver.js.map +1 -1
- package/dist/app/SkillAppSchema.d.ts +84 -8
- package/dist/app/SkillAppSchema.d.ts.map +1 -1
- package/dist/app/SkillAppSchema.js +2 -1
- package/dist/app/SkillAppSchema.js.map +1 -1
- package/dist/config/ConfigLoader.d.ts.map +1 -1
- package/dist/config/ConfigLoader.js +17 -3
- package/dist/config/ConfigLoader.js.map +1 -1
- package/dist/config/ConfigManager.d.ts.map +1 -1
- package/dist/config/ConfigManager.js +13 -2
- package/dist/config/ConfigManager.js.map +1 -1
- package/dist/config/ConfigSchema.d.ts +8 -2
- package/dist/config/ConfigSchema.d.ts.map +1 -1
- package/dist/config/ConfigSchema.js.map +1 -1
- package/dist/config/MarifoldOpenAICompatProvider.d.ts +1 -1
- package/dist/config/MarifoldOpenAICompatProvider.d.ts.map +1 -1
- package/dist/config/MarifoldOpenAICompatProvider.js +8 -6
- package/dist/config/MarifoldOpenAICompatProvider.js.map +1 -1
- package/dist/config/ProviderFactory.d.ts +6 -4
- package/dist/config/ProviderFactory.d.ts.map +1 -1
- package/dist/config/ProviderFactory.js +41 -6
- package/dist/config/ProviderFactory.js.map +1 -1
- package/dist/index.d.ts +8 -6
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +14 -3
- package/dist/index.js.map +1 -1
- package/dist/runtime/MarifoldRuntime.d.ts +17 -9
- package/dist/runtime/MarifoldRuntime.d.ts.map +1 -1
- package/dist/runtime/MarifoldRuntime.js +270 -59
- package/dist/runtime/MarifoldRuntime.js.map +1 -1
- package/dist/runtime/MarifoldTypes.d.ts +1 -1
- package/dist/runtime/MarifoldTypes.d.ts.map +1 -1
- package/dist/runtime/NativeWebSearch.d.ts +9 -0
- package/dist/runtime/NativeWebSearch.d.ts.map +1 -0
- package/dist/runtime/NativeWebSearch.js +17 -0
- package/dist/runtime/NativeWebSearch.js.map +1 -0
- package/dist/search/OllamaSearchBackend.d.ts +22 -0
- package/dist/search/OllamaSearchBackend.d.ts.map +1 -0
- package/dist/search/OllamaSearchBackend.js +64 -0
- package/dist/search/OllamaSearchBackend.js.map +1 -0
- package/dist/search/createSearchBackend.d.ts +4 -3
- package/dist/search/createSearchBackend.d.ts.map +1 -1
- package/dist/search/createSearchBackend.js +13 -3
- package/dist/search/createSearchBackend.js.map +1 -1
- package/dist/skill/SkillStore.d.ts +2 -2
- package/dist/skill/SkillStore.js +2 -2
- package/package.json +1 -1
|
@@ -81,6 +81,7 @@ const SkillAppResolver_1 = require("../app/SkillAppResolver");
|
|
|
81
81
|
const SkillAppInstanceRegistry_1 = require("../app/SkillAppInstanceRegistry");
|
|
82
82
|
const TaskStore_1 = require("../tasks/TaskStore");
|
|
83
83
|
const WorkspacePaths_1 = require("../workspace/WorkspacePaths");
|
|
84
|
+
const NativeWebSearch_1 = require("./NativeWebSearch");
|
|
84
85
|
// Older OpenAI-compatible gateways still take a raw `{think}` body option.
|
|
85
86
|
// Priest 2.8 owns neutral reasoning for Ollama, Anthropic, and Responses.
|
|
86
87
|
const LEGACY_THINK_PROVIDER_NAMES = new Set(['bailian', 'alibaba_cloud']);
|
|
@@ -97,6 +98,7 @@ class MarifoldRuntime {
|
|
|
97
98
|
memoryStore;
|
|
98
99
|
taskStore;
|
|
99
100
|
searchBackend;
|
|
101
|
+
searchBackendOverridden;
|
|
100
102
|
scheduleStore;
|
|
101
103
|
constructor(options) {
|
|
102
104
|
this.options = options;
|
|
@@ -107,6 +109,7 @@ class MarifoldRuntime {
|
|
|
107
109
|
this.providerFactory = new ProviderFactory_1.ProviderFactory(config, configPath);
|
|
108
110
|
this.memoryStore = new MemoryStore_1.MemoryStore(config.paths.profilesDir);
|
|
109
111
|
this.taskStore = new TaskStore_1.TaskStore(config.paths.tasksDir);
|
|
112
|
+
this.searchBackendOverridden = options.searchBackend !== undefined;
|
|
110
113
|
this.searchBackend = options.searchBackend
|
|
111
114
|
?? (0, createSearchBackend_1.createSearchBackend)((0, ConfigSchema_1.resolveWebSearchConfig)(config.webSearch));
|
|
112
115
|
this.scheduleStore = new ScheduleStore_1.ScheduleStore(config.paths.schedulesDir ?? (0, WorkspacePaths_1.defaultSchedulesDir)());
|
|
@@ -138,10 +141,14 @@ class MarifoldRuntime {
|
|
|
138
141
|
const engine = this.createEngine(settings.provider, Boolean(request.sessionId) && !replacing && !isolated, request.profileContext !== false);
|
|
139
142
|
const memoryOn = this.memoryEnabled(settings.profile, request.memories);
|
|
140
143
|
const memory = this.memoryForRequest(settings.profile, request.memories, request.prompt, settings.think);
|
|
141
|
-
const
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
144
|
+
const searchResolution = this.resolveWebSearch(settings, request.chatTools !== false);
|
|
145
|
+
let webSearchMode = searchResolution.mode;
|
|
146
|
+
let chatTools = this.chatTools(request, webSearchMode);
|
|
147
|
+
const nativeFallbackAvailable = webSearchMode === 'native'
|
|
148
|
+
&& this.fallbackWebSearchAvailable(settings, request.chatTools !== false);
|
|
149
|
+
let nativeFallbackAttempted = false;
|
|
150
|
+
const buildPriestRequest = () => ({
|
|
151
|
+
config: this.toPriestConfig(settings, webSearchMode === 'native' ? searchResolution.nativeStrategy : 'none'),
|
|
145
152
|
profile: settings.profile,
|
|
146
153
|
prompt: request.prompt,
|
|
147
154
|
session: request.sessionId && !replacing && !isolated
|
|
@@ -155,10 +162,11 @@ class MarifoldRuntime {
|
|
|
155
162
|
memory,
|
|
156
163
|
images: preparedImages.images.length > 0 ? preparedImages.images : undefined,
|
|
157
164
|
userContext: request.userContext,
|
|
158
|
-
providerTools: this.providerToolsFor(webSearchMode),
|
|
159
|
-
};
|
|
165
|
+
providerTools: this.providerToolsFor(webSearchMode, searchResolution.nativeStrategy),
|
|
166
|
+
});
|
|
167
|
+
let priestRequest = buildPriestRequest();
|
|
160
168
|
const exchange = [];
|
|
161
|
-
const maxIterations = chatTools ? CHAT_TOOL_MAX_ITERATIONS : 1;
|
|
169
|
+
const maxIterations = chatTools || nativeFallbackAvailable ? CHAT_TOOL_MAX_ITERATIONS : 1;
|
|
162
170
|
let response;
|
|
163
171
|
let aggregateUsage;
|
|
164
172
|
// Keep the non-streaming CLI/service path at parity with stream(): a model
|
|
@@ -172,6 +180,18 @@ class MarifoldRuntime {
|
|
|
172
180
|
...(exchange.length > 0 ? { toolExchange: exchange } : {}),
|
|
173
181
|
}, request.signal ? { signal: request.signal } : undefined);
|
|
174
182
|
aggregateUsage = sumUsage(aggregateUsage, response.usage);
|
|
183
|
+
if (!response.ok
|
|
184
|
+
&& webSearchMode === 'native'
|
|
185
|
+
&& nativeFallbackAvailable
|
|
186
|
+
&& !nativeFallbackAttempted
|
|
187
|
+
&& (0, NativeWebSearch_1.isNativeWebSearchCapabilityError)(response.error)) {
|
|
188
|
+
nativeFallbackAttempted = true;
|
|
189
|
+
webSearchMode = 'fallback';
|
|
190
|
+
chatTools = this.chatTools(request, webSearchMode);
|
|
191
|
+
priestRequest = buildPriestRequest();
|
|
192
|
+
iteration -= 1;
|
|
193
|
+
continue;
|
|
194
|
+
}
|
|
175
195
|
if (!response.ok || !chatTools || !response.toolCalls?.length)
|
|
176
196
|
break;
|
|
177
197
|
exchange.push({
|
|
@@ -241,10 +261,14 @@ class MarifoldRuntime {
|
|
|
241
261
|
const engine = this.createEngine(settings.provider, enginePersistsSession, request.profileContext !== false);
|
|
242
262
|
const memoryOn = this.memoryEnabled(settings.profile, request.memories);
|
|
243
263
|
const memory = this.memoryForRequest(settings.profile, request.memories, request.prompt, settings.think);
|
|
244
|
-
const
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
264
|
+
const searchResolution = this.resolveWebSearch(settings, request.chatTools !== false);
|
|
265
|
+
let webSearchMode = searchResolution.mode;
|
|
266
|
+
let chatTools = this.chatTools(request, webSearchMode);
|
|
267
|
+
const nativeFallbackAvailable = webSearchMode === 'native'
|
|
268
|
+
&& this.fallbackWebSearchAvailable(settings, request.chatTools !== false);
|
|
269
|
+
let nativeFallbackAttempted = false;
|
|
270
|
+
const buildBaseRequest = () => ({
|
|
271
|
+
config: this.toPriestConfig(settings, webSearchMode === 'native' ? searchResolution.nativeStrategy : 'none'),
|
|
248
272
|
profile: settings.profile,
|
|
249
273
|
prompt: request.prompt,
|
|
250
274
|
session: request.sessionId && !replacing && !isolated
|
|
@@ -258,19 +282,21 @@ class MarifoldRuntime {
|
|
|
258
282
|
memory,
|
|
259
283
|
images: preparedImages.images.length > 0 ? preparedImages.images : undefined,
|
|
260
284
|
userContext: request.userContext,
|
|
261
|
-
providerTools: this.providerToolsFor(webSearchMode),
|
|
262
|
-
};
|
|
285
|
+
providerTools: this.providerToolsFor(webSearchMode, searchResolution.nativeStrategy),
|
|
286
|
+
});
|
|
287
|
+
let baseRequest = buildBaseRequest();
|
|
263
288
|
// Caller-executed fallback/read loop. Provider-hosted search is carried
|
|
264
289
|
// separately and does not enter Marifold's tool exchange.
|
|
265
290
|
// Intermediate tool-call turns are turn-local; the engine persists the
|
|
266
291
|
// session only on the loop's final response, and memory payloads are
|
|
267
292
|
// applied only from that final response.
|
|
268
293
|
const exchange = [];
|
|
269
|
-
const maxIterations = chatTools ? CHAT_TOOL_MAX_ITERATIONS : 1;
|
|
294
|
+
const maxIterations = chatTools || nativeFallbackAvailable ? CHAT_TOOL_MAX_ITERATIONS : 1;
|
|
270
295
|
for (let iteration = 0; iteration < maxIterations; iteration += 1) {
|
|
271
296
|
const stripper = new MemoryControls_1.MemoryControlStripper();
|
|
272
297
|
const visibleParts = [];
|
|
273
298
|
let done;
|
|
299
|
+
let providerOutputStarted = false;
|
|
274
300
|
const lastIteration = iteration === maxIterations - 1;
|
|
275
301
|
for await (const event of engine.streamEvents({
|
|
276
302
|
...baseRequest,
|
|
@@ -278,6 +304,7 @@ class MarifoldRuntime {
|
|
|
278
304
|
...(exchange.length > 0 ? { toolExchange: exchange } : {}),
|
|
279
305
|
}, request.signal ? { signal: request.signal } : undefined)) {
|
|
280
306
|
if (event.type === 'text_delta') {
|
|
307
|
+
providerOutputStarted = true;
|
|
281
308
|
const visible = stripper.feed(event.text);
|
|
282
309
|
if (visible) {
|
|
283
310
|
visibleParts.push(visible);
|
|
@@ -285,8 +312,14 @@ class MarifoldRuntime {
|
|
|
285
312
|
}
|
|
286
313
|
}
|
|
287
314
|
else if (event.type === 'reasoning_summary_delta') {
|
|
315
|
+
providerOutputStarted = true;
|
|
288
316
|
onReasoningSummary?.(event.text);
|
|
289
317
|
}
|
|
318
|
+
else if (event.type === 'tool_call_start'
|
|
319
|
+
|| event.type === 'tool_call_delta'
|
|
320
|
+
|| event.type === 'tool_call_end') {
|
|
321
|
+
providerOutputStarted = true;
|
|
322
|
+
}
|
|
290
323
|
else if (event.type === 'done') {
|
|
291
324
|
done = event.response;
|
|
292
325
|
}
|
|
@@ -297,6 +330,18 @@ class MarifoldRuntime {
|
|
|
297
330
|
yield tail;
|
|
298
331
|
}
|
|
299
332
|
aggregateUsage = sumUsage(aggregateUsage, done?.usage);
|
|
333
|
+
if (!providerOutputStarted
|
|
334
|
+
&& webSearchMode === 'native'
|
|
335
|
+
&& nativeFallbackAvailable
|
|
336
|
+
&& !nativeFallbackAttempted
|
|
337
|
+
&& (0, NativeWebSearch_1.isNativeWebSearchCapabilityError)(done?.error)) {
|
|
338
|
+
nativeFallbackAttempted = true;
|
|
339
|
+
webSearchMode = 'fallback';
|
|
340
|
+
chatTools = this.chatTools(request, webSearchMode);
|
|
341
|
+
baseRequest = buildBaseRequest();
|
|
342
|
+
iteration -= 1;
|
|
343
|
+
continue;
|
|
344
|
+
}
|
|
300
345
|
if (done?.error) {
|
|
301
346
|
this.discardFailedNewSession(request.sessionId, sessionWasMissing);
|
|
302
347
|
throw MarifoldError_1.MarifoldError.providerError(done.error.message, settings.provider, settings.model, done.error.code);
|
|
@@ -355,7 +400,7 @@ class MarifoldRuntime {
|
|
|
355
400
|
}
|
|
356
401
|
}
|
|
357
402
|
}
|
|
358
|
-
/** Run the web
|
|
403
|
+
/** Run the selected web-search backend directly for non-chat integrations. */
|
|
359
404
|
async searchWeb(query, maxResults) {
|
|
360
405
|
const config = (0, ConfigSchema_1.resolveWebSearchConfig)(this.options.loadedConfig.config.webSearch);
|
|
361
406
|
const results = await this.searchBackend.search(query, maxResults ?? config.maxResults);
|
|
@@ -495,6 +540,9 @@ class MarifoldRuntime {
|
|
|
495
540
|
* validation as the CLI's `config set` (see ConfigManager.setValue). */
|
|
496
541
|
setConfigValue(key, value) {
|
|
497
542
|
new ConfigManager_1.ConfigManager(this.options.loadedConfig).setValue(key, value);
|
|
543
|
+
if (key.startsWith('web_search.') && !this.searchBackendOverridden) {
|
|
544
|
+
this.searchBackend = (0, createSearchBackend_1.createSearchBackend)((0, ConfigSchema_1.resolveWebSearchConfig)(this.options.loadedConfig.config.webSearch));
|
|
545
|
+
}
|
|
498
546
|
}
|
|
499
547
|
/** Read a config value by dotted key (CLI `config get`). */
|
|
500
548
|
getConfigValue(key) {
|
|
@@ -623,23 +671,28 @@ class MarifoldRuntime {
|
|
|
623
671
|
toolMode: override.toolMode ?? global.toolMode,
|
|
624
672
|
};
|
|
625
673
|
}
|
|
626
|
-
createAgentRunner(profile, registry) {
|
|
674
|
+
createAgentRunner(profile, registry, agentConfigOverride, runtimeOptions = {}) {
|
|
627
675
|
return new AgentRunner_1.AgentRunner({
|
|
628
676
|
taskStore: this.taskStore,
|
|
629
677
|
registry: registry ?? this.createDefaultToolRegistry(profile),
|
|
630
|
-
agentConfig: this.resolveAgentConfigForProfile(profile),
|
|
678
|
+
agentConfig: agentConfigOverride ?? this.resolveAgentConfigForProfile(profile),
|
|
631
679
|
resolveSettings: request => this.resolveSettings(request),
|
|
632
680
|
prepareEngine: async (settings) => {
|
|
633
681
|
await this.refreshProviderCredentialsIfNeeded(settings.provider);
|
|
634
|
-
const
|
|
682
|
+
const searchResolution = runtimeOptions.webSearch === false
|
|
683
|
+
? { mode: 'unavailable', nativeStrategy: 'none' }
|
|
684
|
+
: this.resolveWebSearch(settings);
|
|
685
|
+
const webSearchMode = searchResolution.mode;
|
|
635
686
|
return {
|
|
636
687
|
// No engine-level session store: priest would otherwise persist the
|
|
637
688
|
// raw per-iteration `Objective:`/tool framing (and duplicates). The
|
|
638
689
|
// runner instead persists one clean turn pair via `persistTurn` below.
|
|
639
690
|
engine: this.createEngine(settings.provider, false),
|
|
640
|
-
config: this.toPriestConfig(settings,
|
|
691
|
+
config: this.toPriestConfig(settings, searchResolution.nativeStrategy),
|
|
641
692
|
webSearchMode,
|
|
642
|
-
|
|
693
|
+
webSearchFallbackAvailable: webSearchMode === 'native'
|
|
694
|
+
&& this.fallbackWebSearchAvailable(settings),
|
|
695
|
+
providerTools: this.providerToolsFor(webSearchMode, searchResolution.nativeStrategy),
|
|
643
696
|
};
|
|
644
697
|
},
|
|
645
698
|
prepareImages: async (images, optimize) => (await (0, ImageOptimizer_1.prepareImageInputs)(images, { optimize })).images,
|
|
@@ -671,12 +724,16 @@ class MarifoldRuntime {
|
|
|
671
724
|
})];
|
|
672
725
|
},
|
|
673
726
|
resolveReadOnlyFolders: resolvedProfile => {
|
|
727
|
+
if (runtimeOptions.readOnlyFolders)
|
|
728
|
+
return runtimeOptions.readOnlyFolders;
|
|
674
729
|
const { config } = this.options.loadedConfig;
|
|
675
730
|
return [
|
|
676
731
|
path.join(config.paths.profilesDir, resolvedProfile, 'skills'),
|
|
677
732
|
config.paths.skillsDir ?? (0, WorkspacePaths_1.defaultSkillsDir)(),
|
|
678
733
|
];
|
|
679
734
|
},
|
|
735
|
+
resolveReadOnlyFiles: () => runtimeOptions.readOnlyFiles ?? [],
|
|
736
|
+
allowExternalReadOnlyFolders: runtimeOptions.allowExternalReadOnlyFolders,
|
|
680
737
|
});
|
|
681
738
|
}
|
|
682
739
|
createDefaultToolRegistry(profile) {
|
|
@@ -759,7 +816,12 @@ class MarifoldRuntime {
|
|
|
759
816
|
}
|
|
760
817
|
createAppStore() {
|
|
761
818
|
const { config } = this.options.loadedConfig;
|
|
762
|
-
return new AppStore_1.AppStore(config.paths.appsDir ?? (0, WorkspacePaths_1.defaultAppsDir)()
|
|
819
|
+
return new AppStore_1.AppStore(config.paths.appsDir ?? (0, WorkspacePaths_1.defaultAppsDir)(), {
|
|
820
|
+
resolveProfileSkill: (profile, skillName) => {
|
|
821
|
+
this.profileResolver.load(profile);
|
|
822
|
+
return this.createSkillStore(profile).get(skillName);
|
|
823
|
+
},
|
|
824
|
+
});
|
|
763
825
|
}
|
|
764
826
|
listApps() {
|
|
765
827
|
return this.createAppStore().list();
|
|
@@ -767,36 +829,82 @@ class MarifoldRuntime {
|
|
|
767
829
|
getApp(name) {
|
|
768
830
|
return this.createAppStore().get(name);
|
|
769
831
|
}
|
|
770
|
-
/** Execute one
|
|
771
|
-
*
|
|
772
|
-
*
|
|
773
|
-
async runSkillAppOperation(appName, operationName, state, signal) {
|
|
832
|
+
/** Execute one statically compiled SkillApp operation. v1 operations remain
|
|
833
|
+
* profile-free; v2 profile operations load the referenced profile and may
|
|
834
|
+
* receive read-only memory plus instance-local history. */
|
|
835
|
+
async runSkillAppOperation(appName, operationName, state, signal, history, attachments) {
|
|
774
836
|
const startedAt = Date.now();
|
|
775
837
|
try {
|
|
776
838
|
const store = this.createAppStore();
|
|
777
839
|
const definition = store.require(appName);
|
|
778
840
|
const operation = (0, SkillAppResolver_1.resolveSkillAppOperation)(store, definition, operationName, state);
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
841
|
+
let settings;
|
|
842
|
+
let text;
|
|
843
|
+
let usage;
|
|
844
|
+
if (operation.profile) {
|
|
845
|
+
settings = this.resolveSettings({
|
|
846
|
+
profile: operation.profile.profile,
|
|
847
|
+
...(operation.profile.provider ? { provider: operation.profile.provider } : {}),
|
|
848
|
+
...(operation.profile.model ? { model: operation.profile.model } : {}),
|
|
849
|
+
...(operation.profile.think !== undefined ? { think: operation.profile.think } : {}),
|
|
850
|
+
});
|
|
851
|
+
const memory = this.memoryForRequest(settings.profile, operation.profile.memory, operation.prompt, settings.think);
|
|
852
|
+
const historyContext = operation.profile.history && history?.length
|
|
853
|
+
? (0, AgentHistory_1.buildHistoryContext)(history, 16_000)
|
|
854
|
+
: undefined;
|
|
855
|
+
const instructions = [
|
|
856
|
+
...operation.instructions,
|
|
857
|
+
...(historyContext ? [historyContext] : []),
|
|
858
|
+
];
|
|
859
|
+
if ((operation.mode ?? settings.mode) === 'agent') {
|
|
860
|
+
const run = await this.runProfileSkillAppAgent(appName, operation.operationName, settings, operation.prompt, instructions, memory, operation.skillDirectory, definition.permissions ?? [], attachments, signal);
|
|
861
|
+
text = run.text;
|
|
862
|
+
usage = run.usage;
|
|
863
|
+
}
|
|
864
|
+
else {
|
|
865
|
+
if (attachments?.some(attachment => attachment.kind === 'file')) {
|
|
866
|
+
throw MarifoldError_1.MarifoldError.appInvalid(`SkillApp operation '${operationName}' needs Agent mode to inspect non-image attachments.`);
|
|
867
|
+
}
|
|
868
|
+
await this.refreshProviderCredentialsIfNeeded(settings.provider);
|
|
869
|
+
const response = await this.createEngine(settings.provider, false).run({
|
|
870
|
+
config: this.toPriestConfig(settings),
|
|
871
|
+
profile: settings.profile,
|
|
872
|
+
prompt: operation.prompt,
|
|
873
|
+
context: instructions,
|
|
874
|
+
...(memory.length > 0 ? { memory } : {}),
|
|
875
|
+
...(attachments?.some(attachment => attachment.kind === 'image') ? {
|
|
876
|
+
images: attachments
|
|
877
|
+
.filter(attachment => attachment.kind === 'image')
|
|
878
|
+
.map(attachment => ({ data: attachment.data, mediaType: attachment.mediaType })),
|
|
879
|
+
} : {}),
|
|
880
|
+
}, signal ? { signal } : undefined);
|
|
881
|
+
text = requireSkillAppResponseText(response, settings);
|
|
882
|
+
usage = response.usage;
|
|
883
|
+
}
|
|
795
884
|
}
|
|
796
|
-
|
|
797
|
-
|
|
885
|
+
else {
|
|
886
|
+
if (!operation.model) {
|
|
887
|
+
throw MarifoldError_1.MarifoldError.appInvalid(`SkillApp operation '${operationName}' has no model.`);
|
|
888
|
+
}
|
|
889
|
+
settings = {
|
|
890
|
+
profile: `skillapp-${appName}`,
|
|
891
|
+
provider: operation.model.provider,
|
|
892
|
+
model: operation.model.model,
|
|
893
|
+
think: operation.model.think,
|
|
894
|
+
mode: 'chat',
|
|
895
|
+
};
|
|
896
|
+
await this.refreshProviderCredentialsIfNeeded(settings.provider);
|
|
897
|
+
const response = await this.createEngine(settings.provider, false, false).run({
|
|
898
|
+
config: this.toPriestConfig(settings),
|
|
899
|
+
profile: settings.profile,
|
|
900
|
+
prompt: operation.prompt,
|
|
901
|
+
context: operation.instructions,
|
|
902
|
+
}, signal ? { signal } : undefined);
|
|
903
|
+
text = requireSkillAppResponseText(response, settings);
|
|
904
|
+
usage = response.usage;
|
|
798
905
|
}
|
|
799
|
-
|
|
906
|
+
text = (0, MemoryControls_1.stripMemoryControls)(text).text;
|
|
907
|
+
text = operation.result.trim ? text.trim() : text;
|
|
800
908
|
return {
|
|
801
909
|
status: 'ok',
|
|
802
910
|
data: { text },
|
|
@@ -804,7 +912,7 @@ class MarifoldRuntime {
|
|
|
804
912
|
engine: settings.provider,
|
|
805
913
|
model: settings.model,
|
|
806
914
|
durationMs: Date.now() - startedAt,
|
|
807
|
-
...(
|
|
915
|
+
...(usage ? { usage } : {}),
|
|
808
916
|
},
|
|
809
917
|
};
|
|
810
918
|
}
|
|
@@ -823,6 +931,81 @@ class MarifoldRuntime {
|
|
|
823
931
|
createSkillAppInstanceRegistry() {
|
|
824
932
|
return new SkillAppInstanceRegistry_1.SkillAppInstanceRegistry(this);
|
|
825
933
|
}
|
|
934
|
+
async runProfileSkillAppAgent(appName, operationName, settings, prompt, instructions, memory, skillDirectory, permissions = [], attachments = [], signal) {
|
|
935
|
+
const registry = new ToolRegistry_1.ToolRegistry();
|
|
936
|
+
registry.register(new InspectAttachmentTool_1.InspectAttachmentTool());
|
|
937
|
+
registry.register(new ReadAttachmentTool_1.ReadAttachmentTool());
|
|
938
|
+
registry.register(new SearchAttachmentTool_1.SearchAttachmentTool());
|
|
939
|
+
registry.register(new ReadFileTool_1.ReadFileTool({ strictWorkspace: true }));
|
|
940
|
+
const base = this.resolveAgentConfigForProfile(settings.profile);
|
|
941
|
+
const isolatedConfig = {
|
|
942
|
+
...base,
|
|
943
|
+
approval: {
|
|
944
|
+
read: 'allow',
|
|
945
|
+
write: 'deny',
|
|
946
|
+
shell: 'deny',
|
|
947
|
+
network: 'deny',
|
|
948
|
+
delegate: 'deny',
|
|
949
|
+
},
|
|
950
|
+
trustedFolders: [],
|
|
951
|
+
};
|
|
952
|
+
const runner = this.createAgentRunner(settings.profile, registry, isolatedConfig, {
|
|
953
|
+
webSearch: false,
|
|
954
|
+
readOnlyFolders: [
|
|
955
|
+
...(skillDirectory ? [skillDirectory] : []),
|
|
956
|
+
...permissions.filter(permission => permission.kind === 'folder').map(permission => permission.path),
|
|
957
|
+
],
|
|
958
|
+
readOnlyFiles: permissions
|
|
959
|
+
.filter(permission => permission.kind === 'file')
|
|
960
|
+
.map(permission => permission.path),
|
|
961
|
+
allowExternalReadOnlyFolders: true,
|
|
962
|
+
});
|
|
963
|
+
const images = attachments
|
|
964
|
+
.filter(attachment => attachment.kind === 'image')
|
|
965
|
+
.map(attachment => ({ data: attachment.data, mediaType: attachment.mediaType }));
|
|
966
|
+
const files = attachments
|
|
967
|
+
.filter(attachment => attachment.kind === 'file')
|
|
968
|
+
.map(attachment => ({
|
|
969
|
+
name: attachment.name,
|
|
970
|
+
mediaType: attachment.mediaType,
|
|
971
|
+
data: attachment.data,
|
|
972
|
+
...(attachment.inspectionText !== undefined ? { inspectionText: attachment.inspectionText } : {}),
|
|
973
|
+
}));
|
|
974
|
+
let finalText;
|
|
975
|
+
let failure;
|
|
976
|
+
let status;
|
|
977
|
+
let usage;
|
|
978
|
+
for await (const event of runner.run({
|
|
979
|
+
objective: prompt,
|
|
980
|
+
profile: settings.profile,
|
|
981
|
+
provider: settings.provider,
|
|
982
|
+
model: settings.model,
|
|
983
|
+
think: settings.think,
|
|
984
|
+
lean: true,
|
|
985
|
+
instructions,
|
|
986
|
+
...(images.length > 0 || files.length > 0 ? {
|
|
987
|
+
images,
|
|
988
|
+
files,
|
|
989
|
+
} : {}),
|
|
990
|
+
...(memory.length > 0 ? { memory } : {}),
|
|
991
|
+
cwd: (0, WorkspacePaths_1.marifoldHome)(),
|
|
992
|
+
tags: ['skillapp', appName, operationName],
|
|
993
|
+
signal,
|
|
994
|
+
})) {
|
|
995
|
+
if (event.type === 'text' && event.phase === 'final')
|
|
996
|
+
finalText = event.text;
|
|
997
|
+
if (event.type === 'error')
|
|
998
|
+
failure = { code: event.code, message: event.message };
|
|
999
|
+
if (event.type === 'done') {
|
|
1000
|
+
status = event.status;
|
|
1001
|
+
usage = event.usage;
|
|
1002
|
+
}
|
|
1003
|
+
}
|
|
1004
|
+
if (status !== 'completed' || finalText === undefined) {
|
|
1005
|
+
throw MarifoldError_1.MarifoldError.providerError(failure?.message ?? `Profile Skill operation '${operationName}' did not produce a final response.`, settings.provider, settings.model, failure?.code ?? 'APP_SKILL_FAILED');
|
|
1006
|
+
}
|
|
1007
|
+
return { text: finalText, ...(usage ? { usage } : {}) };
|
|
1008
|
+
}
|
|
826
1009
|
createSchedule(input) {
|
|
827
1010
|
return this.scheduleStore.create(input);
|
|
828
1011
|
}
|
|
@@ -1048,7 +1231,7 @@ class MarifoldRuntime {
|
|
|
1048
1231
|
},
|
|
1049
1232
|
};
|
|
1050
1233
|
}
|
|
1051
|
-
toPriestConfig(settings, nativeWebSearch =
|
|
1234
|
+
toPriestConfig(settings, nativeWebSearch = 'none') {
|
|
1052
1235
|
const { config } = this.options.loadedConfig;
|
|
1053
1236
|
const provider = config.providers[settings.provider];
|
|
1054
1237
|
const neutralReasoning = this.supportsNeutralReasoning(settings.provider, settings.model);
|
|
@@ -1058,8 +1241,12 @@ class MarifoldRuntime {
|
|
|
1058
1241
|
// Compatibility bridge for Priest 3.0.x. Priest 3.1 reads providerTools
|
|
1059
1242
|
// directly; Marifold's Responses wrapper consumes and removes this marker
|
|
1060
1243
|
// when an older engine does not forward that additive request field.
|
|
1061
|
-
if (nativeWebSearch)
|
|
1244
|
+
if (nativeWebSearch === 'responses-tool') {
|
|
1062
1245
|
providerOptions[NATIVE_WEB_SEARCH_COMPAT_OPTION] = true;
|
|
1246
|
+
}
|
|
1247
|
+
else if (nativeWebSearch === 'chat-option') {
|
|
1248
|
+
providerOptions['enable_search'] = true;
|
|
1249
|
+
}
|
|
1063
1250
|
return {
|
|
1064
1251
|
provider: settings.provider,
|
|
1065
1252
|
model: settings.model,
|
|
@@ -1108,20 +1295,35 @@ class MarifoldRuntime {
|
|
|
1108
1295
|
thinking,
|
|
1109
1296
|
});
|
|
1110
1297
|
}
|
|
1111
|
-
|
|
1112
|
-
if (!modelToolsEnabled)
|
|
1113
|
-
return 'unavailable';
|
|
1298
|
+
resolveWebSearch(settings, modelToolsEnabled = true) {
|
|
1299
|
+
if (!modelToolsEnabled) {
|
|
1300
|
+
return { mode: 'unavailable', nativeStrategy: 'none' };
|
|
1301
|
+
}
|
|
1114
1302
|
const approval = this.resolveAgentConfigForProfile(settings.profile).approval;
|
|
1115
|
-
if (approval.network === 'deny')
|
|
1116
|
-
return 'unavailable';
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1303
|
+
if (approval.network === 'deny') {
|
|
1304
|
+
return { mode: 'unavailable', nativeStrategy: 'none' };
|
|
1305
|
+
}
|
|
1306
|
+
const nativeStrategy = this.providerFactory.nativeWebSearchStrategy(settings.provider, settings.model);
|
|
1307
|
+
if (nativeStrategy !== 'none') {
|
|
1308
|
+
return { mode: 'native', nativeStrategy };
|
|
1309
|
+
}
|
|
1310
|
+
return {
|
|
1311
|
+
mode: this.fallbackWebSearchAvailable(settings, modelToolsEnabled) ? 'fallback' : 'unavailable',
|
|
1312
|
+
nativeStrategy: 'none',
|
|
1313
|
+
};
|
|
1122
1314
|
}
|
|
1123
|
-
|
|
1124
|
-
|
|
1315
|
+
fallbackWebSearchAvailable(settings, modelToolsEnabled = true) {
|
|
1316
|
+
if (!modelToolsEnabled) {
|
|
1317
|
+
return false;
|
|
1318
|
+
}
|
|
1319
|
+
const approval = this.resolveAgentConfigForProfile(settings.profile).approval;
|
|
1320
|
+
return approval.network !== 'deny'
|
|
1321
|
+
&& (0, ConfigSchema_1.resolveWebSearchConfig)(this.options.loadedConfig.config.webSearch).enabled;
|
|
1322
|
+
}
|
|
1323
|
+
providerToolsFor(mode, nativeStrategy) {
|
|
1324
|
+
return mode === 'native' && nativeStrategy === 'responses-tool'
|
|
1325
|
+
? [{ type: 'web_search' }]
|
|
1326
|
+
: undefined;
|
|
1125
1327
|
}
|
|
1126
1328
|
runtimeContext(memory, prompt, memoryOn, webSearchMode) {
|
|
1127
1329
|
const context = ['Running inside Marifold.'];
|
|
@@ -1171,6 +1373,15 @@ class MarifoldRuntime {
|
|
|
1171
1373
|
}
|
|
1172
1374
|
}
|
|
1173
1375
|
exports.MarifoldRuntime = MarifoldRuntime;
|
|
1376
|
+
function requireSkillAppResponseText(response, settings) {
|
|
1377
|
+
if (response.error) {
|
|
1378
|
+
throw MarifoldError_1.MarifoldError.providerError(response.error.message, settings.provider, settings.model, response.error.code);
|
|
1379
|
+
}
|
|
1380
|
+
if (response.text === undefined) {
|
|
1381
|
+
throw MarifoldError_1.MarifoldError.providerError(`Provider '${settings.provider}' returned no text for model '${settings.model}'.`, settings.provider, settings.model, 'EMPTY_RESPONSE');
|
|
1382
|
+
}
|
|
1383
|
+
return response.text;
|
|
1384
|
+
}
|
|
1174
1385
|
function completedResponseMetrics(mode, settings, startedAt, startedAtMs, usage) {
|
|
1175
1386
|
const finishedAtMs = Date.now();
|
|
1176
1387
|
return {
|