@modelprofile.com/flexharness 9.6.1 → 9.7.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.
@@ -61,7 +61,7 @@ const defaultReversionMaintenanceTimeoutMs = 30_000;
61
61
  const maximumReversionMaintenanceTimeoutMs = 30 * 60 * 1000;
62
62
 
63
63
  export function normalizeSubagents(
64
- definitions: IFlexSubagentDefinition[] | undefined,
64
+ definitions: readonly IFlexSubagentDefinition[] | undefined,
65
65
  ): ReadonlyMap<string, Readonly<IFlexSubagentDefinition>> {
66
66
  if (definitions === undefined) return new Map();
67
67
  if (!Array.isArray(definitions) || definitions.length > maxSubagentDefinitions) {
package/ts/utils.json.ts CHANGED
@@ -20,6 +20,7 @@ import type {
20
20
  TFlexAgentModelMessage,
21
21
  TJsonValue,
22
22
  } from './interfaces.js';
23
+ import { isValidSessionConfigurationRef } from './utils.validation.js';
23
24
 
24
25
  const DEFAULT_MAX_DEPTH = 12;
25
26
  const DEFAULT_MAX_BYTES = 256 * 1024;
@@ -483,6 +484,7 @@ function validateSession(value: unknown, path: string): IValidatedSessionIdentit
483
484
  'sessionId',
484
485
  'sessionGenerationId',
485
486
  'sessionGenerationSequence',
487
+ 'configurationRef',
486
488
  'title',
487
489
  'createdAt',
488
490
  'updatedAt',
@@ -502,6 +504,9 @@ function validateSession(value: unknown, path: string): IValidatedSessionIdentit
502
504
  if (session.origin !== undefined) validateSessionOrigin(session.origin, `${path}.origin`);
503
505
  const sessionId = requireString(session.sessionId, `${path}.sessionId`);
504
506
  const generation = validateOptionalSessionGeneration(session, path);
507
+ if (session.configurationRef !== undefined && !isValidSessionConfigurationRef(session.configurationRef)) {
508
+ throw new FlexHarnessStoreFormatError(`${path}.configurationRef is invalid.`);
509
+ }
505
510
  requireOptionalString(session.title, `${path}.title`);
506
511
  requireString(session.createdAt, `${path}.createdAt`);
507
512
  requireString(session.updatedAt, `${path}.updatedAt`);
@@ -545,6 +550,7 @@ function validateSession(value: unknown, path: string): IValidatedSessionIdentit
545
550
  return {
546
551
  sessionId,
547
552
  ...generation,
553
+ ...(session.configurationRef === undefined ? {} : { configurationRef: session.configurationRef as string }),
548
554
  ...(relationshipCount === 0
549
555
  ? {}
550
556
  : {
@@ -689,6 +695,7 @@ interface IValidatedSessionIdentity {
689
695
  sessionId: string;
690
696
  sessionGenerationId?: string;
691
697
  sessionGenerationSequence?: number;
698
+ configurationRef?: string;
692
699
  parentSessionId?: string;
693
700
  parentRunId?: string;
694
701
  parentToolCallId?: string;
@@ -889,6 +896,11 @@ export function assertFlexScopeSnapshot(value: unknown): asserts value is IFlexS
889
896
  `Snapshot child session "${session.sessionId}" has no live parent "${session.parentSessionId}".`,
890
897
  );
891
898
  }
899
+ if (session.configurationRef !== parent.configurationRef) {
900
+ throw new FlexHarnessStoreFormatError(
901
+ `Snapshot child session "${session.sessionId}" has a different configurationRef from its parent.`,
902
+ );
903
+ }
892
904
  const expectedDepth = (parent.depth ?? 0) + 1;
893
905
  if (session.depth !== expectedDepth) {
894
906
  throw new FlexHarnessStoreFormatError(
@@ -4,6 +4,7 @@ import {
4
4
  FLEX_PROJECT_MANAGEMENT_LIMITS,
5
5
  FLEX_SESSION_GENERATION_COHORT_MAX_ENTRIES,
6
6
  FLEX_SESSION_GENERATION_ID_MAX_BYTES,
7
+ FLEX_SESSION_CONFIGURATION_REF_MAX_BYTES,
7
8
  } from './interfaces.js';
8
9
  import type {
9
10
  IFlexCompactSessionOptions,
@@ -23,6 +24,24 @@ const maxProjectedErrorNameBytes = 128;
23
24
  const maxProjectedErrorMessageBytes = 2048;
24
25
  const maxProjectedErrorCodeBytes = 128;
25
26
  const controlCharacterPattern = /[\u0000-\u001f\u007f]/u;
27
+ const configurationControlCharacterPattern = /[\u0000-\u001f\u007f-\u009f]/u;
28
+ const unpairedSurrogatePattern = /[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?<![\uD800-\uDBFF])[\uDC00-\uDFFF]/u;
29
+
30
+ export function isValidSessionConfigurationRef(value: unknown): value is string {
31
+ return typeof value === 'string'
32
+ && Boolean(value.trim())
33
+ && Buffer.byteLength(value, 'utf8') <= FLEX_SESSION_CONFIGURATION_REF_MAX_BYTES
34
+ && !configurationControlCharacterPattern.test(value)
35
+ && !unpairedSurrogatePattern.test(value);
36
+ }
37
+
38
+ export function validateSessionConfigurationRef(value: unknown): asserts value is string {
39
+ if (!isValidSessionConfigurationRef(value)) {
40
+ throw new FlexHarnessValidationError(
41
+ `configurationRef must be a non-empty well-formed string without control characters of at most ${FLEX_SESSION_CONFIGURATION_REF_MAX_BYTES} UTF-8 bytes.`,
42
+ );
43
+ }
44
+ }
26
45
 
27
46
  export function validateIdentifier(value: string, name: string): void {
28
47
  if (typeof value !== 'string' || value.length === 0) {