@namzu/sdk 56.0.1 → 56.2.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 (119) hide show
  1. package/CHANGELOG.md +27 -0
  2. package/dist/compaction/context-breakdown.d.ts +1 -1
  3. package/dist/compaction/context-breakdown.d.ts.map +1 -1
  4. package/dist/compaction/context-breakdown.js +9 -2
  5. package/dist/compaction/context-breakdown.js.map +1 -1
  6. package/dist/compaction/verifier.d.ts.map +1 -1
  7. package/dist/compaction/verifier.js +3 -1
  8. package/dist/compaction/verifier.js.map +1 -1
  9. package/dist/public-runtime.d.ts +1 -1
  10. package/dist/public-runtime.d.ts.map +1 -1
  11. package/dist/public-runtime.js +1 -1
  12. package/dist/public-runtime.js.map +1 -1
  13. package/dist/runtime/query/executor.d.ts +17 -1
  14. package/dist/runtime/query/executor.d.ts.map +1 -1
  15. package/dist/runtime/query/executor.js +73 -5
  16. package/dist/runtime/query/executor.js.map +1 -1
  17. package/dist/runtime/query/file-evidence-context.d.ts +21 -4
  18. package/dist/runtime/query/file-evidence-context.d.ts.map +1 -1
  19. package/dist/runtime/query/file-evidence-context.js +70 -8
  20. package/dist/runtime/query/file-evidence-context.js.map +1 -1
  21. package/dist/runtime/query/index.d.ts.map +1 -1
  22. package/dist/runtime/query/index.js +2 -11
  23. package/dist/runtime/query/index.js.map +1 -1
  24. package/dist/runtime/query/iteration/index.d.ts +1 -2
  25. package/dist/runtime/query/iteration/index.d.ts.map +1 -1
  26. package/dist/runtime/query/iteration/index.js +30 -19
  27. package/dist/runtime/query/iteration/index.js.map +1 -1
  28. package/dist/runtime/query/iteration/recorded-context.d.ts +18 -0
  29. package/dist/runtime/query/iteration/recorded-context.d.ts.map +1 -0
  30. package/dist/runtime/query/iteration/recorded-context.js +37 -0
  31. package/dist/runtime/query/iteration/recorded-context.js.map +1 -0
  32. package/dist/runtime/query/iteration/step-context.d.ts +15 -51
  33. package/dist/runtime/query/iteration/step-context.d.ts.map +1 -1
  34. package/dist/runtime/query/iteration/step-context.js +24 -134
  35. package/dist/runtime/query/iteration/step-context.js.map +1 -1
  36. package/dist/runtime/query/iteration/step-shaping.d.ts +20 -8
  37. package/dist/runtime/query/iteration/step-shaping.d.ts.map +1 -1
  38. package/dist/runtime/query/iteration/step-shaping.js +52 -26
  39. package/dist/runtime/query/iteration/step-shaping.js.map +1 -1
  40. package/dist/scheduler/completion-inbox.d.ts +27 -0
  41. package/dist/scheduler/completion-inbox.d.ts.map +1 -1
  42. package/dist/scheduler/completion-inbox.js +88 -21
  43. package/dist/scheduler/completion-inbox.js.map +1 -1
  44. package/dist/store/session-index/fts.d.ts.map +1 -1
  45. package/dist/store/session-index/fts.js +6 -0
  46. package/dist/store/session-index/fts.js.map +1 -1
  47. package/dist/test-support/file-evidence-held.d.ts +11 -0
  48. package/dist/test-support/file-evidence-held.d.ts.map +1 -0
  49. package/dist/test-support/file-evidence-held.js +28 -0
  50. package/dist/test-support/file-evidence-held.js.map +1 -0
  51. package/dist/test-support/request-only.d.ts +10 -0
  52. package/dist/test-support/request-only.d.ts.map +1 -0
  53. package/dist/test-support/request-only.js +15 -0
  54. package/dist/test-support/request-only.js.map +1 -0
  55. package/dist/tools/builtins/content-fingerprint.d.ts +12 -0
  56. package/dist/tools/builtins/content-fingerprint.d.ts.map +1 -1
  57. package/dist/tools/builtins/content-fingerprint.js +14 -0
  58. package/dist/tools/builtins/content-fingerprint.js.map +1 -1
  59. package/dist/tools/builtins/edit.d.ts.map +1 -1
  60. package/dist/tools/builtins/edit.js +19 -16
  61. package/dist/tools/builtins/edit.js.map +1 -1
  62. package/dist/tools/builtins/stale-before-review.d.ts +18 -0
  63. package/dist/tools/builtins/stale-before-review.d.ts.map +1 -0
  64. package/dist/tools/builtins/stale-before-review.js +42 -0
  65. package/dist/tools/builtins/stale-before-review.js.map +1 -0
  66. package/dist/tools/builtins/write-file.d.ts.map +1 -1
  67. package/dist/tools/builtins/write-file.js +4 -0
  68. package/dist/tools/builtins/write-file.js.map +1 -1
  69. package/dist/tools/defineTool.d.ts +2 -0
  70. package/dist/tools/defineTool.d.ts.map +1 -1
  71. package/dist/tools/defineTool.js +1 -0
  72. package/dist/tools/defineTool.js.map +1 -1
  73. package/dist/tools/untrusted-envelope.d.ts +7 -0
  74. package/dist/tools/untrusted-envelope.d.ts.map +1 -1
  75. package/dist/tools/untrusted-envelope.js +3 -1
  76. package/dist/tools/untrusted-envelope.js.map +1 -1
  77. package/dist/turn/evidence-recall.d.ts +19 -8
  78. package/dist/turn/evidence-recall.d.ts.map +1 -1
  79. package/dist/turn/evidence-recall.js +134 -53
  80. package/dist/turn/evidence-recall.js.map +1 -1
  81. package/dist/turn/memory-recall.d.ts +18 -0
  82. package/dist/turn/memory-recall.d.ts.map +1 -1
  83. package/dist/turn/memory-recall.js +43 -4
  84. package/dist/turn/memory-recall.js.map +1 -1
  85. package/dist/types/message/index.d.ts +46 -1
  86. package/dist/types/message/index.d.ts.map +1 -1
  87. package/dist/types/message/index.js +78 -1
  88. package/dist/types/message/index.js.map +1 -1
  89. package/dist/types/session/prepare-step.d.ts +24 -0
  90. package/dist/types/session/prepare-step.d.ts.map +1 -1
  91. package/dist/types/tool/index.d.ts +16 -0
  92. package/dist/types/tool/index.d.ts.map +1 -1
  93. package/dist/types/tool/index.js.map +1 -1
  94. package/package.json +1 -1
  95. package/src/compaction/context-breakdown.ts +11 -3
  96. package/src/compaction/verifier.ts +3 -1
  97. package/src/public-runtime.ts +7 -0
  98. package/src/runtime/query/executor.ts +84 -5
  99. package/src/runtime/query/file-evidence-context.ts +79 -11
  100. package/src/runtime/query/index.ts +2 -10
  101. package/src/runtime/query/iteration/index.ts +32 -26
  102. package/src/runtime/query/iteration/recorded-context.ts +48 -0
  103. package/src/runtime/query/iteration/step-context.ts +27 -155
  104. package/src/runtime/query/iteration/step-shaping.ts +64 -40
  105. package/src/scheduler/completion-inbox.ts +87 -20
  106. package/src/store/session-index/fts.ts +5 -0
  107. package/src/test-support/file-evidence-held.ts +27 -0
  108. package/src/test-support/request-only.ts +19 -0
  109. package/src/tools/builtins/content-fingerprint.ts +20 -0
  110. package/src/tools/builtins/edit.ts +18 -15
  111. package/src/tools/builtins/stale-before-review.ts +45 -0
  112. package/src/tools/builtins/write-file.ts +5 -0
  113. package/src/tools/defineTool.ts +3 -0
  114. package/src/tools/untrusted-envelope.ts +10 -1
  115. package/src/turn/evidence-recall.ts +189 -58
  116. package/src/turn/memory-recall.ts +59 -5
  117. package/src/types/message/index.ts +108 -1
  118. package/src/types/session/prepare-step.ts +26 -0
  119. package/src/types/tool/index.ts +18 -0
@@ -371,6 +371,7 @@ export const RUNTIME_CONTEXT_MESSAGE_KINDS = [
371
371
  'step-context',
372
372
  'structured-output',
373
373
  'task-completion',
374
+ 'turn-context',
374
375
  ] as const
375
376
 
376
377
  export type RuntimeContextMessageKind = (typeof RUNTIME_CONTEXT_MESSAGE_KINDS)[number]
@@ -381,8 +382,18 @@ export interface RuntimeContextMessageSource {
381
382
  readonly kind: RuntimeContextMessageKind
382
383
  /** Optional durable host delivery identity; it never grants operator authority. */
383
384
  readonly deliveryRef?: InboundDeliveryRef
385
+ /**
386
+ * What a `turn-context` entry reports (for example `repository`). A later
387
+ * entry with the same key adds to or replaces what an earlier one said.
388
+ */
389
+ readonly key?: string
384
390
  }
385
391
 
392
+ /** The longest key a recorded context entry may carry. */
393
+ export const MAX_TURN_CONTEXT_KEY_LENGTH = 64
394
+
395
+ const TURN_CONTEXT_KEY = /^[a-z][a-z0-9-]*$/
396
+
386
397
  export type UserMessageSource =
387
398
  | GoalRoundMessageSource
388
399
  | ProjectInstructionMessageSource
@@ -437,12 +448,14 @@ export function isRuntimeContextMessageSource(
437
448
  readonly type?: unknown
438
449
  readonly kind?: unknown
439
450
  readonly deliveryRef?: unknown
451
+ readonly key?: unknown
440
452
  }
441
453
  return (
442
454
  candidate.type === 'runtime-context' &&
443
455
  typeof candidate.kind === 'string' &&
444
456
  (RUNTIME_CONTEXT_MESSAGE_KINDS as readonly string[]).includes(candidate.kind) &&
445
- (candidate.deliveryRef === undefined || isInboundDeliveryRef(candidate.deliveryRef))
457
+ (candidate.deliveryRef === undefined || isInboundDeliveryRef(candidate.deliveryRef)) &&
458
+ (candidate.key === undefined || isTurnContextKey(candidate.key))
446
459
  )
447
460
  }
448
461
 
@@ -640,6 +653,100 @@ export function createRuntimeContextMessage(
640
653
  })
641
654
  }
642
655
 
656
+ /** Whether `value` is a name a recorded context entry may be filed under. */
657
+ export function isTurnContextKey(value: unknown): value is string {
658
+ return (
659
+ typeof value === 'string' &&
660
+ value.length <= MAX_TURN_CONTEXT_KEY_LENGTH &&
661
+ TURN_CONTEXT_KEY.test(value)
662
+ )
663
+ }
664
+
665
+ function localTime(at: Date): string {
666
+ const pad = (n: number) => String(n).padStart(2, '0')
667
+ return `${at.getFullYear()}-${pad(at.getMonth() + 1)}-${pad(at.getDate())} ${pad(at.getHours())}:${pad(at.getMinutes())}`
668
+ }
669
+
670
+ /**
671
+ * Build a recorded context entry: text a step learned for this turn that
672
+ * stays in the conversation, after whatever came before it, so later requests
673
+ * keep beginning with it. The header is written into the content once and the
674
+ * entry is never edited afterwards; a later entry under the same key says what
675
+ * changed. It is not an operator message and carries no authority.
676
+ *
677
+ * The first entry under a key says that a later one adds to or replaces it;
678
+ * with `later` set, for an entry that follows another under the same key, the
679
+ * header leaves that sentence out, since the conversation already holds it.
680
+ */
681
+ export function createTurnContextEntry(
682
+ key: string,
683
+ text: string,
684
+ at: Date = new Date(),
685
+ options: { readonly later?: boolean } = {},
686
+ ): UserMessage {
687
+ if (!isTurnContextKey(key))
688
+ throw new TypeError('A recorded context key is lowercase words joined by hyphens.')
689
+ const label = `Recorded context (runtime-generated; not a new user request) - ${key}, as of ${localTime(at)}`
690
+ return createUserMessage(
691
+ `${label}${options.later ? ':' : '. A later entry with this key adds to or replaces what it says:'}\n${text}`,
692
+ undefined,
693
+ { type: 'runtime-context', kind: 'turn-context', key },
694
+ )
695
+ }
696
+
697
+ /** The key a recorded context entry is filed under, or undefined for any other message. */
698
+ export function turnContextKey(message: { readonly role: string; readonly source?: unknown }):
699
+ | string
700
+ | undefined {
701
+ if (message.role !== 'user') return undefined
702
+ const source = message.source as RuntimeContextMessageSource | undefined
703
+ return source?.type === 'runtime-context' && source.kind === 'turn-context'
704
+ ? source.key
705
+ : undefined
706
+ }
707
+
708
+ /** Whether `message` is a recorded context entry. */
709
+ export function isTurnContextEntry(message: {
710
+ readonly role: string
711
+ readonly source?: unknown
712
+ }): boolean {
713
+ if (message.role !== 'user') return false
714
+ const source = message.source as RuntimeContextMessageSource | undefined
715
+ return source?.type === 'runtime-context' && source.kind === 'turn-context'
716
+ }
717
+
718
+ /**
719
+ * What a step recorded under `key`, oldest first, without each entry's header.
720
+ * A history that was compacted holds only the entries the compaction kept, so
721
+ * an empty list means the step may say everything again.
722
+ */
723
+ export function turnContextEntries(messages: readonly Message[], key: string): readonly string[] {
724
+ const bodies: string[] = []
725
+ for (const message of messages) {
726
+ if (turnContextKey(message) !== key || typeof message.content !== 'string') continue
727
+ bodies.push(message.content.slice(message.content.indexOf('\n') + 1))
728
+ }
729
+ return bodies
730
+ }
731
+
732
+ /**
733
+ * The text of the newest user-role message with plain text, skipping recorded
734
+ * context entries: a history that ends in one (a resumed session) must not
735
+ * take the host's own recalled text for the question.
736
+ */
737
+ export function lastPromptText(messages: readonly Message[]): string {
738
+ for (let i = messages.length - 1; i >= 0; i--) {
739
+ const message = messages[i]
740
+ if (
741
+ message?.role === 'user' &&
742
+ typeof message.content === 'string' &&
743
+ !isTurnContextEntry(message)
744
+ )
745
+ return message.content
746
+ }
747
+ return ''
748
+ }
749
+
643
750
  /** Build the retained user-context message that carries live project policy. */
644
751
  export function createProjectInstructionMessage(
645
752
  content: string,
@@ -227,10 +227,36 @@ export interface PrepareStepResult {
227
227
  */
228
228
  readonly context?: string
229
229
 
230
+ /**
231
+ * Text to keep in the conversation from this step on, filed under a key.
232
+ *
233
+ * Where `context` is gone after the request, an item here becomes a
234
+ * recorded entry appended after whatever the history ends with, so every
235
+ * later request (of this turn and of the next turns) begins with it and a
236
+ * caching provider keeps reading the same prefix. Entries are never edited
237
+ * or moved; a step that has something new says only that, under the same
238
+ * key, and reads what it said before with `turnContextEntries`. An item
239
+ * whose text is empty, or equal to the last entry under its key, adds
240
+ * nothing. Entries are ordinary history to compaction, which drops them
241
+ * with the messages around them, after which a step sees none and may say
242
+ * everything again.
243
+ *
244
+ * The model reads an entry as recorded context the host generated, not as
245
+ * something the operator said, and a person is never shown one.
246
+ */
247
+ readonly recordedContext?: readonly RecordedContextItem[]
248
+
230
249
  readonly temperature?: number
231
250
  readonly maxResponseTokens?: number
232
251
  }
233
252
 
253
+ /** One piece of text a step asks to have recorded, under what it reports. */
254
+ export interface RecordedContextItem {
255
+ /** Lowercase words joined by hyphens (for example `repository`). */
256
+ readonly key: string
257
+ readonly text: string
258
+ }
259
+
234
260
  /**
235
261
  * Called before each model call, with everything the turn has produced so
236
262
  * far.
@@ -1050,6 +1050,24 @@ export interface ToolDefinition<TInput = unknown> extends ToolPresentation<TInpu
1050
1050
  * the safe direction to be wrong in.
1051
1051
  */
1052
1052
  pathArgument?: string
1053
+ /**
1054
+ * A refusal that needs no person's answer: the call cannot run as it stands,
1055
+ * and the tool can already tell.
1056
+ *
1057
+ * Asked once the arguments are valid and BEFORE the call is put to a
1058
+ * reviewer, so a person is never asked to approve a change that would be
1059
+ * refused the moment they said yes. A file tool answers here when the file
1060
+ * moved on disk after the session read it. Returning `undefined` means no
1061
+ * objection; the call goes on to review and `execute`, which keep their own
1062
+ * checks, since the state may move again in between. A hook that throws is
1063
+ * read as no objection too.
1064
+ */
1065
+ refuseBeforeReview?(
1066
+ input: TInput,
1067
+ context: ToolContext,
1068
+ ): Promise<
1069
+ { readonly error: string; readonly facts?: import('./presentation.js').ToolFacts } | undefined
1070
+ >
1053
1071
  /**
1054
1072
  * The argument that holds an absolute URL the tool has already
1055
1073
  * canonicalised in its input schema — one spelling, no whitespace.