@namzu/sdk 48.0.0 → 48.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.
- package/CHANGELOG.md +34 -0
- package/dist/connector/mcp/adapter.d.ts.map +1 -1
- package/dist/connector/mcp/adapter.js +11 -0
- package/dist/connector/mcp/adapter.js.map +1 -1
- package/dist/connector/mcp/client.d.ts +19 -0
- package/dist/connector/mcp/client.d.ts.map +1 -1
- package/dist/connector/mcp/client.js +363 -2
- package/dist/connector/mcp/client.js.map +1 -1
- package/dist/connector/mcp/era.d.ts.map +1 -1
- package/dist/connector/mcp/era.js +7 -0
- package/dist/connector/mcp/era.js.map +1 -1
- package/dist/connector/mcp/streamable-http.d.ts +15 -0
- package/dist/connector/mcp/streamable-http.d.ts.map +1 -1
- package/dist/connector/mcp/streamable-http.js +281 -6
- package/dist/connector/mcp/streamable-http.js.map +1 -1
- package/dist/manager/agent/lifecycle.d.ts +1 -0
- package/dist/manager/agent/lifecycle.d.ts.map +1 -1
- package/dist/manager/agent/lifecycle.js +137 -18
- package/dist/manager/agent/lifecycle.js.map +1 -1
- package/dist/manager/resident/initiative.d.ts +6 -6
- package/dist/manager/resident/outbox.d.ts +4 -4
- package/dist/scheduler/local.d.ts.map +1 -1
- package/dist/scheduler/local.js +2 -0
- package/dist/scheduler/local.js.map +1 -1
- package/dist/session/retention/archive.js +1 -1
- package/dist/session/retention/archive.js.map +1 -1
- package/dist/store/session/disk.d.ts.map +1 -1
- package/dist/store/session/disk.js +2 -0
- package/dist/store/session/disk.js.map +1 -1
- package/dist/tools/builtins/browser.js +2 -2
- package/dist/tools/builtins/browser.js.map +1 -1
- package/dist/tools/schedules/schedule-tool.d.ts.map +1 -1
- package/dist/tools/schedules/schedule-tool.js +12 -5
- package/dist/tools/schedules/schedule-tool.js.map +1 -1
- package/dist/tools/schedules/types.d.ts +6 -0
- package/dist/tools/schedules/types.d.ts.map +1 -1
- package/dist/types/agent/scheduler.d.ts +6 -1
- package/dist/types/agent/scheduler.d.ts.map +1 -1
- package/dist/types/agent/task.d.ts +19 -1
- package/dist/types/agent/task.d.ts.map +1 -1
- package/dist/types/agent/task.js.map +1 -1
- package/dist/types/connector/mcp.d.ts +13 -0
- package/dist/types/connector/mcp.d.ts.map +1 -1
- package/dist/types/session/sub-session.d.ts +2 -0
- package/dist/types/session/sub-session.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/connector/mcp/adapter.ts +15 -0
- package/src/connector/mcp/client.ts +405 -2
- package/src/connector/mcp/era.ts +7 -0
- package/src/connector/mcp/streamable-http.ts +302 -5
- package/src/manager/agent/lifecycle.ts +158 -19
- package/src/scheduler/local.ts +2 -0
- package/src/session/retention/archive.ts +1 -1
- package/src/store/session/disk.ts +3 -0
- package/src/tools/builtins/browser.ts +2 -2
- package/src/tools/schedules/schedule-tool.ts +16 -5
- package/src/tools/schedules/types.ts +6 -0
- package/src/types/agent/scheduler.ts +6 -1
- package/src/types/agent/task.ts +21 -1
- package/src/types/connector/mcp.ts +14 -0
- package/src/types/session/sub-session.ts +2 -0
|
@@ -223,7 +223,7 @@ export class ArchivalManager {
|
|
|
223
223
|
|
|
224
224
|
// 6. Dispose the workspace (idempotent — driver contract tolerates
|
|
225
225
|
// already-disposed refs; a missing ref is a no-op).
|
|
226
|
-
if (workspace) {
|
|
226
|
+
if (workspace && sub.workspaceRetention !== 'retain') {
|
|
227
227
|
try {
|
|
228
228
|
const driver = this.deps.workspaceRegistry.get(workspace.meta.backend)
|
|
229
229
|
await driver.dispose(workspace)
|
|
@@ -226,6 +226,7 @@ interface PersistedSubSession {
|
|
|
226
226
|
failureMode: SubSession['failureMode']
|
|
227
227
|
completionMode: SubSession['completionMode']
|
|
228
228
|
workspaceId: SubSession['workspaceId']
|
|
229
|
+
workspaceRetention?: SubSession['workspaceRetention']
|
|
229
230
|
broadcastGroupId?: string
|
|
230
231
|
summaryRef?: SubSession['summaryRef']
|
|
231
232
|
archiveRef?: SubSession['archiveRef']
|
|
@@ -1126,6 +1127,7 @@ function serializeSubSession(s: SubSession, tenantId: TenantId): PersistedSubSes
|
|
|
1126
1127
|
failureMode: s.failureMode,
|
|
1127
1128
|
completionMode: s.completionMode,
|
|
1128
1129
|
workspaceId: s.workspaceId,
|
|
1130
|
+
...(s.workspaceRetention !== undefined && { workspaceRetention: s.workspaceRetention }),
|
|
1129
1131
|
...(s.broadcastGroupId !== undefined && { broadcastGroupId: s.broadcastGroupId }),
|
|
1130
1132
|
...(s.summaryRef !== undefined && { summaryRef: s.summaryRef }),
|
|
1131
1133
|
...(s.archiveRef !== undefined && { archiveRef: s.archiveRef }),
|
|
@@ -1146,6 +1148,7 @@ function deserializeSubSession(s: PersistedSubSession): SubSession {
|
|
|
1146
1148
|
failureMode: s.failureMode,
|
|
1147
1149
|
completionMode: s.completionMode,
|
|
1148
1150
|
workspaceId: s.workspaceId,
|
|
1151
|
+
...(s.workspaceRetention !== undefined && { workspaceRetention: s.workspaceRetention }),
|
|
1149
1152
|
...(s.broadcastGroupId !== undefined && { broadcastGroupId: s.broadcastGroupId }),
|
|
1150
1153
|
...(s.summaryRef !== undefined && { summaryRef: s.summaryRef }),
|
|
1151
1154
|
...(s.archiveRef !== undefined && { archiveRef: s.archiveRef }),
|
|
@@ -508,7 +508,7 @@ const HUMAN_REASON_WORDS: Record<BrowserHumanRequired['reason'], string> = {
|
|
|
508
508
|
'two-factor': 'a second sign-in step',
|
|
509
509
|
captcha: 'a CAPTCHA',
|
|
510
510
|
'bot-block': 'a bot check',
|
|
511
|
-
'http-auth': '
|
|
511
|
+
'http-auth': 'an HTTP authentication challenge',
|
|
512
512
|
'credential-field': 'a password or one-time-code field',
|
|
513
513
|
}
|
|
514
514
|
|
|
@@ -527,7 +527,7 @@ function hostErrorToResult(tool: string, error: BrowserHostError): ToolResult {
|
|
|
527
527
|
case 'browser_human_required': {
|
|
528
528
|
const what = HUMAN_REASON_WORDS[error.reason] ?? 'something only a person can do'
|
|
529
529
|
const how = error.loginCommand
|
|
530
|
-
? ` The user can sign in with: ${oneLine(error.loginCommand, 300)}`
|
|
530
|
+
? ` The user can ${error.reason === 'http-auth' ? 'check access' : 'sign in'} with: ${oneLine(error.loginCommand, 300)}`
|
|
531
531
|
: ''
|
|
532
532
|
const detail = {
|
|
533
533
|
origin: error.origin,
|
|
@@ -74,20 +74,28 @@ const inputSchema = z.object({
|
|
|
74
74
|
folder: z
|
|
75
75
|
.string()
|
|
76
76
|
.optional()
|
|
77
|
-
.describe(
|
|
77
|
+
.describe(
|
|
78
|
+
"create: existing working directory for the job; leave unset for the session's folder when valid. The file system root, the operator's home directory, NAMZU_HOME and a folder containing NAMZU_HOME are refused. If this session is in one of those, choose an existing project subfolder and set folder explicitly",
|
|
79
|
+
),
|
|
78
80
|
tz: z
|
|
79
81
|
.string()
|
|
80
82
|
.optional()
|
|
81
83
|
.describe(
|
|
82
84
|
"create: IANA time zone; leave unset for the operator's own zone unless the user named another",
|
|
83
85
|
),
|
|
86
|
+
notifyOnFinish: z
|
|
87
|
+
.boolean()
|
|
88
|
+
.optional()
|
|
89
|
+
.describe(
|
|
90
|
+
'create/update: enable routine Namzu desktop completion notices, subject to rate limits (default true). Set false for a script that sends its own notice only when something changes; failure notices stay enabled.',
|
|
91
|
+
),
|
|
84
92
|
permissions: z
|
|
85
93
|
.object({
|
|
86
94
|
preset: z
|
|
87
95
|
.enum(['read-only', 'edit-in-folder'])
|
|
88
96
|
.optional()
|
|
89
97
|
.describe(
|
|
90
|
-
'read-only: read/glob/grep/ls only. edit-in-folder: also edit and write, bash asks',
|
|
98
|
+
'read-only: read/glob/grep/ls only; its bash deny blocks every script. edit-in-folder: also edit and write, bash asks. For a pure script, omit the preset and set rules to {} with unmatched: deny',
|
|
91
99
|
),
|
|
92
100
|
unmatched: z
|
|
93
101
|
.enum(['park', 'deny'])
|
|
@@ -120,7 +128,7 @@ const inputSchema = z.object({
|
|
|
120
128
|
})
|
|
121
129
|
.optional()
|
|
122
130
|
.describe(
|
|
123
|
-
'create: REQUIRED explicit permission set; there is no default. A pure script cannot use a browser grant. update: the whole new set, only when the permissions change',
|
|
131
|
+
'create: REQUIRED explicit permission set; there is no default. For a pure script, use {rules:{}, unmatched:"deny"} without a preset unless you intend deny rules: read-only denies bash and blocks every script. A pure script cannot use a browser grant. update: the whole new set, only when the permissions change',
|
|
124
132
|
),
|
|
125
133
|
budget: z
|
|
126
134
|
.object({
|
|
@@ -311,6 +319,7 @@ async function create(
|
|
|
311
319
|
...(input.prompt !== undefined ? { prompt: input.prompt } : {}),
|
|
312
320
|
...(input.folder !== undefined ? { folder: input.folder } : {}),
|
|
313
321
|
...(input.tz !== undefined ? { tz: input.tz } : {}),
|
|
322
|
+
...(input.notifyOnFinish !== undefined ? { notifyOnFinish: input.notifyOnFinish } : {}),
|
|
314
323
|
permissions,
|
|
315
324
|
...(input.budget ? { budget: input.budget } : {}),
|
|
316
325
|
}
|
|
@@ -352,7 +361,7 @@ async function create(
|
|
|
352
361
|
? `Job "${created.name}" was created paused. The operator can resume it with /schedule.`
|
|
353
362
|
: runKind === 'script'
|
|
354
363
|
? `Job "${created.name}" was created. It runs ${preview.schedule}, with nobody watching; results are recorded in its history and may arrive as a notification. It creates no session.`
|
|
355
|
-
: `Job "${created.name}" was created. It runs ${preview.schedule}, with nobody watching; results
|
|
364
|
+
: `Job "${created.name}" was created. It runs ${preview.schedule}, with nobody watching; results are recorded in a session. Completion notices ${draft.notifyOnFinish === false ? 'are off' : 'are enabled, subject to rate limits'}.`
|
|
356
365
|
return {
|
|
357
366
|
success: true,
|
|
358
367
|
output: created.note ? `${said} ${created.note}` : said,
|
|
@@ -381,6 +390,7 @@ const CHANGEABLE = [
|
|
|
381
390
|
'when',
|
|
382
391
|
'folder',
|
|
383
392
|
'tz',
|
|
393
|
+
'notifyOnFinish',
|
|
384
394
|
'permissions',
|
|
385
395
|
'budget',
|
|
386
396
|
'kind',
|
|
@@ -439,6 +449,7 @@ async function update(
|
|
|
439
449
|
...(input.when !== undefined ? { when: input.when } : {}),
|
|
440
450
|
...(input.folder !== undefined ? { folder: input.folder } : {}),
|
|
441
451
|
...(input.tz !== undefined ? { tz: input.tz } : {}),
|
|
452
|
+
...(input.notifyOnFinish !== undefined ? { notifyOnFinish: input.notifyOnFinish } : {}),
|
|
442
453
|
...(permissions ? { permissions } : {}),
|
|
443
454
|
...(input.budget ? { budget: input.budget } : {}),
|
|
444
455
|
...(input.kind !== undefined ? { runKind: input.kind } : {}),
|
|
@@ -543,7 +554,7 @@ export function buildScheduleTools(host: ScheduleToolHost): ToolDefinition[] {
|
|
|
543
554
|
defineTool({
|
|
544
555
|
name: SCHEDULE_TOOL_NAME,
|
|
545
556
|
description:
|
|
546
|
-
"Manage the operator's scheduled jobs: model prompts or fixed scripts that run later in a folder, with nobody watching, under an explicit permission set. Use it only when the user asks for something to happen on a schedule. create, update, resume and delete are confirmed by the operator; pause is not. A job needs name, when and permissions (unmatched: park or deny, plus a preset, rules or a browser grant). agent and script+agent also need prompt; script and script+agent also need script. A pure script has no prompt, model, agent budget, browser grant or session; set script.timeoutMs to limit it. To change a job, update it with job and only the fields that change; do not delete and recreate it. Leave
|
|
557
|
+
"Manage the operator's scheduled jobs: model prompts or fixed scripts that run later in a folder, with nobody watching, under an explicit permission set. Use it only when the user asks for something to happen on a schedule. create, update, resume and delete are confirmed by the operator; pause is not. A job needs name, when and permissions (unmatched: park or deny, plus a preset, rules or a browser grant). agent and script+agent also need prompt; script and script+agent also need script. For a pure script, use permissions {rules:{},unmatched:'deny'} without a preset unless you intend deny rules: read-only denies bash and blocks every script. A pure script has no prompt, model, agent budget, browser grant or session; set script.timeoutMs to limit it. To change a job, update it with job and only the fields that change; do not delete and recreate it. Leave folder unset when the session folder is valid; home, root and NAMZU_HOME are invalid, so choose an existing project subfolder there. Leave tz, execution, budget and headed unset unless the user asked for them: the defaults are the operator's, and the confirmation marks each value you chose. Scheduled runs cannot ask questions.",
|
|
547
558
|
inputSchema,
|
|
548
559
|
category: 'custom',
|
|
549
560
|
permissions: [],
|
|
@@ -40,6 +40,8 @@ export interface ScheduleJobDraft {
|
|
|
40
40
|
readonly folder?: string
|
|
41
41
|
/** IANA zone for a cron expression or a local time. Absent: the host's. */
|
|
42
42
|
readonly tz?: string
|
|
43
|
+
/** Enable routine completion notices. Absent: the host's usual setting. */
|
|
44
|
+
readonly notifyOnFinish?: boolean
|
|
43
45
|
readonly permissions: {
|
|
44
46
|
readonly preset?: 'read-only' | 'edit-in-folder'
|
|
45
47
|
/**
|
|
@@ -109,6 +111,8 @@ export interface ScheduleJobPreview {
|
|
|
109
111
|
}
|
|
110
112
|
/** The schedule in words, with its zone. */
|
|
111
113
|
readonly schedule: string
|
|
114
|
+
/** Whether a completed run sends a Namzu desktop notice; absent for older hosts. */
|
|
115
|
+
readonly notifyOnFinish?: boolean
|
|
112
116
|
/** The next fire times, ISO-8601 UTC. */
|
|
113
117
|
readonly nextFireTimes: readonly string[]
|
|
114
118
|
/** The permission set expanded to one line per rule, config denies included. */
|
|
@@ -164,6 +168,8 @@ export interface ScheduleJobChanges {
|
|
|
164
168
|
readonly when?: string
|
|
165
169
|
readonly folder?: string
|
|
166
170
|
readonly tz?: string
|
|
171
|
+
/** Whether routine Namzu desktop completion notices are enabled. */
|
|
172
|
+
readonly notifyOnFinish?: boolean
|
|
167
173
|
readonly permissions?: ScheduleJobDraft['permissions']
|
|
168
174
|
readonly budget?: ScheduleJobDraft['budget']
|
|
169
175
|
/**
|
|
@@ -3,8 +3,9 @@ import type { TaskId } from '../ids/index.js'
|
|
|
3
3
|
import type { AgentPersona } from '../persona/index.js'
|
|
4
4
|
import type { CancelCause } from '../session/cancel-cause.js'
|
|
5
5
|
import type { ChildSessionLifecycleEvent, SessionEventListener } from '../session/events.js'
|
|
6
|
+
import type { WorkspaceRef } from '../workspace/ref.js'
|
|
6
7
|
import type { AgentRuntimeContext, BaseAgentConfig, BaseAgentResult } from './base.js'
|
|
7
|
-
import type { AgentTaskState } from './task.js'
|
|
8
|
+
import type { AgentTaskState, ChildWorkspaceRequest } from './task.js'
|
|
8
9
|
|
|
9
10
|
export interface TaskHandle {
|
|
10
11
|
readonly taskId: TaskId
|
|
@@ -13,6 +14,8 @@ export interface TaskHandle {
|
|
|
13
14
|
readonly result?: BaseAgentResult
|
|
14
15
|
readonly createdAt: number
|
|
15
16
|
readonly completedAt?: number
|
|
17
|
+
/** The workspace assigned to an explicitly isolated child, when admitted. */
|
|
18
|
+
readonly workspace?: WorkspaceRef
|
|
16
19
|
}
|
|
17
20
|
|
|
18
21
|
/**
|
|
@@ -29,6 +32,8 @@ export interface TaskHandle {
|
|
|
29
32
|
export type SiblingFailurePolicy = 'continue' | 'cancel-siblings'
|
|
30
33
|
|
|
31
34
|
export interface CreateTaskOptions {
|
|
35
|
+
/** Per-task filesystem choice, forwarded to the local manager at admission. */
|
|
36
|
+
readonly workspace?: ChildWorkspaceRequest
|
|
32
37
|
/**
|
|
33
38
|
* Revalidate host authority at actual admission, including after a capacity wait.
|
|
34
39
|
* Queue retries may invoke this more than once; checks must tolerate repeated calls.
|
package/src/types/agent/task.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { SessionTokenBudget } from '../../store/budget/index.js'
|
|
2
2
|
import type { ActorRef } from '../../types/session/actor.js'
|
|
3
|
-
import type { WorkspaceBackendKind } from '../../types/workspace/ref.js'
|
|
3
|
+
import type { WorkspaceBackendKind, WorkspaceRef } from '../../types/workspace/ref.js'
|
|
4
4
|
import type { ResumeHandler } from '../hitl/index.js'
|
|
5
5
|
import type { SessionId, TaskId, TenantId, TurnId } from '../ids/index.js'
|
|
6
6
|
import type { Message } from '../message/index.js'
|
|
@@ -19,6 +19,19 @@ export type AgentTaskState =
|
|
|
19
19
|
| 'rejected'
|
|
20
20
|
| 'input-required'
|
|
21
21
|
|
|
22
|
+
/** Per-spawn filesystem choice. Omission preserves the manager's existing behavior. */
|
|
23
|
+
export type ChildWorkspaceRequest =
|
|
24
|
+
| { readonly mode: 'shared' }
|
|
25
|
+
| {
|
|
26
|
+
readonly mode: 'isolated'
|
|
27
|
+
readonly backend: 'git-worktree'
|
|
28
|
+
readonly baseRef?: string
|
|
29
|
+
/** Relative directory within the checkout where this child starts. */
|
|
30
|
+
readonly subdirectory?: string
|
|
31
|
+
/** The existing SDK behavior is `dispose`; CLI delegates select `retain`. */
|
|
32
|
+
readonly retention?: 'dispose' | 'retain'
|
|
33
|
+
}
|
|
34
|
+
|
|
22
35
|
export function isTerminalAgentTaskState(state: AgentTaskState): boolean {
|
|
23
36
|
return state === 'completed' || state === 'failed' || state === 'canceled' || state === 'rejected'
|
|
24
37
|
}
|
|
@@ -206,6 +219,8 @@ export interface AgentTask {
|
|
|
206
219
|
pendingMessages: Message[]
|
|
207
220
|
createdAt: number
|
|
208
221
|
completedAt?: number
|
|
222
|
+
/** Populated after an explicitly isolated spawn is admitted. */
|
|
223
|
+
workspace?: WorkspaceRef
|
|
209
224
|
|
|
210
225
|
evictAfter?: number
|
|
211
226
|
|
|
@@ -219,6 +234,8 @@ export interface AgentTask {
|
|
|
219
234
|
* WorkspaceRef triple atomically on every spawn.
|
|
220
235
|
*/
|
|
221
236
|
export interface SendMessageOptions {
|
|
237
|
+
/** Explicit child filesystem policy; omitted preserves legacy backend behavior. */
|
|
238
|
+
readonly workspace?: ChildWorkspaceRequest
|
|
222
239
|
/**
|
|
223
240
|
* Revalidate host authority before admission, including after a capacity wait.
|
|
224
241
|
* Queue retries may invoke this more than once; checks must tolerate repeated calls.
|
|
@@ -287,6 +304,9 @@ export interface SendMessageOptions {
|
|
|
287
304
|
}
|
|
288
305
|
|
|
289
306
|
export interface AgentManagerConfig {
|
|
307
|
+
/** When neither task workspace field is set, use the registered backend (legacy) or share cwd. */
|
|
308
|
+
workspaceDefault?: 'registered' | 'shared'
|
|
309
|
+
|
|
290
310
|
/** Reject a full parent immediately (default), or retain bounded pending task handles. */
|
|
291
311
|
capacityBehavior?: 'reject' | 'queue'
|
|
292
312
|
|
|
@@ -178,6 +178,14 @@ export interface MCPJsonRpcMessage {
|
|
|
178
178
|
error?: MCPJsonRpcError
|
|
179
179
|
}
|
|
180
180
|
|
|
181
|
+
/** A validated, bounded update from one MCP tool call. */
|
|
182
|
+
export interface MCPProgressUpdate {
|
|
183
|
+
readonly progress: number
|
|
184
|
+
readonly total?: number
|
|
185
|
+
/** Server text with terminal controls removed, limited to 512 UTF-8 bytes. */
|
|
186
|
+
readonly message?: string
|
|
187
|
+
}
|
|
188
|
+
|
|
181
189
|
/** Authority for one MCP JSON-RPC request. */
|
|
182
190
|
export interface MCPRequestOptions {
|
|
183
191
|
/**
|
|
@@ -187,6 +195,12 @@ export interface MCPRequestOptions {
|
|
|
187
195
|
* waiting, not that an already-started remote side effect was rolled back.
|
|
188
196
|
*/
|
|
189
197
|
readonly signal?: AbortSignal
|
|
198
|
+
/**
|
|
199
|
+
* Receive progress for this `tools/call` only. The client adds a unique
|
|
200
|
+
* `_meta.progressToken` when this is supplied and stops delivery as soon as
|
|
201
|
+
* the request completes, fails or is cancelled. Other methods ignore it.
|
|
202
|
+
*/
|
|
203
|
+
readonly onProgress?: (update: MCPProgressUpdate) => void
|
|
190
204
|
/**
|
|
191
205
|
* Extra headers for this one request, merged over the transport's static
|
|
192
206
|
* config headers (a collision resolves to this value) and under this same
|
|
@@ -100,6 +100,8 @@ export interface SubSession {
|
|
|
100
100
|
failureMode: FailureMode
|
|
101
101
|
completionMode: CompletionMode
|
|
102
102
|
workspaceId: WorkspaceId | null
|
|
103
|
+
/** Keep this delegated workspace when the child ends or its session is archived. */
|
|
104
|
+
workspaceRetention?: 'retain'
|
|
103
105
|
/**
|
|
104
106
|
* For interventions, the immutable artifact being addressed. Chains form
|
|
105
107
|
* a strict acyclic DAG — see session-hierarchy.md §4.5.
|