@noodleseed/one 0.168.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.
Files changed (142) hide show
  1. package/dist/cli.d.ts.map +1 -1
  2. package/dist/cli.js +3 -0
  3. package/dist/cli.js.map +1 -1
  4. package/dist/commands/capabilities.d.ts +19 -0
  5. package/dist/commands/capabilities.d.ts.map +1 -0
  6. package/dist/commands/capabilities.js +128 -0
  7. package/dist/commands/capabilities.js.map +1 -0
  8. package/dist/commands/deployment-delete-ops.d.ts +12 -0
  9. package/dist/commands/deployment-delete-ops.d.ts.map +1 -0
  10. package/dist/commands/deployment-delete-ops.js +230 -0
  11. package/dist/commands/deployment-delete-ops.js.map +1 -0
  12. package/dist/commands/deployment-delete-recovery.d.ts +35 -0
  13. package/dist/commands/deployment-delete-recovery.d.ts.map +1 -0
  14. package/dist/commands/deployment-delete-recovery.js +99 -0
  15. package/dist/commands/deployment-delete-recovery.js.map +1 -0
  16. package/dist/commands/deployments-ops.d.ts +2 -1
  17. package/dist/commands/deployments-ops.d.ts.map +1 -1
  18. package/dist/commands/deployments-ops.js +5 -1
  19. package/dist/commands/deployments-ops.js.map +1 -1
  20. package/dist/index.d.ts +1 -1
  21. package/dist/index.d.ts.map +1 -1
  22. package/dist/index.js +1 -1
  23. package/dist/index.js.map +1 -1
  24. package/dist/plugin-mode/plugin-operation-contract.d.ts +2 -2
  25. package/node_modules/@noodle-borg/agent-kit/dist/curated/command-groups.js +4 -0
  26. package/node_modules/@noodle-borg/agent-kit/dist/generated/example-files.js +1 -1
  27. package/node_modules/@noodle-borg/agent-kit/dist/generated/surface.js +2 -0
  28. package/node_modules/@noodle-borg/agent-kit/dist/skill-authoring-refs.js +3 -2
  29. package/node_modules/@noodle-borg/agent-kit/package.json +1 -1
  30. package/node_modules/@noodle-borg/assistant-gateway/dist/assistant-interactive.d.ts +1 -0
  31. package/node_modules/@noodle-borg/assistant-gateway/dist/assistant-interactive.js +4 -1
  32. package/node_modules/@noodle-borg/authoring/dist/assistant.d.ts +2 -2
  33. package/node_modules/@noodle-borg/authoring/dist/assistant.js +3 -1
  34. package/node_modules/@noodle-borg/authoring/dist/index.d.ts +1 -0
  35. package/node_modules/@noodle-borg/authoring/dist/index.js +1 -0
  36. package/node_modules/@noodle-borg/authoring/dist/load-authored.js +1 -1
  37. package/node_modules/@noodle-borg/authoring/dist/recording.d.ts +2 -1
  38. package/node_modules/@noodle-borg/authoring/dist/recording.js +29 -1
  39. package/node_modules/@noodle-borg/authoring/dist/server.d.ts +3 -0
  40. package/node_modules/@noodle-borg/authoring/dist/server.js +5 -1
  41. package/node_modules/@noodle-borg/authoring/dist/web-capabilities.d.ts +17 -0
  42. package/node_modules/@noodle-borg/authoring/dist/web-capabilities.js +15 -0
  43. package/node_modules/@noodle-borg/authoring/package.json +1 -0
  44. package/node_modules/@noodle-borg/capabilities/dist/index.js +7 -0
  45. package/node_modules/@noodle-borg/cli-catalog/dist/catalog-data-hosted-observability.js +102 -0
  46. package/node_modules/@noodle-borg/cli-catalog/dist/catalog-data-tenant-resources.js +27 -1
  47. package/node_modules/@noodle-borg/compiler/dist/artifact/assemble.js +3 -0
  48. package/node_modules/@noodle-borg/compiler/dist/artifact/types.d.ts +2 -0
  49. package/node_modules/@noodle-borg/compiler/dist/artifact/version.d.ts +2 -1
  50. package/node_modules/@noodle-borg/compiler/dist/artifact/version.js +2 -1
  51. package/node_modules/@noodle-borg/compiler/dist/compile.js +2 -0
  52. package/node_modules/@noodle-borg/compiler/dist/fulfilment-emit.js +18 -3
  53. package/node_modules/@noodle-borg/compiler/dist/manifest/schema.d.ts +34 -0
  54. package/node_modules/@noodle-borg/compiler/dist/manifest/schema.js +9 -2
  55. package/node_modules/@noodle-borg/compiler/dist/web-capabilities.js +55 -0
  56. package/node_modules/@noodle-borg/compiler/package.json +1 -0
  57. package/node_modules/@noodle-borg/connector-http/dist/ssrf.js +5 -0
  58. package/node_modules/@noodle-borg/control-plane/dist/delete-deployment.d.ts +44 -0
  59. package/node_modules/@noodle-borg/control-plane/dist/delete-deployment.js +105 -0
  60. package/node_modules/@noodle-borg/control-plane/dist/deployment-deletion-contracts.d.ts +20 -0
  61. package/node_modules/@noodle-borg/control-plane/dist/portable.d.ts +2 -0
  62. package/node_modules/@noodle-borg/control-plane/dist/portable.js +1 -0
  63. package/node_modules/@noodle-borg/knowledge-crawl/dist/bounded-body.js +38 -0
  64. package/node_modules/@noodle-borg/knowledge-crawl/dist/first-party.js +2 -3
  65. package/node_modules/@noodle-borg/knowledge-crawl/dist/html-text.js +10 -2
  66. package/node_modules/@noodle-borg/knowledge-crawl/dist/index.d.ts +1 -0
  67. package/node_modules/@noodle-borg/knowledge-crawl/dist/index.js +1 -0
  68. package/node_modules/@noodle-borg/knowledge-crawl/dist/page-reader.d.ts +26 -0
  69. package/node_modules/@noodle-borg/knowledge-crawl/dist/page-reader.js +127 -0
  70. package/node_modules/@noodle-borg/knowledge-crawl/dist/robots.js +48 -23
  71. package/node_modules/@noodle-borg/knowledge-crawl/package.json +1 -0
  72. package/node_modules/@noodle-borg/managed-capabilities/dist/budget.d.ts +29 -0
  73. package/node_modules/@noodle-borg/managed-capabilities/dist/budget.js +124 -0
  74. package/node_modules/@noodle-borg/managed-capabilities/dist/contracts.d.ts +212 -0
  75. package/node_modules/@noodle-borg/managed-capabilities/dist/contracts.js +113 -0
  76. package/node_modules/@noodle-borg/managed-capabilities/dist/errors.d.ts +8 -0
  77. package/node_modules/@noodle-borg/managed-capabilities/dist/errors.js +21 -0
  78. package/node_modules/@noodle-borg/managed-capabilities/dist/executor.d.ts +26 -0
  79. package/node_modules/@noodle-borg/managed-capabilities/dist/executor.js +156 -0
  80. package/node_modules/@noodle-borg/managed-capabilities/dist/limits.d.ts +15 -0
  81. package/node_modules/@noodle-borg/managed-capabilities/dist/limits.js +15 -0
  82. package/node_modules/@noodle-borg/managed-capabilities/dist/operator-contracts.d.ts +159 -0
  83. package/node_modules/@noodle-borg/managed-capabilities/dist/operator-contracts.js +69 -0
  84. package/node_modules/@noodle-borg/managed-capabilities/dist/operator-route.d.ts +5 -0
  85. package/node_modules/@noodle-borg/managed-capabilities/dist/operator-route.js +160 -0
  86. package/node_modules/@noodle-borg/managed-capabilities/dist/policy-store.d.ts +34 -0
  87. package/node_modules/@noodle-borg/managed-capabilities/dist/policy-store.js +61 -0
  88. package/node_modules/@noodle-borg/managed-capabilities/dist/portable.d.ts +10 -0
  89. package/node_modules/@noodle-borg/managed-capabilities/dist/portable.js +10 -0
  90. package/node_modules/@noodle-borg/managed-capabilities/dist/service.d.ts +83 -0
  91. package/node_modules/@noodle-borg/managed-capabilities/dist/service.js +139 -0
  92. package/node_modules/@noodle-borg/managed-capabilities/dist/urls.d.ts +3 -0
  93. package/node_modules/@noodle-borg/managed-capabilities/dist/urls.js +30 -0
  94. package/node_modules/@noodle-borg/managed-capabilities/package.json +49 -0
  95. package/node_modules/@noodle-borg/module/dist/contract.d.ts +11 -0
  96. package/node_modules/@noodle-borg/runtime/dist/confirmation.js +29 -0
  97. package/node_modules/@noodle-borg/runtime/dist/connector/types.d.ts +2 -0
  98. package/node_modules/@noodle-borg/runtime/dist/execute.d.ts +3 -0
  99. package/node_modules/@noodle-borg/runtime/dist/execute.js +6 -1
  100. package/node_modules/@noodle-borg/runtime/dist/index.d.ts +2 -1
  101. package/node_modules/@noodle-borg/runtime/dist/index.js +2 -1
  102. package/node_modules/@noodle-borg/runtime/dist/interactive.js +10 -1
  103. package/node_modules/@noodle-borg/runtime/dist/operation-execution.js +3 -0
  104. package/node_modules/@noodle-borg/runtime/dist/result-meta.d.ts +2 -0
  105. package/node_modules/@noodle-borg/runtime/dist/result-meta.js +6 -0
  106. package/node_modules/@noodle-borg/runtime/dist/result.d.ts +4 -0
  107. package/node_modules/@noodle-borg/runtime/dist/web-capabilities.d.ts +71 -0
  108. package/node_modules/@noodle-borg/runtime/dist/web-capabilities.js +41 -0
  109. package/node_modules/@noodle-borg/runtime/package.json +1 -0
  110. package/node_modules/@noodle-borg/service/dist/deployment-deletion.js +40 -0
  111. package/node_modules/@noodle-borg/service/dist/local-options.d.ts +1 -0
  112. package/node_modules/@noodle-borg/service/dist/local-web-capabilities.js +13 -0
  113. package/node_modules/@noodle-borg/service/dist/mcp-protocol-runtime.js +21 -0
  114. package/node_modules/@noodle-borg/service/dist/modules/route-dispatch.js +13 -0
  115. package/node_modules/@noodle-borg/service/dist/registry-compile.js +9 -0
  116. package/node_modules/@noodle-borg/service/dist/registry-deletion.js +75 -0
  117. package/node_modules/@noodle-borg/service/dist/registry-state.js +4 -2
  118. package/node_modules/@noodle-borg/service/dist/registry-targets.js +4 -0
  119. package/node_modules/@noodle-borg/service/dist/registry-types.d.ts +1 -0
  120. package/node_modules/@noodle-borg/service/dist/registry.d.ts +2 -0
  121. package/node_modules/@noodle-borg/service/dist/registry.js +10 -23
  122. package/node_modules/@noodle-borg/service/dist/routes/assistant-agent.js +5 -2
  123. package/node_modules/@noodle-borg/service/dist/routes/assistant-interactions.js +7 -4
  124. package/node_modules/@noodle-borg/service/dist/routes/deploy-dispatch.js +15 -1
  125. package/node_modules/@noodle-borg/service/dist/routes/deployment-delete.js +53 -0
  126. package/node_modules/@noodle-borg/service/dist/serve-local.js +14 -0
  127. package/node_modules/@noodle-borg/service/dist/serve-resource-auth.js +10 -0
  128. package/node_modules/@noodle-borg/service/dist/service.js +7 -1
  129. package/node_modules/@noodle-borg/service/dist/store/in-memory.d.ts +2 -1
  130. package/node_modules/@noodle-borg/service/dist/store/in-memory.js +8 -0
  131. package/node_modules/@noodle-borg/service/dist/store/json-file-deletion.js +64 -0
  132. package/node_modules/@noodle-borg/service/dist/store/json-file.d.ts +2 -1
  133. package/node_modules/@noodle-borg/service/dist/store/json-file.js +23 -5
  134. package/node_modules/@noodle-borg/service/dist/store.d.ts +5 -1
  135. package/node_modules/@noodle-borg/service/dist/web-capabilities.js +39 -0
  136. package/node_modules/@noodle-borg/service/package.json +3 -1
  137. package/node_modules/@noodle-borg/wire-contracts/dist/deployment-deletion.d.ts +29 -0
  138. package/node_modules/@noodle-borg/wire-contracts/dist/deployment-deletion.js +33 -0
  139. package/node_modules/@noodle-borg/wire-contracts/dist/index.d.ts +2 -0
  140. package/node_modules/@noodle-borg/wire-contracts/dist/index.js +2 -0
  141. package/node_modules/@noodle-borg/wire-contracts/package.json +1 -0
  142. package/package.json +3 -2
@@ -17,7 +17,7 @@ export function when(condition, record) {
17
17
  activeRecording.pendingCondition = previous;
18
18
  }
19
19
  }
20
- export async function recordTool(fulfil, connectors) {
20
+ export async function recordTool(fulfil, connectors, capabilities = []) {
21
21
  const ctx = newRecordingContext();
22
22
  activeRecording = ctx;
23
23
  try {
@@ -26,6 +26,7 @@ export async function recordTool(fulfil, connectors) {
26
26
  user: makeScope('user'),
27
27
  context: makeScope('context'),
28
28
  connectors: makeConnectors(connectors, ctx),
29
+ capabilities: makeCapabilities(capabilities, ctx),
29
30
  elicit: makeElicitor(ctx),
30
31
  });
31
32
  return { steps: ctx.steps, output: serializeMap(result) };
@@ -91,6 +92,33 @@ export async function recordAmbientContext(fulfil, connectors) {
91
92
  function newRecordingContext() {
92
93
  return { steps: [], counts: new Map(), stepIds: new Set() };
93
94
  }
95
+ function makeCapabilities(declarations, ctx) {
96
+ const names = new Set(declarations.map((value) => value.name));
97
+ return new Proxy({}, {
98
+ get(_target, name) {
99
+ if (typeof name !== 'string')
100
+ return undefined;
101
+ if (!names.has(name))
102
+ throw new Error(`unknown capability "${name}"`);
103
+ return new Proxy({}, {
104
+ get(_client, method) {
105
+ if (method !== 'extract')
106
+ throw new Error(`unknown capability method "${String(method)}"`);
107
+ return (request) => {
108
+ const id = nextStepId(ctx, 'extract');
109
+ ctx.steps.push({
110
+ id,
111
+ use: 'noodle_web.extract',
112
+ args: serializeConnectorArgs({ name, request }),
113
+ ...(ctx.pendingCondition ? { if: ctx.pendingCondition } : {}),
114
+ });
115
+ return makeScope(`steps.${id}`);
116
+ };
117
+ },
118
+ });
119
+ },
120
+ });
121
+ }
94
122
  function makeElicitor(ctx) {
95
123
  return ((options) => {
96
124
  if (!isValidName(options.id)) {
@@ -12,6 +12,7 @@ import { type JsonSchema } from './json-schema.js';
12
12
  import { type KnowledgeDeclaration } from './knowledge.js';
13
13
  import * as collections from './managed-collection.js';
14
14
  import { type ConnectorClient, type SymbolicScope } from './recording.js';
15
+ import { type WebExtractDeclaration } from './web-capabilities.js';
15
16
  export type StateHandleKind = 'session' | 'draft' | 'selection' | 'search' | 'cart' | 'workflow';
16
17
  export type StateHandleScope = 'deployment' | 'caller';
17
18
  export interface StateHandleOptions {
@@ -53,6 +54,7 @@ export interface ServerOptions {
53
54
  readonly assistant?: EmbeddedAssistantConfig;
54
55
  /** Customer-owned knowledge components (ADR 0202): compile to generated `search_<name>` capabilities. */
55
56
  readonly knowledge?: readonly KnowledgeDeclaration[];
57
+ readonly capabilities?: readonly WebExtractDeclaration[];
56
58
  /** Typed managed records; operator-owned lifecycle and policy are bound outside reusable source. */
57
59
  readonly collections?: readonly collections.ManagedCollectionDeclaration[];
58
60
  readonly branding?: {
@@ -180,6 +182,7 @@ export interface ToolContext {
180
182
  readonly user: SymbolicScope;
181
183
  readonly context: SymbolicScope;
182
184
  readonly connectors: Record<string, ConnectorClient>;
185
+ readonly capabilities: Record<string, ConnectorClient>;
183
186
  /** Request one bounded, non-sensitive form input and continue with its symbolic response. */
184
187
  readonly elicit: (options: ElicitationOptions) => SymbolicScope;
185
188
  }
@@ -14,6 +14,7 @@ import { manifestKnowledge } from './knowledge.js';
14
14
  import * as collections from './managed-collection.js';
15
15
  import { manifestToolAnnotations } from './model-tool-visibility.js';
16
16
  import { recordFulfilment, recordTool, } from './recording.js';
17
+ import { manifestWebCapability } from './web-capabilities.js';
17
18
  const WIDGET_RESULT_META_KEY = '__noodleResultMeta';
18
19
  export function server(name, options, definitions = []) {
19
20
  const { use = {}, provides = {} } = options;
@@ -127,7 +128,7 @@ class ServerBuilder {
127
128
  : await manifestContext(this.options.context, this.connectors);
128
129
  const tools = [];
129
130
  for (const tool of this.tools) {
130
- const recorded = await recordTool(tool.options.fulfil, this.connectors);
131
+ const recorded = await recordTool(tool.options.fulfil, this.connectors, this.options.capabilities);
131
132
  const { discovery, requiredScopes, allowedRoles, ...authorization } = tool.options.authorization ?? {};
132
133
  tools.push({
133
134
  name: tool.name,
@@ -209,6 +210,9 @@ class ServerBuilder {
209
210
  ...(this.options.knowledge && this.options.knowledge.length > 0
210
211
  ? { knowledge: this.options.knowledge.map(manifestKnowledge) }
211
212
  : {}),
213
+ ...(this.options.capabilities?.length
214
+ ? { capabilities: this.options.capabilities.map(manifestWebCapability) }
215
+ : {}),
212
216
  ...collections.manifestCollections(this.options.collections, this.connectors),
213
217
  ...manifestVariables(this.options.variables),
214
218
  ...(this.options.branding ? { branding: this.options.branding } : {}),
@@ -0,0 +1,17 @@
1
+ import { type WebCapability, type WebPolicy } from '@noodle-borg/managed-capabilities';
2
+ import type { NoodleManagedModel } from './assistant.js';
3
+ import type { ToolAuthorizationOptions } from './server.js';
4
+ export interface WebExtractOptions {
5
+ readonly title: string;
6
+ readonly description: string;
7
+ readonly provider: NoodleManagedModel;
8
+ readonly policy?: WebPolicy;
9
+ readonly authorization?: ToolAuthorizationOptions;
10
+ }
11
+ export type WebExtractDeclaration = WebCapability & {
12
+ readonly kind: 'web-extract';
13
+ };
14
+ /** Read explicit public pages through the platform's governed extraction capability. */
15
+ export declare function webExtract(name: string, options: WebExtractOptions): WebExtractDeclaration;
16
+ export declare function manifestWebCapability(value: WebExtractDeclaration): WebCapability;
17
+ //# sourceMappingURL=web-capabilities.d.ts.map
@@ -0,0 +1,15 @@
1
+ import { webCapabilityBaseSchema, } from '@noodle-borg/managed-capabilities';
2
+ /** Read explicit public pages through the platform's governed extraction capability. */
3
+ export function webExtract(name, options) {
4
+ const { authorization, ...base } = options;
5
+ return {
6
+ kind: 'web-extract',
7
+ ...webCapabilityBaseSchema.parse({ name, class: 'web.extract.v1', ...base }),
8
+ ...(authorization === undefined ? {} : { authorization: structuredClone(authorization) }),
9
+ };
10
+ }
11
+ export function manifestWebCapability(value) {
12
+ const { kind: _kind, ...declaration } = value;
13
+ return structuredClone(declaration);
14
+ }
15
+ //# sourceMappingURL=web-capabilities.js.map
@@ -30,6 +30,7 @@
30
30
  "typecheck": "tsc -p tsconfig.json --noEmit && tsc -p tsconfig.type-tests.json --noEmit"
31
31
  },
32
32
  "dependencies": {
33
+ "@noodle-borg/managed-capabilities": "0.0.0",
33
34
  "typescript": "^6.0.3",
34
35
  "@noodle-borg/compiler": "0.0.0",
35
36
  "@noodle-borg/connector-defs": "0.0.0",
@@ -10,6 +10,13 @@ export const CAPABILITY_NAMES = [
10
10
  ];
11
11
  /** Single public compatibility registry used by CLI output, docs, and release notes. */
12
12
  export const PRODUCT_FEATURES = [
13
+ {
14
+ id: 'bounded-public-page-extraction',
15
+ title: 'Bounded public-page extraction',
16
+ since: 'next',
17
+ description: 'Managed-only learning cohort: explicit public HTTPS pages through ordinary tools, with revisioned operator policy, shared budgets and evidence references. General search and BYO are not included.',
18
+ hosts: { claude: 'preview', chatgpt: 'preview', embedded: 'preview' },
19
+ },
13
20
  {
14
21
  id: 'mcp-core',
15
22
  title: 'MCP tools, resources, and prompts',
@@ -67,6 +67,108 @@ const TENANT_TARGET_FLAGS = [
67
67
  JSON_FLAG,
68
68
  ];
69
69
  export const CATALOG_HOSTED_OBSERVABILITY = [
70
+ {
71
+ name: 'capabilities',
72
+ section: 'operate',
73
+ helpRank: 16,
74
+ summary: 'Inspect, configure and test bounded managed capabilities for an exact app/environment.',
75
+ arguments: [],
76
+ flags: [],
77
+ subcommands: [
78
+ {
79
+ ...SUBCOMMAND_FIELDS,
80
+ name: 'inspect',
81
+ summary: 'List capabilities or inspect one with effective policy.',
82
+ arguments: [
83
+ {
84
+ ...ARGUMENT_FIELDS,
85
+ name: 'name',
86
+ type: 'string',
87
+ summary: 'Capability name.',
88
+ required: false,
89
+ },
90
+ ],
91
+ flags: TENANT_TARGET_FLAGS,
92
+ jsonOutput: { mode: 'single' },
93
+ },
94
+ {
95
+ ...SUBCOMMAND_FIELDS,
96
+ name: 'configure',
97
+ summary: 'Replace policy with a revision and retry-safe mutation ID.',
98
+ arguments: [
99
+ {
100
+ ...ARGUMENT_FIELDS,
101
+ name: 'name',
102
+ type: 'string',
103
+ summary: 'Capability name.',
104
+ required: true,
105
+ },
106
+ ],
107
+ flags: [
108
+ ...TENANT_TARGET_FLAGS,
109
+ {
110
+ ...FLAG_FIELDS,
111
+ name: 'policy-file',
112
+ type: 'string',
113
+ value: '<path>',
114
+ required: true,
115
+ summary: 'Bounded JSON policy file.',
116
+ },
117
+ {
118
+ ...FLAG_FIELDS,
119
+ name: 'expected-revision',
120
+ type: 'string',
121
+ value: '<revision>',
122
+ required: true,
123
+ summary: 'Current policy revision; zero creates it.',
124
+ },
125
+ {
126
+ ...FLAG_FIELDS,
127
+ name: 'mutation-id',
128
+ type: 'string',
129
+ value: '<id>',
130
+ required: true,
131
+ summary: 'Stable ID reused for identical retries.',
132
+ },
133
+ ],
134
+ jsonOutput: { mode: 'single' },
135
+ },
136
+ {
137
+ ...SUBCOMMAND_FIELDS,
138
+ name: 'test',
139
+ summary: 'Run a governed diagnostic without returning page bodies.',
140
+ arguments: [
141
+ {
142
+ ...ARGUMENT_FIELDS,
143
+ name: 'name',
144
+ type: 'string',
145
+ summary: 'Capability name.',
146
+ required: true,
147
+ },
148
+ ],
149
+ flags: [
150
+ ...TENANT_TARGET_FLAGS,
151
+ {
152
+ ...FLAG_FIELDS,
153
+ name: 'request-file',
154
+ type: 'string',
155
+ value: '<path>',
156
+ required: true,
157
+ summary: 'JSON request containing explicit public URLs.',
158
+ },
159
+ {
160
+ ...FLAG_FIELDS,
161
+ name: 'mode',
162
+ type: 'string',
163
+ value: '<fixture|live>',
164
+ required: true,
165
+ summary: 'Fixture performs no website I/O; live fetches the specified pages.',
166
+ },
167
+ ],
168
+ jsonOutput: { mode: 'single' },
169
+ },
170
+ ],
171
+ },
70
172
  {
71
173
  name: 'knowledge',
72
174
  section: 'operate',
@@ -174,7 +174,7 @@ export const CATALOG_TENANT_RESOURCES = [
174
174
  {
175
175
  name: 'deployments',
176
176
  section: 'resources',
177
- summary: 'List, inspect, or read packages for individual deployments.',
177
+ summary: 'List, inspect, read packages, or permanently delete deployment records.',
178
178
  arguments: [],
179
179
  flags: [],
180
180
  subcommands: [
@@ -203,6 +203,32 @@ export const CATALOG_TENANT_RESOURCES = [
203
203
  flags: DEPLOYMENT_INSPECT_FLAGS,
204
204
  jsonOutput: { mode: 'single' },
205
205
  },
206
+ {
207
+ name: 'delete',
208
+ summary: 'Permanently delete one inactive deployment record.',
209
+ arguments: [
210
+ {
211
+ ...REQUIRED_ARGUMENT,
212
+ name: 'deployment-id',
213
+ summary: 'Inactive deployment identifier to delete permanently.',
214
+ },
215
+ ],
216
+ flags: [ORG, SERVICE, AUTH_TOKEN, YES, JSON_FLAG],
217
+ jsonOutput: { mode: 'single' },
218
+ },
219
+ {
220
+ name: 'delete-version',
221
+ summary: 'Permanently delete every deployment record for one exact version.',
222
+ arguments: [
223
+ {
224
+ ...REQUIRED_ARGUMENT,
225
+ name: 'version-or-legacy',
226
+ summary: 'Exact numeric server version, or legacy for unversioned deployments.',
227
+ },
228
+ ],
229
+ flags: [...DEPLOYMENT_BASE_FLAGS, YES, JSON_FLAG],
230
+ jsonOutput: { mode: 'single' },
231
+ },
206
232
  {
207
233
  name: 'lock',
208
234
  summary: 'Freeze an active server version against deploys and rollbacks.',
@@ -40,6 +40,9 @@ export function assembleRuntimeArtifact({ manifest, options, runtimeBranding, ru
40
40
  : {}),
41
41
  ...(manifest.server.auth !== undefined ? { auth: manifest.server.auth } : {}),
42
42
  ...(knowledge !== undefined && knowledge.length > 0 ? { knowledge } : {}),
43
+ ...(manifest.manifestVersion === '2' && manifest.server.capabilities?.length
44
+ ? { capabilities: manifest.server.capabilities }
45
+ : {}),
43
46
  ...(variables !== undefined && variables.length > 0 ? { variables } : {}),
44
47
  ...(managedCollections !== undefined && managedCollections.length > 0
45
48
  ? { managedCollections }
@@ -1,5 +1,6 @@
1
1
  import type { CapabilityRequirementName } from '@noodle-borg/capabilities';
2
2
  import type { CompiledKnowledgeComponent } from '@noodle-borg/knowledge/portable';
3
+ import type { WebCapability } from '@noodle-borg/managed-capabilities';
3
4
  import type { ArtifactVariableDeclaration } from '../business-variables.js';
4
5
  import type { CustomerEndpointPolicy } from '../customer-endpoint.js';
5
6
  import type { ManagedCollectionControls } from '../managed-collection-controls.js';
@@ -251,6 +252,7 @@ export interface ArtifactServer {
251
252
  readonly auth?: ArtifactAuth;
252
253
  /** Compiled knowledge components (ADR 0202, Core v2): descriptors + generated tool metadata, never bytes. */
253
254
  readonly knowledge?: readonly CompiledKnowledgeComponent[];
255
+ readonly capabilities?: readonly WebCapability[];
254
256
  /** Compiled managed-record schema intent; lifecycle and operator state remain outside artifacts. */
255
257
  readonly managedCollections?: readonly ArtifactManagedCollection[];
256
258
  /** Typed reusable managed-variable declarations, never live operator values. */
@@ -63,7 +63,8 @@
63
63
  * including independently validated credential bindings for sandboxed compute dependencies.
64
64
  */
65
65
  /** `0.21.0`: protected tools may opt into public descriptor discovery without execution permission. */
66
- export declare const ARTIFACT_SCHEMA_VERSION = "0.21.0";
66
+ /** `0.22.0`: governed public-page extraction declarations and ordinary generated tools. */
67
+ export declare const ARTIFACT_SCHEMA_VERSION = "0.22.0";
67
68
  /** mimeType for an MCP Apps UI resource (SEP-1865). Widgets are served under this profile. */
68
69
  export declare const MCP_APP_MIME_TYPE = "text/html;profile=mcp-app";
69
70
  //# sourceMappingURL=version.d.ts.map
@@ -63,7 +63,8 @@
63
63
  * including independently validated credential bindings for sandboxed compute dependencies.
64
64
  */
65
65
  /** `0.21.0`: protected tools may opt into public descriptor discovery without execution permission. */
66
- export const ARTIFACT_SCHEMA_VERSION = '0.21.0';
66
+ /** `0.22.0`: governed public-page extraction declarations and ordinary generated tools. */
67
+ export const ARTIFACT_SCHEMA_VERSION = '0.22.0';
67
68
  /** mimeType for an MCP Apps UI resource (SEP-1865). Widgets are served under this profile. */
68
69
  export const MCP_APP_MIME_TYPE = 'text/html;profile=mcp-app';
69
70
  //# sourceMappingURL=version.js.map
@@ -21,6 +21,7 @@ import { resolveSchemaUses } from './manifest/schema-refs.js';
21
21
  import { validateWebsiteProjection } from './manifest/website-projection.js';
22
22
  import { compileState } from './state-handles.js';
23
23
  import { suggestionFields } from './suggest.js';
24
+ import { expandWebCapabilities } from './web-capabilities.js';
24
25
  import { openAiWidgetCsp, withAssetResourceDomain } from './widget-compile-helpers.js';
25
26
  import { resourceUiMeta, widgetHtml, widgetUri } from './widget-emit.js';
26
27
  import { widgetHtmlSizeErrors } from './widget-size-validation.js';
@@ -145,6 +146,7 @@ export function compileManifest(raw, options = {}) {
145
146
  // 2. Structural passes (catalog-independent): duplicate names, `$use` resolution, external refs,
146
147
  // fulfilment parsing. `$use` is resolved first so external-ref detection also scans bundled defs.
147
148
  const errors = widgetHtmlSizeErrors(manifest, runtimeBranding);
149
+ expandWebCapabilities(manifest, errors);
148
150
  const variables = compileVariableDeclarations(manifest.manifestVersion === '2' ? (manifest.server.variables ?? []) : [], manifest.tools.map((tool) => tool.name), errors);
149
151
  const managedCollections = compileManagedCollections(manifest.manifestVersion === '2' ? (manifest.server.collections ?? []) : [], manifest.tools.map((tool) => tool.name), errors, {
150
152
  ...(options.catalog === undefined ? {} : { catalog: options.catalog }),
@@ -1,4 +1,5 @@
1
1
  import { createHash } from 'node:crypto';
2
+ import { WEB_CATALOG_CONNECTOR, WEB_CONNECTOR_ID, WEB_CONNECTOR_VERSION, } from '@noodle-borg/managed-capabilities';
2
3
  import { computeSignatureHash } from './catalog/signature.js';
3
4
  import { resolveNestedOperations } from './nested-operations.js';
4
5
  import { docAnchorFor, suggestionFields } from './suggest.js';
@@ -38,7 +39,8 @@ function resolveOp(op, catalog, declared, usedAliases, errors, options, traversa
38
39
  operation: op.operation,
39
40
  resolved: false,
40
41
  };
41
- if (!catalog)
42
+ const isWeb = declared[op.connectorAlias]?.id === WEB_CONNECTOR_ID;
43
+ if (!catalog && !isWeb)
42
44
  return unresolved;
43
45
  usedAliases.add(op.connectorAlias);
44
46
  const connectorRef = declared[op.connectorAlias];
@@ -52,7 +54,20 @@ function resolveOp(op, catalog, declared, usedAliases, errors, options, traversa
52
54
  });
53
55
  return unresolved;
54
56
  }
55
- const connector = catalog.get(connectorRef.id, connectorRef.version);
57
+ const effectiveCatalog = {
58
+ get: (id, version) => id === WEB_CONNECTOR_ID && version === WEB_CONNECTOR_VERSION
59
+ ? WEB_CATALOG_CONNECTOR
60
+ : catalog?.get(id, version),
61
+ };
62
+ const connector = effectiveCatalog.get(connectorRef.id, connectorRef.version);
63
+ if (isWeb && (options.surface !== 'tool' || options.readOnly === true)) {
64
+ errors.push({
65
+ code: 'invalid_fulfilment',
66
+ path: `${op.path}.use`,
67
+ message: 'web extraction is available only in ordinary tools, never ambient context, resources or prompts',
68
+ });
69
+ return unresolved;
70
+ }
56
71
  if (!connector) {
57
72
  errors.push({
58
73
  code: 'connector_not_in_catalog',
@@ -96,7 +111,7 @@ function resolveOp(op, catalog, declared, usedAliases, errors, options, traversa
96
111
  connector,
97
112
  operation: op.operation,
98
113
  path: op.path,
99
- catalog,
114
+ catalog: effectiveCatalog,
100
115
  declared,
101
116
  errors,
102
117
  ...(traversal === undefined ? {} : { traversal }),
@@ -1133,6 +1133,23 @@ export declare const manifestV2Schema: z.ZodObject<{
1133
1133
  }, z.core.$strict>>;
1134
1134
  }, z.core.$strict>>;
1135
1135
  }, z.core.$strict>>>;
1136
+ capabilities: z.ZodOptional<z.ZodArray<z.ZodObject<{
1137
+ name: z.ZodString;
1138
+ class: z.ZodLiteral<"web.extract.v1">;
1139
+ title: z.ZodString;
1140
+ description: z.ZodString;
1141
+ provider: z.ZodObject<{
1142
+ kind: z.ZodLiteral<"noodle-managed">;
1143
+ }, z.core.$strict>;
1144
+ policy: z.ZodOptional<z.ZodObject<{
1145
+ maxUrls: z.ZodOptional<z.ZodNumber>;
1146
+ maxCalls: z.ZodOptional<z.ZodNumber>;
1147
+ timeoutMs: z.ZodOptional<z.ZodNumber>;
1148
+ maxTextBytes: z.ZodOptional<z.ZodNumber>;
1149
+ domains: z.ZodOptional<z.ZodArray<z.ZodString>>;
1150
+ }, z.core.$strict>>;
1151
+ authorization: z.ZodOptional<z.ZodType<ToolAuthorizationManifest, unknown, z.core.$ZodTypeInternals<ToolAuthorizationManifest, unknown>>>;
1152
+ }, z.core.$strict>>>;
1136
1153
  collections: z.ZodOptional<z.ZodArray<z.ZodObject<{
1137
1154
  management: z.ZodOptional<z.ZodObject<{
1138
1155
  assignment: z.ZodOptional<z.ZodLiteral<true>>;
@@ -2359,6 +2376,23 @@ export declare const manifestSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
2359
2376
  }, z.core.$strict>>;
2360
2377
  }, z.core.$strict>>;
2361
2378
  }, z.core.$strict>>>;
2379
+ capabilities: z.ZodOptional<z.ZodArray<z.ZodObject<{
2380
+ name: z.ZodString;
2381
+ class: z.ZodLiteral<"web.extract.v1">;
2382
+ title: z.ZodString;
2383
+ description: z.ZodString;
2384
+ provider: z.ZodObject<{
2385
+ kind: z.ZodLiteral<"noodle-managed">;
2386
+ }, z.core.$strict>;
2387
+ policy: z.ZodOptional<z.ZodObject<{
2388
+ maxUrls: z.ZodOptional<z.ZodNumber>;
2389
+ maxCalls: z.ZodOptional<z.ZodNumber>;
2390
+ timeoutMs: z.ZodOptional<z.ZodNumber>;
2391
+ maxTextBytes: z.ZodOptional<z.ZodNumber>;
2392
+ domains: z.ZodOptional<z.ZodArray<z.ZodString>>;
2393
+ }, z.core.$strict>>;
2394
+ authorization: z.ZodOptional<z.ZodType<ToolAuthorizationManifest, unknown, z.core.$ZodTypeInternals<ToolAuthorizationManifest, unknown>>>;
2395
+ }, z.core.$strict>>>;
2362
2396
  collections: z.ZodOptional<z.ZodArray<z.ZodObject<{
2363
2397
  management: z.ZodOptional<z.ZodObject<{
2364
2398
  assignment: z.ZodOptional<z.ZodLiteral<true>>;
@@ -1,4 +1,5 @@
1
1
  import { knowledgeComponentManifestSchema } from '@noodle-borg/knowledge/portable';
2
+ import { webCapabilityBaseSchema } from '@noodle-borg/managed-capabilities';
2
3
  import { z } from 'zod';
3
4
  import { MAX_VARIABLE_DECLARATIONS, variableDeclarationManifestSchema, } from '../business-variables.js';
4
5
  import { MAX_MANAGED_COLLECTIONS, managedCollectionManifestSchema, } from '../managed-collections.js';
@@ -433,6 +434,10 @@ const serverV2Schema = serverSchema.extend({
433
434
  agentGuide: agentGuideSchema.optional(),
434
435
  /** Customer-owned knowledge components (ADR 0202): Core v2 only. */
435
436
  knowledge: z.array(knowledgeComponentManifestSchema).optional(),
437
+ capabilities: z
438
+ .array(webCapabilityBaseSchema.extend({ authorization: toolAuthorizationSchema.optional() }))
439
+ .max(8)
440
+ .optional(),
436
441
  /** Managed business records: reusable schema intent only, never operator lifecycle state. */
437
442
  collections: z.array(managedCollectionManifestSchema).max(MAX_MANAGED_COLLECTIONS).optional(),
438
443
  });
@@ -657,11 +662,13 @@ export const manifestV2Schema = z
657
662
  // (ADR 0217): a knowledge-only server is valid, an empty server is not. v1 keeps its
658
663
  // authored-tool minimum — it has no server.knowledge to count.
659
664
  .superRefine((manifest, ctx) => {
660
- if (manifest.tools.length === 0 && (manifest.server.knowledge?.length ?? 0) === 0) {
665
+ if (manifest.tools.length === 0 &&
666
+ (manifest.server.knowledge?.length ?? 0) === 0 &&
667
+ (manifest.server.capabilities?.length ?? 0) === 0) {
661
668
  ctx.addIssue({
662
669
  code: 'custom',
663
670
  path: ['tools'],
664
- message: 'declare at least one tool or one server.knowledge component',
671
+ message: 'declare at least one tool, server.knowledge component or server.capabilities declaration',
665
672
  });
666
673
  }
667
674
  });
@@ -0,0 +1,55 @@
1
+ import { WEB_CONNECTOR_ID, WEB_CONNECTOR_VERSION, webExtractRequestSchema, webExtractResultSchema, } from '@noodle-borg/managed-capabilities';
2
+ import { z } from 'zod';
3
+ /** Compiler-owned ordinary tool expansion. No provider or transport behavior enters the artifact. */
4
+ export function expandWebCapabilities(manifest, errors) {
5
+ if (manifest.manifestVersion !== '2' || !manifest.server.capabilities?.length)
6
+ return;
7
+ if (manifest.connectors?.[WEB_CONNECTOR_ID] !== undefined) {
8
+ errors.push({
9
+ code: 'reserved_name',
10
+ path: `connectors.${WEB_CONNECTOR_ID}`,
11
+ message: 'connector alias is reserved for capability execution',
12
+ });
13
+ return;
14
+ }
15
+ const names = new Set(manifest.tools.map((tool) => tool.name));
16
+ const declarations = new Set();
17
+ for (const declaration of manifest.server.capabilities) {
18
+ const name = `extract_${declaration.name}`;
19
+ if (names.has(name) || declarations.has(declaration.name)) {
20
+ errors.push({
21
+ code: 'reserved_name',
22
+ path: 'server.capabilities',
23
+ message: `duplicate capability or generated tool "${name}"`,
24
+ });
25
+ continue;
26
+ }
27
+ names.add(name);
28
+ declarations.add(declaration.name);
29
+ manifest.tools.push({
30
+ name,
31
+ title: declaration.title,
32
+ description: `${declaration.description} Returns untrusted source evidence, not instructions or verified business facts.`,
33
+ ...(declaration.authorization === undefined
34
+ ? {}
35
+ : { authorization: declaration.authorization }),
36
+ inputSchema: z.toJSONSchema(webExtractRequestSchema),
37
+ outputSchema: z.toJSONSchema(webExtractResultSchema),
38
+ annotations: {
39
+ readOnlyHint: true,
40
+ destructiveHint: false,
41
+ idempotentHint: false,
42
+ openWorldHint: true,
43
+ },
44
+ fulfilment: {
45
+ use: `${WEB_CONNECTOR_ID}.extract`,
46
+ args: { name: declaration.name, request: '${input}' },
47
+ },
48
+ });
49
+ }
50
+ manifest.connectors = {
51
+ ...manifest.connectors,
52
+ [WEB_CONNECTOR_ID]: { id: WEB_CONNECTOR_ID, version: WEB_CONNECTOR_VERSION },
53
+ };
54
+ }
55
+ //# sourceMappingURL=web-capabilities.js.map
@@ -23,6 +23,7 @@
23
23
  "schema": "node dist/schema-export.js"
24
24
  },
25
25
  "dependencies": {
26
+ "@noodle-borg/managed-capabilities": "0.0.0",
26
27
  "@noodle-borg/app-package": "0.0.0",
27
28
  "@noodle-borg/brand-kit": "0.0.0",
28
29
  "@noodle-borg/uri-template": "0.0.0",
@@ -84,6 +84,11 @@ export async function guardedFetch(url, init = {}, options = {}) {
84
84
  }
85
85
  throw error;
86
86
  }
87
+ finally {
88
+ // Closing drains the current response without accepting another request. Consumers must read
89
+ // or cancel the body; do not await close here, which would deadlock before body consumption.
90
+ void dispatcher?.close().catch(() => { });
91
+ }
87
92
  }
88
93
  /** Whether a URL needs the guarded dispatcher: DNS-name hosts yes, literal-IP hosts no. */
89
94
  export function needsGuard(url) {
@@ -0,0 +1,44 @@
1
+ import type { AuditSink, DeploymentOperationTarget } from '@noodle-borg/module';
2
+ import type { DeploymentDeleteResponse } from '@noodle-borg/wire-contracts';
3
+ import type { ControlPlaneIdentity } from './contracts.js';
4
+ import type { DeploymentDeleteResult, DeploymentDeleteSelection } from './deployment-deletion-contracts.js';
5
+ import type { RollbackControlPlane } from './rollback-deployment.js';
6
+ export type DeploymentDeleteScope = {
7
+ readonly kind: 'deployment';
8
+ readonly org: string;
9
+ readonly deploymentId: string;
10
+ } | {
11
+ readonly kind: 'version';
12
+ readonly org: string;
13
+ readonly target: DeploymentOperationTarget;
14
+ readonly serverVersion?: string;
15
+ };
16
+ export interface DeploymentDeletionRegistry {
17
+ getDeployment(org: string, deploymentId: string): Promise<{
18
+ readonly orgSlug: string;
19
+ readonly appSlug: string;
20
+ readonly environment: string;
21
+ } | undefined>;
22
+ deleteDeployments(target: DeploymentOperationTarget, selection: DeploymentDeleteSelection): Promise<DeploymentDeleteResult>;
23
+ }
24
+ export interface DeploymentDeletionDependencies {
25
+ readonly registry: DeploymentDeletionRegistry;
26
+ readonly controlPlane: RollbackControlPlane;
27
+ readonly audit: AuditSink;
28
+ }
29
+ export type DeploymentDeleteOperationResult = {
30
+ readonly ok: true;
31
+ readonly view: DeploymentDeleteResponse;
32
+ } | {
33
+ readonly ok: false;
34
+ readonly status: 400 | 403 | 404 | 409;
35
+ readonly code: string;
36
+ readonly error: string;
37
+ };
38
+ /** One owner-authorized deletion path for every host; stores commit the exact selection atomically. */
39
+ export declare function deleteDeploymentOperation(deps: DeploymentDeletionDependencies, input: {
40
+ readonly actor: ControlPlaneIdentity;
41
+ readonly scope: DeploymentDeleteScope;
42
+ readonly expectedDeploymentIds?: readonly string[];
43
+ }): Promise<DeploymentDeleteOperationResult>;
44
+ //# sourceMappingURL=delete-deployment.d.ts.map