@noodleseed/one 0.169.0 → 0.170.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/cli.d.ts.map +1 -1
- package/dist/cli.js +3 -0
- package/dist/cli.js.map +1 -1
- package/dist/commands/capabilities.d.ts +19 -0
- package/dist/commands/capabilities.d.ts.map +1 -0
- package/dist/commands/capabilities.js +128 -0
- package/dist/commands/capabilities.js.map +1 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/plugin-mode/plugin-operation-contract.d.ts +2 -2
- package/node_modules/@noodle-borg/agent-kit/dist/curated/command-groups.js +4 -0
- package/node_modules/@noodle-borg/agent-kit/dist/generated/example-files.js +1 -1
- package/node_modules/@noodle-borg/agent-kit/dist/generated/surface.js +2 -0
- package/node_modules/@noodle-borg/agent-kit/dist/skill-authoring-refs.js +3 -2
- package/node_modules/@noodle-borg/agent-kit/package.json +1 -1
- package/node_modules/@noodle-borg/assistant-gateway/dist/assistant-interactive.d.ts +1 -0
- package/node_modules/@noodle-borg/assistant-gateway/dist/assistant-interactive.js +4 -1
- package/node_modules/@noodle-borg/authoring/dist/assistant.d.ts +2 -2
- package/node_modules/@noodle-borg/authoring/dist/assistant.js +3 -1
- package/node_modules/@noodle-borg/authoring/dist/index.d.ts +1 -0
- package/node_modules/@noodle-borg/authoring/dist/index.js +1 -0
- package/node_modules/@noodle-borg/authoring/dist/load-authored.js +1 -1
- package/node_modules/@noodle-borg/authoring/dist/recording.d.ts +2 -1
- package/node_modules/@noodle-borg/authoring/dist/recording.js +29 -1
- package/node_modules/@noodle-borg/authoring/dist/server.d.ts +3 -0
- package/node_modules/@noodle-borg/authoring/dist/server.js +5 -1
- package/node_modules/@noodle-borg/authoring/dist/web-capabilities.d.ts +17 -0
- package/node_modules/@noodle-borg/authoring/dist/web-capabilities.js +15 -0
- package/node_modules/@noodle-borg/authoring/package.json +1 -0
- package/node_modules/@noodle-borg/capabilities/dist/index.js +7 -0
- package/node_modules/@noodle-borg/cli-catalog/dist/catalog-data-hosted-observability.js +102 -0
- package/node_modules/@noodle-borg/compiler/dist/artifact/assemble.js +3 -0
- package/node_modules/@noodle-borg/compiler/dist/artifact/types.d.ts +2 -0
- package/node_modules/@noodle-borg/compiler/dist/artifact/version.d.ts +2 -1
- package/node_modules/@noodle-borg/compiler/dist/artifact/version.js +2 -1
- package/node_modules/@noodle-borg/compiler/dist/compile.js +2 -0
- package/node_modules/@noodle-borg/compiler/dist/fulfilment-emit.js +18 -3
- package/node_modules/@noodle-borg/compiler/dist/manifest/schema.d.ts +34 -0
- package/node_modules/@noodle-borg/compiler/dist/manifest/schema.js +9 -2
- package/node_modules/@noodle-borg/compiler/dist/web-capabilities.js +55 -0
- package/node_modules/@noodle-borg/compiler/package.json +1 -0
- package/node_modules/@noodle-borg/connector-http/dist/ssrf.js +5 -0
- package/node_modules/@noodle-borg/knowledge-crawl/dist/bounded-body.js +38 -0
- package/node_modules/@noodle-borg/knowledge-crawl/dist/first-party.js +2 -3
- package/node_modules/@noodle-borg/knowledge-crawl/dist/html-text.js +10 -2
- package/node_modules/@noodle-borg/knowledge-crawl/dist/index.d.ts +1 -0
- package/node_modules/@noodle-borg/knowledge-crawl/dist/index.js +1 -0
- package/node_modules/@noodle-borg/knowledge-crawl/dist/page-reader.d.ts +26 -0
- package/node_modules/@noodle-borg/knowledge-crawl/dist/page-reader.js +127 -0
- package/node_modules/@noodle-borg/knowledge-crawl/dist/robots.js +48 -23
- package/node_modules/@noodle-borg/knowledge-crawl/package.json +1 -0
- package/node_modules/@noodle-borg/managed-capabilities/dist/budget.d.ts +29 -0
- package/node_modules/@noodle-borg/managed-capabilities/dist/budget.js +124 -0
- package/node_modules/@noodle-borg/managed-capabilities/dist/contracts.d.ts +212 -0
- package/node_modules/@noodle-borg/managed-capabilities/dist/contracts.js +113 -0
- package/node_modules/@noodle-borg/managed-capabilities/dist/errors.d.ts +8 -0
- package/node_modules/@noodle-borg/managed-capabilities/dist/errors.js +21 -0
- package/node_modules/@noodle-borg/managed-capabilities/dist/executor.d.ts +26 -0
- package/node_modules/@noodle-borg/managed-capabilities/dist/executor.js +156 -0
- package/node_modules/@noodle-borg/managed-capabilities/dist/limits.d.ts +15 -0
- package/node_modules/@noodle-borg/managed-capabilities/dist/limits.js +15 -0
- package/node_modules/@noodle-borg/managed-capabilities/dist/operator-contracts.d.ts +159 -0
- package/node_modules/@noodle-borg/managed-capabilities/dist/operator-contracts.js +69 -0
- package/node_modules/@noodle-borg/managed-capabilities/dist/operator-route.d.ts +5 -0
- package/node_modules/@noodle-borg/managed-capabilities/dist/operator-route.js +160 -0
- package/node_modules/@noodle-borg/managed-capabilities/dist/policy-store.d.ts +34 -0
- package/node_modules/@noodle-borg/managed-capabilities/dist/policy-store.js +61 -0
- package/node_modules/@noodle-borg/managed-capabilities/dist/portable.d.ts +10 -0
- package/node_modules/@noodle-borg/managed-capabilities/dist/portable.js +10 -0
- package/node_modules/@noodle-borg/managed-capabilities/dist/service.d.ts +83 -0
- package/node_modules/@noodle-borg/managed-capabilities/dist/service.js +139 -0
- package/node_modules/@noodle-borg/managed-capabilities/dist/urls.d.ts +3 -0
- package/node_modules/@noodle-borg/managed-capabilities/dist/urls.js +30 -0
- package/node_modules/@noodle-borg/managed-capabilities/package.json +49 -0
- package/node_modules/@noodle-borg/module/dist/contract.d.ts +11 -0
- package/node_modules/@noodle-borg/runtime/dist/confirmation.js +29 -0
- package/node_modules/@noodle-borg/runtime/dist/connector/types.d.ts +2 -0
- package/node_modules/@noodle-borg/runtime/dist/execute.d.ts +3 -0
- package/node_modules/@noodle-borg/runtime/dist/execute.js +6 -1
- package/node_modules/@noodle-borg/runtime/dist/index.d.ts +2 -1
- package/node_modules/@noodle-borg/runtime/dist/index.js +2 -1
- package/node_modules/@noodle-borg/runtime/dist/interactive.js +10 -1
- package/node_modules/@noodle-borg/runtime/dist/operation-execution.js +3 -0
- package/node_modules/@noodle-borg/runtime/dist/result-meta.d.ts +2 -0
- package/node_modules/@noodle-borg/runtime/dist/result-meta.js +6 -0
- package/node_modules/@noodle-borg/runtime/dist/result.d.ts +4 -0
- package/node_modules/@noodle-borg/runtime/dist/web-capabilities.d.ts +71 -0
- package/node_modules/@noodle-borg/runtime/dist/web-capabilities.js +41 -0
- package/node_modules/@noodle-borg/runtime/package.json +1 -0
- package/node_modules/@noodle-borg/service/dist/local-options.d.ts +1 -0
- package/node_modules/@noodle-borg/service/dist/local-web-capabilities.js +13 -0
- package/node_modules/@noodle-borg/service/dist/mcp-protocol-runtime.js +21 -0
- package/node_modules/@noodle-borg/service/dist/modules/route-dispatch.js +13 -0
- package/node_modules/@noodle-borg/service/dist/registry-compile.js +3 -0
- package/node_modules/@noodle-borg/service/dist/registry-types.d.ts +1 -0
- package/node_modules/@noodle-borg/service/dist/registry.js +3 -0
- package/node_modules/@noodle-borg/service/dist/routes/assistant-agent.js +5 -2
- package/node_modules/@noodle-borg/service/dist/routes/assistant-interactions.js +7 -4
- package/node_modules/@noodle-borg/service/dist/serve-local.js +14 -0
- package/node_modules/@noodle-borg/service/dist/serve-resource-auth.js +10 -0
- package/node_modules/@noodle-borg/service/dist/service.js +7 -1
- package/node_modules/@noodle-borg/service/dist/web-capabilities.js +39 -0
- package/node_modules/@noodle-borg/service/package.json +3 -1
- package/node_modules/@noodle-borg/wire-contracts/dist/index.d.ts +1 -0
- package/node_modules/@noodle-borg/wire-contracts/dist/index.js +1 -0
- package/node_modules/@noodle-borg/wire-contracts/package.json +1 -0
- package/package.json +3 -2
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { CredentialProfile, OperationSignature, ResolvedOperationRef } from '@noodle-borg/compiler';
|
|
2
|
+
import type { CapabilityBudget } from '@noodle-borg/managed-capabilities';
|
|
2
3
|
import type { DownstreamCredential } from '../broker/types.js';
|
|
3
4
|
import type { CustomerConnectorRoute } from '../customer-routing.js';
|
|
4
5
|
import type { OperationCoordinationDeclaration, OperationCoordinationSnapshot } from '../operation-coordination.js';
|
|
@@ -81,6 +82,7 @@ export interface ConnectorCallHost {
|
|
|
81
82
|
}
|
|
82
83
|
/** A single connector-operation invocation, fully resolved and credentialed by the runtime. */
|
|
83
84
|
export interface ConnectorCall {
|
|
85
|
+
readonly capabilityBudget?: CapabilityBudget;
|
|
84
86
|
readonly operation: string;
|
|
85
87
|
/** Runtime-generated, deployment/step-bound identity. Not a business input or recovery authority. */
|
|
86
88
|
readonly execution?: Readonly<{
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { ArtifactFulfilment, RuntimeArtifact } from '@noodle-borg/compiler';
|
|
2
|
+
import { CapabilityBudget } from '@noodle-borg/managed-capabilities';
|
|
2
3
|
import type { CredentialBroker } from './broker/types.js';
|
|
3
4
|
import type { CallerIdentity, ConnectorRegistry, ExecutionTraceSink } from './connector/types.js';
|
|
4
5
|
import type { FrozenCustomerRoutes } from './customer-routing.js';
|
|
@@ -18,6 +19,8 @@ export { evalExprMap, validateAgainstSchema, validateAgainstSchemaWithDefaults,
|
|
|
18
19
|
* [ADR 0005](../../../docs/decisions/0005-runtime-execution-boundary.md)).
|
|
19
20
|
*/
|
|
20
21
|
export interface ExecuteDeps {
|
|
22
|
+
/** Trusted shared assistant-turn / MCP-invocation budget; never part of the expression scope. */
|
|
23
|
+
readonly capabilityBudget?: CapabilityBudget;
|
|
21
24
|
readonly connectors: ConnectorRegistry;
|
|
22
25
|
readonly broker: CredentialBroker;
|
|
23
26
|
readonly policy?: PolicyGate;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { CapabilityBudget } from '@noodle-borg/managed-capabilities';
|
|
1
2
|
import { resolveVariableEnvironment } from './business-variables.js';
|
|
2
3
|
import { preflightFulfilmentSignatures } from './connector-snapshot.js';
|
|
3
4
|
import { preflightFulfilmentCustomerRoutes } from './customer-routing.js';
|
|
@@ -29,7 +30,11 @@ export async function executeTool(artifact, toolName, input, deps) {
|
|
|
29
30
|
const variables = resolveVariableEnvironment(artifact.server.variables ?? [], await resolveEnv(deps), toolName);
|
|
30
31
|
if (!variables.ok)
|
|
31
32
|
return variables;
|
|
32
|
-
return runFulfilment(tool.fulfilment, input, toolName, {
|
|
33
|
+
return runFulfilment(tool.fulfilment, input, toolName, {
|
|
34
|
+
...deps,
|
|
35
|
+
env: variables.env,
|
|
36
|
+
capabilityBudget: deps.capabilityBudget ?? new CapabilityBudget(),
|
|
37
|
+
}, deps.beforeDispatch);
|
|
33
38
|
}
|
|
34
39
|
/**
|
|
35
40
|
* Execute a resource read against a resolved artifact. `input` is the resource's variable scope — the
|
|
@@ -20,8 +20,9 @@ export type { OperationEvidence, OperationEvidenceIntent, OperationEvidencePort,
|
|
|
20
20
|
export { AllowAllPolicy } from './policy/allow-all.js';
|
|
21
21
|
export type { PolicyContext, PolicyDecision, PolicyGate } from './policy/types.js';
|
|
22
22
|
export { type ConfirmationActionReview, type ConfirmationPreparationResult, type ConfirmationReview, type ConnectorFailureAttribution, type ElicitationRequest, type ElicitationResponse, type ExecutionError, type ExecutionErrorCode, type ExecutionResult, type InteractiveExecutionResult, isConfirmationRequired, isInputRequired, isInputRequiredForConfirmation, type PreparedOperationAction, type PreparedToolContinuation, type ToolContinuation, type ToolPreparationContinuation, } from './result.js';
|
|
23
|
-
export { splitResultMeta } from './result-meta.js';
|
|
23
|
+
export { hasEphemeralEvidence, splitResultMeta } from './result-meta.js';
|
|
24
24
|
export { type CallerStateAdoptionInput, type CallerStateAdoptionResult, claimableStateHandleNames, } from './state-handle-ownership.js';
|
|
25
25
|
export { assertExpectedStateRevision, assertNoSecretValue, assertSchemaValue, assertStateHandleNotCompleted, COMPLETE_STATE_OPERATION, createMutableStateHandleRecord, createStateConnector, InMemoryStateHandleStore, type MutableStateHandleRecord, PATCH_STATE_OPERATION, READ_STATE_OPERATION, STATE_CONNECTOR_ID, STATE_CONNECTOR_VERSION, STATE_OPERATION_SIGNATURES, StateConnector, type StateHandleRecord, type StateHandleStore, type StateInput, type StateMutationInput, type StatePatchInput, stateHandleRecordForMutation, toPublicStateHandleRecord, } from './state-handles.js';
|
|
26
26
|
export type { ToolDispatchContext, ToolDispatchDecision, ToolDispatchHook, } from './tool-dispatch.js';
|
|
27
|
+
export { WebCapabilityConnector, type WebCapabilityExecutionPort } from './web-capabilities.js';
|
|
27
28
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -15,7 +15,8 @@ export { executeToolInteractive, resumeTool } from './interactive.js';
|
|
|
15
15
|
export { resolveManagedOrigins, } from './managed-origins.js';
|
|
16
16
|
export { AllowAllPolicy } from './policy/allow-all.js';
|
|
17
17
|
export { isConfirmationRequired, isInputRequired, isInputRequiredForConfirmation, } from './result.js';
|
|
18
|
-
export { splitResultMeta } from './result-meta.js';
|
|
18
|
+
export { hasEphemeralEvidence, splitResultMeta } from './result-meta.js';
|
|
19
19
|
export { claimableStateHandleNames, } from './state-handle-ownership.js';
|
|
20
20
|
export { assertExpectedStateRevision, assertNoSecretValue, assertSchemaValue, assertStateHandleNotCompleted, COMPLETE_STATE_OPERATION, createMutableStateHandleRecord, createStateConnector, InMemoryStateHandleStore, PATCH_STATE_OPERATION, READ_STATE_OPERATION, STATE_CONNECTOR_ID, STATE_CONNECTOR_VERSION, STATE_OPERATION_SIGNATURES, StateConnector, stateHandleRecordForMutation, toPublicStateHandleRecord, } from './state-handles.js';
|
|
21
|
+
export { WebCapabilityConnector } from './web-capabilities.js';
|
|
21
22
|
//# sourceMappingURL=index.js.map
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { CapabilityBudget } from '@noodle-borg/managed-capabilities';
|
|
1
2
|
import { resolveVariableEnvironment, validateVariableContinuation } from './business-variables.js';
|
|
2
3
|
import { preflightFulfilmentCustomerRoutes } from './customer-routing.js';
|
|
3
4
|
import { validateElicitationContent } from './elicitation-response.js';
|
|
@@ -17,7 +18,11 @@ export async function executeToolInteractive(artifact, toolName, input, deps) {
|
|
|
17
18
|
const variables = resolveVariableEnvironment(artifact.server.variables ?? [], await resolveEnv(deps), toolName);
|
|
18
19
|
if (!variables.ok)
|
|
19
20
|
return { status: 'failed', error: variables.error };
|
|
20
|
-
deps = {
|
|
21
|
+
deps = {
|
|
22
|
+
...deps,
|
|
23
|
+
env: variables.env,
|
|
24
|
+
capabilityBudget: deps.capabilityBudget ?? new CapabilityBudget(),
|
|
25
|
+
};
|
|
21
26
|
if (tool.fulfilment.kind !== 'flow' || !tool.fulfilment.steps.some((s) => s.kind === 'elicit')) {
|
|
22
27
|
return toInteractive(await runFulfilment(tool.fulfilment, input, toolName, deps, deps.beforeDispatch));
|
|
23
28
|
}
|
|
@@ -32,6 +37,7 @@ export async function executeToolInteractive(artifact, toolName, input, deps) {
|
|
|
32
37
|
}
|
|
33
38
|
/** Resume one server-held continuation with the user's reviewed response. */
|
|
34
39
|
export async function resumeTool(artifact, continuation, response, deps) {
|
|
40
|
+
deps = { ...deps, capabilityBudget: new CapabilityBudget(continuation.capabilityBudget) };
|
|
35
41
|
if (!sameArtifact(artifact, continuation) || continuation.version !== 1) {
|
|
36
42
|
return interactiveFail('invalid_continuation', 'tool continuation does not match the artifact');
|
|
37
43
|
}
|
|
@@ -84,6 +90,9 @@ async function runInteractiveFlow(artifact, toolName, flow, input, startIndex, s
|
|
|
84
90
|
status: 'input_required',
|
|
85
91
|
request,
|
|
86
92
|
continuation: {
|
|
93
|
+
...(deps.capabilityBudget === undefined
|
|
94
|
+
? {}
|
|
95
|
+
: { capabilityBudget: deps.capabilityBudget.snapshot() }),
|
|
87
96
|
version: 1,
|
|
88
97
|
artifact: artifactIdentity(artifact),
|
|
89
98
|
toolName,
|
|
@@ -224,6 +224,9 @@ async function invokeOperation(ref, args, sig, toolName, deps, policy, host, env
|
|
|
224
224
|
if (signal?.aborted)
|
|
225
225
|
return fail('execution_cancelled', 'Execution deadline elapsed before connector dispatch.');
|
|
226
226
|
output = await connector.invoke({
|
|
227
|
+
...(deps.capabilityBudget === undefined
|
|
228
|
+
? {}
|
|
229
|
+
: { capabilityBudget: deps.capabilityBudget }),
|
|
227
230
|
operation: ref.operation,
|
|
228
231
|
execution,
|
|
229
232
|
reportOutcome: (value) => {
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
/** Ephemeral extraction evidence is usable in the current turn but never replay/persistence data. */
|
|
2
|
+
export declare function hasEphemeralEvidence(output: unknown): boolean;
|
|
1
3
|
/** @internal Shared with suspension-aware execution and surface adapters. */
|
|
2
4
|
export declare function splitResultMeta(output: unknown): {
|
|
3
5
|
readonly visible: unknown;
|
|
@@ -1,4 +1,8 @@
|
|
|
1
1
|
const RESULT_META_KEY = '__noodleResultMeta';
|
|
2
|
+
/** Ephemeral extraction evidence is usable in the current turn but never replay/persistence data. */
|
|
3
|
+
export function hasEphemeralEvidence(output) {
|
|
4
|
+
return splitResultMeta(output).meta?.['noodle/ephemeralEvidence'] === true;
|
|
5
|
+
}
|
|
2
6
|
/** @internal Shared with suspension-aware execution and surface adapters. */
|
|
3
7
|
export function splitResultMeta(output) {
|
|
4
8
|
if (output === null || typeof output !== 'object' || Array.isArray(output)) {
|
|
@@ -31,6 +35,8 @@ export function attachResultMeta(output, metas) {
|
|
|
31
35
|
}
|
|
32
36
|
function mergeRecords(target, source) {
|
|
33
37
|
for (const [key, value] of Object.entries(source)) {
|
|
38
|
+
if (key === 'noodle/ephemeralEvidence' && target[key] === true)
|
|
39
|
+
continue;
|
|
34
40
|
const existing = target[key];
|
|
35
41
|
if (isPlainRecord(existing) && isPlainRecord(value)) {
|
|
36
42
|
mergeRecords(existing, value);
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { CredentialProfile } from '@noodle-borg/compiler';
|
|
2
|
+
import type { CapabilityBudgetSnapshot } from '@noodle-borg/managed-capabilities';
|
|
2
3
|
import type { ConnectorFailureCategory } from './connector/types.js';
|
|
3
4
|
import type { CustomerRouteBinding } from './customer-routing.js';
|
|
4
5
|
/** Why a tool call could not be fulfilled. Protocol and embedded adapters map this internal contract. */
|
|
@@ -60,6 +61,7 @@ export type ElicitationResponse = {
|
|
|
60
61
|
* never be serialized into MCP or embedded-assistant client payloads.
|
|
61
62
|
*/
|
|
62
63
|
export interface ToolContinuation {
|
|
64
|
+
readonly capabilityBudget?: CapabilityBudgetSnapshot;
|
|
63
65
|
readonly version: 1;
|
|
64
66
|
readonly artifact: {
|
|
65
67
|
readonly manifestName: string;
|
|
@@ -86,6 +88,7 @@ interface ContinuationArtifactIdentity {
|
|
|
86
88
|
* can evaluate pure maps and request more input, but cannot execute a connector operation.
|
|
87
89
|
*/
|
|
88
90
|
export interface ToolPreparationContinuation {
|
|
91
|
+
readonly capabilityBudget?: CapabilityBudgetSnapshot;
|
|
89
92
|
readonly kind: 'confirmation_preparation';
|
|
90
93
|
readonly version: 1;
|
|
91
94
|
readonly artifact: ContinuationArtifactIdentity;
|
|
@@ -102,6 +105,7 @@ export interface ToolPreparationContinuation {
|
|
|
102
105
|
* behind an opaque interaction id and release it to {@code executePreparedTool} only after approval.
|
|
103
106
|
*/
|
|
104
107
|
export interface PreparedToolContinuation {
|
|
108
|
+
readonly capabilityBudget?: CapabilityBudgetSnapshot;
|
|
105
109
|
readonly kind: 'prepared_confirmation';
|
|
106
110
|
/** Private hosting snapshot; never projected into a model-visible confirmation. */
|
|
107
111
|
readonly executionRevision?: string;
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import type { WebCapability, WebExtractResult } from '@noodle-borg/managed-capabilities';
|
|
2
|
+
import { type Connector, type ConnectorCall } from './connector/types.js';
|
|
3
|
+
export type WebCapabilityExecutionPort = (declaration: WebCapability, request: unknown, call: ConnectorCall) => Promise<WebExtractResult>;
|
|
4
|
+
/** Thin ordinary connector; deployment binding and policy authority are injected by the service. */
|
|
5
|
+
export declare class WebCapabilityConnector implements Connector {
|
|
6
|
+
private readonly declarations;
|
|
7
|
+
private readonly execute;
|
|
8
|
+
readonly id = "noodle_web";
|
|
9
|
+
readonly version = "1.0.0";
|
|
10
|
+
constructor(declarations: readonly WebCapability[], execute: WebCapabilityExecutionPort);
|
|
11
|
+
signature(operation: string): {
|
|
12
|
+
type: "read";
|
|
13
|
+
input: import("zod/v4/core").ZodStandardJSONSchemaPayload<import("zod").ZodObject<{
|
|
14
|
+
name: import("zod").ZodString;
|
|
15
|
+
request: import("zod").ZodObject<{
|
|
16
|
+
urls: import("zod").ZodArray<import("zod").ZodString>;
|
|
17
|
+
domains: import("zod").ZodOptional<import("zod").ZodArray<import("zod").ZodString>>;
|
|
18
|
+
}, import("zod/v4/core").$strict>;
|
|
19
|
+
}, import("zod/v4/core").$strict>>;
|
|
20
|
+
output: import("zod/v4/core").ZodStandardJSONSchemaPayload<import("zod").ZodObject<{
|
|
21
|
+
status: import("zod").ZodEnum<{
|
|
22
|
+
complete: "complete";
|
|
23
|
+
partial: "partial";
|
|
24
|
+
}>;
|
|
25
|
+
items: import("zod").ZodArray<import("zod").ZodObject<{
|
|
26
|
+
requestIndex: import("zod").ZodNumber;
|
|
27
|
+
sourceRef: import("zod").ZodString;
|
|
28
|
+
content: import("zod").ZodObject<{
|
|
29
|
+
format: import("zod").ZodLiteral<"text">;
|
|
30
|
+
text: import("zod").ZodString;
|
|
31
|
+
}, import("zod/v4/core").$strict>;
|
|
32
|
+
links: import("zod").ZodArray<import("zod").ZodObject<{
|
|
33
|
+
url: import("zod").ZodString;
|
|
34
|
+
label: import("zod").ZodOptional<import("zod").ZodString>;
|
|
35
|
+
}, import("zod/v4/core").$strict>>;
|
|
36
|
+
truncated: import("zod").ZodBoolean;
|
|
37
|
+
}, import("zod/v4/core").$strict>>;
|
|
38
|
+
sources: import("zod").ZodArray<import("zod").ZodObject<{
|
|
39
|
+
ref: import("zod").ZodString;
|
|
40
|
+
url: import("zod").ZodString;
|
|
41
|
+
title: import("zod").ZodOptional<import("zod").ZodString>;
|
|
42
|
+
retrievedAt: import("zod").ZodISODateTime;
|
|
43
|
+
publishedAt: import("zod").ZodOptional<import("zod").ZodISODateTime>;
|
|
44
|
+
observedAt: import("zod").ZodOptional<import("zod").ZodISODateTime>;
|
|
45
|
+
expiresAt: import("zod").ZodOptional<import("zod").ZodISODateTime>;
|
|
46
|
+
attribution: import("zod").ZodOptional<import("zod").ZodString>;
|
|
47
|
+
rights: import("zod").ZodOptional<import("zod").ZodString>;
|
|
48
|
+
}, import("zod/v4/core").$strict>>;
|
|
49
|
+
warnings: import("zod").ZodArray<import("zod").ZodObject<{
|
|
50
|
+
requestIndex: import("zod").ZodNumber;
|
|
51
|
+
code: import("zod").ZodEnum<{
|
|
52
|
+
capability_unavailable: "capability_unavailable";
|
|
53
|
+
capability_binding_invalid: "capability_binding_invalid";
|
|
54
|
+
capability_requirement_unsupported: "capability_requirement_unsupported";
|
|
55
|
+
capability_policy_denied: "capability_policy_denied";
|
|
56
|
+
capability_budget_exhausted: "capability_budget_exhausted";
|
|
57
|
+
capability_source_rejected: "capability_source_rejected";
|
|
58
|
+
capability_provider_failed: "capability_provider_failed";
|
|
59
|
+
capability_result_invalid: "capability_result_invalid";
|
|
60
|
+
capability_cancelled: "capability_cancelled";
|
|
61
|
+
content_truncated: "content_truncated";
|
|
62
|
+
}>;
|
|
63
|
+
}, import("zod/v4/core").$strict>>;
|
|
64
|
+
}, import("zod/v4/core").$strict>>;
|
|
65
|
+
} | undefined;
|
|
66
|
+
executionBoundMs(): number;
|
|
67
|
+
invoke(call: ConnectorCall): Promise<WebExtractResult & {
|
|
68
|
+
readonly __noodleResultMeta: Readonly<Record<string, unknown>>;
|
|
69
|
+
}>;
|
|
70
|
+
}
|
|
71
|
+
//# sourceMappingURL=web-capabilities.d.ts.map
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { CapabilityError, WEB_CONNECTOR_ID, WEB_CONNECTOR_VERSION, WEB_OPERATION_SIGNATURE, webOperationInputSchema, } from '@noodle-borg/managed-capabilities';
|
|
2
|
+
import { ConnectorInvocationError } from './connector/types.js';
|
|
3
|
+
/** Thin ordinary connector; deployment binding and policy authority are injected by the service. */
|
|
4
|
+
export class WebCapabilityConnector {
|
|
5
|
+
declarations;
|
|
6
|
+
execute;
|
|
7
|
+
id = WEB_CONNECTOR_ID;
|
|
8
|
+
version = WEB_CONNECTOR_VERSION;
|
|
9
|
+
constructor(declarations, execute) {
|
|
10
|
+
this.declarations = declarations;
|
|
11
|
+
this.execute = execute;
|
|
12
|
+
}
|
|
13
|
+
signature(operation) {
|
|
14
|
+
return operation === 'extract' ? WEB_OPERATION_SIGNATURE : undefined;
|
|
15
|
+
}
|
|
16
|
+
executionBoundMs() {
|
|
17
|
+
return 30_000;
|
|
18
|
+
}
|
|
19
|
+
async invoke(call) {
|
|
20
|
+
const input = webOperationInputSchema.safeParse(call.args);
|
|
21
|
+
const declaration = input.success
|
|
22
|
+
? this.declarations.find((value) => value.name === input.data.name)
|
|
23
|
+
: undefined;
|
|
24
|
+
if (call.operation !== 'extract' ||
|
|
25
|
+
declaration === undefined ||
|
|
26
|
+
!input.success ||
|
|
27
|
+
call.capabilityBudget === undefined) {
|
|
28
|
+
throw new ConnectorInvocationError('capability_policy_denied', { retryable: false });
|
|
29
|
+
}
|
|
30
|
+
try {
|
|
31
|
+
return {
|
|
32
|
+
...(await this.execute(declaration, input.data.request, call)),
|
|
33
|
+
__noodleResultMeta: { 'noodle/ephemeralEvidence': true },
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
catch (error) {
|
|
37
|
+
throw new ConnectorInvocationError(error instanceof CapabilityError ? error.code : 'capability_unavailable', { retryable: false });
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
//# sourceMappingURL=web-capabilities.js.map
|
|
@@ -6,6 +6,7 @@ import type { LocalDevtoolsDelegatedExchangeRuntime } from './local-devtools-del
|
|
|
6
6
|
import type { ServerRegistry } from './registry.js';
|
|
7
7
|
import type { ConfigStore, TenantBridgeAuthConfig } from './store.js';
|
|
8
8
|
type LocalRuntimeOptions = {
|
|
9
|
+
readonly capabilities?: import('@noodle-borg/managed-capabilities').CapabilityService;
|
|
9
10
|
readonly assistantStore?: import('@noodle-borg/assistant-gateway/portable').AssistantStore;
|
|
10
11
|
readonly assistantAppearance?: import('@noodle-borg/assistant-gateway/portable').AssistantAppearanceSettingsStore;
|
|
11
12
|
readonly publicEmbeds?: import('@noodle-borg/assistant-gateway/portable').PublicEmbedStore;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { InMemoryDailyCounterStore } from '@noodle-borg/admission-limits/portable';
|
|
2
|
+
import { PublicPageReader } from '@noodle-borg/knowledge-crawl';
|
|
3
|
+
import { CapabilityService, InMemoryCapabilityPolicyStore, } from '@noodle-borg/managed-capabilities';
|
|
4
|
+
/** Loopback-only composition. Keep PostgreSQL imports out of the published CLI graph. */
|
|
5
|
+
export function localWebCapabilities() {
|
|
6
|
+
return new CapabilityService({
|
|
7
|
+
profile: 'development',
|
|
8
|
+
policies: new InMemoryCapabilityPolicyStore(),
|
|
9
|
+
counters: new InMemoryDailyCounterStore(),
|
|
10
|
+
reader: new PublicPageReader(),
|
|
11
|
+
});
|
|
12
|
+
}
|
|
13
|
+
//# sourceMappingURL=local-web-capabilities.js.map
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { RequestStateManager, requestStateSecretBox, } from '@noodle-borg/protocol';
|
|
2
|
+
/**
|
|
3
|
+
* Build the fleet-shared request-state manager. Static-key deployments use an HKDF domain-separated key;
|
|
4
|
+
* KMS deployments reuse the configured envelope-encryption custodian because its raw KEK cannot be
|
|
5
|
+
* exported for HKDF.
|
|
6
|
+
*/
|
|
7
|
+
export function createHostedMcpRequestStateManager(input) {
|
|
8
|
+
if (input.secretMasterKey !== undefined) {
|
|
9
|
+
return new RequestStateManager(requestStateSecretBox(Buffer.from(input.secretMasterKey, 'base64')));
|
|
10
|
+
}
|
|
11
|
+
return input.secretBox === undefined ? undefined : new RequestStateManager(input.secretBox);
|
|
12
|
+
}
|
|
13
|
+
/** Resolve the temporary origin-wide rollout gate from operator configuration. */
|
|
14
|
+
export function resolveMcpProtocolMode(value) {
|
|
15
|
+
if (value === undefined || value === 'dual')
|
|
16
|
+
return 'dual';
|
|
17
|
+
if (value === 'legacy-only')
|
|
18
|
+
return value;
|
|
19
|
+
throw new Error('NOODLE_MCP_PROTOCOL_MODE must be dual or legacy-only');
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=mcp-protocol-runtime.js.map
|
|
@@ -14,6 +14,19 @@ export function createModuleRouteContext(hostRequest, deps) {
|
|
|
14
14
|
logger: deps.logger ?? noopModuleLogger,
|
|
15
15
|
controlPlane: deps.gate,
|
|
16
16
|
audit: deps.audit,
|
|
17
|
+
capabilityDeployments: {
|
|
18
|
+
get: async (request, scope) => {
|
|
19
|
+
if (request !== hostRequest || !authorizedOrgs.has(scope.org))
|
|
20
|
+
return undefined;
|
|
21
|
+
const target = await deps.registry.getActiveByTenant(scope);
|
|
22
|
+
if (target?.deploymentId === undefined)
|
|
23
|
+
return undefined;
|
|
24
|
+
return {
|
|
25
|
+
deploymentId: target.deploymentId,
|
|
26
|
+
declarations: target.served.artifact.server.capabilities ?? [],
|
|
27
|
+
};
|
|
28
|
+
},
|
|
29
|
+
},
|
|
17
30
|
platformIdentityRecovery: {
|
|
18
31
|
reconcile: (plan) => deps.registry.reconcilePlatformAccountReset(plan),
|
|
19
32
|
customerAuthRestoreProjections: async (deploymentIds) => (await deps.registry.customerAuthRestoreProjections(deploymentIds)).map((projection) => ({
|
|
@@ -14,6 +14,7 @@ import { missingCapabilityErrors, missingSecretErrors, missingVariableErrors, }
|
|
|
14
14
|
import { servedTargetFor } from './registry-targets.js';
|
|
15
15
|
import { createDeploymentStateConnector, } from './state-connector-factory.js';
|
|
16
16
|
import { resolveConfigScope, } from './store.js';
|
|
17
|
+
import { deploymentWebConnector } from './web-capabilities.js';
|
|
17
18
|
/** Reject unsupported persisted semantics before constructing executable runtime dependencies. */
|
|
18
19
|
export async function compilePersistedRegistryRecord(record, compileTarget) {
|
|
19
20
|
const versionError = deploymentRecordVersionError(record);
|
|
@@ -197,11 +198,13 @@ export async function compileRegistryTarget(context, input) {
|
|
|
197
198
|
artifact,
|
|
198
199
|
...(boundDeploymentId === undefined ? {} : { deploymentId: boundDeploymentId }),
|
|
199
200
|
});
|
|
201
|
+
const webConnector = deploymentWebConnector(artifact, tenant, boundDeploymentId, context.capabilities);
|
|
200
202
|
return {
|
|
201
203
|
artifact,
|
|
202
204
|
deps: {
|
|
203
205
|
connectors: new InMemoryConnectorRegistry([
|
|
204
206
|
...context.platformConnectors,
|
|
207
|
+
...(webConnector === undefined ? [] : [webConnector]),
|
|
205
208
|
...(nativeRecords === undefined ? [] : [nativeRecords]),
|
|
206
209
|
...(stateConnector !== undefined ? [stateConnector] : []),
|
|
207
210
|
...httpConnectors,
|
|
@@ -96,6 +96,7 @@ export interface AccessUpdateOptions {
|
|
|
96
96
|
readonly serverVersion?: string | undefined;
|
|
97
97
|
}
|
|
98
98
|
export interface ServerRegistryOptions {
|
|
99
|
+
readonly capabilities?: import('@noodle-borg/managed-capabilities').CapabilityService;
|
|
99
100
|
readonly nativeRecords?: NativeRecordConnectorFactory;
|
|
100
101
|
/** Pure renderer injection used for deployment-bound package construction and failure testing. */
|
|
101
102
|
readonly renderAppPackage?: AppPackageRenderer;
|
|
@@ -32,6 +32,7 @@ export class ServerRegistry {
|
|
|
32
32
|
#platformCatalog;
|
|
33
33
|
#platformConnectors;
|
|
34
34
|
#nativeRecords;
|
|
35
|
+
#capabilities;
|
|
35
36
|
#stateHandleStoreFactory;
|
|
36
37
|
#delegatedCredentialStore;
|
|
37
38
|
#sealCustomerCredential;
|
|
@@ -61,6 +62,7 @@ export class ServerRegistry {
|
|
|
61
62
|
this.#platformCatalog = withBuiltinStateCatalog(options.platformCatalog ?? []);
|
|
62
63
|
this.#platformConnectors = options.platformConnectors ?? [];
|
|
63
64
|
this.#nativeRecords = options.nativeRecords;
|
|
65
|
+
this.#capabilities = options.capabilities;
|
|
64
66
|
this.#stateHandleStoreFactory = options.stateHandleStoreFactory;
|
|
65
67
|
this.#delegatedCredentialStore = options.delegatedCredentialStore;
|
|
66
68
|
this.#sealCustomerCredential = options.sealCustomerCredential;
|
|
@@ -311,6 +313,7 @@ export class ServerRegistry {
|
|
|
311
313
|
stateHandleStoreFactory: this.#stateHandleStoreFactory,
|
|
312
314
|
platformConnectors: this.#platformConnectors,
|
|
313
315
|
nativeRecords: this.#nativeRecords,
|
|
316
|
+
capabilities: this.#capabilities,
|
|
314
317
|
policyGate: this.#policyGate,
|
|
315
318
|
appPackageRenderer: this.#appPackageRenderer,
|
|
316
319
|
knowledgeSearch: this.#knowledgeSearch,
|
|
@@ -3,6 +3,7 @@ import { assistantCoreModelMessages, assistantTurnModelContextMessages, requestA
|
|
|
3
3
|
import { assistantGuideModelContext, assistantModelToolOncePerSession, assistantModelToolRequiredWhenVisible, assistantOmittedToolResult, assistantViewAvailableData, dispatchAssistantTool, projectAssistantGuide, publicSurfaceOf, recoverableAssistantView, remainingTurnTokens, selectAssistantModelTools, toolTouchesDelegatedAuth, withAssistantSessionExecutionAuthority, } from '@noodle-borg/assistant-gateway/portable';
|
|
4
4
|
import { validateJsonSchemaWithDefaults } from '@noodle-borg/compiler';
|
|
5
5
|
import { guardedFetch } from '@noodle-borg/connector-http';
|
|
6
|
+
import { CapabilityBudget } from '@noodle-borg/managed-capabilities';
|
|
6
7
|
import { evaluateToolAuthorization } from '@noodle-borg/protocol';
|
|
7
8
|
import { interceptForElevation, offersSignIn } from './assistant-elevation.js';
|
|
8
9
|
import { assistantKnowledgeModelTools, executeAssistantKnowledgeSearch, findAssistantKnowledgeComponent, KNOWLEDGE_CITATION_GUIDANCE, resolveAssistantKnowledge, } from './assistant-knowledge.js';
|
|
@@ -98,6 +99,7 @@ export async function runAgentTurn(target, session, message, context, deps, emit
|
|
|
98
99
|
// Across every step of this turn, not per step: eight tool calls is eight, however the model splits
|
|
99
100
|
// them, or a model that loops one call per step would spend the budget a step at a time.
|
|
100
101
|
let toolCallsThisTurn = 0;
|
|
102
|
+
const capabilityBudget = new CapabilityBudget();
|
|
101
103
|
let omittedToolRecoveries = 0;
|
|
102
104
|
let remainingTokens = binding.requestPolicy?.maxTokensPerTurn;
|
|
103
105
|
const turnSignal = binding.requestPolicy?.maxTurnMs === undefined
|
|
@@ -247,7 +249,7 @@ export async function runAgentTurn(target, session, message, context, deps, emit
|
|
|
247
249
|
artifact: target.served.artifact,
|
|
248
250
|
tool,
|
|
249
251
|
arguments: args,
|
|
250
|
-
executeDeps: withAssistantSessionExecutionAuthority(target.served.deps, target.served.artifact, session),
|
|
252
|
+
executeDeps: withAssistantSessionExecutionAuthority({ ...target.served.deps, capabilityBudget }, target.served.artifact, session),
|
|
251
253
|
caller: session.caller,
|
|
252
254
|
context,
|
|
253
255
|
session,
|
|
@@ -273,7 +275,8 @@ export async function runAgentTurn(target, session, message, context, deps, emit
|
|
|
273
275
|
arguments: args,
|
|
274
276
|
}, (failure) => deps.logger?.warn('assistant.view.unresolved', { ...failure }));
|
|
275
277
|
if (view) {
|
|
276
|
-
|
|
278
|
+
if (!dispatch.ephemeral)
|
|
279
|
+
await deps.store.replaceLatestView(session.id, recoverableAssistantView(view));
|
|
277
280
|
emit({ event: 'view_available', data: { ...view } });
|
|
278
281
|
}
|
|
279
282
|
messages.push({
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { AssistantInteractionCapacityError, assistantConfirmationReview, assistantConfirmationTransition, assistantInputTransition, assistantInteractionTool, assistantPreparedArgumentReview, assistantPreparedToolContinuation, assistantSafeOutput, assistantToolContinuation, assistantViewAvailableData, auditAssistantInteraction, boundedAssistantExecution, recoverableAssistantView, withAssistantSessionExecutionAuthority, } from '@noodle-borg/assistant-gateway/portable';
|
|
2
|
-
import { executePreparedTool, executeToolInteractive, resumeTool, resumeToolPreparation, } from '@noodle-borg/runtime';
|
|
2
|
+
import { executePreparedTool, executeToolInteractive, hasEphemeralEvidence, resumeTool, resumeToolPreparation, } from '@noodle-borg/runtime';
|
|
3
3
|
import { readJsonBody, sendJson } from '@noodle-borg/transport-http';
|
|
4
4
|
import { applyBrowserCors, authenticateSession, now, } from './assistant.js';
|
|
5
5
|
import { replayOrConflict, writeUnknownOutcome } from './assistant-interaction-replay.js';
|
|
@@ -347,7 +347,9 @@ async function finishExecution(res, deps, session, interaction, context, result,
|
|
|
347
347
|
}
|
|
348
348
|
const completedTool = target.served.artifact.tools.find((tool) => tool.name === toolName);
|
|
349
349
|
const safeOutput = assistantSafeOutput(completedTool?.outputSchema, result.output);
|
|
350
|
-
const
|
|
350
|
+
const ephemeral = hasEphemeralEvidence(result.output);
|
|
351
|
+
const retainedOutput = ephemeral ? { evidenceRetained: false } : safeOutput;
|
|
352
|
+
const completed = await completeAssistantInteractionExecution(deps, session, interaction, 'succeeded', 'tool_completed', toolName, { result: retainedOutput });
|
|
351
353
|
if (!completed)
|
|
352
354
|
return writeUnknownOutcome(res, deps, session, interaction, 'accept');
|
|
353
355
|
await auditAssistantInteraction({
|
|
@@ -364,7 +366,7 @@ async function finishExecution(res, deps, session, interaction, context, result,
|
|
|
364
366
|
// Model-facing scaffolding: the panel saw the tool_completed card, never this row's tool JSON.
|
|
365
367
|
{
|
|
366
368
|
role: 'assistant',
|
|
367
|
-
content: `Completed ${toolName}: ${JSON.stringify(
|
|
369
|
+
content: `Completed ${toolName}: ${JSON.stringify(retainedOutput)}`,
|
|
368
370
|
kind: 'narration',
|
|
369
371
|
},
|
|
370
372
|
]);
|
|
@@ -377,7 +379,8 @@ async function finishExecution(res, deps, session, interaction, context, result,
|
|
|
377
379
|
result: safeOutput,
|
|
378
380
|
}, (failure) => deps.logger?.warn('assistant.view.unresolved', { ...failure }));
|
|
379
381
|
if (view) {
|
|
380
|
-
|
|
382
|
+
if (!ephemeral)
|
|
383
|
+
await deps.store.replaceLatestView(session.id, recoverableAssistantView(view));
|
|
381
384
|
writeViewAvailable(res, view);
|
|
382
385
|
}
|
|
383
386
|
await narrateResolvedInteraction(res, deps, target, session, toolName, 'accept', safeOutput, context, suggestions);
|
|
@@ -3,6 +3,7 @@ import { InMemoryControlPlaneStore } from '@noodle-borg/control-plane/portable';
|
|
|
3
3
|
import { InMemoryAssetStore } from './assets.js';
|
|
4
4
|
import { createCustomerVerifierFactory, createHostedCustomerVerifierFactory, createLocalDevtoolsCustomerVerifierFactory, } from './customer-verifier.js';
|
|
5
5
|
import { createLocalDevtoolsDelegatedCredentialSource } from './local-devtools-delegated-credentials.js';
|
|
6
|
+
import { localWebCapabilities } from './local-web-capabilities.js';
|
|
6
7
|
import { ServerRegistry } from './registry.js';
|
|
7
8
|
import { isLoopbackHost } from './serve-resource-auth.js';
|
|
8
9
|
import { createServiceHandler } from './service.js';
|
|
@@ -48,7 +49,9 @@ export async function serveLocalService(options = {}) {
|
|
|
48
49
|
const delegatedCredentials = directCustomerAuth
|
|
49
50
|
? createLocalDevtoolsDelegatedCredentialSource()
|
|
50
51
|
: undefined;
|
|
52
|
+
const capabilities = options.runtime?.capabilities ?? localWebCapabilities();
|
|
51
53
|
const registry = new ServerRegistry(undefined, undefined, configStore, {
|
|
54
|
+
capabilities,
|
|
52
55
|
customerVerifierFactory,
|
|
53
56
|
...(delegatedCredentials === undefined
|
|
54
57
|
? {}
|
|
@@ -62,6 +65,17 @@ export async function serveLocalService(options = {}) {
|
|
|
62
65
|
: { localDevtoolsDelegatedExchange: options.localDevtoolsDelegatedExchange }),
|
|
63
66
|
});
|
|
64
67
|
const handler = createServiceHandler(registry, {
|
|
68
|
+
capabilities,
|
|
69
|
+
deployGate: {
|
|
70
|
+
authorize: () => ({
|
|
71
|
+
ok: true,
|
|
72
|
+
identity: {
|
|
73
|
+
subject: 'local-operator',
|
|
74
|
+
email: 'local-operator@localhost',
|
|
75
|
+
superAdmin: true,
|
|
76
|
+
},
|
|
77
|
+
}),
|
|
78
|
+
},
|
|
65
79
|
controlPlaneStore,
|
|
66
80
|
configStore,
|
|
67
81
|
assetStore: new InMemoryAssetStore(),
|
|
@@ -1,10 +1,20 @@
|
|
|
1
1
|
import { resolveMcpSubdomainTenant } from '@noodle-borg/control-plane/portable';
|
|
2
2
|
import { normalizePublicBaseDomain, parseCanonicalPublicMcpUrl, parseLegacyTenantMcpPath, } from '@noodle-borg/module';
|
|
3
3
|
import { resolveTenantBridgeAuthVariables } from './managed-config-expressions.js';
|
|
4
|
+
import { createHostedMcpRequestStateManager } from './mcp-protocol-runtime.js';
|
|
4
5
|
import { resolveConfigScope, } from './store.js';
|
|
5
6
|
export function isLoopbackHost(host) {
|
|
6
7
|
return host === '127.0.0.1' || host === '::1' || host === 'localhost';
|
|
7
8
|
}
|
|
9
|
+
export function resolveMcpRequestState(options, secretBox) {
|
|
10
|
+
return (options.mcpRequestState ??
|
|
11
|
+
createHostedMcpRequestStateManager({
|
|
12
|
+
...(options.wrappingMasterKey === undefined && options.secretMasterKey !== undefined
|
|
13
|
+
? { secretMasterKey: options.secretMasterKey }
|
|
14
|
+
: {}),
|
|
15
|
+
...(secretBox === undefined ? {} : { secretBox }),
|
|
16
|
+
}));
|
|
17
|
+
}
|
|
8
18
|
export function assertLocalDevtoolsServiceBoundary(host, options) {
|
|
9
19
|
if (options.localDevtoolsDirectFirebaseAuth === true && !isLoopbackHost(host)) {
|
|
10
20
|
throw new Error('local Devtools Firebase verification requires a loopback service bind');
|
|
@@ -2,6 +2,7 @@ import { InMemoryDailyCounterStore } from '@noodle-borg/admission-limits/portabl
|
|
|
2
2
|
import { InMemoryAssistantAppearanceSettingsStore, InMemoryAssistantStore, } from '@noodle-borg/assistant-gateway/portable';
|
|
3
3
|
import { allowAllGate, InMemoryControlPlaneStore } from '@noodle-borg/control-plane/portable';
|
|
4
4
|
import { dispatchKnowledgeRequest } from '@noodle-borg/knowledge-operations/portable';
|
|
5
|
+
import { capabilityOperatorRoute } from '@noodle-borg/managed-capabilities';
|
|
5
6
|
import { OPENAI_APPS_CHALLENGE_PATH } from '@noodle-borg/module';
|
|
6
7
|
import { applySecurityHeaders, createMcpRouter, enforceHttps, noopLogger, sendJson, } from '@noodle-borg/transport-http';
|
|
7
8
|
import { AnonymousConsumerLimiter, createAdmissionGate } from './admission.js';
|
|
@@ -163,7 +164,12 @@ export function createServiceHandler(registry, options = {}) {
|
|
|
163
164
|
});
|
|
164
165
|
archiveSweeper.maybeSweep();
|
|
165
166
|
const moduleRouteDeps = {
|
|
166
|
-
routes:
|
|
167
|
+
routes: [
|
|
168
|
+
...moduleHost.routes,
|
|
169
|
+
...(options.capabilities === undefined
|
|
170
|
+
? []
|
|
171
|
+
: [capabilityOperatorRoute(options.capabilities)]),
|
|
172
|
+
],
|
|
167
173
|
logger,
|
|
168
174
|
gate,
|
|
169
175
|
controlPlane,
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { CapabilityError } from '@noodle-borg/managed-capabilities';
|
|
2
|
+
import { evaluateToolAuthorization } from '@noodle-borg/protocol';
|
|
3
|
+
import { WebCapabilityConnector } from '@noodle-borg/runtime';
|
|
4
|
+
export function deploymentWebConnector(artifact, tenant, deploymentId, service) {
|
|
5
|
+
if (!artifact.server.capabilities?.length)
|
|
6
|
+
return undefined;
|
|
7
|
+
return new WebCapabilityConnector(artifact.server.capabilities, async (declaration, request, call) => {
|
|
8
|
+
if (service === undefined ||
|
|
9
|
+
deploymentId === undefined ||
|
|
10
|
+
call.execution === undefined ||
|
|
11
|
+
call.capabilityBudget === undefined) {
|
|
12
|
+
throw new CapabilityError('capability_unavailable');
|
|
13
|
+
}
|
|
14
|
+
return service.execute(declaration, request, {
|
|
15
|
+
tenant,
|
|
16
|
+
deploymentId,
|
|
17
|
+
executionId: call.execution.id,
|
|
18
|
+
authorized: evaluateToolAuthorization(declaration.authorization === undefined
|
|
19
|
+
? undefined
|
|
20
|
+
: {
|
|
21
|
+
...(declaration.authorization.discovery === 'public'
|
|
22
|
+
? { discovery: 'public' }
|
|
23
|
+
: {}),
|
|
24
|
+
...(declaration.authorization.requiredScopes === undefined
|
|
25
|
+
? {}
|
|
26
|
+
: { requiredScopes: declaration.authorization.requiredScopes }),
|
|
27
|
+
...(declaration.authorization.allowedRoles === undefined
|
|
28
|
+
? {}
|
|
29
|
+
: { allowedRoles: declaration.authorization.allowedRoles }),
|
|
30
|
+
}, call.caller).allow,
|
|
31
|
+
anonymous: call.caller === undefined || call.caller.identityKind === 'anonymous',
|
|
32
|
+
...(call.caller === undefined ? {} : { subject: call.caller.subject }),
|
|
33
|
+
...(call.publicAdmission === undefined ? {} : { network: call.publicAdmission.network }),
|
|
34
|
+
budget: call.capabilityBudget,
|
|
35
|
+
...(call.signal === undefined ? {} : { signal: call.signal }),
|
|
36
|
+
});
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
//# sourceMappingURL=web-capabilities.js.map
|