Skip to content

Commit 60d31d8

Browse files
committed
feat(node-sdk): expose subagent task query API
Mirrors the new Session APIs from the core crate so JS/TS callers can introspect delegated subagent tasks without parsing run_events. - `Session.subagentTask(taskId)` → snapshot or null - `Session.subagentTasks()` → snapshots from this session - `Session.pendingSubagentTasks()` → only `running` entries Regenerated index.d.ts also picks up doc-comment drift and napi-rs ordering churn that had accumulated since the last build. The hand-added type aliases (ToolErrorKind union, VerificationStatus / VerificationCheck / VerificationReport / ToolArtifact) are preserved — they aren't generatable from Rust and have to be reinserted around each rebuild. test.mjs gains a small smoke block confirming the three methods exist and return the expected empty-state shapes (array, array, null).
1 parent 56fb57a commit 60d31d8

3 files changed

Lines changed: 101 additions & 32 deletions

File tree

sdk/node/index.d.ts

Lines changed: 49 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -73,10 +73,9 @@ export interface AgentEvent {
7373
data?: string
7474
/**
7575
* Structured discriminant for tool failures on `tool_end` events
76-
* (JSON-encoded with a `type` field on the top level, e.g.
77-
* `{"type":"version_conflict","path":"doc.md","expected":"etag-1","actual":"etag-2"}`).
78-
* Undefined on success or untyped failure. Streaming consumers parse
79-
* this to branch on the failure kind without scanning `toolOutput`.
76+
* (JSON-encoded with a `type` field). `None` on success or untyped
77+
* failure. Lets streaming consumers branch on the failure kind
78+
* without scanning `tool_output`.
8079
*/
8180
errorKindJson?: string
8281
}
@@ -126,7 +125,7 @@ export interface ToolResult {
126125
* Structured discriminant for tool failures, JSON-encoded with a
127126
* `type` field on the top level — e.g.
128127
* `{"type":"version_conflict","path":"doc.md","expected":"etag-1","actual":"etag-2"}`.
129-
* Undefined on success or untyped failure. SDK callers parse it to
128+
* `None` on success or untyped failure. SDK callers parse it to
130129
* branch on the failure kind without scanning the `output` string.
131130
*/
132131
errorKindJson?: string
@@ -225,16 +224,6 @@ export interface InlineSkill {
225224
/** Markdown content for the skill. */
226225
content: string
227226
}
228-
export interface AutoDelegationOptions {
229-
/** Enable runtime-driven automatic child-agent delegation. */
230-
enabled?: boolean
231-
/** Allow automatic delegation to launch multiple child agents in parallel. */
232-
autoParallel?: boolean
233-
/** Minimum local confidence required to auto-delegate a child task. */
234-
minConfidence?: number
235-
/** Maximum number of automatic child tasks per user request. */
236-
maxTasks?: number
237-
}
238227
export interface JsMemoryStore {
239228
backend: string
240229
dir?: string
@@ -305,20 +294,21 @@ export interface JsS3BackendConfig {
305294
*/
306295
maxGrepBytesPerObject?: number
307296
/**
308-
* Concurrent object downloads during `grep`. Defaults to 8 on the Rust
309-
* side. Set lower when the gitserver / S3 endpoint rate-limits
297+
* Concurrent object downloads during `grep`. Defaults to 8 on the
298+
* Rust side. Set lower when the gitserver / S3 endpoint rate-limits
310299
* aggressively; set higher when latency dominates. Ignored when
311300
* `searchEnabled` is `false`.
312301
*/
313302
searchConcurrency?: number
314303
}
315304
/**
316-
* Configuration for a `RemoteGitBackend` — an HTTP/JSON client that
305+
* Configuration for a [`RemoteGitBackend`] — an HTTP/JSON client that
317306
* brings the `git` tool to non-local workspaces (S3, future container /
318307
* DFS).
319308
*
320309
* Pass alongside `workspaceBackend` on a session to attach remote git
321-
* on top of any filesystem backend.
310+
* on top of any filesystem backend. The protocol is specified in the
311+
* repository RFC `apps/docs/content/docs/en/code/rfcs/workspace-remote-git.mdx`.
322312
*/
323313
export interface JsRemoteGitBackendConfig {
324314
/**
@@ -333,14 +323,15 @@ export interface JsRemoteGitBackendConfig {
333323
repoId: string
334324
/**
335325
* Bearer token sent as `Authorization: Bearer <token>`. Required in
336-
* production; omitting it emits a server-side warning and is only safe
326+
* production; omitting it emits a `tracing::warn!` and is only safe
337327
* on a trusted localhost gitserver.
338328
*/
339329
bearerToken?: string
340330
/**
341-
* mTLS client certificate path (PEM). When set together with `clientKeyPem`,
342-
* the backend reads both files at construction and configures mTLS on the
343-
* HTTP client. Setting only one of the pair errors at construction.
331+
* mTLS client certificate path (PEM). When set together with
332+
* `clientKeyPem`, the backend reads both files at construction and
333+
* configures mTLS on the HTTP client. Setting only one of the pair
334+
* errors at construction.
344335
*/
345336
clientCertPem?: string
346337
/**
@@ -444,12 +435,19 @@ export interface PendingConfirmation {
444435
/** Milliseconds remaining before the confirmation times out. */
445436
remainingMs: number
446437
}
447-
/** Retention limits for large tool/program artifacts. */
448-
export interface ArtifactStoreLimits {
449-
/** Maximum number of artifacts retained by a session. */
450-
maxArtifacts?: number
451-
/** Maximum total artifact content bytes retained by a session. */
452-
maxBytes?: number
438+
export interface AutoDelegationOptions {
439+
/** Enable runtime-driven automatic child-agent delegation. */
440+
enabled?: boolean
441+
/**
442+
* Allow automatic delegation to launch multiple child agents in parallel.
443+
*
444+
* Manual `parallel_task` calls remain available when this is false.
445+
*/
446+
autoParallel?: boolean
447+
/** Minimum local confidence required to auto-delegate a child task. */
448+
minConfidence?: number
449+
/** Maximum number of automatic child tasks per user request. */
450+
maxTasks?: number
453451
}
454452
export interface SessionOptions {
455453
/** Override the default model. Format: "provider/model" (e.g., "openai/gpt-4o"). */
@@ -668,6 +666,13 @@ export interface SessionOptions {
668666
*/
669667
maxExecutionTimeMs?: number
670668
}
669+
/** Retention limits for large tool/program artifacts. */
670+
export interface ArtifactStoreLimits {
671+
/** Maximum number of artifacts retained by a session. */
672+
maxArtifacts?: number
673+
/** Maximum total artifact content bytes retained by a session. */
674+
maxBytes?: number
675+
}
671676
/** A single message in conversation history. */
672677
export interface MessageObject {
673678
role: string
@@ -1174,6 +1179,18 @@ export declare class Session {
11741179
currentRun(): Promise<any>
11751180
/** Return active tool calls observed for the currently running operation. */
11761181
activeTools(): Promise<any>
1182+
/**
1183+
* Look up a delegated subagent task by id. Resolves to `null` when no
1184+
* such task has been observed in this session.
1185+
*/
1186+
subagentTask(taskId: string): Promise<any>
1187+
/**
1188+
* Return snapshots of every delegated subagent task observed in this
1189+
* session (including completed and failed ones), oldest first.
1190+
*/
1191+
subagentTasks(): Promise<any>
1192+
/** Return snapshots of subagent tasks still in `running` state. */
1193+
pendingSubagentTasks(): Promise<any>
11771194
/** Cancel a specific run only if it is still the active run. */
11781195
cancelRun(runId: string): Promise<boolean>
11791196
/** Execute a tool by name, bypassing the LLM. */
@@ -1261,9 +1278,9 @@ export declare class Session {
12611278
/** Return compact execution trace events recorded for this session. */
12621279
traceEvents(): any
12631280
/** Return structured verification reports recorded for this session. */
1264-
verificationReports(): Array<VerificationReport>
1281+
verificationReports(): any
12651282
/** Add externally produced verification reports to this session. */
1266-
recordVerificationReports(reports: Array<VerificationReport> | VerificationReport): void
1283+
recordVerificationReports(reports: any): void
12671284
/** Return a structured verification summary for this session. */
12681285
verificationSummary(): any
12691286
/** Return a concise human-readable verification summary for this session. */
@@ -1369,7 +1386,7 @@ export declare class Session {
13691386
/** Return full model-visible tool definitions currently registered on this session. */
13701387
toolDefinitions(): any
13711388
/** Return a stored tool artifact by URI, or null if it is not retained. */
1372-
getArtifact(artifactUri: string): ToolArtifact | null
1389+
getArtifact(artifactUri: string): any
13731390
/**
13741391
* Register a hook for lifecycle event interception.
13751392
*

sdk/node/src/lib.rs

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3098,6 +3098,44 @@ impl Session {
30983098
.map_err(|e| napi::Error::from_reason(format!("Serialization error: {e}")))
30993099
}
31003100

3101+
/// Look up a delegated subagent task by id. Resolves to `null` when no
3102+
/// such task has been observed in this session.
3103+
#[napi(js_name = "subagentTask")]
3104+
pub async fn subagent_task(&self, task_id: String) -> napi::Result<serde_json::Value> {
3105+
let session = self.inner.clone();
3106+
let snapshot = get_runtime()
3107+
.spawn(async move { session.subagent_task(&task_id).await })
3108+
.await
3109+
.map_err(|e| napi::Error::from_reason(format!("Task join error: {e}")))?;
3110+
serde_json::to_value(snapshot)
3111+
.map_err(|e| napi::Error::from_reason(format!("Serialization error: {e}")))
3112+
}
3113+
3114+
/// Return snapshots of every delegated subagent task observed in this
3115+
/// session (including completed and failed ones), oldest first.
3116+
#[napi(js_name = "subagentTasks")]
3117+
pub async fn subagent_tasks(&self) -> napi::Result<serde_json::Value> {
3118+
let session = self.inner.clone();
3119+
let tasks = get_runtime()
3120+
.spawn(async move { session.subagent_tasks().await })
3121+
.await
3122+
.map_err(|e| napi::Error::from_reason(format!("Task join error: {e}")))?;
3123+
serde_json::to_value(tasks)
3124+
.map_err(|e| napi::Error::from_reason(format!("Serialization error: {e}")))
3125+
}
3126+
3127+
/// Return snapshots of subagent tasks still in `running` state.
3128+
#[napi(js_name = "pendingSubagentTasks")]
3129+
pub async fn pending_subagent_tasks(&self) -> napi::Result<serde_json::Value> {
3130+
let session = self.inner.clone();
3131+
let tasks = get_runtime()
3132+
.spawn(async move { session.pending_subagent_tasks().await })
3133+
.await
3134+
.map_err(|e| napi::Error::from_reason(format!("Task join error: {e}")))?;
3135+
serde_json::to_value(tasks)
3136+
.map_err(|e| napi::Error::from_reason(format!("Serialization error: {e}")))
3137+
}
3138+
31013139
/// Cancel a specific run only if it is still the active run.
31023140
#[napi(js_name = "cancelRun")]
31033141
pub async fn cancel_run(&self, run_id: String) -> napi::Result<bool> {

sdk/node/test.mjs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,20 @@ assert.equal(
100100
)
101101
assert.match(result.text, /tools=\d+$/, 'custom slash command should receive toolNames in context')
102102

103+
// --- Subagent task query API (PR #3): three new Session methods ---
104+
{
105+
const list = await session.subagentTasks()
106+
assert.ok(Array.isArray(list), 'subagentTasks() should resolve to an array')
107+
assert.equal(list.length, 0, 'fresh session should have no subagent tasks')
108+
109+
const pending = await session.pendingSubagentTasks()
110+
assert.ok(Array.isArray(pending), 'pendingSubagentTasks() should resolve to an array')
111+
assert.equal(pending.length, 0, 'fresh session should have no pending subagent tasks')
112+
113+
const missing = await session.subagentTask('task-does-not-exist')
114+
assert.equal(missing, null, 'unknown subagent task id should resolve to null')
115+
}
116+
103117
session.close()
104118

105119
console.log('node sdk integration ok')

0 commit comments

Comments
 (0)