@noodleseed/one 0.137.0 → 0.138.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/commands/assistant-ops.d.ts.map +1 -1
- package/dist/commands/assistant-ops.js +30 -1
- package/dist/commands/assistant-ops.js.map +1 -1
- package/dist/commands/deploy-first-flow.d.ts +2 -0
- package/dist/commands/deploy-first-flow.d.ts.map +1 -1
- package/dist/commands/deploy-first-flow.js +46 -14
- package/dist/commands/deploy-first-flow.js.map +1 -1
- package/dist/commands/deploy-ops.d.ts.map +1 -1
- package/dist/commands/deploy-ops.js +27 -1
- package/dist/commands/deploy-ops.js.map +1 -1
- package/dist/commands/deploy-preflight.d.ts +1 -0
- package/dist/commands/deploy-preflight.d.ts.map +1 -1
- package/dist/commands/deploy-preflight.js +1 -0
- package/dist/commands/deploy-preflight.js.map +1 -1
- package/dist/commands/deploy-status-ops.d.ts +1 -0
- package/dist/commands/deploy-status-ops.d.ts.map +1 -1
- package/dist/commands/deploy-status-ops.js +59 -4
- package/dist/commands/deploy-status-ops.js.map +1 -1
- package/dist/commands/deployments-ops.d.ts.map +1 -1
- package/dist/commands/deployments-ops.js +2 -0
- package/dist/commands/deployments-ops.js.map +1 -1
- package/dist/commands/diagnostics-ops.d.ts +1 -0
- package/dist/commands/diagnostics-ops.d.ts.map +1 -1
- package/dist/commands/diagnostics-ops.js +3 -0
- package/dist/commands/diagnostics-ops.js.map +1 -1
- package/dist/deploy.d.ts +3 -0
- package/dist/deploy.d.ts.map +1 -1
- package/dist/deploy.js +4 -0
- package/dist/deploy.js.map +1 -1
- 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/node_modules/@noodle-borg/admission-limits/dist/envelope.js +1 -1
- package/node_modules/@noodle-borg/agent-kit/dist/generated/example-files.js +3 -3
- package/node_modules/@noodle-borg/agent-kit/dist/generated/surface.js +1 -0
- package/node_modules/@noodle-borg/agent-kit/dist/skill-embedded-assistant-ref.js +6 -7
- package/node_modules/@noodle-borg/agent-kit/package.json +1 -1
- package/node_modules/@noodle-borg/assistant-gateway/dist/assistant-store.d.ts +6 -2
- package/node_modules/@noodle-borg/assistant-gateway/dist/assistant-store.js +5 -2
- package/node_modules/@noodle-borg/assistant-gateway/dist/model-request.js +37 -0
- package/node_modules/@noodle-borg/assistant-gateway/dist/model-runtime.js +4 -0
- package/node_modules/@noodle-borg/{service/dist/assistant-model-stream.js → assistant-gateway/dist/model-stream.js} +34 -2
- package/node_modules/@noodle-borg/assistant-gateway/dist/public-session.d.ts +3 -0
- package/node_modules/@noodle-borg/assistant-gateway/dist/public-session.js +2 -1
- package/node_modules/@noodle-borg/assistant-gateway/dist/public-turn.d.ts +4 -1
- package/node_modules/@noodle-borg/assistant-gateway/dist/public-turn.js +2 -1
- package/node_modules/@noodle-borg/assistant-gateway/dist/surface-budget.d.ts +6 -1
- package/node_modules/@noodle-borg/assistant-gateway/dist/surface-budget.js +11 -5
- package/node_modules/@noodle-borg/assistant-gateway/package.json +5 -1
- package/node_modules/@noodle-borg/authoring/dist/assistant.d.ts +10 -2
- package/node_modules/@noodle-borg/authoring/dist/assistant.js +4 -0
- package/node_modules/@noodle-borg/authoring/dist/index.d.ts +1 -1
- package/node_modules/@noodle-borg/authoring/dist/index.js +1 -1
- package/node_modules/@noodle-borg/authoring/dist/load-authored.js +1 -1
- package/node_modules/@noodle-borg/cli-catalog/dist/catalog-data-assistant.js +17 -0
- package/node_modules/@noodle-borg/cli-catalog/dist/catalog-data-hosted-deployment.js +14 -0
- package/node_modules/@noodle-borg/compiler/dist/artifact/types.d.ts +1 -7
- package/node_modules/@noodle-borg/compiler/dist/manifest/schema.d.ts +20 -8
- package/node_modules/@noodle-borg/compiler/dist/manifest/schema.js +12 -8
- package/node_modules/@noodle-borg/control-plane/dist/portable.d.ts +2 -0
- package/node_modules/@noodle-borg/control-plane/dist/portable.js +1 -0
- package/node_modules/@noodle-borg/control-plane/dist/rollback-deployment.d.ts +61 -0
- package/node_modules/@noodle-borg/{service/dist/operations → control-plane/dist}/rollback-deployment.js +3 -2
- package/node_modules/@noodle-borg/control-plane/dist/rollback-result.d.ts +19 -0
- package/node_modules/@noodle-borg/control-plane/package.json +3 -1
- package/node_modules/@noodle-borg/developer-mcp/dist/contracts.js +4 -0
- package/node_modules/@noodle-borg/developer-mcp/dist/widgets/app-overview.js +1 -1
- package/node_modules/@noodle-borg/developer-mcp/dist/widgets/deployment-detail.js +1 -1
- package/node_modules/@noodle-borg/module/dist/contract.d.ts +1 -0
- package/node_modules/@noodle-borg/module/dist/deployment-automation.d.ts +1 -1
- package/node_modules/@noodle-borg/module/dist/endpoint-url.d.ts +11 -0
- package/node_modules/@noodle-borg/module/dist/endpoint-url.js +20 -0
- package/node_modules/@noodle-borg/module/dist/index.d.ts +1 -0
- package/node_modules/@noodle-borg/module/dist/index.js +1 -0
- package/node_modules/@noodle-borg/observability/dist/assistant-usage.js +217 -0
- package/node_modules/@noodle-borg/observability/dist/index.js +2 -0
- package/node_modules/@noodle-borg/{service → observability}/dist/request-event-metrics.js +5 -2
- package/node_modules/@noodle-borg/observability/dist/request-events-postgres.js +6 -0
- package/node_modules/@noodle-borg/observability/dist/request-events.js +2 -0
- package/node_modules/@noodle-borg/service/dist/assistant-bindings.js +3 -1
- package/node_modules/@noodle-borg/service/dist/developer-mcp/control-plane-adapter.js +3 -3
- package/node_modules/@noodle-borg/service/dist/developer-mcp/inspection.js +2 -1
- package/node_modules/@noodle-borg/service/dist/registry-access.js +73 -24
- package/node_modules/@noodle-borg/service/dist/registry-deploy-transaction.js +5 -2
- package/node_modules/@noodle-borg/service/dist/registry-helpers.d.ts +5 -9
- package/node_modules/@noodle-borg/service/dist/registry-helpers.js +4 -18
- package/node_modules/@noodle-borg/service/dist/registry-rollback.js +3 -1
- package/node_modules/@noodle-borg/service/dist/registry-status.js +4 -1
- package/node_modules/@noodle-borg/service/dist/registry-targets.js +4 -4
- package/node_modules/@noodle-borg/service/dist/registry-types.d.ts +11 -16
- package/node_modules/@noodle-borg/service/dist/registry.d.ts +8 -5
- package/node_modules/@noodle-borg/service/dist/registry.js +8 -5
- package/node_modules/@noodle-borg/service/dist/routes/access.js +19 -1
- package/node_modules/@noodle-borg/service/dist/routes/analytics-dispatch.js +17 -1
- package/node_modules/@noodle-borg/service/dist/routes/analytics.js +1 -1
- package/node_modules/@noodle-borg/service/dist/routes/assistant-agent.js +73 -59
- package/node_modules/@noodle-borg/service/dist/routes/assistant-doctor.js +1 -1
- package/node_modules/@noodle-borg/service/dist/routes/assistant-model-binding.js +28 -0
- package/node_modules/@noodle-borg/service/dist/routes/assistant-public-session.js +18 -0
- package/node_modules/@noodle-borg/service/dist/routes/assistant-public-turn.js +6 -0
- package/node_modules/@noodle-borg/service/dist/routes/assistant-usage.js +42 -0
- package/node_modules/@noodle-borg/service/dist/routes/assistant.js +20 -3
- package/node_modules/@noodle-borg/service/dist/routes/auth-doctor-live.js +1 -2
- package/node_modules/@noodle-borg/service/dist/routes/control-plane.js +49 -4
- package/node_modules/@noodle-borg/service/dist/routes/deploy-preflight.js +11 -1
- package/node_modules/@noodle-borg/service/dist/routes/endpoint-enrichment.js +2 -1
- package/node_modules/@noodle-borg/service/dist/routes/paths.js +4 -0
- package/node_modules/@noodle-borg/service/dist/routes/rollback.js +1 -1
- package/node_modules/@noodle-borg/service/dist/service.js +6 -0
- package/node_modules/@noodle-borg/service/dist/store/in-memory.d.ts +2 -5
- package/node_modules/@noodle-borg/service/dist/store/in-memory.js +9 -21
- package/node_modules/@noodle-borg/service/dist/store/json-file.d.ts +2 -5
- package/node_modules/@noodle-borg/service/dist/store/json-file.js +8 -20
- package/node_modules/@noodle-borg/service/dist/store/records.js +39 -0
- package/node_modules/@noodle-borg/service/dist/store.d.ts +21 -10
- package/node_modules/@noodle-borg/service/package.json +5 -1
- package/node_modules/@noodle-borg/wire-contracts/dist/control-plane.d.ts +120 -0
- package/node_modules/@noodle-borg/wire-contracts/dist/control-plane.js +123 -1
- package/node_modules/@noodle-borg/wire-contracts/dist/index.d.ts +4 -0
- package/node_modules/@noodle-borg/wire-contracts/dist/index.js +15 -1
- package/node_modules/@noodleseed/assistant/package.json +1 -1
- package/package.json +2 -2
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { readModelCompletion } from './model-stream.js';
|
|
2
|
+
export async function requestModelCompletion(input) {
|
|
3
|
+
const { binding } = input;
|
|
4
|
+
const url = new URL(`${binding.baseUrl.replace(/\/$/, '')}/chat/completions`);
|
|
5
|
+
if (url.protocol !== 'https:' || url.username || url.password) {
|
|
6
|
+
throw new Error('unsafe model endpoint');
|
|
7
|
+
}
|
|
8
|
+
const completionLimit = input.maxCompletionTokens ?? binding.requestPolicy?.maxCompletionTokens;
|
|
9
|
+
const body = JSON.stringify({
|
|
10
|
+
...binding.requestPolicy?.extraBody,
|
|
11
|
+
model: binding.model,
|
|
12
|
+
stream: true,
|
|
13
|
+
messages: input.messages,
|
|
14
|
+
tools: input.tools,
|
|
15
|
+
...(completionLimit === undefined ? {} : { max_completion_tokens: completionLimit }),
|
|
16
|
+
});
|
|
17
|
+
const requestBytes = new TextEncoder().encode(body).byteLength;
|
|
18
|
+
const maxRequestBytes = binding.requestPolicy?.maxRequestBytes;
|
|
19
|
+
if (maxRequestBytes !== undefined && requestBytes > maxRequestBytes) {
|
|
20
|
+
throw new Error('model request too large');
|
|
21
|
+
}
|
|
22
|
+
const bearerToken = binding.apiKey ?? (await binding.bearerToken());
|
|
23
|
+
if (!/^[^\s]{1,8192}$/.test(bearerToken))
|
|
24
|
+
throw new Error('invalid model bearer token');
|
|
25
|
+
const timeoutSignal = AbortSignal.timeout(binding.requestPolicy?.timeoutMs ?? 30_000);
|
|
26
|
+
const response = await input.fetcher(url.href, {
|
|
27
|
+
method: 'POST',
|
|
28
|
+
headers: { Authorization: `Bearer ${bearerToken}`, 'content-type': 'application/json' },
|
|
29
|
+
body,
|
|
30
|
+
redirect: 'manual',
|
|
31
|
+
signal: input.signal === undefined ? timeoutSignal : AbortSignal.any([input.signal, timeoutSignal]),
|
|
32
|
+
});
|
|
33
|
+
if (!response.ok)
|
|
34
|
+
throw new Error(`model request failed (${response.status})`);
|
|
35
|
+
return readModelCompletion(response, input.onContent ?? (() => undefined), input.maxResponseBytes);
|
|
36
|
+
}
|
|
37
|
+
//# sourceMappingURL=model-request.js.map
|
|
@@ -2,7 +2,11 @@ export async function readModelCompletion(response, onContent, maxBytes = 1 << 2
|
|
|
2
2
|
const contentType = response.headers.get('content-type') ?? '';
|
|
3
3
|
if (!contentType.includes('text/event-stream')) {
|
|
4
4
|
const text = await readBoundedText(response, maxBytes);
|
|
5
|
-
const
|
|
5
|
+
const parsed = JSON.parse(text);
|
|
6
|
+
const completion = {
|
|
7
|
+
choices: parsed.choices,
|
|
8
|
+
...normalizeUsage(parsed.usage),
|
|
9
|
+
};
|
|
6
10
|
const message = completion.choices[0]?.message;
|
|
7
11
|
if (!message?.tool_calls?.length && message?.content)
|
|
8
12
|
onContent(message.content);
|
|
@@ -15,6 +19,7 @@ export async function readModelCompletion(response, onContent, maxBytes = 1 << 2
|
|
|
15
19
|
const toolCalls = new Map();
|
|
16
20
|
let pending = '';
|
|
17
21
|
let content = '';
|
|
22
|
+
let usage;
|
|
18
23
|
let bytes = 0;
|
|
19
24
|
while (true) {
|
|
20
25
|
const { done, value } = await reader.read();
|
|
@@ -36,6 +41,7 @@ export async function readModelCompletion(response, onContent, maxBytes = 1 << 2
|
|
|
36
41
|
const parsed = JSON.parse(data);
|
|
37
42
|
if (parsed.error !== undefined)
|
|
38
43
|
throw new Error('model stream returned an error');
|
|
44
|
+
usage = normalizeUsageValue(parsed.usage) ?? usage;
|
|
39
45
|
const delta = parsed.choices?.[0]?.delta;
|
|
40
46
|
if (delta?.content) {
|
|
41
47
|
content += delta.content;
|
|
@@ -80,8 +86,34 @@ export async function readModelCompletion(response, onContent, maxBytes = 1 << 2
|
|
|
80
86
|
},
|
|
81
87
|
},
|
|
82
88
|
],
|
|
89
|
+
...(usage === undefined ? {} : { usage }),
|
|
83
90
|
};
|
|
84
91
|
}
|
|
92
|
+
function normalizeUsage(usage) {
|
|
93
|
+
const normalized = normalizeUsageValue(usage);
|
|
94
|
+
return normalized === undefined ? {} : { usage: normalized };
|
|
95
|
+
}
|
|
96
|
+
function normalizeUsageValue(usage) {
|
|
97
|
+
if (usage === undefined)
|
|
98
|
+
return undefined;
|
|
99
|
+
const promptTokens = nonNegativeInteger(usage.prompt_tokens);
|
|
100
|
+
const completionTokens = nonNegativeInteger(usage.completion_tokens);
|
|
101
|
+
const reportedTotalTokens = nonNegativeInteger(usage.total_tokens);
|
|
102
|
+
if (promptTokens === undefined || completionTokens === undefined) {
|
|
103
|
+
return undefined;
|
|
104
|
+
}
|
|
105
|
+
const totalTokens = reportedTotalTokens ?? promptTokens + completionTokens;
|
|
106
|
+
const reasoningTokens = nonNegativeInteger(usage.completion_tokens_details?.reasoning_tokens);
|
|
107
|
+
return {
|
|
108
|
+
promptTokens,
|
|
109
|
+
completionTokens,
|
|
110
|
+
totalTokens,
|
|
111
|
+
...(reasoningTokens === undefined ? {} : { reasoningTokens }),
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
function nonNegativeInteger(value) {
|
|
115
|
+
return typeof value === 'number' && Number.isSafeInteger(value) && value >= 0 ? value : undefined;
|
|
116
|
+
}
|
|
85
117
|
async function readBoundedText(response, maxBytes) {
|
|
86
118
|
const text = await response.text();
|
|
87
119
|
if (new TextEncoder().encode(text).byteLength > maxBytes) {
|
|
@@ -89,4 +121,4 @@ async function readBoundedText(response, maxBytes) {
|
|
|
89
121
|
}
|
|
90
122
|
return text;
|
|
91
123
|
}
|
|
92
|
-
//# sourceMappingURL=
|
|
124
|
+
//# sourceMappingURL=model-stream.js.map
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { AdmissionEnvelope, DailyCounterStore } from '@noodle-borg/admission-limits/portable';
|
|
2
2
|
import { type PublicEmbedRecord, type PublicEmbedStore } from './embed-store.js';
|
|
3
3
|
import type { PublicSurface } from './public-surface.js';
|
|
4
|
+
import { type SurfaceBudgetBounds } from './surface-budget.js';
|
|
4
5
|
/**
|
|
5
6
|
* Minting an anonymous session for a public page.
|
|
6
7
|
*
|
|
@@ -17,6 +18,8 @@ export interface PublicSessionPorts {
|
|
|
17
18
|
readonly counters: DailyCounterStore;
|
|
18
19
|
/** The live surface for this tenant, read from the *active* deployment at mint time. */
|
|
19
20
|
resolveActiveSurface(embed: PublicEmbedRecord): Promise<PublicSurface | undefined>;
|
|
21
|
+
/** Optional hosted entitlement; absent preserves the ordinary customer-funded envelope. */
|
|
22
|
+
readonly resolveBudgetBounds?: (embed: PublicEmbedRecord) => Promise<SurfaceBudgetBounds | undefined>;
|
|
20
23
|
/** Persist the anonymous session and return its bearer token and expiry. */
|
|
21
24
|
createSession(input: {
|
|
22
25
|
readonly embed: PublicEmbedRecord;
|
|
@@ -30,7 +30,8 @@ export async function mintPublicSession(request, envelope, ports) {
|
|
|
30
30
|
}
|
|
31
31
|
// The surface's own budget, which an operator may have lowered — or set to zero, which is the kill
|
|
32
32
|
// switch. Resolved after the embed is known and before anything is spent.
|
|
33
|
-
const
|
|
33
|
+
const budgetBounds = await ports.resolveBudgetBounds?.(embed);
|
|
34
|
+
const surfaceLimits = surfaceEnvelope(envelope, embed, budgetBounds);
|
|
34
35
|
const now = ports.now();
|
|
35
36
|
// Fairness before solvency: an address at its hourly ceiling is refused without spending any of the
|
|
36
37
|
// surface's day, so one visitor cannot burn the customer's budget on refusals.
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { AdmissionEnvelope, DailyCounterStore } from '@noodle-borg/admission-limits/portable';
|
|
2
2
|
import type { AssistantTurnConsumption } from './assistant-store.js';
|
|
3
|
-
import type { PublicEmbedStore } from './embed-store.js';
|
|
3
|
+
import type { PublicEmbedRecord, PublicEmbedStore } from './embed-store.js';
|
|
4
|
+
import { type SurfaceBudgetBounds } from './surface-budget.js';
|
|
4
5
|
/**
|
|
5
6
|
* Whether an anonymous visitor's next turn runs.
|
|
6
7
|
*
|
|
@@ -16,6 +17,8 @@ export interface PublicTurnPorts {
|
|
|
16
17
|
readonly counters: DailyCounterStore;
|
|
17
18
|
/** Re-read per turn: it carries the operator's live budget, and whether the surface still exists. */
|
|
18
19
|
readonly embeds: Pick<PublicEmbedStore, 'lookup'>;
|
|
20
|
+
/** Optional hosted entitlement; resolved live so cohort removal lowers the envelope immediately. */
|
|
21
|
+
readonly resolveBudgetBounds?: (embed: PublicEmbedRecord) => Promise<SurfaceBudgetBounds | undefined>;
|
|
19
22
|
/** Spend one of this session's turns, atomically (admission tier 1). */
|
|
20
23
|
consumeTurn(id: string, limit: number): Promise<AssistantTurnConsumption>;
|
|
21
24
|
now(): Date;
|
|
@@ -22,7 +22,8 @@ export async function admitPublicTurn(request, defaults, ports) {
|
|
|
22
22
|
message: 'assistant is unavailable right now',
|
|
23
23
|
};
|
|
24
24
|
}
|
|
25
|
-
const
|
|
25
|
+
const budgetBounds = await ports.resolveBudgetBounds?.(embed);
|
|
26
|
+
const envelope = surfaceEnvelope(defaults, embed, budgetBounds);
|
|
26
27
|
// Fairness before either of the budgets below: an address at its hourly ceiling is turned away
|
|
27
28
|
// without spending the session's allowance or the customer's day, so one visitor cannot burn either
|
|
28
29
|
// on turns that were never served. Mirrors the ordering the mint uses.
|
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
import { type AdmissionEnvelope } from '@noodle-borg/admission-limits/portable';
|
|
2
2
|
import type { PublicEmbedRecord } from './embed-store.js';
|
|
3
|
+
/** Hosted/operator entitlement layered between structural maxima and per-surface overrides. */
|
|
4
|
+
export interface SurfaceBudgetBounds {
|
|
5
|
+
readonly defaults: Pick<AdmissionEnvelope, 'turnsPerSession' | 'turnsPerDay' | 'mintsPerDay'>;
|
|
6
|
+
readonly ceiling: Pick<AdmissionEnvelope, 'turnsPerDay' | 'mintsPerDay'>;
|
|
7
|
+
}
|
|
3
8
|
/**
|
|
4
9
|
* One surface's daily budget, resolved from the operator's override and the deployment's defaults.
|
|
5
10
|
*
|
|
@@ -12,5 +17,5 @@ import type { PublicEmbedRecord } from './embed-store.js';
|
|
|
12
17
|
* operator any more than by app code, so an over-eager `--turns-per-day 999999999` degrades to the
|
|
13
18
|
* ceiling instead of becoming the ceiling. Zero survives clamping and is the kill switch.
|
|
14
19
|
*/
|
|
15
|
-
export declare function surfaceEnvelope(base: AdmissionEnvelope, embed: Pick<PublicEmbedRecord, 'turnsPerDay' | 'mintsPerDay'
|
|
20
|
+
export declare function surfaceEnvelope(base: AdmissionEnvelope, embed: Pick<PublicEmbedRecord, 'turnsPerDay' | 'mintsPerDay'>, bounds?: SurfaceBudgetBounds): AdmissionEnvelope;
|
|
16
21
|
//# sourceMappingURL=surface-budget.d.ts.map
|
|
@@ -11,13 +11,19 @@ import { clamp } from '@noodle-borg/admission-limits/portable';
|
|
|
11
11
|
* operator any more than by app code, so an over-eager `--turns-per-day 999999999` degrades to the
|
|
12
12
|
* ceiling instead of becoming the ceiling. Zero survives clamping and is the kill switch.
|
|
13
13
|
*/
|
|
14
|
-
export function surfaceEnvelope(base, embed) {
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
...base,
|
|
14
|
+
export function surfaceEnvelope(base, embed, bounds) {
|
|
15
|
+
const effectiveBase = bounds === undefined ? base : clamp({ ...base, ...bounds.defaults });
|
|
16
|
+
const requested = clamp({
|
|
17
|
+
...effectiveBase,
|
|
19
18
|
...(embed.turnsPerDay !== undefined ? { turnsPerDay: embed.turnsPerDay } : {}),
|
|
20
19
|
...(embed.mintsPerDay !== undefined ? { mintsPerDay: embed.mintsPerDay } : {}),
|
|
21
20
|
});
|
|
21
|
+
if (bounds === undefined)
|
|
22
|
+
return requested;
|
|
23
|
+
return {
|
|
24
|
+
...requested,
|
|
25
|
+
turnsPerDay: Math.min(requested.turnsPerDay, bounds.ceiling.turnsPerDay),
|
|
26
|
+
mintsPerDay: Math.min(requested.mintsPerDay, bounds.ceiling.mintsPerDay),
|
|
27
|
+
};
|
|
22
28
|
}
|
|
23
29
|
//# sourceMappingURL=surface-budget.js.map
|
|
@@ -17,6 +17,10 @@
|
|
|
17
17
|
"types": "./dist/portable.d.ts",
|
|
18
18
|
"import": "./dist/portable.js"
|
|
19
19
|
},
|
|
20
|
+
"./model-runtime": {
|
|
21
|
+
"types": "./dist/model-runtime.d.ts",
|
|
22
|
+
"import": "./dist/model-runtime.js"
|
|
23
|
+
},
|
|
20
24
|
"./postgres": {
|
|
21
25
|
"types": "./dist/postgres.d.ts",
|
|
22
26
|
"import": "./dist/postgres.js"
|
|
@@ -36,7 +40,7 @@
|
|
|
36
40
|
"@noodle-borg/module": "0.0.0",
|
|
37
41
|
"@noodle-borg/protocol": "0.0.0",
|
|
38
42
|
"@noodle-borg/runtime": "0.0.0",
|
|
39
|
-
"@noodleseed/assistant": "1.
|
|
43
|
+
"@noodleseed/assistant": "1.23.0"
|
|
40
44
|
},
|
|
41
45
|
"devDependencies": {
|
|
42
46
|
"@types/node": "^24.13.1",
|
|
@@ -59,6 +59,7 @@ export interface AssistantLabels {
|
|
|
59
59
|
readonly copy?: string;
|
|
60
60
|
readonly newMessages?: string;
|
|
61
61
|
readonly reconnect?: string;
|
|
62
|
+
readonly newConversation?: string;
|
|
62
63
|
readonly retry?: string;
|
|
63
64
|
readonly unavailable?: string;
|
|
64
65
|
readonly sessionExpired?: string;
|
|
@@ -108,6 +109,11 @@ export interface OpenAICompatibleModel {
|
|
|
108
109
|
/** Managed secret name, never the secret value. */
|
|
109
110
|
readonly apiKey: string;
|
|
110
111
|
}
|
|
112
|
+
/** Provider-neutral request for the model selected and operated by Noodle Seed Cloud. */
|
|
113
|
+
export interface NoodleManagedModel {
|
|
114
|
+
readonly kind: 'noodle-managed';
|
|
115
|
+
}
|
|
116
|
+
export type AssistantModel = OpenAICompatibleModel | NoodleManagedModel;
|
|
111
117
|
/**
|
|
112
118
|
* A verified session claim the embedding backend may pass at session exchange. Keys become
|
|
113
119
|
* `${user.claims.<key>}` in tool fulfilment; `exposeToModel: true` additionally places the value
|
|
@@ -184,7 +190,7 @@ export interface PublicWebsiteInput {
|
|
|
184
190
|
export declare function authenticatedWebsite(input: AuthenticatedWebsiteInput): AuthenticatedWebsiteAccess;
|
|
185
191
|
export declare function publicWebsite(input: PublicWebsiteInput): PublicWebsiteAccess;
|
|
186
192
|
export interface EmbeddedAssistantOptions extends AssistantUiOptions {
|
|
187
|
-
readonly model:
|
|
193
|
+
readonly model: AssistantModel;
|
|
188
194
|
/** One surface, or every front door this assistant serves. */
|
|
189
195
|
readonly access: AssistantAccess | readonly AssistantAccess[];
|
|
190
196
|
}
|
|
@@ -197,7 +203,7 @@ export interface AssistantSurfaceConfig {
|
|
|
197
203
|
readonly sessionClaims?: Readonly<Record<string, SessionClaimDeclaration>>;
|
|
198
204
|
}
|
|
199
205
|
export interface EmbeddedAssistantConfig extends AssistantUiOptions {
|
|
200
|
-
readonly model:
|
|
206
|
+
readonly model: AssistantModel;
|
|
201
207
|
readonly surfaces: readonly AssistantSurfaceConfig[];
|
|
202
208
|
/**
|
|
203
209
|
* Union of every surface's origins. Kept at the top level so the service's origin check and the
|
|
@@ -208,5 +214,7 @@ export interface EmbeddedAssistantConfig extends AssistantUiOptions {
|
|
|
208
214
|
readonly sessionClaims?: Readonly<Record<string, SessionClaimDeclaration>>;
|
|
209
215
|
}
|
|
210
216
|
export declare function openAICompatible(input: OpenAICompatibleModelInput): OpenAICompatibleModel;
|
|
217
|
+
/** Use Noodle Seed Cloud's operator-selected model. Provider details never enter authored source. */
|
|
218
|
+
export declare function noodleManaged(): NoodleManagedModel;
|
|
211
219
|
export declare function embeddedAssistant(input: EmbeddedAssistantOptions): EmbeddedAssistantConfig;
|
|
212
220
|
//# sourceMappingURL=assistant.d.ts.map
|
|
@@ -33,6 +33,10 @@ export function openAICompatible(input) {
|
|
|
33
33
|
apiKey: serializeSecretRef(input.apiKey, 'assistant.model.apiKey'),
|
|
34
34
|
};
|
|
35
35
|
}
|
|
36
|
+
/** Use Noodle Seed Cloud's operator-selected model. Provider details never enter authored source. */
|
|
37
|
+
export function noodleManaged() {
|
|
38
|
+
return { kind: 'noodle-managed' };
|
|
39
|
+
}
|
|
36
40
|
export function embeddedAssistant(input) {
|
|
37
41
|
const { model, access, suggestedPrompts, ...ui } = input;
|
|
38
42
|
assertAccessDeclared(input, access);
|
|
@@ -2,7 +2,7 @@ import type { ConnectorFile, HttpConnectorDef } from '@noodle-borg/connector-def
|
|
|
2
2
|
import { z } from 'zod';
|
|
3
3
|
export type { PackagedAssetReference } from '@noodle-borg/compiler';
|
|
4
4
|
export type { AgentCapabilityKind, AgentCapabilityRef, AgentExampleSource, AgentGuideSource, AgentWorkflowSource, AgentWorkflowStepSource, } from './agent-guide.js';
|
|
5
|
-
export { type AssistantAccess, type AssistantCapability, type AssistantLabels, type AssistantLayoutMode, type AssistantPosition, type AssistantPresentationOptions, type AssistantPresentationTone, type AssistantSurfaceConfig, type AssistantSurfaceMode, type AssistantThemeMode, type AssistantUiOptions, type AuthenticatedWebsiteAccess, type AuthenticatedWebsiteInput, authenticatedWebsite, type CapabilityRef, type EmbeddedAssistantConfig, type EmbeddedAssistantOptions, embeddedAssistant, type OpenAICompatibleModel, type OpenAICompatibleModelInput, openAICompatible, type PublicWebsiteAccess, type PublicWebsiteInput, publicWebsite, } from './assistant.js';
|
|
5
|
+
export { type AssistantAccess, type AssistantCapability, type AssistantLabels, type AssistantLayoutMode, type AssistantModel, type AssistantPosition, type AssistantPresentationOptions, type AssistantPresentationTone, type AssistantSurfaceConfig, type AssistantSurfaceMode, type AssistantThemeMode, type AssistantUiOptions, type AuthenticatedWebsiteAccess, type AuthenticatedWebsiteInput, authenticatedWebsite, type CapabilityRef, type EmbeddedAssistantConfig, type EmbeddedAssistantOptions, embeddedAssistant, type NoodleManagedModel, noodleManaged, type OpenAICompatibleModel, type OpenAICompatibleModelInput, openAICompatible, type PublicWebsiteAccess, type PublicWebsiteInput, publicWebsite, } from './assistant.js';
|
|
6
6
|
export { type ConfigRef, type ConfigRefKind, secret, variable, } from './config.js';
|
|
7
7
|
export { type BoundConnectorRef, bind, type ConnectionBinding, type ConnectionRef, type ConnectionSource, clientCredentials, connection, externalExchange, type GoogleWorkloadIdentityAccess, googleWorkloadIdentity, managedSecret, } from './connections.js';
|
|
8
8
|
export { type ComputeHost, type ComputeLimits, type ComputeOperationOptions, ConnectorBuilder, type ConnectorCatalogDoc, type ConnectorOpDefinition, type ConnectorOperationOptions, type ConnectorRef, connector, type HttpConnectorOptions, } from './connectors.js';
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
|
-
export { authenticatedWebsite, embeddedAssistant, openAICompatible, publicWebsite, } from './assistant.js';
|
|
2
|
+
export { authenticatedWebsite, embeddedAssistant, noodleManaged, openAICompatible, publicWebsite, } from './assistant.js';
|
|
3
3
|
export { secret, variable, } from './config.js';
|
|
4
4
|
export { bind, clientCredentials, connection, externalExchange, googleWorkloadIdentity, managedSecret, } from './connections.js';
|
|
5
5
|
export { ConnectorBuilder, connector, } from './connectors.js';
|
|
@@ -33,7 +33,7 @@ export function prepareAuthoringRuntimeDir(dir, options) {
|
|
|
33
33
|
'./react': './react.mjs',
|
|
34
34
|
},
|
|
35
35
|
}));
|
|
36
|
-
writeFileSync(join(self, 'index.mjs'), "export { annotations, asset, authenticatedWebsite, bind, clientCredentials, connector, connection, customerAuth, customerEndpoint, embeddedAssistant, externalExchange, file, gmailConnector, googleWorkloadIdentity, handoffSession, knowledge, managedSecret, openAICompatible, prompt, publicWebsite, resource, secret, server, site, tool, variable, when, z } from '@noodle-borg/authoring';\n");
|
|
36
|
+
writeFileSync(join(self, 'index.mjs'), "export { annotations, asset, authenticatedWebsite, bind, clientCredentials, connector, connection, customerAuth, customerEndpoint, embeddedAssistant, externalExchange, file, gmailConnector, googleWorkloadIdentity, handoffSession, knowledge, managedSecret, noodleManaged, openAICompatible, prompt, publicWebsite, resource, secret, server, site, tool, variable, when, z } from '@noodle-borg/authoring';\n");
|
|
37
37
|
writeFileSync(join(self, 'platform.mjs'), "export { noodlePlatform, noodlePlatformCatalog } from '@noodle-borg/authoring';\n");
|
|
38
38
|
writeFileSync(join(self, 'react.mjs'), "export { generateHelpers } from '@noodle-borg/authoring/react';\n");
|
|
39
39
|
}
|
|
@@ -203,6 +203,23 @@ export const ASSISTANT_COMMAND = {
|
|
|
203
203
|
CLIENTS_SUBCOMMAND,
|
|
204
204
|
EMBEDS_SUBCOMMAND,
|
|
205
205
|
BUDGET_SUBCOMMAND,
|
|
206
|
+
subcommand({
|
|
207
|
+
...SUBCOMMAND_FIELDS,
|
|
208
|
+
name: 'usage',
|
|
209
|
+
summary: 'Show assistant sessions, conversation depth, engagement, latency, and model tokens.',
|
|
210
|
+
flags: [
|
|
211
|
+
flag({
|
|
212
|
+
...FLAG_FIELDS,
|
|
213
|
+
name: 'window',
|
|
214
|
+
type: 'string',
|
|
215
|
+
value: '<window>',
|
|
216
|
+
summary: 'Aggregation window.',
|
|
217
|
+
constraints: { choices: ['24h', '7d', '30d'], default: '7d' },
|
|
218
|
+
}),
|
|
219
|
+
...TENANT_FLAGS,
|
|
220
|
+
],
|
|
221
|
+
jsonOutput: { mode: 'single' },
|
|
222
|
+
}),
|
|
206
223
|
subcommand({
|
|
207
224
|
...SUBCOMMAND_FIELDS,
|
|
208
225
|
name: 'embed',
|
|
@@ -132,6 +132,13 @@ export const CATALOG_HOSTED_DEPLOYMENT = [
|
|
|
132
132
|
summary: 'Identity access mode for the deployment.',
|
|
133
133
|
constraints: { choices: ACCESS_MODES },
|
|
134
134
|
}),
|
|
135
|
+
flag({
|
|
136
|
+
...FLAG_FIELDS,
|
|
137
|
+
name: 'owner-subject',
|
|
138
|
+
type: 'string',
|
|
139
|
+
value: '<subject>',
|
|
140
|
+
summary: 'Exact OAuth subject bound when access is owner-only.',
|
|
141
|
+
}),
|
|
135
142
|
flag({
|
|
136
143
|
...FLAG_FIELDS,
|
|
137
144
|
name: 'connectors',
|
|
@@ -318,6 +325,13 @@ export const CATALOG_HOSTED_DEPLOYMENT = [
|
|
|
318
325
|
value: '<version>',
|
|
319
326
|
summary: 'Server version whose access mode is changed.',
|
|
320
327
|
}),
|
|
328
|
+
flag({
|
|
329
|
+
...FLAG_FIELDS,
|
|
330
|
+
name: 'owner-subject',
|
|
331
|
+
type: 'string',
|
|
332
|
+
value: '<subject>',
|
|
333
|
+
summary: 'Exact OAuth subject to bind or transfer for owner-only access.',
|
|
334
|
+
}),
|
|
321
335
|
...TENANT_TARGET_FLAGS,
|
|
322
336
|
],
|
|
323
337
|
jsonOutput: { mode: 'single' },
|
|
@@ -227,13 +227,7 @@ export interface ArtifactServer {
|
|
|
227
227
|
/** Compiled knowledge components (ADR 0202, Core v2): descriptors + generated tool metadata, never bytes. */
|
|
228
228
|
readonly knowledge?: readonly CompiledKnowledgeComponent[];
|
|
229
229
|
readonly assistant?: {
|
|
230
|
-
readonly model:
|
|
231
|
-
readonly kind: 'openai-compatible';
|
|
232
|
-
readonly baseUrl: string;
|
|
233
|
-
readonly model: string;
|
|
234
|
-
/** Managed secret name, never the secret value. */
|
|
235
|
-
readonly apiKey: string;
|
|
236
|
-
};
|
|
230
|
+
readonly model: NonNullable<Manifest['server']['assistant']>['model'];
|
|
237
231
|
readonly allowedOrigins: readonly string[];
|
|
238
232
|
} & Omit<NonNullable<Manifest['server']['assistant']>, 'model' | 'allowedOrigins'>;
|
|
239
233
|
readonly branding?: {
|
|
@@ -231,6 +231,7 @@ export declare const manifestV1Schema: z.ZodObject<{
|
|
|
231
231
|
copy: z.ZodOptional<z.ZodString>;
|
|
232
232
|
newMessages: z.ZodOptional<z.ZodString>;
|
|
233
233
|
reconnect: z.ZodOptional<z.ZodString>;
|
|
234
|
+
newConversation: z.ZodOptional<z.ZodString>;
|
|
234
235
|
retry: z.ZodOptional<z.ZodString>;
|
|
235
236
|
unavailable: z.ZodOptional<z.ZodString>;
|
|
236
237
|
sessionExpired: z.ZodOptional<z.ZodString>;
|
|
@@ -325,12 +326,14 @@ export declare const manifestV1Schema: z.ZodObject<{
|
|
|
325
326
|
ltr: "ltr";
|
|
326
327
|
rtl: "rtl";
|
|
327
328
|
}>>;
|
|
328
|
-
model: z.ZodObject<{
|
|
329
|
+
model: z.ZodUnion<readonly [z.ZodObject<{
|
|
329
330
|
kind: z.ZodLiteral<"openai-compatible">;
|
|
330
331
|
baseUrl: z.ZodString;
|
|
331
332
|
model: z.ZodString;
|
|
332
333
|
apiKey: z.ZodString;
|
|
333
|
-
}, z.core.$strict
|
|
334
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
335
|
+
kind: z.ZodLiteral<"noodle-managed">;
|
|
336
|
+
}, z.core.$strict>]>;
|
|
334
337
|
allowedOrigins: z.ZodArray<z.ZodString>;
|
|
335
338
|
surfaces: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
336
339
|
mode: z.ZodEnum<{
|
|
@@ -682,6 +685,7 @@ export declare const manifestV2Schema: z.ZodObject<{
|
|
|
682
685
|
copy: z.ZodOptional<z.ZodString>;
|
|
683
686
|
newMessages: z.ZodOptional<z.ZodString>;
|
|
684
687
|
reconnect: z.ZodOptional<z.ZodString>;
|
|
688
|
+
newConversation: z.ZodOptional<z.ZodString>;
|
|
685
689
|
retry: z.ZodOptional<z.ZodString>;
|
|
686
690
|
unavailable: z.ZodOptional<z.ZodString>;
|
|
687
691
|
sessionExpired: z.ZodOptional<z.ZodString>;
|
|
@@ -776,12 +780,14 @@ export declare const manifestV2Schema: z.ZodObject<{
|
|
|
776
780
|
ltr: "ltr";
|
|
777
781
|
rtl: "rtl";
|
|
778
782
|
}>>;
|
|
779
|
-
model: z.ZodObject<{
|
|
783
|
+
model: z.ZodUnion<readonly [z.ZodObject<{
|
|
780
784
|
kind: z.ZodLiteral<"openai-compatible">;
|
|
781
785
|
baseUrl: z.ZodString;
|
|
782
786
|
model: z.ZodString;
|
|
783
787
|
apiKey: z.ZodString;
|
|
784
|
-
}, z.core.$strict
|
|
788
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
789
|
+
kind: z.ZodLiteral<"noodle-managed">;
|
|
790
|
+
}, z.core.$strict>]>;
|
|
785
791
|
allowedOrigins: z.ZodArray<z.ZodString>;
|
|
786
792
|
surfaces: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
787
793
|
mode: z.ZodEnum<{
|
|
@@ -1343,6 +1349,7 @@ export declare const manifestSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
|
1343
1349
|
copy: z.ZodOptional<z.ZodString>;
|
|
1344
1350
|
newMessages: z.ZodOptional<z.ZodString>;
|
|
1345
1351
|
reconnect: z.ZodOptional<z.ZodString>;
|
|
1352
|
+
newConversation: z.ZodOptional<z.ZodString>;
|
|
1346
1353
|
retry: z.ZodOptional<z.ZodString>;
|
|
1347
1354
|
unavailable: z.ZodOptional<z.ZodString>;
|
|
1348
1355
|
sessionExpired: z.ZodOptional<z.ZodString>;
|
|
@@ -1437,12 +1444,14 @@ export declare const manifestSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
|
1437
1444
|
ltr: "ltr";
|
|
1438
1445
|
rtl: "rtl";
|
|
1439
1446
|
}>>;
|
|
1440
|
-
model: z.ZodObject<{
|
|
1447
|
+
model: z.ZodUnion<readonly [z.ZodObject<{
|
|
1441
1448
|
kind: z.ZodLiteral<"openai-compatible">;
|
|
1442
1449
|
baseUrl: z.ZodString;
|
|
1443
1450
|
model: z.ZodString;
|
|
1444
1451
|
apiKey: z.ZodString;
|
|
1445
|
-
}, z.core.$strict
|
|
1452
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
1453
|
+
kind: z.ZodLiteral<"noodle-managed">;
|
|
1454
|
+
}, z.core.$strict>]>;
|
|
1446
1455
|
allowedOrigins: z.ZodArray<z.ZodString>;
|
|
1447
1456
|
surfaces: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
1448
1457
|
mode: z.ZodEnum<{
|
|
@@ -1793,6 +1802,7 @@ export declare const manifestSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
|
1793
1802
|
copy: z.ZodOptional<z.ZodString>;
|
|
1794
1803
|
newMessages: z.ZodOptional<z.ZodString>;
|
|
1795
1804
|
reconnect: z.ZodOptional<z.ZodString>;
|
|
1805
|
+
newConversation: z.ZodOptional<z.ZodString>;
|
|
1796
1806
|
retry: z.ZodOptional<z.ZodString>;
|
|
1797
1807
|
unavailable: z.ZodOptional<z.ZodString>;
|
|
1798
1808
|
sessionExpired: z.ZodOptional<z.ZodString>;
|
|
@@ -1887,12 +1897,14 @@ export declare const manifestSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
|
1887
1897
|
ltr: "ltr";
|
|
1888
1898
|
rtl: "rtl";
|
|
1889
1899
|
}>>;
|
|
1890
|
-
model: z.ZodObject<{
|
|
1900
|
+
model: z.ZodUnion<readonly [z.ZodObject<{
|
|
1891
1901
|
kind: z.ZodLiteral<"openai-compatible">;
|
|
1892
1902
|
baseUrl: z.ZodString;
|
|
1893
1903
|
model: z.ZodString;
|
|
1894
1904
|
apiKey: z.ZodString;
|
|
1895
|
-
}, z.core.$strict
|
|
1905
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
1906
|
+
kind: z.ZodLiteral<"noodle-managed">;
|
|
1907
|
+
}, z.core.$strict>]>;
|
|
1896
1908
|
allowedOrigins: z.ZodArray<z.ZodString>;
|
|
1897
1909
|
surfaces: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
1898
1910
|
mode: z.ZodEnum<{
|
|
@@ -310,6 +310,7 @@ const assistantUiSchema = z
|
|
|
310
310
|
copy: z.string().trim().min(1).max(80).optional(),
|
|
311
311
|
newMessages: z.string().trim().min(1).max(80).optional(),
|
|
312
312
|
reconnect: z.string().trim().min(1).max(80).optional(),
|
|
313
|
+
newConversation: z.string().trim().min(1).max(80).optional(),
|
|
313
314
|
retry: z.string().trim().min(1).max(80).optional(),
|
|
314
315
|
unavailable: z.string().trim().min(1).max(240).optional(),
|
|
315
316
|
sessionExpired: z.string().trim().min(1).max(240).optional(),
|
|
@@ -343,14 +344,17 @@ const MAX_SERVER_INSTRUCTIONS = 4000;
|
|
|
343
344
|
const sessionClaimsSchema = z.record(z.string().regex(/^[A-Za-z][A-Za-z0-9_]{0,63}$/, 'claim keys are identifier-style'), z.object({ exposeToModel: z.boolean().optional() }).strict());
|
|
344
345
|
const embeddedAssistantSchema = z
|
|
345
346
|
.object({
|
|
346
|
-
model: z
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
347
|
+
model: z.union([
|
|
348
|
+
z
|
|
349
|
+
.object({
|
|
350
|
+
kind: z.literal('openai-compatible'),
|
|
351
|
+
baseUrl: z.string().trim().min(1),
|
|
352
|
+
model: z.string().trim().min(1),
|
|
353
|
+
apiKey: z.string().regex(/^[A-Za-z0-9_]+$/),
|
|
354
|
+
})
|
|
355
|
+
.strict(),
|
|
356
|
+
z.object({ kind: z.literal('noodle-managed') }).strict(),
|
|
357
|
+
]),
|
|
354
358
|
allowedOrigins: z.array(assistantOriginOrVariableSchema).min(1),
|
|
355
359
|
// The front doors this assistant serves (ADR 0201, amended 2026-08-12). Absent means the pre-0201
|
|
356
360
|
// authenticated shape, so released artifacts keep their meaning; `allowedOrigins` stays the union
|
|
@@ -4,5 +4,7 @@ export { InMemoryControlPlaneStore } from './in-memory-control-plane-store.js';
|
|
|
4
4
|
export { bindInMemoryOrganizationStore, type InMemoryOrganizationOperations, InMemoryOrganizationStore, } from './in-memory-organization-store.js';
|
|
5
5
|
export { InMemoryMcpSubdomainClaimStore, McpSubdomainCooldownError, McpSubdomainIdempotencyConflictError, McpSubdomainOwnerRequiredError, type McpSubdomainRouteRef, McpSubdomainUnavailableError, mcpSubdomainEndpointOptions, type ResolvedMcpTenantRef, resolveMcpSubdomainTenant, } from './mcp-subdomain-claims.js';
|
|
6
6
|
export { domainFromEmail, domainKey, memberKey, normalizeSignupAllowlistValue, personalOrgSlug, personalOrgSlugSuffix, signupKey, } from './organization-helpers.js';
|
|
7
|
+
export { type RollbackControlPlane, type RollbackOperationDependencies, type RollbackOperationInput, type RollbackOperationResult, type RollbackRegistry, rollbackDeploymentOperation, } from './rollback-deployment.js';
|
|
8
|
+
export type { RollbackResult } from './rollback-result.js';
|
|
7
9
|
export { DOMAIN_PATTERN, isSystemOwnedOrgSlug, OPENAI_APPS_CHALLENGE_MAX_LENGTH, SLUG_PATTERN, validateDomain, validateMcpSubdomain, validateOpenAIAppsChallenge, validateOrgMembershipDomain, validateOrgRole, validateSignupAllowlistKind, validateSlug, validateUserOwnedOrgSlug, } from './validation.js';
|
|
8
10
|
//# sourceMappingURL=portable.d.ts.map
|
|
@@ -3,5 +3,6 @@ export { InMemoryControlPlaneStore } from './in-memory-control-plane-store.js';
|
|
|
3
3
|
export { bindInMemoryOrganizationStore, InMemoryOrganizationStore, } from './in-memory-organization-store.js';
|
|
4
4
|
export { InMemoryMcpSubdomainClaimStore, McpSubdomainCooldownError, McpSubdomainIdempotencyConflictError, McpSubdomainOwnerRequiredError, McpSubdomainUnavailableError, mcpSubdomainEndpointOptions, resolveMcpSubdomainTenant, } from './mcp-subdomain-claims.js';
|
|
5
5
|
export { domainFromEmail, domainKey, memberKey, normalizeSignupAllowlistValue, personalOrgSlug, personalOrgSlugSuffix, signupKey, } from './organization-helpers.js';
|
|
6
|
+
export { rollbackDeploymentOperation, } from './rollback-deployment.js';
|
|
6
7
|
export { DOMAIN_PATTERN, isSystemOwnedOrgSlug, OPENAI_APPS_CHALLENGE_MAX_LENGTH, SLUG_PATTERN, validateDomain, validateMcpSubdomain, validateOpenAIAppsChallenge, validateOrgMembershipDomain, validateOrgRole, validateSignupAllowlistKind, validateSlug, validateUserOwnedOrgSlug, } from './validation.js';
|
|
7
8
|
//# sourceMappingURL=portable.js.map
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { type AuditSink, type DeploymentOperationTarget, type EndpointUrlOptions } from '@noodle-borg/module';
|
|
2
|
+
import type { RollbackResult } from './rollback-result.js';
|
|
3
|
+
export interface RollbackRegistry {
|
|
4
|
+
getAppArchivedAt(org: string, app: string): Promise<string | undefined>;
|
|
5
|
+
rollback(target: DeploymentOperationTarget, deploymentId: string): Promise<RollbackResult>;
|
|
6
|
+
}
|
|
7
|
+
export interface RollbackControlPlane {
|
|
8
|
+
getOrgMember(input: {
|
|
9
|
+
readonly org: string;
|
|
10
|
+
readonly subject: string;
|
|
11
|
+
}): Promise<{
|
|
12
|
+
readonly role: string;
|
|
13
|
+
} | undefined>;
|
|
14
|
+
}
|
|
15
|
+
export interface RollbackOperationDependencies {
|
|
16
|
+
readonly registry: RollbackRegistry;
|
|
17
|
+
readonly controlPlane: RollbackControlPlane;
|
|
18
|
+
readonly audit: AuditSink;
|
|
19
|
+
}
|
|
20
|
+
export interface RollbackOperationInput {
|
|
21
|
+
readonly actor: {
|
|
22
|
+
readonly subject: string;
|
|
23
|
+
readonly email?: string;
|
|
24
|
+
readonly superAdmin: boolean;
|
|
25
|
+
};
|
|
26
|
+
readonly target: DeploymentOperationTarget;
|
|
27
|
+
readonly deploymentId: string;
|
|
28
|
+
readonly reason?: string;
|
|
29
|
+
readonly publicBaseUrl: string;
|
|
30
|
+
readonly endpointOptions?: EndpointUrlOptions;
|
|
31
|
+
}
|
|
32
|
+
export type RollbackOperationResult = {
|
|
33
|
+
readonly ok: true;
|
|
34
|
+
readonly view: {
|
|
35
|
+
readonly target: DeploymentOperationTarget;
|
|
36
|
+
readonly rollback: {
|
|
37
|
+
readonly deploymentId: string;
|
|
38
|
+
readonly serverVersion?: string;
|
|
39
|
+
readonly previousDeploymentId?: string;
|
|
40
|
+
readonly alreadyActive: boolean;
|
|
41
|
+
readonly endpointUrl: string;
|
|
42
|
+
readonly accessMode: string;
|
|
43
|
+
readonly ownerSubject?: string;
|
|
44
|
+
readonly previousAccessMode?: string;
|
|
45
|
+
readonly serverName: string;
|
|
46
|
+
readonly createdAt: string;
|
|
47
|
+
};
|
|
48
|
+
};
|
|
49
|
+
} | {
|
|
50
|
+
readonly ok: false;
|
|
51
|
+
readonly status: 403 | 404 | 409 | 503;
|
|
52
|
+
readonly code: 'forbidden' | 'app_archived' | 'deployment_not_found' | 'deployment_incompatible' | 'deployment_locked' | 'production_app_limit_exceeded' | 'billing_enforcement_unavailable';
|
|
53
|
+
readonly message: string;
|
|
54
|
+
};
|
|
55
|
+
/**
|
|
56
|
+
* Activate a previous deployment through the service's canonical governance boundary.
|
|
57
|
+
* HTTP routes, agent tools, and MCP App widgets must all call this operation rather than
|
|
58
|
+
* duplicating owner checks, commercial admission, endpoint construction, or audit behavior.
|
|
59
|
+
*/
|
|
60
|
+
export declare function rollbackDeploymentOperation(dependencies: RollbackOperationDependencies, input: RollbackOperationInput): Promise<RollbackOperationResult>;
|
|
61
|
+
//# sourceMappingURL=rollback-deployment.d.ts.map
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import { DeploymentActivationError } from '@noodle-borg/module';
|
|
2
|
-
import { tenantMcpUrl } from '../registry-helpers.js';
|
|
1
|
+
import { DeploymentActivationError, tenantMcpUrl, } from '@noodle-borg/module';
|
|
3
2
|
/**
|
|
4
3
|
* Activate a previous deployment through the service's canonical governance boundary.
|
|
5
4
|
* HTTP routes, agent tools, and MCP App widgets must all call this operation rather than
|
|
@@ -81,6 +80,7 @@ export async function rollbackDeploymentOperation(dependencies, input) {
|
|
|
81
80
|
: {}),
|
|
82
81
|
alreadyActive: result.alreadyActive,
|
|
83
82
|
accessMode: result.accessMode,
|
|
83
|
+
...(result.ownerSubject !== undefined ? { ownerSubject: result.ownerSubject } : {}),
|
|
84
84
|
...(result.previousAccessMode !== undefined
|
|
85
85
|
? { previousAccessMode: result.previousAccessMode }
|
|
86
86
|
: {}),
|
|
@@ -101,6 +101,7 @@ export async function rollbackDeploymentOperation(dependencies, input) {
|
|
|
101
101
|
alreadyActive: result.alreadyActive,
|
|
102
102
|
endpointUrl,
|
|
103
103
|
accessMode: result.accessMode,
|
|
104
|
+
...(result.ownerSubject !== undefined ? { ownerSubject: result.ownerSubject } : {}),
|
|
104
105
|
...(result.previousAccessMode !== undefined
|
|
105
106
|
? { previousAccessMode: result.previousAccessMode }
|
|
106
107
|
: {}),
|