@schlenkr/ragents 0.1.8 → 0.1.10
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/apps/server/package.json +1 -1
- package/apps/server/src/access-projection.ts +6 -36
- package/apps/server/src/api/contracts.ts +5 -2
- package/apps/server/src/api/core-methods.ts +5 -3
- package/apps/server/src/config-definition.ts +24 -2
- package/apps/server/src/config-file.ts +1 -1
- package/apps/server/src/config.ts +0 -6
- package/apps/server/src/host-api.json +5 -10
- package/apps/server/src/host-api.ts +6 -7
- package/apps/server/src/plugin-build/build.ts +28 -5
- package/apps/server/src/plugin-build/plugin-description.ts +1 -1
- package/apps/server/src/plugin-build/typecheck.ts +2 -2
- package/apps/server/src/plugin-support/language-server/plugin.ts +8 -7
- package/apps/server/src/plugin-support/language-server/tools.ts +7 -6
- package/apps/server/src/plugin-support/model-aliases.ts +55 -25
- package/apps/server/src/plugin-support/process-sandbox.ts +16 -15
- package/apps/server/src/plugin-support/product-relay.ts +10 -2
- package/apps/server/src/plugin-support/workspace-sandbox-host.ts +18 -9
- package/apps/server/src/profile/bundle-manifest.ts +7 -3
- package/apps/server/src/profile/compose.ts +6 -0
- package/apps/server/src/profile/plugin-discovery.ts +6 -1
- package/apps/server/src/profile/provisioning.ts +6 -5
- package/apps/server/src/provider.ts +2 -2
- package/apps/server/src/ragents/engine.ts +2 -2
- package/apps/server/src/ragents/global-chat.ts +7 -1
- package/apps/server/src/ragents/host-services.ts +4 -0
- package/apps/server/src/ragents/session.ts +1 -1
- package/apps/server/src/server.ts +4 -1
- package/apps/server/tsconfig.json +2 -0
- package/apps/web/dist/assets/{highlighted-body-KPVGNVTW-xXXhTDbh.js → highlighted-body-KPVGNVTW-BO4wLQtE.js} +1 -1
- package/apps/web/dist/assets/main-DnnqWHkH.js +11 -0
- package/apps/web/dist/assets/mermaid-HWGCJPDP-BLLeth5_.js +568 -0
- package/apps/web/dist/assets/{runPanel-ZT6TPDLM.js → runPanel-DPm7s3KM.js} +2 -2
- package/apps/web/dist/help/guide-clients.html +26 -8
- package/apps/web/dist/help/guide-clients.md +27 -8
- package/apps/web/dist/help/guide-distributed.html +12 -4
- package/apps/web/dist/help/guide-distributed.md +12 -4
- package/apps/web/dist/help/guide-getting-started.html +12 -8
- package/apps/web/dist/help/guide-getting-started.md +12 -8
- package/apps/web/dist/help/guide-plugins.html +6 -2
- package/apps/web/dist/help/guide-plugins.md +6 -2
- package/apps/web/dist/help/guide-runtime.html +2 -1
- package/apps/web/dist/help/guide-runtime.md +2 -1
- package/apps/web/dist/help/index.html +4328 -1132
- package/apps/web/dist/help/mini-app.css +24 -0
- package/apps/web/dist/host-web.json +4 -4
- package/apps/web/dist/index.html +2 -2
- package/apps/web/dist/run-panel.html +2 -2
- package/apps/web/package.json +1 -1
- package/apps/web/src/panel/ConnectionsPage.tsx +3 -0
- package/apps/web/src/panel/StartPage.tsx +3 -0
- package/apps/web/src/panel/contract.ts +7 -0
- package/bundles/ragents.activity/ragents-bundle.json +3 -3
- package/bundles/ragents.actor-programs/ragents-bundle.json +4 -4
- package/bundles/ragents.actor-programs/server/index.js +31 -3
- package/bundles/ragents.actor-programs/server/index.js.map +4 -4
- package/bundles/ragents.actor-programs/web/index.js.map +1 -1
- package/bundles/ragents.ask/ragents-bundle.json +4 -6
- package/bundles/ragents.ask/server/index.js +42 -11
- package/bundles/ragents.ask/server/index.js.map +3 -3
- package/bundles/ragents.ask/web/chunks/{chunk-V7W3QDVS.js → chunk-MBRPS477.js} +2 -2
- package/bundles/ragents.ask/web/chunks/{chunk-V7W3QDVS.js.map → chunk-MBRPS477.js.map} +4 -4
- package/bundles/ragents.ask/web/chunks/chunk-WFN4374U.js +2 -0
- package/bundles/ragents.ask/web/chunks/chunk-WFN4374U.js.map +7 -0
- package/bundles/ragents.ask/web/classes.json +1 -1
- package/bundles/ragents.ask/web/exports/ask-payload.js +1 -1
- package/bundles/ragents.ask/web/exports/web/QuestionCard.js +1 -1
- package/bundles/ragents.ask/web/index.js +1 -1
- package/bundles/ragents.ask/web/index.js.map +4 -4
- package/bundles/ragents.browser/executor/index.mjs +357 -0
- package/bundles/ragents.browser/executor/index.mjs.map +7 -0
- package/bundles/ragents.browser/ragents-bundle.json +5 -8
- package/bundles/ragents.browser/server/chunks/{chunk-2GKLLCBE.js → chunk-CWLX4VA5.js} +1 -1
- package/bundles/ragents.browser/server/chunks/chunk-CWLX4VA5.js.map +7 -0
- package/bundles/ragents.browser/server/exports/server/contract.js +1 -1
- package/bundles/ragents.browser/server/index.js +20 -9
- package/bundles/ragents.browser/server/index.js.map +4 -4
- package/bundles/ragents.documents/ragents-bundle.json +3 -3
- package/bundles/ragents.lsp-fsharp/executor/index.mjs +68 -0
- package/bundles/ragents.lsp-fsharp/executor/index.mjs.map +7 -0
- package/bundles/ragents.lsp-fsharp/ragents-bundle.json +5 -9
- package/bundles/ragents.lsp-fsharp/server/index.js +21 -6
- package/bundles/ragents.lsp-fsharp/server/index.js.map +4 -4
- package/bundles/ragents.lsp-roslyn/executor/index.mjs +68 -0
- package/bundles/ragents.lsp-roslyn/executor/index.mjs.map +7 -0
- package/bundles/ragents.lsp-roslyn/ragents-bundle.json +6 -8
- package/bundles/ragents.lsp-roslyn/server/index.js +54 -15
- package/bundles/ragents.lsp-roslyn/server/index.js.map +4 -4
- package/bundles/ragents.lsp-typescript/executor/index.mjs +49 -0
- package/bundles/ragents.lsp-typescript/executor/index.mjs.map +7 -0
- package/bundles/ragents.lsp-typescript/ragents-bundle.json +5 -7
- package/bundles/ragents.lsp-typescript/server/index.js +22 -2
- package/bundles/ragents.lsp-typescript/server/index.js.map +3 -3
- package/bundles/ragents.model-relay/ragents-bundle.json +4 -4
- package/bundles/ragents.model-relay/server/index.js +3 -2
- package/bundles/ragents.model-relay/server/index.js.map +2 -2
- package/bundles/ragents.orchestration/ragents-bundle.json +4 -4
- package/bundles/ragents.orchestration/web/classes.json +1 -1
- package/bundles/ragents.orchestration/web/index.js +6 -6
- package/bundles/ragents.orchestration/web/index.js.map +3 -3
- package/bundles/ragents.overseer/ragents-bundle.json +4 -4
- package/bundles/ragents.overseer/server/index.js +1 -1
- package/bundles/ragents.overseer/server/index.js.map +2 -2
- package/bundles/ragents.processes/ragents-bundle.json +3 -3
- package/bundles/ragents.product/ragents-bundle.json +3 -3
- package/bundles/ragents.profile-distribution/ragents-bundle.json +4 -4
- package/bundles/ragents.profile-distribution/server/index.js +1 -1
- package/bundles/ragents.profile-distribution/server/index.js.map +2 -2
- package/bundles/ragents.reference/ragents-bundle.json +3 -3
- package/bundles/ragents.todo/ragents-bundle.json +3 -3
- package/bundles/ragents.transcript/ragents-bundle.json +3 -3
- package/bundles/ragents.watch/ragents-bundle.json +3 -3
- package/bundles/ragents.workspace/ragents-bundle.json +11 -5
- package/bundles/ragents.workspace/server/index.js +105 -30
- package/bundles/ragents.workspace/server/index.js.map +3 -3
- package/bundles/ragents.workspace/web/classes.json +1 -1
- package/bundles/ragents.workspace/web/index.js +1 -1
- package/bundles/ragents.workspace/web/index.js.map +3 -3
- package/package.json +3 -3
- package/packages/agent/dist/core/agent-settings.d.ts +1 -7
- package/packages/agent/dist/core/compaction/compaction.d.ts +17 -13
- package/packages/agent/dist/core/model-runtime.d.ts +5 -4
- package/packages/agent/dist/core/provider-composer.d.ts +2 -1
- package/packages/agent/dist/core/tools/bash.d.ts +9 -3
- package/packages/agent/dist/index.d.ts +1 -1
- package/packages/agent/src/core/agent-settings.ts +1 -4
- package/packages/agent/src/core/compaction/compaction.ts +68 -30
- package/packages/agent/src/core/model-runtime.ts +12 -5
- package/packages/agent/src/core/provider-composer.ts +5 -0
- package/packages/agent/src/core/tools/bash.ts +36 -30
- package/packages/agent/src/index.ts +3 -0
- package/packages/ai/dist/types.d.ts +11 -0
- package/packages/ai/src/types.ts +12 -0
- package/packages/ragents/src/domain/event-semantics.ts +3 -0
- package/packages/ragents/src/domain/event-validation.ts +15 -2
- package/packages/ragents/src/domain/events.ts +3 -0
- package/packages/ragents/src/domain/model.ts +2 -0
- package/packages/ragents/src/domain/projection.ts +1 -0
- package/packages/ragents/src/drivers/agent-runtime.ts +1 -1
- package/packages/ragents/src/drivers/agent-turn.ts +8 -6
- package/packages/ragents/src/index.ts +1 -0
- package/packages/ragents/src/plugin-host.ts +46 -0
- package/packages/ragents/src/plugin-types.ts +19 -0
- package/packages/ragents/src/runtime/decisions/inputs.ts +6 -2
- package/packages/ragents/src/runtime/journal-storage.ts +5 -4
- package/packages/workspace-executor/package.json +0 -1
- package/packages/workspace-executor/src/bash-launch.ts +56 -10
- package/packages/workspace-executor/src/context.ts +4 -0
- package/packages/workspace-executor/src/contributions.ts +150 -0
- package/packages/workspace-executor/src/executor.ts +1 -1
- package/packages/workspace-executor/src/index.ts +16 -19
- package/packages/workspace-executor/src/language-server/host.ts +3 -0
- package/packages/workspace-executor/src/language-server/module.ts +12 -2
- package/packages/workspace-executor/src/language-server/roots.ts +0 -5
- package/packages/workspace-executor/src/managed-process.ts +28 -0
- package/packages/workspace-executor/src/modules.ts +7 -6
- package/packages/workspace-executor/src/sandbox-tools.ts +12 -12
- package/packages/workspace-executor/src/shell-platform.ts +14 -3
- package/packages/workspace-executor/src/tools.ts +0 -3
- package/plugins/ragents.actor-programs/server/access-projections.ts +31 -0
- package/plugins/ragents.actor-programs/server/index.ts +2 -0
- package/plugins/ragents.ask/ask-payload.ts +9 -0
- package/plugins/ragents.ask/server/ask-service.ts +53 -13
- package/plugins/ragents.ask/web/AskActionView.tsx +3 -2
- package/plugins/ragents.ask/web/index.tsx +0 -6
- package/plugins/ragents.browser/executor/index.ts +5 -0
- package/{packages/workspace-executor/src/browser → plugins/ragents.browser/executor}/module.ts +25 -31
- package/{packages/workspace-executor/src/browser → plugins/ragents.browser/executor}/playwright.ts +9 -23
- package/plugins/ragents.browser/provision.ts +1 -1
- package/plugins/ragents.browser/server/browser.ts +3 -3
- package/plugins/ragents.browser/server/contract.ts +2 -2
- package/plugins/ragents.browser/server/index.ts +1 -1
- package/plugins/ragents.lsp-fsharp/executor.ts +80 -0
- package/plugins/ragents.lsp-fsharp/provision.ts +1 -1
- package/plugins/ragents.lsp-fsharp/server/index.ts +2 -2
- package/plugins/ragents.lsp-roslyn/executor.ts +64 -0
- package/plugins/ragents.lsp-roslyn/provision.ts +1 -1
- package/plugins/ragents.lsp-roslyn/server/index.ts +28 -5
- package/plugins/ragents.lsp-roslyn/server/solution-on-start.ts +18 -6
- package/plugins/ragents.lsp-typescript/executor.ts +50 -0
- package/plugins/ragents.lsp-typescript/server/index.ts +2 -2
- package/plugins/ragents.model-relay/server/config.ts +1 -1
- package/plugins/ragents.model-relay/server/relay.ts +4 -2
- package/plugins/ragents.orchestration/web/ActorTile.tsx +1 -1
- package/plugins/ragents.orchestration/web/run-panel/RunPanel.tsx +8 -7
- package/plugins/ragents.orchestration/web/run-panel/sheet-status.ts +3 -3
- package/plugins/ragents.overseer/server/api.ts +2 -2
- package/plugins/ragents.profile-distribution/server/archive.ts +2 -1
- package/plugins/ragents.workspace/client/workspace-client.ts +128 -32
- package/plugins/ragents.workspace/contract.ts +33 -2
- package/plugins/ragents.workspace/server/binding.ts +10 -4
- package/plugins/ragents.workspace/server/clients.ts +56 -9
- package/plugins/ragents.workspace/server/config.ts +12 -0
- package/plugins/ragents.workspace/server/index.ts +15 -5
- package/plugins/ragents.workspace/server/runtime.ts +10 -0
- package/plugins/ragents.workspace/server/shell-platform.ts +6 -5
- package/plugins/ragents.workspace/web/WorkspaceBinding.tsx +1 -1
- package/ragents.config.core.ts +4 -1
- package/ragents.config.showcase.ts +4 -1
- package/scripts/agent/journal.ts +3 -1
- package/scripts/package/build-package.ts +3 -1
- package/scripts/provision/run-provision.ts +2 -2
- package/scripts/workspace-client/run-workspace-client.ts +7 -4
- package/apps/web/dist/assets/main-C7JeZFjs.js +0 -6
- package/apps/web/dist/assets/mermaid-HWGCJPDP-DfsU5ofC.js +0 -478
- package/apps/web/dist/help/screenshots/release-checklist-vscode.png +0 -0
- package/apps/web/dist/help/screenshots/release-checklist-web.png +0 -0
- package/bundles/ragents.ask/web/chunks/chunk-HGFDGTNC.js +0 -2
- package/bundles/ragents.ask/web/chunks/chunk-HGFDGTNC.js.map +0 -7
- package/bundles/ragents.browser/server/chunks/chunk-2GKLLCBE.js.map +0 -7
- package/packages/workspace-executor/src/language-server/adapters/fsharp.ts +0 -60
- package/packages/workspace-executor/src/language-server/adapters/index.ts +0 -7
- package/packages/workspace-executor/src/language-server/adapters/roslyn.ts +0 -56
- package/packages/workspace-executor/src/language-server/adapters/typescript.ts +0 -74
- package/packages/workspace-executor/src/language-server/solution.ts +0 -13
- package/plugins/ragents.ask/web/QuestionSection.tsx +0 -48
- /package/{packages/workspace-executor/src/browser → plugins/ragents.browser/executor}/contract.ts +0 -0
- /package/{packages/workspace-executor/src/browser → plugins/ragents.browser/executor}/pages.ts +0 -0
|
@@ -520,6 +520,15 @@ export interface ModelCost extends ModelCostRates {
|
|
|
520
520
|
/** Request-wide pricing tiers. The highest matching input threshold applies to the full request. */
|
|
521
521
|
tiers?: ModelCostTier[];
|
|
522
522
|
}
|
|
523
|
+
/** When an agent compacts its context on a model and how much it keeps, in absolute tokens of that model. */
|
|
524
|
+
export interface ModelCompaction {
|
|
525
|
+
/** Context tokens above which the agent compacts. */
|
|
526
|
+
threshold: number;
|
|
527
|
+
/** Tokens of the newest context the compaction keeps verbatim. */
|
|
528
|
+
keepRecentTokens: number;
|
|
529
|
+
/** Output budget of the summary. */
|
|
530
|
+
summaryTokens: number;
|
|
531
|
+
}
|
|
523
532
|
export interface Model<TApi extends Api> {
|
|
524
533
|
id: string;
|
|
525
534
|
name: string;
|
|
@@ -536,6 +545,8 @@ export interface Model<TApi extends Api> {
|
|
|
536
545
|
cost: ModelCost;
|
|
537
546
|
contextWindow: number;
|
|
538
547
|
maxTokens: number;
|
|
548
|
+
/** The model's own compaction values; without them the agent applies the catalog standard of its context window. */
|
|
549
|
+
compaction?: ModelCompaction;
|
|
539
550
|
headers?: Record<string, string>;
|
|
540
551
|
/** Compatibility overrides for OpenAI-compatible APIs. If not set, auto-detected from baseUrl. */
|
|
541
552
|
compat?: TApi extends "openai-completions" ? OpenAICompletionsCompat : TApi extends "openai-responses" | "openai-codex-responses" ? OpenAIResponsesCompat : TApi extends "anthropic-messages" ? AnthropicMessagesCompat : never;
|
package/packages/ai/src/types.ts
CHANGED
|
@@ -561,6 +561,16 @@ export interface ModelCost extends ModelCostRates {
|
|
|
561
561
|
tiers?: ModelCostTier[];
|
|
562
562
|
}
|
|
563
563
|
|
|
564
|
+
/** When an agent compacts its context on a model and how much it keeps, in absolute tokens of that model. */
|
|
565
|
+
export interface ModelCompaction {
|
|
566
|
+
/** Context tokens above which the agent compacts. */
|
|
567
|
+
threshold: number;
|
|
568
|
+
/** Tokens of the newest context the compaction keeps verbatim. */
|
|
569
|
+
keepRecentTokens: number;
|
|
570
|
+
/** Output budget of the summary. */
|
|
571
|
+
summaryTokens: number;
|
|
572
|
+
}
|
|
573
|
+
|
|
564
574
|
// Model interface for the unified model system
|
|
565
575
|
export interface Model<TApi extends Api> {
|
|
566
576
|
id: string;
|
|
@@ -578,6 +588,8 @@ export interface Model<TApi extends Api> {
|
|
|
578
588
|
cost: ModelCost;
|
|
579
589
|
contextWindow: number;
|
|
580
590
|
maxTokens: number;
|
|
591
|
+
/** The model's own compaction values; without them the agent applies the catalog standard of its context window. */
|
|
592
|
+
compaction?: ModelCompaction;
|
|
581
593
|
headers?: Record<string, string>;
|
|
582
594
|
/** Compatibility overrides for OpenAI-compatible APIs. If not set, auto-detected from baseUrl. */
|
|
583
595
|
compat?: TApi extends "openai-completions"
|
|
@@ -358,6 +358,9 @@ export const assertEventSemantics = (
|
|
|
358
358
|
for (const artifactId of event.payload.artifactIds)
|
|
359
359
|
assertArtifactRead(state, event.actorId, artifactId);
|
|
360
360
|
|
|
361
|
+
if (event.payload.origin === "human" && existingActorOf(state, event.actorId).kind !== "human")
|
|
362
|
+
throw new Error(`Input ${event.payload.inputId} of human origin was not enqueued by a human actor.`);
|
|
363
|
+
|
|
361
364
|
if (event.payload.subscriptionId) {
|
|
362
365
|
const subscription = state.subscriptions.get(event.payload.subscriptionId);
|
|
363
366
|
|
|
@@ -431,9 +431,13 @@ const payloadOf = (type: EventType, value: unknown, path: string) => {
|
|
|
431
431
|
"artifactIds",
|
|
432
432
|
"sourceEventIds",
|
|
433
433
|
"subscriptionId",
|
|
434
|
-
], ["presentation"]);
|
|
434
|
+
], ["presentation", "origin"]);
|
|
435
435
|
if (payload.presentation !== undefined && payload.presentation !== "background")
|
|
436
436
|
fail(`${path}.presentation`, "must be background");
|
|
437
|
+
if (payload.origin !== undefined && payload.origin !== "human")
|
|
438
|
+
fail(`${path}.origin`, "must be human");
|
|
439
|
+
if (subscriptionInput && Object.hasOwn(payload, "origin"))
|
|
440
|
+
fail(`${path}.origin`, "is not supported for a subscription input");
|
|
437
441
|
stringOf(payload.inputId, `${path}.inputId`);
|
|
438
442
|
actorIdOf(payload.actorId, `${path}.actorId`);
|
|
439
443
|
stringArrayOf(payload.artifactIds, `${path}.artifactIds`);
|
|
@@ -545,7 +549,7 @@ const payloadOf = (type: EventType, value: unknown, path: string) => {
|
|
|
545
549
|
"model",
|
|
546
550
|
"readFiles",
|
|
547
551
|
"modifiedFiles",
|
|
548
|
-
]);
|
|
552
|
+
], ["threshold"]);
|
|
549
553
|
stringOf(payload.turnId, `${path}.turnId`);
|
|
550
554
|
nonEmptyStringOf(payload.summary, `${path}.summary`);
|
|
551
555
|
nonEmptyStringOf(payload.firstKeptEventId, `${path}.firstKeptEventId`);
|
|
@@ -554,6 +558,15 @@ const payloadOf = (type: EventType, value: unknown, path: string) => {
|
|
|
554
558
|
nonEmptyStringOf(payload.model, `${path}.model`);
|
|
555
559
|
stringArrayOf(payload.readFiles, `${path}.readFiles`);
|
|
556
560
|
stringArrayOf(payload.modifiedFiles, `${path}.modifiedFiles`);
|
|
561
|
+
|
|
562
|
+
if (Object.hasOwn(payload, "threshold")) {
|
|
563
|
+
const threshold = exactObject(payload.threshold, `${path}.threshold`, ["tokens", "source"]);
|
|
564
|
+
if (!Number.isSafeInteger(threshold.tokens))
|
|
565
|
+
fail(`${path}.threshold.tokens`, "must be a safe integer");
|
|
566
|
+
if (threshold.source !== "model" && threshold.source !== "catalog")
|
|
567
|
+
fail(`${path}.threshold.source`, "must be model or catalog");
|
|
568
|
+
}
|
|
569
|
+
|
|
557
570
|
return;
|
|
558
571
|
}
|
|
559
572
|
|
|
@@ -93,6 +93,7 @@ export type EventPayloads = {
|
|
|
93
93
|
actorId: ActorId;
|
|
94
94
|
artifactIds: string[];
|
|
95
95
|
presentation?: "background";
|
|
96
|
+
origin?: "human";
|
|
96
97
|
} & (
|
|
97
98
|
| { subscriptionId: null; sourceEventIds: string[]; content: string }
|
|
98
99
|
| { subscriptionId: SubscriptionId; sourceEventIds: [string]; content?: never }
|
|
@@ -151,6 +152,8 @@ export type EventPayloads = {
|
|
|
151
152
|
model: string;
|
|
152
153
|
readFiles: string[];
|
|
153
154
|
modifiedFiles: string[];
|
|
155
|
+
/** The compaction threshold of the model and whether it is the model's own or the catalog standard; absent before file format 9. */
|
|
156
|
+
threshold?: { tokens: number; source: "model" | "catalog" };
|
|
154
157
|
};
|
|
155
158
|
"model.output.completed": {
|
|
156
159
|
turnId: TurnId;
|
|
@@ -89,6 +89,8 @@ export type ActorInput = {
|
|
|
89
89
|
actorId: ActorId;
|
|
90
90
|
content: string;
|
|
91
91
|
presentation?: "background";
|
|
92
|
+
/** Set only on a person's own message, because system inputs are enqueued under the owner too. */
|
|
93
|
+
origin?: "human";
|
|
92
94
|
artifactIds: readonly ArtifactId[];
|
|
93
95
|
enqueuedBy: ActorId;
|
|
94
96
|
enqueuedAt: string;
|
|
@@ -222,6 +222,7 @@ export function applyEvent(
|
|
|
222
222
|
actorId: event.payload.actorId,
|
|
223
223
|
content: event.payload.subscriptionId === null ? event.payload.content : JSON.stringify(source),
|
|
224
224
|
...(event.payload.presentation ? { presentation: event.payload.presentation } : {}),
|
|
225
|
+
...(event.payload.origin ? { origin: event.payload.origin } : {}),
|
|
225
226
|
artifactIds: event.payload.artifactIds,
|
|
226
227
|
enqueuedBy: event.actorId,
|
|
227
228
|
enqueuedAt: event.occurredAt,
|
|
@@ -36,7 +36,7 @@ export type AgentRuntimeManagerOptions = {
|
|
|
36
36
|
context: AgentRuntimeContext,
|
|
37
37
|
signal: AbortSignal,
|
|
38
38
|
) => readonly AgentHook[] | Promise<readonly AgentHook[]>;
|
|
39
|
-
/**
|
|
39
|
+
/** Retry and provider request limits; unset values keep the defaults. Compaction comes from the model. */
|
|
40
40
|
settings?: AgentSettingsInput;
|
|
41
41
|
turnAbortTimeoutMs?: number;
|
|
42
42
|
onDiagnostic?: (diagnostic: AgentRuntimeDiagnostic) => void;
|
|
@@ -10,6 +10,7 @@ import {
|
|
|
10
10
|
type AgentTool,
|
|
11
11
|
calculateContextTokens,
|
|
12
12
|
compact,
|
|
13
|
+
compactionOf,
|
|
13
14
|
contextMessages,
|
|
14
15
|
convertToLlm,
|
|
15
16
|
EMPTY_RESPONSE_NUDGE,
|
|
@@ -626,12 +627,11 @@ export class AgentTurn {
|
|
|
626
627
|
return true;
|
|
627
628
|
}
|
|
628
629
|
|
|
629
|
-
/** After a context overflow compacts and retries once; over the threshold compacts without a retry. */
|
|
630
|
+
/** After a context overflow compacts and retries once; over the threshold of the turn's model compacts without a retry. */
|
|
630
631
|
async #checkCompaction(assistant: AssistantMessage | undefined, skipAborted = true): Promise<boolean> {
|
|
631
|
-
const settings = this.#options.settings.compaction;
|
|
632
632
|
const { model } = this.#options;
|
|
633
633
|
|
|
634
|
-
if (!assistant ||
|
|
634
|
+
if (!assistant || (skipAborted && assistant.stopReason === "aborted"))
|
|
635
635
|
return false;
|
|
636
636
|
|
|
637
637
|
const contextWindow = model.contextWindow ?? 0;
|
|
@@ -672,12 +672,13 @@ export class AgentTurn {
|
|
|
672
672
|
contextTokens = estimate.tokens;
|
|
673
673
|
}
|
|
674
674
|
|
|
675
|
-
return shouldCompact(contextTokens,
|
|
675
|
+
return shouldCompact(contextTokens, compactionOf(model).values) ? this.#compact(false) : false;
|
|
676
676
|
}
|
|
677
677
|
|
|
678
678
|
async #compact(retry: boolean): Promise<boolean> {
|
|
679
|
-
const { model, modelRuntime, thinkingLevel
|
|
680
|
-
const
|
|
679
|
+
const { model, modelRuntime, thinkingLevel } = this.#options;
|
|
680
|
+
const compaction = compactionOf(model);
|
|
681
|
+
const preparation = prepareCompaction([...this.#request.modelContext().entries], compaction.values);
|
|
681
682
|
|
|
682
683
|
if (!preparation)
|
|
683
684
|
return false;
|
|
@@ -715,6 +716,7 @@ export class AgentTurn {
|
|
|
715
716
|
model: model.id,
|
|
716
717
|
readFiles: result.readFiles,
|
|
717
718
|
modifiedFiles: result.modifiedFiles,
|
|
719
|
+
threshold: { tokens: compaction.values.threshold, source: compaction.source },
|
|
718
720
|
},
|
|
719
721
|
});
|
|
720
722
|
const messages = this.#request.modelContext().messages;
|
|
@@ -11,7 +11,9 @@ import type { AgentProfile, CatalogModel } from "./agents/catalog.ts";
|
|
|
11
11
|
import type { ToolContributor } from "./agents/plugins.ts";
|
|
12
12
|
import { describeToolAvailability, type RunFunction } from "./agents/tools.ts";
|
|
13
13
|
import type { ChannelContribution, ChannelDescriptor, MethodContribution, MethodDescriptor } from "./rpc/contribution.ts";
|
|
14
|
+
import type { PluginState } from "./domain/model.ts";
|
|
14
15
|
import type {
|
|
16
|
+
AccessProjectionContribution,
|
|
15
17
|
AgentAudience,
|
|
16
18
|
HttpRouteContribution,
|
|
17
19
|
OperationContext,
|
|
@@ -19,6 +21,7 @@ import type {
|
|
|
19
21
|
RegisteredOperationDescriptor,
|
|
20
22
|
AgentContribution,
|
|
21
23
|
AgentContributionContext,
|
|
24
|
+
PluginChatEvent,
|
|
22
25
|
PluginConfigDescriptor,
|
|
23
26
|
PluginManifest,
|
|
24
27
|
PluginRegistration,
|
|
@@ -977,6 +980,47 @@ export class StartOptionContributionRegistry {
|
|
|
977
980
|
}
|
|
978
981
|
}
|
|
979
982
|
|
|
983
|
+
/** Was ein Zugang ohne runs.inspect von Plugin-Zuständen sieht: eine Startoption nur mit ihren Rechten, sonst die Projektion ihres Plugins, ohne sie alles. */
|
|
984
|
+
export class AccessProjectionRegistry {
|
|
985
|
+
readonly #projections = new ContributionRegistry<AccessProjectionContribution>("Zugriffsprojektion");
|
|
986
|
+
readonly #startOptions: StartOptionContributionRegistry;
|
|
987
|
+
|
|
988
|
+
constructor(startOptions = new StartOptionContributionRegistry()) {
|
|
989
|
+
this.#startOptions = startOptions;
|
|
990
|
+
}
|
|
991
|
+
|
|
992
|
+
register(owner: string, contributions: readonly AccessProjectionContribution[]): void {
|
|
993
|
+
for (const contribution of contributions) {
|
|
994
|
+
for (const name of ["state", "chatEvent"] as const) {
|
|
995
|
+
if (typeof contribution[name] !== "function") throw new Error(`Zugriffsprojektion ${contribution.id} hat kein ${name}`);
|
|
996
|
+
}
|
|
997
|
+
}
|
|
998
|
+
this.#projections.register(owner, contributions);
|
|
999
|
+
}
|
|
1000
|
+
|
|
1001
|
+
state(entry: PluginState, access: Pick<AccessContext, "can">): PluginState | undefined {
|
|
1002
|
+
if (access.can("runs.inspect")) return entry;
|
|
1003
|
+
if (this.#startOptions.missingRight(entry.pluginId, access) !== undefined) return undefined;
|
|
1004
|
+
const projection = this.#find(entry.pluginId);
|
|
1005
|
+
if (!projection) return entry;
|
|
1006
|
+
const state = projection.state(entry);
|
|
1007
|
+
return state === undefined ? undefined : { ...entry, state };
|
|
1008
|
+
}
|
|
1009
|
+
|
|
1010
|
+
chatEvent<T extends PluginChatEvent>(pluginId: string, event: T, access: Pick<AccessContext, "can">): T | undefined {
|
|
1011
|
+
if (access.can("runs.inspect")) return event;
|
|
1012
|
+
if (this.#startOptions.missingRight(pluginId, access) !== undefined) return undefined;
|
|
1013
|
+
const projection = this.#find(pluginId);
|
|
1014
|
+
if (!projection) return event;
|
|
1015
|
+
const projected = projection.chatEvent(event.payload === undefined ? { type: event.type } : { type: event.type, payload: event.payload });
|
|
1016
|
+
return projected === undefined ? undefined : { ...event, type: projected.type, payload: projected.payload };
|
|
1017
|
+
}
|
|
1018
|
+
|
|
1019
|
+
#find(id: string): AccessProjectionContribution | undefined {
|
|
1020
|
+
return this.#projections.entries().find(({ value }) => value.id === id)?.value;
|
|
1021
|
+
}
|
|
1022
|
+
}
|
|
1023
|
+
|
|
980
1024
|
export class ConfigContributionRegistry {
|
|
981
1025
|
readonly #entries: Array<{ owners: string[]; value: PluginConfigDescriptor }> = [];
|
|
982
1026
|
|
|
@@ -1125,6 +1169,7 @@ export class PluginHost {
|
|
|
1125
1169
|
readonly lifecycle = new LifecycleContributionRegistry();
|
|
1126
1170
|
readonly sessionMetadata = new SessionMetadataContributionRegistry();
|
|
1127
1171
|
readonly startOptions = new StartOptionContributionRegistry();
|
|
1172
|
+
readonly accessProjections = new AccessProjectionRegistry(this.startOptions);
|
|
1128
1173
|
readonly config = new ConfigContributionRegistry();
|
|
1129
1174
|
readonly storage: StorageRegistry;
|
|
1130
1175
|
readonly #product: ProductDescriptor;
|
|
@@ -1176,6 +1221,7 @@ export class PluginHost {
|
|
|
1176
1221
|
skills: (...entries) => this.skills.register(manifest.id, entries),
|
|
1177
1222
|
startEntries: (...entries) => this.startEntries.register(manifest.id, entries),
|
|
1178
1223
|
startOptions: (...entries) => this.startOptions.register(manifest.id, entries),
|
|
1224
|
+
accessProjections: (...entries) => this.accessProjections.register(manifest.id, entries),
|
|
1179
1225
|
functions: (...entries) => this.tools.registerFunctions(manifest.id, entries),
|
|
1180
1226
|
script: (...entries) => this.script.register(manifest.id, entries),
|
|
1181
1227
|
};
|
|
@@ -8,6 +8,7 @@ import type { WorkspaceToolNaming } from "./agents/workspace-tools.ts";
|
|
|
8
8
|
import type { Orchestration } from "./runtime/orchestration.ts";
|
|
9
9
|
import type { AgentDriver } from "./drivers/types.ts";
|
|
10
10
|
import type { JsonValue } from "./domain/json.ts";
|
|
11
|
+
import type { PluginState } from "./domain/model.ts";
|
|
11
12
|
import type { AccessContext } from "./access.ts";
|
|
12
13
|
import type { ChannelContribution, MethodContribution } from "./rpc/contribution.ts";
|
|
13
14
|
|
|
@@ -370,6 +371,22 @@ export interface RegisteredStartOption {
|
|
|
370
371
|
option: StartOptionContribution;
|
|
371
372
|
}
|
|
372
373
|
|
|
374
|
+
/** Ein Chat-Ereignis zu einem Plugin-Zustand, ohne die Kennung, die die Projektion schon nennt. */
|
|
375
|
+
export interface PluginChatEvent {
|
|
376
|
+
type: string;
|
|
377
|
+
payload?: unknown;
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
/** Was ein Zugang ohne runs.inspect von einem Plugin-Zustand und dessen Chat-Ereignissen sieht; ohne Projektion sieht er beides unverändert. */
|
|
381
|
+
export interface AccessProjectionContribution {
|
|
382
|
+
/** Die Kennung des Zustands, wie sie im Journal (`pluginId`) und im Chat-Ereignis steht. */
|
|
383
|
+
id: string;
|
|
384
|
+
/** Der sichtbare Zustand; undefined nimmt ihn aus der Run-Ansicht. */
|
|
385
|
+
state: (entry: PluginState) => JsonValue | undefined;
|
|
386
|
+
/** Das sichtbare Chat-Ereignis; undefined unterdrückt es. */
|
|
387
|
+
chatEvent: (event: PluginChatEvent) => PluginChatEvent | undefined;
|
|
388
|
+
}
|
|
389
|
+
|
|
373
390
|
export interface SessionMetadataContribution {
|
|
374
391
|
id: string;
|
|
375
392
|
/** Ob `describe` den Arbeitsbereich des Runs erreicht; dann ruft der Host es nur für Aufrufer, die ihn erreichen dürfen. */
|
|
@@ -432,6 +449,8 @@ export interface PluginRegistration {
|
|
|
432
449
|
skills: (...contributions: readonly SkillContribution[]) => void;
|
|
433
450
|
startEntries: (...contributions: readonly StartEntryContribution[]) => void;
|
|
434
451
|
startOptions: (...contributions: readonly StartOptionContribution[]) => void;
|
|
452
|
+
/** Wie Zugänge ohne runs.inspect die Zustände dieses Plugins und ihre Chat-Ereignisse sehen, je Kennung eines Zustands. */
|
|
453
|
+
accessProjections: (...contributions: readonly AccessProjectionContribution[]) => void;
|
|
435
454
|
functions: (...functions: readonly (RunFunction | ToolContributor)[]) => void;
|
|
436
455
|
script: (...contributions: readonly ScriptContribution[]) => void;
|
|
437
456
|
}
|
|
@@ -17,8 +17,8 @@ export type EnqueueInput = {
|
|
|
17
17
|
artifactIds?: readonly string[];
|
|
18
18
|
presentation?: "background";
|
|
19
19
|
} & (
|
|
20
|
-
| { content: string; sourceEventIds?: readonly string[]; subscriptionId?: null }
|
|
21
|
-
| { content?: never; sourceEventIds: readonly [string]; subscriptionId: string }
|
|
20
|
+
| { content: string; sourceEventIds?: readonly string[]; subscriptionId?: null; origin?: "human" }
|
|
21
|
+
| { content?: never; sourceEventIds: readonly [string]; subscriptionId: string; origin?: never }
|
|
22
22
|
);
|
|
23
23
|
|
|
24
24
|
export const enqueueInput =
|
|
@@ -43,6 +43,9 @@ export const enqueueInput =
|
|
|
43
43
|
assertCapability(caller, "actor.input", { kind: "run" });
|
|
44
44
|
}
|
|
45
45
|
|
|
46
|
+
if (input.origin === "human" && caller.kind !== "human")
|
|
47
|
+
throw new DomainError("input-origin-invalid", "Only a human can enqueue an input of human origin.", 403);
|
|
48
|
+
|
|
46
49
|
const artifactIds = [...new Set(input.artifactIds ?? [])];
|
|
47
50
|
|
|
48
51
|
for (const artifactId of artifactIds)
|
|
@@ -55,6 +58,7 @@ export const enqueueInput =
|
|
|
55
58
|
actorId: target.id,
|
|
56
59
|
artifactIds,
|
|
57
60
|
...(input.presentation !== undefined ? { presentation: input.presentation } : {}),
|
|
61
|
+
...(input.origin !== undefined ? { origin: input.origin } : {}),
|
|
58
62
|
};
|
|
59
63
|
|
|
60
64
|
if (subscriptionId && firstSourceEventId === undefined)
|
|
@@ -8,9 +8,10 @@ import { isRunId } from "../domain/portable-id.ts";
|
|
|
8
8
|
import { syncDirectory } from "./durable-fs.ts";
|
|
9
9
|
import type { CommandRecord, JournalCommand } from "./journal.ts";
|
|
10
10
|
|
|
11
|
-
/** Rises whenever an older stand would reject newly written lines;
|
|
12
|
-
export const journalStorageVersion =
|
|
13
|
-
const
|
|
11
|
+
/** Rises whenever an older stand would reject newly written lines; formats 7 and 8 stay readable because they only lack the input origin and the compaction threshold. */
|
|
12
|
+
export const journalStorageVersion = 9;
|
|
13
|
+
const oldestReadableJournalStorageVersion = 7;
|
|
14
|
+
const readableJournalStorageVersions: readonly unknown[] = [oldestReadableJournalStorageVersion, 8, journalStorageVersion];
|
|
14
15
|
export const journalPayloadThresholdBytes = 4096;
|
|
15
16
|
|
|
16
17
|
type PayloadReference = { sha256: string; bytes: number };
|
|
@@ -162,7 +163,7 @@ export const parseJournalRecord = (line: string, runDirectory: string, location:
|
|
|
162
163
|
|
|
163
164
|
if (!readableJournalStorageVersions.includes(record.formatVersion))
|
|
164
165
|
throw new Error(`${location} has unsupported journal format version ${String(record.formatVersion)}.${
|
|
165
|
-
typeof record.formatVersion === "number" && record.formatVersion <
|
|
166
|
+
typeof record.formatVersion === "number" && record.formatVersion < oldestReadableJournalStorageVersion
|
|
166
167
|
? " Journals before format 7 hold no model context and are not migrated."
|
|
167
168
|
: ""}`);
|
|
168
169
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { existsSync } from "node:fs";
|
|
1
|
+
import { accessSync, constants, existsSync, statSync } from "node:fs";
|
|
2
2
|
import path from "node:path";
|
|
3
3
|
import { getShellConfig } from "@ragents/agent";
|
|
4
4
|
|
|
@@ -9,6 +9,12 @@ export interface BashLaunch {
|
|
|
9
9
|
readonly env: NodeJS.ProcessEnv;
|
|
10
10
|
}
|
|
11
11
|
|
|
12
|
+
/** Was der Executor dem Werkzeug bash mitgibt: die Bash selbst und rg; ohne Angabe gilt jeweils das des Systems. */
|
|
13
|
+
export interface BashPrograms {
|
|
14
|
+
readonly bash: string | undefined;
|
|
15
|
+
readonly rg: string | undefined;
|
|
16
|
+
}
|
|
17
|
+
|
|
12
18
|
/** Unter Windows sucht RAgents keine Bash; der Executor nennt die mitgebrachte. */
|
|
13
19
|
const missingWindowsBash = (): Error => new Error(
|
|
14
20
|
"Unter Windows arbeitet das Werkzeug bash nur mit der Bash, die RAgents mitbringt, und für diesen Executor ist keine genannt. "
|
|
@@ -16,17 +22,51 @@ const missingWindowsBash = (): Error => new Error(
|
|
|
16
22
|
+ "und reicht sie an Arbeitsplatz und lokalen Host weiter; ein Host oder Arbeitsplatz ohne Erweiterung braucht RAGENTS_BASH mit dem Pfad dieser bash.exe.",
|
|
17
23
|
);
|
|
18
24
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
+
const missingRipgrep = (rg: string): Error =>
|
|
26
|
+
new Error(`Das rg dieses Executors fehlt: ${rg}. Es gehört zur Erweiterung (dist/rg/<plattform>) oder steht in RAGENTS_RG.`);
|
|
27
|
+
|
|
28
|
+
const pathModule = (platform: NodeJS.Platform): path.PlatformPath => platform === "win32" ? path.win32 : path.posix;
|
|
29
|
+
|
|
30
|
+
/** Die Namen der PATH-Variablen; unter Windows zählt jede Schreibweise (`Path`). */
|
|
31
|
+
const pathNames = (env: NodeJS.ProcessEnv, platform: NodeJS.Platform): readonly string[] =>
|
|
32
|
+
platform === "win32" ? Object.keys(env).filter((name) => name.toUpperCase() === "PATH") : ["PATH"];
|
|
33
|
+
|
|
34
|
+
const currentPath = (env: NodeJS.ProcessEnv, platform: NodeJS.Platform): string | undefined =>
|
|
35
|
+
pathNames(env, platform).map((name) => env[name]).find((value) => value !== undefined && value !== "");
|
|
36
|
+
|
|
37
|
+
/** Die Ordner vorn im PATH, als eine Variable PATH; MSYSTEM gehört unter Windows einer Git-Bash-Anmeldung und fällt weg. */
|
|
38
|
+
const withPathFront = (env: NodeJS.ProcessEnv, directories: readonly string[], platform: NodeJS.Platform): NodeJS.ProcessEnv => {
|
|
39
|
+
if (directories.length === 0) return env;
|
|
40
|
+
const names = pathNames(env, platform);
|
|
41
|
+
const current = currentPath(env, platform);
|
|
42
|
+
const kept = Object.entries(env).filter(([name]) => !names.includes(name) && (platform !== "win32" || name !== "MSYSTEM"));
|
|
43
|
+
const delimiter = pathModule(platform).delimiter;
|
|
44
|
+
return { ...Object.fromEntries(kept), PATH: [...directories, ...(current ? [current] : [])].join(delimiter) };
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
const isExecutableFile = (file: string, platform: NodeJS.Platform): boolean => {
|
|
48
|
+
try {
|
|
49
|
+
if (platform !== "win32") accessSync(file, constants.X_OK);
|
|
50
|
+
return statSync(file).isFile();
|
|
51
|
+
} catch {
|
|
52
|
+
return false;
|
|
53
|
+
}
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
/** Ob die Bash dieses Executors rg findet: das genannte, sonst eines im PATH; ein genanntes, das fehlt, ist ein Fehler. */
|
|
57
|
+
export const ripgrepAvailable = (rg: string | undefined, env: NodeJS.ProcessEnv, platform: NodeJS.Platform = process.platform): boolean => {
|
|
58
|
+
if (rg !== undefined) {
|
|
59
|
+
if (!existsSync(rg)) throw missingRipgrep(rg);
|
|
60
|
+
return true;
|
|
61
|
+
}
|
|
62
|
+
const file = platform === "win32" ? "rg.exe" : "rg";
|
|
63
|
+
return (currentPath(env, platform) ?? "").split(pathModule(platform).delimiter).filter(Boolean)
|
|
64
|
+
.some((directory) => isExecutableFile(path.join(directory, file), platform));
|
|
25
65
|
};
|
|
26
66
|
|
|
27
|
-
/** Wie ein Befehl in der Bash dieses Executors startet
|
|
67
|
+
/** Wie ein Befehl in der Bash dieses Executors startet: das Verzeichnis von rg vorn im PATH, unter Windows dahinter das usr/bin der Bash, damit find.exe und sort.exe aus System32 nicht gewinnen. */
|
|
28
68
|
export const bashLaunch = (
|
|
29
|
-
bash
|
|
69
|
+
{ bash, rg }: BashPrograms,
|
|
30
70
|
command: string,
|
|
31
71
|
env: NodeJS.ProcessEnv,
|
|
32
72
|
platform: NodeJS.Platform = process.platform,
|
|
@@ -35,11 +75,17 @@ export const bashLaunch = (
|
|
|
35
75
|
if (bash !== undefined && !existsSync(bash)) {
|
|
36
76
|
throw new Error(`Die Bash dieses Executors fehlt: ${bash}. Unter Windows gehört sie zur Erweiterung (dist/bash/<plattform>) oder steht in RAGENTS_BASH.`);
|
|
37
77
|
}
|
|
78
|
+
if (rg !== undefined && !existsSync(rg)) throw missingRipgrep(rg);
|
|
38
79
|
const shell = getShellConfig(bash, platform);
|
|
39
80
|
if (!/bash(\.exe)?$/i.test(shell.shell)) throw new Error(`${shell.shell} ist keine Bash; das Werkzeug heißt bash und der Prompt beschreibt bash`);
|
|
81
|
+
const paths = pathModule(platform);
|
|
82
|
+
const front = [
|
|
83
|
+
...(rg === undefined ? [] : [paths.dirname(rg)]),
|
|
84
|
+
...(platform === "win32" ? [paths.dirname(shell.shell)] : []),
|
|
85
|
+
];
|
|
40
86
|
return {
|
|
41
87
|
command: shell.shell,
|
|
42
88
|
args: [...shell.args, command],
|
|
43
|
-
env:
|
|
89
|
+
env: withPathFront(env, front, platform),
|
|
44
90
|
};
|
|
45
91
|
};
|
|
@@ -27,6 +27,8 @@ export interface WorkspaceProcessContext {
|
|
|
27
27
|
sandbox?: ProcessSandbox;
|
|
28
28
|
/** Die Bash, mit der das Werkzeug bash startet; unter Windows Pflicht, sonst gilt ohne Angabe die des Systems. */
|
|
29
29
|
bash?: string;
|
|
30
|
+
/** Das rg, dessen Ordner das Werkzeug bash vorn im PATH hat; ohne Angabe gilt eines im PATH, falls es eines gibt. */
|
|
31
|
+
rg?: string;
|
|
30
32
|
}
|
|
31
33
|
|
|
32
34
|
export interface SandboxHomeEnvironment {
|
|
@@ -103,6 +105,7 @@ export interface WorkspaceContextOptions {
|
|
|
103
105
|
source?: NodeJS.ProcessEnv;
|
|
104
106
|
baseEnvironment?: BaseEnvironment;
|
|
105
107
|
bash?: string;
|
|
108
|
+
rg?: string;
|
|
106
109
|
}
|
|
107
110
|
|
|
108
111
|
const namedEntries = (
|
|
@@ -151,5 +154,6 @@ export const workspaceProcessContext = (options: WorkspaceContextOptions): Works
|
|
|
151
154
|
...(options.runOperation === undefined ? {} : { runOperation: options.runOperation }),
|
|
152
155
|
...(options.sandbox === undefined ? {} : { sandbox: options.sandbox }),
|
|
153
156
|
...(options.bash === undefined ? {} : { bash: options.bash }),
|
|
157
|
+
...(options.rg === undefined ? {} : { rg: options.rg }),
|
|
154
158
|
};
|
|
155
159
|
};
|