@namzu/sdk 53.1.0 → 53.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 (87) hide show
  1. package/CHANGELOG.md +13 -0
  2. package/dist/compaction/index.d.ts +1 -1
  3. package/dist/compaction/index.d.ts.map +1 -1
  4. package/dist/compaction/index.js +1 -1
  5. package/dist/compaction/index.js.map +1 -1
  6. package/dist/compaction/manual.d.ts +5 -0
  7. package/dist/compaction/manual.d.ts.map +1 -1
  8. package/dist/compaction/manual.js +4 -4
  9. package/dist/compaction/manual.js.map +1 -1
  10. package/dist/compaction/summary.d.ts +12 -2
  11. package/dist/compaction/summary.d.ts.map +1 -1
  12. package/dist/compaction/summary.js +13 -3
  13. package/dist/compaction/summary.js.map +1 -1
  14. package/dist/compaction/tool-result-editing.d.ts.map +1 -1
  15. package/dist/compaction/tool-result-editing.js +9 -6
  16. package/dist/compaction/tool-result-editing.js.map +1 -1
  17. package/dist/manager/agent/lifecycle.d.ts +15 -0
  18. package/dist/manager/agent/lifecycle.d.ts.map +1 -1
  19. package/dist/manager/agent/lifecycle.js +169 -1
  20. package/dist/manager/agent/lifecycle.js.map +1 -1
  21. package/dist/public-runtime.d.ts +2 -1
  22. package/dist/public-runtime.d.ts.map +1 -1
  23. package/dist/public-runtime.js +2 -1
  24. package/dist/public-runtime.js.map +1 -1
  25. package/dist/runtime/query/executor.d.ts +2 -0
  26. package/dist/runtime/query/executor.d.ts.map +1 -1
  27. package/dist/runtime/query/executor.js +21 -1
  28. package/dist/runtime/query/executor.js.map +1 -1
  29. package/dist/runtime/query/iteration/phases/compaction.d.ts.map +1 -1
  30. package/dist/runtime/query/iteration/phases/compaction.js +6 -2
  31. package/dist/runtime/query/iteration/phases/compaction.js.map +1 -1
  32. package/dist/runtime/query/tool-output-budget.d.ts +30 -2
  33. package/dist/runtime/query/tool-output-budget.d.ts.map +1 -1
  34. package/dist/runtime/query/tool-output-budget.js +43 -10
  35. package/dist/runtime/query/tool-output-budget.js.map +1 -1
  36. package/dist/scheduler/local.d.ts +2 -1
  37. package/dist/scheduler/local.d.ts.map +1 -1
  38. package/dist/scheduler/local.js +8 -0
  39. package/dist/scheduler/local.js.map +1 -1
  40. package/dist/store/evidence/disk.d.ts +3 -2
  41. package/dist/store/evidence/disk.d.ts.map +1 -1
  42. package/dist/store/evidence/disk.js +23 -3
  43. package/dist/store/evidence/disk.js.map +1 -1
  44. package/dist/store/evidence/source-text.d.ts +20 -0
  45. package/dist/store/evidence/source-text.d.ts.map +1 -1
  46. package/dist/store/evidence/source-text.js +29 -2
  47. package/dist/store/evidence/source-text.js.map +1 -1
  48. package/dist/tools/builtins/read-file.d.ts.map +1 -1
  49. package/dist/tools/builtins/read-file.js +7 -2
  50. package/dist/tools/builtins/read-file.js.map +1 -1
  51. package/dist/tools/retained-output.d.ts +12 -0
  52. package/dist/tools/retained-output.d.ts.map +1 -0
  53. package/dist/tools/retained-output.js +39 -0
  54. package/dist/tools/retained-output.js.map +1 -0
  55. package/dist/types/agent/manager.d.ts +48 -0
  56. package/dist/types/agent/manager.d.ts.map +1 -1
  57. package/dist/types/agent/scheduler.d.ts +20 -0
  58. package/dist/types/agent/scheduler.d.ts.map +1 -1
  59. package/dist/types/agent/task.d.ts +2 -0
  60. package/dist/types/agent/task.d.ts.map +1 -1
  61. package/dist/types/session/records.d.ts +25 -0
  62. package/dist/types/session/records.d.ts.map +1 -1
  63. package/dist/types/session/records.js +16 -0
  64. package/dist/types/session/records.js.map +1 -1
  65. package/dist/types/tool/index.d.ts +8 -0
  66. package/dist/types/tool/index.d.ts.map +1 -1
  67. package/dist/types/tool/index.js.map +1 -1
  68. package/package.json +1 -1
  69. package/src/compaction/index.ts +6 -1
  70. package/src/compaction/manual.ts +15 -3
  71. package/src/compaction/summary.ts +17 -3
  72. package/src/compaction/tool-result-editing.ts +12 -9
  73. package/src/manager/agent/lifecycle.ts +181 -1
  74. package/src/public-runtime.ts +2 -1
  75. package/src/runtime/query/executor.ts +25 -1
  76. package/src/runtime/query/iteration/phases/compaction.ts +13 -2
  77. package/src/runtime/query/tool-output-budget.ts +65 -11
  78. package/src/scheduler/local.ts +14 -1
  79. package/src/store/evidence/disk.ts +28 -3
  80. package/src/store/evidence/source-text.ts +38 -2
  81. package/src/tools/builtins/read-file.ts +7 -2
  82. package/src/tools/retained-output.ts +38 -0
  83. package/src/types/agent/manager.ts +54 -0
  84. package/src/types/agent/scheduler.ts +21 -0
  85. package/src/types/agent/task.ts +2 -0
  86. package/src/types/session/records.ts +16 -0
  87. package/src/types/tool/index.ts +8 -0
@@ -0,0 +1,38 @@
1
+ import { lstat, realpath } from 'node:fs/promises'
2
+ import { dirname, extname, isAbsolute, relative, resolve } from 'node:path'
3
+
4
+ function inside(root: string, path: string): boolean {
5
+ const rel = relative(root, path)
6
+ return rel !== '' && !rel.startsWith('..') && !isAbsolute(rel)
7
+ }
8
+
9
+ /**
10
+ * The real path of a retained tool-output file the model may read, or
11
+ * `undefined` when `candidate` is not one.
12
+ *
13
+ * Only this session's own retained directory counts. The file must be an
14
+ * absolute path to a regular `.txt` file that is not a symbolic link, has no
15
+ * other hard link, and whose real location is inside the directory's real
16
+ * location (so a link anywhere along the path, or `..`, takes it out). Nothing
17
+ * is created, and nothing but a read is offered.
18
+ */
19
+ export async function resolveRetainedOutput(
20
+ directory: string | undefined,
21
+ candidate: string | undefined,
22
+ ): Promise<string | undefined> {
23
+ if (!directory || !candidate || !isAbsolute(candidate) || candidate.includes('\0'))
24
+ return undefined
25
+ try {
26
+ const base = await realpath(directory)
27
+ const lexical = resolve(candidate)
28
+ if (extname(lexical).toLowerCase() !== '.txt') return undefined
29
+ if (!inside(resolve(directory), lexical) && !inside(base, lexical)) return undefined
30
+ const stat = await lstat(lexical)
31
+ if (stat.isSymbolicLink() || !stat.isFile() || stat.nlink !== 1) return undefined
32
+ const real = await realpath(lexical)
33
+ if (!inside(base, real) || dirname(real) === real) return undefined
34
+ return real
35
+ } catch {
36
+ return undefined
37
+ }
38
+ }
@@ -5,6 +5,48 @@ import type { SessionEventListener } from '../session/events.js'
5
5
  import type { AgentLifecycleListener } from './lifecycle-event.js'
6
6
  import type { AgentTask, AgentTaskContext, AgentTaskState, SendMessageOptions } from './task.js'
7
7
 
8
+ /** Why a saved child could not be made continuable again. */
9
+ export type RestoreChildRefusal =
10
+ /** No project layout is known, so there is no saved log to read. */
11
+ | 'no-layout'
12
+ /** Nothing readable is saved under that id for this parent. */
13
+ | 'not-saved'
14
+ /** The saved record belongs to another parent session. */
15
+ | 'foreign'
16
+ /** The saved record carries no continuation profile, was isolated, or names an agent the host cannot rebuild. */
17
+ | 'not-resumable'
18
+ /** The child never recorded an end: its process died mid-turn. */
19
+ | 'unsettled'
20
+ /** The child was cancelled. */
21
+ | 'stopped'
22
+ /** This manager already holds a continuation for it that is still running. */
23
+ | 'running'
24
+ /** Too many continuations are retained to take another. */
25
+ | 'full'
26
+
27
+ export interface RestoreChildOptions {
28
+ /** The saved child's session id. */
29
+ readonly childSessionId: SessionId
30
+ /** The directory the continued child works in; the same one it ran in. */
31
+ readonly workingDirectory: string
32
+ /**
33
+ * Which registered agent the child continues as, given the profile the host
34
+ * recorded at launch. Return `undefined` when the host cannot rebuild it.
35
+ */
36
+ readonly agentFor: (profile: Readonly<Record<string, string>>) => string | undefined
37
+ }
38
+
39
+ export type RestoreChildResult =
40
+ | {
41
+ readonly status: 'restored'
42
+ readonly childSessionId: SessionId
43
+ /** The agent chosen by {@link RestoreChildOptions.agentFor}; pass it to `createTask` with `resumeSessionId`. */
44
+ readonly agentId: string
45
+ readonly profile: Readonly<Record<string, string>>
46
+ readonly description: string
47
+ }
48
+ | { readonly status: 'refused'; readonly reason: RestoreChildRefusal }
49
+
8
50
  /**
9
51
  * Agent task lifecycle contract — task creation, cancellation, messaging, and completion tracking.
10
52
  * Concrete implementation: `AgentManager` in `manager/agent/lifecycle.ts`.
@@ -48,6 +90,18 @@ export interface AgentManagerContract {
48
90
  on(listener: AgentLifecycleListener): void
49
91
  off(listener: AgentLifecycleListener): void
50
92
 
93
+ /**
94
+ * Rebuild the right to continue a child that finished in an earlier process
95
+ * from its saved log and meta document, under the invoking parent's scope.
96
+ * Optional: only a manager that can read saved children offers it. Grants
97
+ * nothing by itself; continuing still goes through `sendMessage` with
98
+ * `resumeSessionId`, with the invoking turn's authority and limits.
99
+ */
100
+ restoreChildConversation?(
101
+ options: RestoreChildOptions,
102
+ context: AgentTaskContext,
103
+ ): Promise<RestoreChildResult>
104
+
51
105
  cleanup(): void
52
106
  dispose(): void
53
107
  }
@@ -5,6 +5,7 @@ import type { CancelCause } from '../session/cancel-cause.js'
5
5
  import type { ChildSessionLifecycleEvent, SessionEventListener } from '../session/events.js'
6
6
  import type { WorkspaceRef } from '../workspace/ref.js'
7
7
  import type { AgentRuntimeContext, BaseAgentConfig, BaseAgentResult } from './base.js'
8
+ import type { RestoreChildOptions, RestoreChildResult } from './manager.js'
8
9
  import type { AgentTaskState, ChildWorkspaceRequest } from './task.js'
9
10
 
10
11
  export interface TaskHandle {
@@ -41,6 +42,15 @@ export interface CreateTaskOptions {
41
42
  * and unchanged agent definition. A saved log alone grants no authority.
42
43
  */
43
44
  readonly resumeSessionId?: SessionId
45
+ /**
46
+ * What a later process needs to rebuild this child, written to the child's
47
+ * saved meta document: at most 16 string entries, keys up to 64 and values up
48
+ * to 256 characters. The host defines the keys (which agent to rebuild,
49
+ * which model) and reads them back from `restoreChild`. Never put a secret
50
+ * here; it lands on disk beside the log. Absent, the child cannot be
51
+ * continued from disk after its process ends.
52
+ */
53
+ readonly continuationProfile?: Readonly<Record<string, string>>
44
54
  /** Per-task filesystem choice, forwarded to the local manager at admission. */
45
55
  readonly workspace?: ChildWorkspaceRequest
46
56
  /**
@@ -156,6 +166,17 @@ export interface TaskScheduler {
156
166
 
157
167
  continueTask(taskId: TaskId, message: string): Promise<void>
158
168
 
169
+ /**
170
+ * Make a child saved by an earlier process continuable again, from its saved
171
+ * log and meta document, under this scheduler's parent scope. OPTIONAL: only
172
+ * a scheduler that can read saved children offers it. It runs nothing; the
173
+ * caller then continues the child with `createTask({ resumeSessionId })`, so
174
+ * the invoking turn's authority and limits apply. See
175
+ * {@link CreateTaskOptions.continuationProfile} for what must have been
176
+ * recorded at launch.
177
+ */
178
+ restoreChild?(options: RestoreChildOptions): Promise<RestoreChildResult>
179
+
159
180
  /**
160
181
  * Stop one task. A cause is relative to the child: a blocking delegation
161
182
  * abandoned by the turn that launched it is cancelled by its `parent`.
@@ -238,6 +238,8 @@ export interface AgentTask {
238
238
  export interface SendMessageOptions {
239
239
  /** See {@link import('./scheduler.js').CreateTaskOptions.resumeSessionId}. */
240
240
  readonly resumeSessionId?: SessionId
241
+ /** See {@link import('./scheduler.js').CreateTaskOptions.continuationProfile}. */
242
+ readonly continuationProfile?: Readonly<Record<string, string>>
241
243
  /** Explicit child filesystem policy; omitted preserves legacy backend behavior. */
242
244
  readonly workspace?: ChildWorkspaceRequest
243
245
  /**
@@ -1039,6 +1039,22 @@ export const ChildSessionMetaSchema = z
1039
1039
  status: turnExecutionStatus,
1040
1040
  createdAt: isoUtc,
1041
1041
  endedAt: isoUtc.optional(),
1042
+ /**
1043
+ * What a later process needs to continue this child from its saved log:
1044
+ * the filesystem policy it ran under and a small host-defined profile
1045
+ * (which agent to rebuild, which model). Absent on children saved before
1046
+ * this field existed and on children whose host recorded no profile; those
1047
+ * cannot be continued from disk.
1048
+ */
1049
+ continuation: z
1050
+ .object({
1051
+ workspace: z.enum(['shared', 'isolated']),
1052
+ profile: z
1053
+ .record(z.string().min(1).max(64), z.string().max(256))
1054
+ .refine((value) => Object.keys(value).length <= 16, 'At most 16 profile entries'),
1055
+ })
1056
+ .strict()
1057
+ .optional(),
1042
1058
  })
1043
1059
  .strict()
1044
1060
  export type ChildSessionMeta = z.infer<typeof ChildSessionMetaSchema>
@@ -458,6 +458,14 @@ export interface ToolContext {
458
458
  * directory; an absolute path inside any of these is accepted.
459
459
  */
460
460
  additionalDirectories?: readonly string[]
461
+ /**
462
+ * Absolute path of the directory holding THIS session's retained tool
463
+ * output (the files an oversized result was saved to). The `read` tool may
464
+ * open a regular file in it, and only that, without the path being a
465
+ * reviewed or added directory: the model was already shown the path in the
466
+ * result it came from. Set by the executor whenever the turn retains output.
467
+ */
468
+ retainedOutputDirectory?: string
461
469
  /**
462
470
  * Absolute paths outside the working directory and the added directories
463
471
  * that THIS call was approved to reach.