@noodleseed/one 0.141.0 → 0.141.1

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/bin.js CHANGED
File without changes
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@noodle-borg/agent-kit",
3
- "version": "0.84.1",
3
+ "version": "0.85.0",
4
4
  "license": "Apache-2.0",
5
5
  "type": "module",
6
6
  "engines": {
@@ -40,7 +40,7 @@
40
40
  "@noodle-borg/module": "0.0.0",
41
41
  "@noodle-borg/protocol": "0.0.0",
42
42
  "@noodle-borg/runtime": "0.0.0",
43
- "@noodleseed/assistant": "1.24.0"
43
+ "@noodleseed/assistant": "1.25.0"
44
44
  },
45
45
  "devDependencies": {
46
46
  "@types/node": "^24.13.1",
@@ -10,7 +10,13 @@ export interface UpstreamHumanIdentity {
10
10
  export declare function normalizePlatformIdentityEmail(value: string): string;
11
11
  export interface UpstreamAuthorizationOptions {
12
12
  readonly forceAuthentication?: boolean;
13
+ readonly screenHint?: 'sign-up' | 'sign-in';
13
14
  }
15
+ export declare const FRESH_AUTH_SCOPE = "noodle:fresh-auth";
16
+ export declare const SIGNUP_INTENT_SCOPE = "noodle:signup-intent";
17
+ export declare function upstreamAuthorizationOptionsInput(scopes: readonly string[] | undefined, signupClient: boolean): {
18
+ readonly options?: UpstreamAuthorizationOptions;
19
+ };
14
20
  export interface UpstreamHumanAuthentication extends UpstreamHumanIdentity {
15
21
  readonly locale?: string;
16
22
  readonly timeZone?: string;
@@ -6,6 +6,20 @@ export function normalizePlatformIdentityEmail(value) {
6
6
  }
7
7
  return normalized;
8
8
  }
9
+ export const FRESH_AUTH_SCOPE = 'noodle:fresh-auth';
10
+ export const SIGNUP_INTENT_SCOPE = 'noodle:signup-intent';
11
+ export function upstreamAuthorizationOptionsInput(scopes, signupClient) {
12
+ const forceAuthentication = scopes?.includes(FRESH_AUTH_SCOPE) === true;
13
+ const signup = signupClient && scopes?.includes(SIGNUP_INTENT_SCOPE) === true;
14
+ if (!forceAuthentication && !signup)
15
+ return {};
16
+ return {
17
+ options: {
18
+ ...(forceAuthentication ? { forceAuthentication: true } : {}),
19
+ ...(signup ? { screenHint: 'sign-up' } : {}),
20
+ },
21
+ };
22
+ }
9
23
  /** Stable cross-package identity failure used by private providers and public consumers alike. */
10
24
  export class PlatformIdentityError extends Error {
11
25
  code;
@@ -18,6 +18,6 @@ export { AllowAllPolicy } from './policy/allow-all.js';
18
18
  export type { PolicyContext, PolicyDecision, PolicyGate } from './policy/types.js';
19
19
  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';
20
20
  export { splitResultMeta } from './result-meta.js';
21
- export { assertNoSecretValue, assertSchemaValue, COMPLETE_STATE_OPERATION, createStateConnector, InMemoryStateHandleStore, 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, } from './state-handles.js';
21
+ 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';
22
22
  export type { ToolDispatchContext, ToolDispatchDecision, ToolDispatchHook, } from './tool-dispatch.js';
23
23
  //# sourceMappingURL=index.d.ts.map
@@ -15,5 +15,5 @@ export { resolveManagedOrigins, } from './managed-origins.js';
15
15
  export { AllowAllPolicy } from './policy/allow-all.js';
16
16
  export { isConfirmationRequired, isInputRequired, isInputRequiredForConfirmation, } from './result.js';
17
17
  export { splitResultMeta } from './result-meta.js';
18
- export { assertNoSecretValue, assertSchemaValue, COMPLETE_STATE_OPERATION, createStateConnector, InMemoryStateHandleStore, PATCH_STATE_OPERATION, READ_STATE_OPERATION, STATE_CONNECTOR_ID, STATE_CONNECTOR_VERSION, STATE_OPERATION_SIGNATURES, StateConnector, } from './state-handles.js';
18
+ 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';
19
19
  //# sourceMappingURL=index.js.map
@@ -14,6 +14,16 @@ export interface StateHandleRecord {
14
14
  readonly status: 'active' | 'completed' | 'expired';
15
15
  readonly expiresAt?: string;
16
16
  }
17
+ export interface MutableStateHandleRecord {
18
+ handle: string;
19
+ key: string;
20
+ value: Record<string, unknown>;
21
+ revision: number;
22
+ status: 'active' | 'completed';
23
+ createdAt: number;
24
+ updatedAt: number;
25
+ expiresAt?: number;
26
+ }
17
27
  export interface StateHandleStore {
18
28
  read(input: StateInput): Promise<StateHandleRecord> | StateHandleRecord;
19
29
  patch(input: StatePatchInput): Promise<StateHandleRecord> | StateHandleRecord;
@@ -46,6 +56,11 @@ export declare class StateConnector implements Connector {
46
56
  invoke(call: ConnectorCall): Promise<unknown>;
47
57
  }
48
58
  export declare function createStateConnector(state: ArtifactState | undefined): StateConnector | undefined;
59
+ export declare function createMutableStateHandleRecord(handle: string, key: string, ttlSeconds: number | undefined, now: number): MutableStateHandleRecord;
60
+ export declare function stateHandleRecordForMutation(record: MutableStateHandleRecord | undefined, handle: string, key: string, ttlSeconds: number | undefined, now: number): MutableStateHandleRecord;
61
+ export declare function assertStateHandleNotCompleted(record: MutableStateHandleRecord): void;
62
+ export declare function assertExpectedStateRevision(record: MutableStateHandleRecord, expectedRevision: number): void;
63
+ export declare function toPublicStateHandleRecord(record: MutableStateHandleRecord, now: number): StateHandleRecord;
49
64
  export declare function assertNoSecretValue(value: unknown, path?: string): void;
50
65
  export declare function assertSchemaValue(schema: Record<string, unknown>, value: Record<string, unknown>): void;
51
66
  //# sourceMappingURL=state-handles.d.ts.map
@@ -55,18 +55,20 @@ export class InMemoryStateHandleStore {
55
55
  read(input) {
56
56
  const def = this.#definition(input.handle);
57
57
  const key = this.#recordKey(def, input);
58
- return this.#publicRecord(this.#records.get(key) ?? this.#emptyRecord(input.handle, input.key ?? 'default', def));
58
+ const now = this.#now().getTime();
59
+ return toPublicStateHandleRecord(this.#records.get(key) ??
60
+ createMutableStateHandleRecord(input.handle, input.key ?? 'default', def.ttlSeconds, now), now);
59
61
  }
60
62
  patch(input) {
61
63
  const def = this.#definition(input.handle);
62
64
  const key = this.#recordKey(def, input);
63
- const current = this.#records.get(key) ?? this.#emptyRecord(input.handle, input.key ?? 'default', def);
64
- assertActive(current, this.#now().getTime());
65
- assertExpectedRevision(current, input.expectedRevision);
65
+ const now = this.#now().getTime();
66
+ const current = stateHandleRecordForMutation(this.#records.get(key), input.handle, input.key ?? 'default', def.ttlSeconds, now);
67
+ assertStateHandleNotCompleted(current);
68
+ assertExpectedStateRevision(current, input.expectedRevision);
66
69
  assertNoSecretValue(input.value);
67
70
  const value = { ...current.value, ...input.value };
68
71
  assertSchemaValue(def.schema, value);
69
- const now = this.#now().getTime();
70
72
  const next = {
71
73
  ...current,
72
74
  value,
@@ -74,22 +76,23 @@ export class InMemoryStateHandleStore {
74
76
  updatedAt: now,
75
77
  };
76
78
  this.#records.set(key, next);
77
- return this.#publicRecord(next);
79
+ return toPublicStateHandleRecord(next, now);
78
80
  }
79
81
  complete(input) {
80
82
  const def = this.#definition(input.handle);
81
83
  const key = this.#recordKey(def, input);
82
- const current = this.#records.get(key) ?? this.#emptyRecord(input.handle, input.key ?? 'default', def);
83
- assertActive(current, this.#now().getTime());
84
- assertExpectedRevision(current, input.expectedRevision);
84
+ const now = this.#now().getTime();
85
+ const current = stateHandleRecordForMutation(this.#records.get(key), input.handle, input.key ?? 'default', def.ttlSeconds, now);
86
+ assertStateHandleNotCompleted(current);
87
+ assertExpectedStateRevision(current, input.expectedRevision);
85
88
  const next = {
86
89
  ...current,
87
90
  status: 'completed',
88
91
  revision: current.revision + 1,
89
- updatedAt: this.#now().getTime(),
92
+ updatedAt: now,
90
93
  };
91
94
  this.#records.set(key, next);
92
- return this.#publicRecord(next);
95
+ return toPublicStateHandleRecord(next, now);
93
96
  }
94
97
  #definition(handle) {
95
98
  const def = this.#state.handles[handle];
@@ -102,34 +105,6 @@ export class InMemoryStateHandleStore {
102
105
  const owner = def.scope === 'caller' ? (input.callerSubject ?? 'anonymous') : 'deployment';
103
106
  return `${input.handle}\u0000${owner}\u0000${userKey}`;
104
107
  }
105
- #emptyRecord(handle, key, def) {
106
- const now = this.#now().getTime();
107
- return {
108
- handle,
109
- key,
110
- value: {},
111
- revision: 0,
112
- status: 'active',
113
- createdAt: now,
114
- updatedAt: now,
115
- ...(def.ttlSeconds !== undefined ? { expiresAt: now + def.ttlSeconds * 1000 } : {}),
116
- };
117
- }
118
- #publicRecord(record) {
119
- const status = record.expiresAt !== undefined && record.expiresAt <= this.#now().getTime()
120
- ? 'expired'
121
- : record.status;
122
- return {
123
- handle: record.handle,
124
- key: record.key,
125
- value: record.value,
126
- revision: record.revision,
127
- status,
128
- ...(record.expiresAt !== undefined
129
- ? { expiresAt: new Date(record.expiresAt).toISOString() }
130
- : {}),
131
- };
132
- }
133
108
  }
134
109
  export class StateConnector {
135
110
  id = STATE_CONNECTOR_ID;
@@ -212,18 +187,53 @@ function objectArg(value, name) {
212
187
  throw new Error(`${name} must be an object`);
213
188
  return value;
214
189
  }
215
- function assertActive(record, now) {
190
+ export function createMutableStateHandleRecord(handle, key, ttlSeconds, now) {
191
+ return {
192
+ handle,
193
+ key,
194
+ value: {},
195
+ revision: 0,
196
+ status: 'active',
197
+ createdAt: now,
198
+ updatedAt: now,
199
+ ...(ttlSeconds !== undefined ? { expiresAt: now + ttlSeconds * 1000 } : {}),
200
+ };
201
+ }
202
+ export function stateHandleRecordForMutation(record, handle, key, ttlSeconds, now) {
203
+ if (record === undefined)
204
+ return createMutableStateHandleRecord(handle, key, ttlSeconds, now);
205
+ if (!isExpired(record, now))
206
+ return record;
207
+ return {
208
+ ...createMutableStateHandleRecord(handle, key, ttlSeconds, now),
209
+ revision: record.revision + 1,
210
+ };
211
+ }
212
+ export function assertStateHandleNotCompleted(record) {
216
213
  if (record.status === 'completed')
217
214
  throw new Error('completed state handles are read-only');
218
- if (record.expiresAt !== undefined && record.expiresAt <= now) {
219
- throw new Error('expired state handles are read-only');
220
- }
221
215
  }
222
- function assertExpectedRevision(record, expectedRevision) {
216
+ function isExpired(record, now) {
217
+ return record.expiresAt !== undefined && record.expiresAt <= now;
218
+ }
219
+ export function assertExpectedStateRevision(record, expectedRevision) {
223
220
  if (record.revision !== expectedRevision) {
224
221
  throw new Error(`state revision conflict: expected ${expectedRevision}, got ${record.revision}`);
225
222
  }
226
223
  }
224
+ export function toPublicStateHandleRecord(record, now) {
225
+ const expired = isExpired(record, now);
226
+ return {
227
+ handle: record.handle,
228
+ key: record.key,
229
+ value: record.value,
230
+ revision: record.revision + (expired ? 1 : 0),
231
+ status: expired ? 'expired' : record.status,
232
+ ...(record.expiresAt !== undefined
233
+ ? { expiresAt: new Date(record.expiresAt).toISOString() }
234
+ : {}),
235
+ };
236
+ }
227
237
  const SECRET_LIKE_FIELD = /(secret|token|api[_-]?key|password|credential|authorization|cookie)/i;
228
238
  export function assertNoSecretValue(value, path = 'value') {
229
239
  if (Array.isArray(value)) {
@@ -39,7 +39,7 @@
39
39
  "dependencies": {
40
40
  "@modelcontextprotocol/sdk": "^1.29.0",
41
41
  "@noodle-borg/admission-limits": "0.0.0",
42
- "@noodle-borg/agent-kit": "0.84.1",
42
+ "@noodle-borg/agent-kit": "0.85.0",
43
43
  "@noodle-borg/app-package": "0.0.0",
44
44
  "@noodle-borg/assistant-gateway": "0.0.0",
45
45
  "@noodle-borg/auth": "0.0.0",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@noodleseed/assistant",
3
- "version": "1.24.0",
3
+ "version": "1.25.0",
4
4
  "description": "Embed the Noodle Seed customer-branded assistant in your web app with managed or framework-owned UI, a framework-neutral MCP App host, a DOM-free client, and a backend session helper. Authoring and deploying the server is @noodleseed/one.",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@noodleseed/one",
3
- "version": "0.141.0",
3
+ "version": "0.141.1",
4
4
  "private": false,
5
5
  "description": "Noodle CLI by Noodle Seed — author, run, and deploy declarative MCP servers. Embedding the assistant in your own web app is @noodleseed/assistant.",
6
6
  "license": "Apache-2.0",
@@ -236,7 +236,7 @@
236
236
  "@modelcontextprotocol/client": "2.0.0",
237
237
  "@modelcontextprotocol/server": "2.0.0",
238
238
  "@noodle-borg/admission-limits": "0.0.0",
239
- "@noodle-borg/agent-kit": "0.84.1",
239
+ "@noodle-borg/agent-kit": "0.85.0",
240
240
  "@noodle-borg/app-audit": "0.0.0",
241
241
  "@noodle-borg/app-package": "0.0.0",
242
242
  "@noodle-borg/assistant-gateway": "0.0.0",