@roll-agent/runtime 0.15.1 → 0.17.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/dist/approval/approval-gate.d.ts +1 -0
- package/dist/approval/approval-memory.d.ts +5 -0
- package/dist/approval/approval-memory.js +1 -0
- package/dist/bash/exec.js +1 -1
- package/dist/bash/format-result.d.ts +4 -0
- package/dist/bash/format-result.js +1 -1
- package/dist/bash/output-dump.d.ts +16 -0
- package/dist/bash/output-dump.js +1 -0
- package/dist/bash/profile.d.ts +5 -0
- package/dist/bash/profile.js +1 -1
- package/dist/bash/session/session-exec.js +1 -1
- package/dist/bash/session/types.d.ts +7 -0
- package/dist/bash/session/yield-loop.js +1 -1
- package/dist/bash/shell-pipe.d.ts +26 -0
- package/dist/bash/shell-pipe.js +1 -0
- package/dist/bash/truncate.js +1 -1
- package/dist/engine/agent-session.d.ts +34 -3
- package/dist/engine/agent-session.js +1 -1
- package/dist/engine/cancelled-turn-recovery.d.ts +1 -0
- package/dist/engine/cancelled-turn-recovery.js +1 -1
- package/dist/engine/capability-manifest.d.ts +3 -0
- package/dist/engine/capability-manifest.js +1 -1
- package/dist/engine/compaction-checkpoint.d.ts +24 -24
- package/dist/engine/compactor.d.ts +3 -0
- package/dist/engine/compactor.js +1 -1
- package/dist/engine/context-window.js +1 -1
- package/dist/engine/conversation-engine.d.ts +8 -0
- package/dist/engine/conversation-engine.js +1 -1
- package/dist/engine/system-prompt.d.ts +16 -1
- package/dist/engine/system-prompt.js +1 -1
- package/dist/engine/workspace-instructions.d.ts +33 -0
- package/dist/engine/workspace-instructions.js +1 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +1 -1
- package/dist/server/runtime-protocol-adapter.js +1 -1
- package/dist/service/runtime-service.d.ts +2 -1
- package/dist/service/runtime-service.js +1 -1
- package/dist/store/thread-store.d.ts +19 -2
- package/dist/store/thread-store.js +1 -1
- package/dist/tool-bridge/bash-tool.d.ts +3 -0
- package/dist/tool-bridge/bash-tool.js +1 -1
- package/dist/tool-bridge/bounded-param.d.ts +14 -0
- package/dist/tool-bridge/bounded-param.js +1 -0
- package/dist/tool-bridge/build-tools.d.ts +8 -0
- package/dist/tool-bridge/build-tools.js +1 -1
- package/dist/tool-bridge/file-tools/control-chars.d.ts +11 -0
- package/dist/tool-bridge/file-tools/control-chars.js +1 -0
- package/dist/tool-bridge/file-tools/edit-file-tool.d.ts +43 -0
- package/dist/tool-bridge/file-tools/edit-file-tool.js +1 -0
- package/dist/tool-bridge/file-tools/edit-plan.d.ts +19 -0
- package/dist/tool-bridge/file-tools/edit-plan.js +1 -0
- package/dist/tool-bridge/file-tools/external-approval.d.ts +3 -0
- package/dist/tool-bridge/file-tools/external-approval.js +1 -0
- package/dist/tool-bridge/file-tools/file-change-result.d.ts +11 -0
- package/dist/tool-bridge/file-tools/file-change-result.js +1 -0
- package/dist/tool-bridge/file-tools/file-io.d.ts +35 -0
- package/dist/tool-bridge/file-tools/file-io.js +1 -0
- package/dist/tool-bridge/file-tools/file-state-tracker.d.ts +11 -0
- package/dist/tool-bridge/file-tools/file-state-tracker.js +1 -0
- package/dist/tool-bridge/file-tools/glob-tool.d.ts +21 -0
- package/dist/tool-bridge/file-tools/glob-tool.js +1 -0
- package/dist/tool-bridge/file-tools/grep-tool.d.ts +33 -0
- package/dist/tool-bridge/file-tools/grep-tool.js +1 -0
- package/dist/tool-bridge/file-tools/index.d.ts +18 -0
- package/dist/tool-bridge/file-tools/index.js +1 -0
- package/dist/tool-bridge/file-tools/list-dir-tool.d.ts +18 -0
- package/dist/tool-bridge/file-tools/list-dir-tool.js +1 -0
- package/dist/tool-bridge/file-tools/match-pipeline.d.ts +22 -0
- package/dist/tool-bridge/file-tools/match-pipeline.js +1 -0
- package/dist/tool-bridge/file-tools/read-file-tool.d.ts +25 -0
- package/dist/tool-bridge/file-tools/read-file-tool.js +1 -0
- package/dist/tool-bridge/file-tools/rg-exec.d.ts +12 -0
- package/dist/tool-bridge/file-tools/rg-exec.js +1 -0
- package/dist/tool-bridge/file-tools/settings.d.ts +12 -0
- package/dist/tool-bridge/file-tools/settings.js +1 -0
- package/dist/tool-bridge/file-tools/text-diff.d.ts +33 -0
- package/dist/tool-bridge/file-tools/text-diff.js +1 -0
- package/dist/tool-bridge/file-tools/text-normalize.d.ts +5 -0
- package/dist/tool-bridge/file-tools/text-normalize.js +1 -0
- package/dist/tool-bridge/file-tools/verifier-registry.d.ts +42 -0
- package/dist/tool-bridge/file-tools/verifier-registry.js +1 -0
- package/dist/tool-bridge/file-tools/verify-file-tool.d.ts +30 -0
- package/dist/tool-bridge/file-tools/verify-file-tool.js +1 -0
- package/dist/tool-bridge/file-tools/write-file-tool.d.ts +22 -0
- package/dist/tool-bridge/file-tools/write-file-tool.js +1 -0
- package/dist/tool-bridge/session-exec-tool.js +1 -1
- package/dist/tool-bridge/tool-execution-coordinator.d.ts +15 -2
- package/dist/tool-bridge/tool-execution-coordinator.js +1 -1
- package/dist/types/events.d.ts +3 -1
- package/package.json +5 -3
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export class SessionApprovalMemory{granted=new Set;isGranted(e){return this.granted.has(e)}grant(e){this.granted.add(e)}}
|
package/dist/bash/exec.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{spawn as e}from"node:child_process";import{existsSync as t}from"node:fs";import{constants as
|
|
1
|
+
import{spawn as e}from"node:child_process";import{existsSync as t,readFileSync as o,unlinkSync as r}from"node:fs";import{constants as i}from"node:os";import{performance as n}from"node:perf_hooks";import{OutputSink as s}from"./output-buffer.js";import{parsePipeSegments as l}from"./shell-pipe.js";import{BASH_TERMINATION_CAUSES as a,EXEC_TIMEOUT_EXIT_CODE as m,normalizeExitCode as c}from"./format-result.js";import{isTimeoutAbortReason as u}from"../types/cancellation.js";const d=2e3,f=2500,p=1e3,v=130,T={spawn:e,killTreeDeadlineMs:f,rootKillSettleTimeoutMs:p};function w(e){return e instanceof Error?e.message:String(e)}function b(e,t){const o=new s(0).collect();return{exitCode:1,timedOut:!1,timeoutMs:t,wallTimeMs:0,stdout:o,stderr:o,spawnError:e}}function h(e,t){const o=new s(0).collect(),r=u(t);return{exitCode:r?m:v,timedOut:r,timeoutMs:e,wallTimeMs:0,stdout:o,stderr:o,terminationCause:r?a.timeout:a.abort}}export function runBashCommand(e,f=T){const{command:p,workdir:y,timeoutMs:M,maxCaptureBytes:C,profile:g,env:E,abortSignal:x,onDelta:S}=e;return new Promise(e=>{if(x?.aborted)return void e(h(M,x.reason));if(!t(y))return void e(b(`工作目录不存在: ${y}`,M));let T,$;try{const e=g.buildSpawn(p,y,E??process.env);$=e.rollSegmentFile,T=f.spawn(e.file,e.args,e.options)}catch(t){return void e(b(w(t),M))}const k=g.pipeCapability?.().capability??"none",D=()=>{if(void 0!==$)try{const e=o($,"utf8");return l(e)}catch{return}finally{try{r($)}catch{}}},L=n.now(),O=new s(C),j=new s(C);let K,P,A,B,F,I,_=!1,G=!1,N=!1,R=!1,q=!1,z=!1,H=null,J=null,Q=void 0!==T.pid,U=!1,V=!1;const W=e=>{I=I?`${I};${e}`:e},X=()=>{if(R||!q||!z)return;if(N&&!0===g.waitForTreeKillAfterRootExit&&!U&&!V)return;const e=null!==J?i.signals[J]:void 0,t=_?m:G?v:c({timedOut:!1,code:H,signalNumber:e}),o=D();oe({exitCode:t,timedOut:_,timeoutMs:M,wallTimeMs:n.now()-L,stdout:O.collect(),stderr:j.collect(),...K?{terminationCause:K}:{},...I?{terminationError:I}:{},...void 0!==o?{pipeSegments:o}:{},pipeCapability:k})},Y=()=>{if(R||q)return;for(const e of ie)e.stream.destroy();T.unref();const e=D();oe({exitCode:_?m:v,timedOut:_,timeoutMs:M,wallTimeMs:n.now()-L,stdout:O.collect(),stderr:j.collect(),...K?{terminationCause:K}:{},terminationError:`${I??"进程树清理未完成"};根进程在强制终止请求后仍未确认退出`,...void 0!==e?{pipeSegments:e}:{},pipeCapability:k})},Z=e=>{if(!R){if(B&&(clearTimeout(B),B=void 0),!U){U=!0;const t=void 0===e?"进程树清理未完成":w(e);W(`${t};已回退仅向根进程发送强制终止请求,无法确认后代进程是否已清理`)}if(q)X();else if(void 0===F){F=setTimeout(Y,f.rootKillSettleTimeoutMs);try{T.kill("SIGKILL")||W("根进程强制终止请求未被接受")}catch(e){W(`根进程强制终止请求失败: ${w(e)}`)}}}},ee=()=>{if(!N){N=!0,A=new AbortController,B=setTimeout(()=>Z(new Error("进程树清理超过独立期限")),f.killTreeDeadlineMs);try{g.killTree(T.pid,"terminate",{signal:A.signal}).then(()=>{V=!0,q&&B&&(clearTimeout(B),B=void 0),X()}).catch(Z)}catch(e){Z(e)}}},te=()=>{if(void 0!==K)return;const e=u(x?.reason);K=e?a.timeout:a.abort,_=e,G=!e,clearTimeout(ne),ee()},oe=t=>{R||(R=!0,clearTimeout(ne),P&&clearTimeout(P),B&&clearTimeout(B),F&&clearTimeout(F),A?.abort(),A=void 0,x?.removeEventListener("abort",te),e(t))},re=(e,t,o)=>{if(null===e)return;const r=new TextDecoder("utf-8");e.on("data",e=>{if(o.append(e),S){const o=r.decode(e,{stream:!0});o.length>0&&S(t,o)}});const i=new Promise(t=>{e.once("close",()=>t())});return{stream:e,closed:i}},ie=[re(T.stdout,"stdout",O),re(T.stderr,"stderr",j)].filter(e=>void 0!==e);T.once("spawn",()=>{Q=!0}),T.on("error",e=>{if(R)return;if(!N||!Q)return void oe(b(w(e),M));const t=`根进程终止请求失败: ${w(e)}`;U?W(t):Z(new Error(t,{cause:e}))}),T.on("exit",(e,t)=>{R||q||(q=!0,H=e,J=t,clearTimeout(ne),x?.removeEventListener("abort",te),V&&B&&(clearTimeout(B),B=void 0),F&&(clearTimeout(F),F=void 0),P=setTimeout(()=>{for(const e of ie)e.stream.destroy()},f.ioDrainTimeoutMs??d),Promise.all(ie.map(e=>e.closed)).then(()=>{z=!0,X()}).catch(()=>{}))});const ne=setTimeout(()=>{void 0===K&&(K=a.timeout,_=!0,ee())},M);x&&(x.aborted?te():x.addEventListener("abort",te))})}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { type NormalizedToolResult } from "../tool-bridge/normalize-result.ts";
|
|
2
2
|
import type { CapturedStream } from "./output-buffer.ts";
|
|
3
|
+
import { type ShellPipeCapability } from "./shell-pipe.ts";
|
|
3
4
|
export declare const EXEC_TIMEOUT_EXIT_CODE = 124;
|
|
4
5
|
export declare const EXIT_CODE_SIGNAL_BASE = 128;
|
|
5
6
|
export declare const BASH_TERMINATION_CAUSES: {
|
|
@@ -17,6 +18,8 @@ export interface BashExecResult {
|
|
|
17
18
|
readonly terminationCause?: BashTerminationCause;
|
|
18
19
|
readonly spawnError?: string;
|
|
19
20
|
readonly terminationError?: string;
|
|
21
|
+
readonly pipeSegments?: readonly number[];
|
|
22
|
+
readonly pipeCapability?: ShellPipeCapability;
|
|
20
23
|
}
|
|
21
24
|
export interface NormalizeExitCodeParams {
|
|
22
25
|
readonly timedOut: boolean;
|
|
@@ -27,5 +30,6 @@ export declare function normalizeExitCode(params: NormalizeExitCodeParams): numb
|
|
|
27
30
|
export interface FormatBashResultInput {
|
|
28
31
|
readonly result: BashExecResult;
|
|
29
32
|
readonly maxModelOutputChars: number;
|
|
33
|
+
readonly fullOutputSink?: (text: string) => string | undefined;
|
|
30
34
|
}
|
|
31
35
|
export declare function formatBashResult(input: FormatBashResultInput): NormalizedToolResult;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{TOOL_OUTCOME_KINDS as t,failedToolResult as r,successfulToolResult as
|
|
1
|
+
import{TOOL_OUTCOME_KINDS as t,failedToolResult as r,successfulToolResult as e}from"../tool-bridge/normalize-result.js";import{partitionModelBudget as o}from"./output-buffer.js";import{allocateOutputDumpFile as n,describeOutputDumpRecovery as i,rollOutputDumpDir as s,writeOutputDump as u}from"./output-dump.js";import{evaluatePipelineExit as d}from"./shell-pipe.js";import{truncateMiddle as a}from"./truncate.js";export const EXEC_TIMEOUT_EXIT_CODE=124;export const EXIT_CODE_SIGNAL_BASE=128;export const BASH_TERMINATION_CAUSES={timeout:"timeout",abort:"abort"};const m=1;export function normalizeExitCode(t){return t.timedOut?124:null!==t.code?t.code:void 0!==t.signalNumber?128+t.signalNumber:1}function l(t,r){if(r.truncated)return`Warning: ${t} 输出已截断(原始 ${String(r.totalBytes)} 字节 / ${String(r.totalLines)} 行)`}function p(t){const r=n(s(),"bash");return u(r,t),r}function c(t,r){const e=r.length>0?r:void 0;return void 0!==e?`[${t}]\n${e}`:void 0}export function formatBashResult(n){const{result:s,maxModelOutputChars:u}=n;if(void 0!==s.spawnError)return r(t.toolFailed,`命令无法启动: ${s.spawnError}`,{raw:s});const m=o(u,Array.from(s.stderr.text).length),f=a(s.stdout.text,m.stdout),E=a(s.stderr.text,m.stderr),x=[];s.terminationCause===BASH_TERMINATION_CAUSES.abort&&x.push("命令已中断(收到取消请求),不能视为正常完成"),s.timedOut&&x.push(s.terminationError?`命令超时(超过 ${String(s.timeoutMs)}ms),终止状态未确认`:`命令超时(超过 ${String(s.timeoutMs)}ms),已终止`),s.terminationError&&x.push(`终止失败: ${s.terminationError}`);const S=d({exitCode:s.exitCode,...void 0!==s.pipeSegments?{segments:s.pipeSegments}:{},capability:s.pipeCapability??"none"});x.push(`Exit code: ${String(S.effectiveExitCode)}`),void 0!==S.note&&x.push(S.note),x.push(`Wall time: ${(s.wallTimeMs/1e3).toFixed(1)} s`);const v=[s.stdout.truncated||f.truncated?l("stdout",s.stdout):void 0,s.stderr.truncated||E.truncated?l("stderr",s.stderr):void 0].filter(t=>void 0!==t);if(f.truncated||E.truncated||s.stdout.truncated||s.stderr.truncated){const t=[s.stdout.text.length>0?`[stdout]\n${s.stdout.text}`:void 0,s.stderr.text.length>0?`[stderr]\n${s.stderr.text}`:void 0].filter(t=>void 0!==t),r=(n.fullOutputSink??p)(t.join("\n\n"));void 0!==r&&v.push(i(r))}x.push(...v);const g=[c("stdout",f.text),c("stderr",E.text)].filter(t=>void 0!==t),h=[x.join("\n"),...g].join("\n\n");return s.terminationCause===BASH_TERMINATION_CAUSES.abort?r(t.cancelled,h,{raw:s}):S.ok&&void 0===s.terminationError?e(h,{raw:s}):r(t.toolFailed,h,{raw:s})}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export declare const OUTPUT_DUMP_MAX_AGE_MS: number;
|
|
2
|
+
export declare const OUTPUT_DUMP_MAX_FILES = 32;
|
|
3
|
+
export declare const OUTPUT_DUMP_SESSION_CAP_BYTES: number;
|
|
4
|
+
export declare function rollOutputDumpDir(base?: string): string;
|
|
5
|
+
export declare function ensureOutputDumpDir(dir: string): void;
|
|
6
|
+
export declare function pruneOutputDumpDir(dir: string, now?: number): void;
|
|
7
|
+
export declare function allocateOutputDumpFile(dir: string, label: string): string;
|
|
8
|
+
export declare function writeOutputDump(path: string, text: string): void;
|
|
9
|
+
export interface OutputDumpWriter {
|
|
10
|
+
readonly path: string;
|
|
11
|
+
write(text: string): void;
|
|
12
|
+
close(): void;
|
|
13
|
+
}
|
|
14
|
+
export declare function createOutputDumpWriter(path: string, capBytes: number): OutputDumpWriter;
|
|
15
|
+
export declare function isWithinOutputDumpDir(path: string, dir?: string): boolean;
|
|
16
|
+
export declare function describeOutputDumpRecovery(path: string): string;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{closeSync as t,mkdirSync as r,openSync as e,readdirSync as o,statSync as u,unlinkSync as n,writeSync as i}from"node:fs";import{homedir as p}from"node:os";import{join as m,resolve as c,sep as f}from"node:path";import{randomUUID as s}from"node:crypto";export const OUTPUT_DUMP_MAX_AGE_MS=864e5;export const OUTPUT_DUMP_MAX_FILES=32;export const OUTPUT_DUMP_SESSION_CAP_BYTES=4194304;const l=m(".roll-agent","bash-output-dumps");export function rollOutputDumpDir(t=p()){return m(t,l)}export function ensureOutputDumpDir(t){r(t,{recursive:!0,mode:448})}export function pruneOutputDumpDir(t,r=Date.now()){let e;try{e=o(t)}catch{return}const i=e.map(r=>{try{return{name:r,mtime:u(m(t,r)).mtimeMs}}catch{return}}).filter(t=>void 0!==t).sort((t,r)=>t.mtime-r.mtime);for(const e of i)if(r-e.mtime>864e5)try{n(m(t,e.name))}catch{}const p=i.filter(t=>r-t.mtime<=864e5),c=p.length-32;for(let r=0;r<c;r+=1){const e=p[r];if(void 0!==e)try{n(m(t,e.name))}catch{}}}export function allocateOutputDumpFile(t,r){return ensureOutputDumpDir(t),pruneOutputDumpDir(t),m(t,`${String(Date.now())}-${r}-${s()}.log`)}export function writeOutputDump(r,o){const u=e(r,"w",384);i(u,o),t(u)}export function createOutputDumpWriter(r,o){const u=e(r,"w",384);let n=0,p=!1;return{path:r,write(t){if(p||n>=o)return;const r=Buffer.from(t,"utf8"),e=o-n,m=r.length>e?r.subarray(0,e):r;i(u,m),n+=m.length},close(){p||(p=!0,t(u))}}}export function isWithinOutputDumpDir(t,r=rollOutputDumpDir()){const e=c(t),o=c(r);return e===o||e.startsWith(o+f)}export function describeOutputDumpRecovery(t){return`完整输出已落盘: ${t};用 roll__read_file 以 offset/limit 分页查看被截断的中段,或重跑更窄的命令`}
|
package/dist/bash/profile.d.ts
CHANGED
|
@@ -1,13 +1,17 @@
|
|
|
1
1
|
import { spawn, spawnSync, type SpawnOptions } from "node:child_process";
|
|
2
2
|
import type { CommandClassification } from "../types/command-classification.ts";
|
|
3
|
+
import { type ShellPipeProbe } from "./shell-pipe.ts";
|
|
3
4
|
export declare const SHELL_PROFILE_IDS: readonly ["posix", "powershell"];
|
|
4
5
|
export type ShellProfileId = (typeof SHELL_PROFILE_IDS)[number];
|
|
5
6
|
export declare const SHELL_TOOL_NAMES: readonly ["bash", "powershell"];
|
|
6
7
|
export type ShellToolName = (typeof SHELL_TOOL_NAMES)[number];
|
|
8
|
+
export declare const POSIX_PIPEFAIL_GUARD = "( set -o pipefail ) 2>/dev/null && set -o pipefail; ";
|
|
9
|
+
export declare function wrapPosixCommand(command: string): string;
|
|
7
10
|
export interface ShellSpawnSpec {
|
|
8
11
|
readonly file: string;
|
|
9
12
|
readonly args: readonly string[];
|
|
10
13
|
readonly options: SpawnOptions;
|
|
14
|
+
readonly rollSegmentFile?: string;
|
|
11
15
|
}
|
|
12
16
|
export interface ShellKillOptions {
|
|
13
17
|
readonly signal?: AbortSignal;
|
|
@@ -22,6 +26,7 @@ export interface ShellProfile {
|
|
|
22
26
|
classify(command: string, workdir: string): CommandClassification;
|
|
23
27
|
killTree(pid: number | undefined, intent: "interrupt" | "terminate", options?: ShellKillOptions): Promise<void>;
|
|
24
28
|
systemPromptHints(): readonly string[];
|
|
29
|
+
pipeCapability?: () => ShellPipeProbe;
|
|
25
30
|
}
|
|
26
31
|
export interface ShellProfileResolutionDeps {
|
|
27
32
|
readonly platform: NodeJS.Platform;
|
package/dist/bash/profile.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{spawn as e,spawnSync as
|
|
1
|
+
import{spawn as e,spawnSync as t}from"node:child_process";import{existsSync as o}from"node:fs";import{win32 as r}from"node:path";import{performance as n}from"node:perf_hooks";import{unknownCommandClassifier as i}from"../types/command-classification.js";import{ruleBasedClassifier as s}from"./classifier/index.js";import{DEFAULT_KILL_GRACE_MS as l,killProcessGroup as a}from"./kill.js";import{allocateOutputDumpFile as c,rollOutputDumpDir as p}from"./output-dump.js";import{buildSegmentCaptureWrapper as u,PIPE_STATUS_ENV as f,probeShellPipeCapability as m}from"./shell-pipe.js";import{resolveUserShell as d}from"./shell.js";export const SHELL_PROFILE_IDS=["posix","powershell"];export const SHELL_TOOL_NAMES=["bash","powershell"];export const POSIX_PIPEFAIL_GUARD="( set -o pipefail ) 2>/dev/null && set -o pipefail; ";export function wrapPosixCommand(e){return`${POSIX_PIPEFAIL_GUARD}${e}`}const w=["-NoLogo","-NoProfile","-NonInteractive","-ExecutionPolicy","Bypass","-EncodedCommand"],h=32767,S=1024,g=5e3,E=2e3,v=128,x=["PowerShell","7","pwsh.exe"],P=["System32","taskkill.exe"];function b(e,t){return t?.aborted?Promise.resolve(!1):new Promise(o=>{let r=!1;const n=e=>{r||(r=!0,clearTimeout(s),t?.removeEventListener("abort",i),o(e))},i=()=>n(!1),s=setTimeout(()=>n(!0),e);t?.addEventListener("abort",i,{once:!0})})}function y(e){const r=e.fileExists??o,n=e.spawnSync??t,i=new Map,w=e=>{const t=i.get(e);if(void 0!==t)return t;const o=m(e,n);return i.set(e,o),o};return{id:"posix",toolName:"bash",supportsSessionExec:!0,supportsSafeCommandClassification:!0,waitForTreeKillAfterRootExit:!1,pipeCapability:()=>w(d({platform:e.platform,env:e.env,fileExists:r})),buildSpawn(t,o,n){const i=d({platform:e.platform,env:n,fileExists:r}),s=w(i);let l,a=t,m=n;return"segments"===s.capability&&void 0!==s.segmentArray?(l=c(p(),"pipestatus"),a=u(t,s.segmentArray),m={...n,[f]:l}):"pipefail"===s.capability&&(a=wrapPosixCommand(t)),{file:i,args:["-c",a],options:{cwd:o,detached:!0,stdio:["ignore","pipe","pipe"],env:m},...void 0!==l?{rollSegmentFile:l}:{}}},classify:(e,t)=>s.classify(e,t),async killTree(e,t,o={}){o.signal?.aborted||("interrupt"!==t?(a(e,"SIGTERM"),await b(l,o.signal)&&a(e,"SIGKILL")):a(e,"SIGINT"))},systemPromptHints(){const t=w(d({platform:e.platform,env:e.env,fileExists:r})).capability;return["当前 shell 后端是 POSIX shell;优先使用 macOS/Linux 常见命令语法。","segments"===t?"管道按逐段退出码判定:末段为 0 且其余段为 0 或被下游提前关闭(SIGPIPE/141)才算成功;…| head 型提前关闭会判成功并附说明,其余中段失败如实报告。":"pipefail"===t?"管道已启用 pipefail:任一阶段失败整条管道即失败;退出码 141 表示上游被下游提前关闭,已标注且不视为失败。":"当前 shell 不支持 pipefail/逐段判定:管道退出码为最后一段的退出码;退出码 141 表示上游被下游提前关闭,已标注且不视为失败。","仅为控制输出量时请用 roll__bash 的 max_output_chars 参数或 roll__read_file / roll__grep 等工具,不要自接 head/tail 管道;需要过滤时仍可用 grep 等工具。"]}}}function C(e,t,o,r,n={}){return void 0===e||n.signal?.aborted?Promise.resolve():void 0===t?Promise.reject(new Error("无法从绝对 SystemRoot 路径解析 taskkill.exe,不能安全清理进程树")):new Promise((i,s)=>{let l,a=!1;const c=e=>{a||(a=!0,clearTimeout(u),n.signal?.removeEventListener("abort",p),e?s(e):i())},p=()=>{try{l.kill()}catch{}try{l.unref()}catch{}c()},u=setTimeout(()=>{try{l.kill()}catch{}try{l.unref()}catch{}c(new Error(`taskkill.exe 在 ${String(r)}ms 内未结束`))},r);try{l=o(t,["/PID",String(e),"/T","/F"],{stdio:"ignore",windowsHide:!0})}catch(e){return void c(new Error(`无法启动 taskkill.exe: ${k(e)}`,{cause:e}))}l.once("error",e=>{c(new Error(`无法启动 taskkill.exe: ${e.message}`,{cause:e}))}),l.once("close",(e,t)=>{if(0===e||e===v)return void c();const o=null===e?`signal=${t??"unknown"}`:`exitCode=${String(e)}`;c(new Error(`taskkill.exe 执行失败: ${o}`))}),n.signal?.addEventListener("abort",p,{once:!0}),n.signal?.aborted&&p()})}function k(e){return e instanceof Error?e.message:String(e)}export function buildPowerShellEncodedCommand(e){const t=["[Console]::OutputEncoding = [System.Text.UTF8Encoding]::new($false)","$OutputEncoding = [Console]::OutputEncoding","$ErrorActionPreference = 'Stop'","try {",e," if (Test-Path variable:LASTEXITCODE) { exit $LASTEXITCODE }","} catch {"," [Console]::Error.WriteLine([string]$_)"," exit 1","}"].join("\n");return Buffer.from(t,"utf16le").toString("base64")}function I(e,t){return[e,...t].reduce((e,t)=>e+t.length+1,0)}function L(e,t){const o=buildPowerShellEncodedCommand(e),r=[...w,o],n=I(t,r)+S;if(n>h)throw new Error(`PowerShell 命令过长:编码后命令行约 ${String(n)} 字符,超过 Windows CreateProcess 上限 ${String(h)};请拆分命令或改为执行脚本文件。`);return r}function T(e,t){const o=t.toLowerCase();for(const[t,r]of Object.entries(e))if(t.toLowerCase()===o&&void 0!==r&&r.length>0)return r}function _(e){const t=e.trim();return t.startsWith('"')&&t.endsWith('"')?t.slice(1,-1).trim():t}function $(e){return r.isAbsolute(e)&&r.parse(e).root.length>1}function j(e){const t=[],o=new Set,n=e=>{if(!$(e))return;const n=r.normalize(e).toLowerCase();o.has(n)||(o.add(n),t.push(r.normalize(e)))},i=T(e.env,"Path");for(const e of i?.split(r.delimiter)??[]){const t=_(e);$(t)&&n(r.join(t,"pwsh.exe"))}const s=[T(e.env,"ProgramFiles"),T(e.env,"ProgramW6432"),T(e.env,"ProgramFiles(x86)")];for(const e of s){if(void 0===e)continue;const t=_(e);$(t)&&n(r.join(t,...x))}return t}function O(e){const t=T(e,"SystemRoot");if(void 0===t)return;const o=_(t);return $(o)?r.join(o,...P):void 0}function A(e,t,o){const r=t(e,["-NoLogo","-NoProfile","-NonInteractive","-Command","$PSVersionTable.PSVersion.Major"],{encoding:"utf8",timeout:o,windowsHide:!0});if(r.error||0!==r.status)return;const n=`${r.stdout??""}`.trim(),i=Number.parseInt(n,10);return Number.isFinite(i)?i:void 0}function F(e,t){const r=e.fileExists??o,i=e.now??(()=>n.now()),s=i()+g;let l=!1;for(const o of j(e)){if(s-i()<=0)break;if(!r(o))continue;const e=Math.ceil(s-i());if(e<=0)break;const n=A(o,t,e);if(void 0!==n){if(n>=7)return{supported:!0,executable:o};l=!0}}return{supported:!1,reason:l?"pwsh-version-unsupported":"pwsh-not-found"}}function N(o){const r=F(o,o.spawnSync??t);if(!r.supported)return r;const n=o.spawn??e,s=O(o.env),l=o.taskkillTimeoutMs??E;return{supported:!0,profile:{id:"powershell",toolName:"powershell",supportsSessionExec:!0,supportsSafeCommandClassification:!1,waitForTreeKillAfterRootExit:!0,buildSpawn:(e,t,o)=>({file:r.executable,args:L(e,r.executable),options:{cwd:t,detached:!1,stdio:["ignore","pipe","pipe"],env:o,windowsHide:!0}}),classify:(e,t)=>i.classify(e,t),async killTree(e,t,o={}){await C(e,s,n,l,o)},systemPromptHints:()=>["当前 shell 后端是 PowerShell 7;请使用 PowerShell 语法,例如 Get-ChildItem、Get-Content、Select-String。","过滤和预览输出时优先使用 Select-String、Select-Object -First、Get-Content -TotalCount。"]}}}export function resolveShellProfile(e){return"win32"===e.platform?N(e):{supported:!0,profile:y(e)}}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{spawn as e}from"node:child_process";import{
|
|
1
|
+
import{spawn as e}from"node:child_process";import{readFileSync as t,unlinkSync as o}from"node:fs";import{constants as i}from"node:os";import{performance as r}from"node:perf_hooks";import{normalizeExitCode as n}from"../format-result.js";import{allocateOutputDumpFile as s,createOutputDumpWriter as a,OUTPUT_DUMP_SESSION_CAP_BYTES as d,rollOutputDumpDir as p}from"../output-dump.js";import{parsePipeSegments as l}from"../shell-pipe.js";import{HeadTailBuffer as m}from"./head-tail-buffer.js";import{SESSION_STATES as c}from"./types.js";class Gate{opened=!1;waiters=[];open(){if(this.opened)return;this.opened=!0;const e=this.waiters;this.waiters=[];for(const t of e)t()}wait(){return this.opened?Promise.resolve():new Promise(e=>{this.waiters.push(e)})}}export function spawnSession(u){const f=u.profile.buildSpawn(u.command,u.workdir,u.env),w=e(f.file,f.args,f.options),g=f.rollSegmentFile,v=a(s(p(),"session"),d),h=new m(u.bufferCapacity),b=r.now(),C=new Gate,x=new Gate,k=new Gate;let y=u.onDelta,S=!1;const O={id:u.id,command:u.command,workdir:u.workdir,profile:u.profile,child:w,buffer:h,startedAt:b,state:c.running,exitCode:void 0,exitObserved:!1,closeObserved:!1,completedAt:void 0,terminationCause:void 0,cleanupError:void 0,lastUsedAt:b,pipeSegments:void 0,pipeCapability:u.profile.pipeCapability?.().capability,dumpPath:v.path,beginPoll:e=>!S&&(S=!0,void 0!==e&&(y=e),!0),endPoll:()=>{y=void 0,S=!1},markStopping:e=>{O.state!==c.completed&&O.state!==c.cleanupFailed&&(O.terminationCause??=e,O.state=c.stopping)},markCompleted:()=>{O.state!==c.cleanupFailed&&(O.exitCode??=1,O.state=c.completed,O.completedAt??=r.now(),k.open())},markCleanupFailed:e=>{O.cleanupError=O.cleanupError?`${O.cleanupError};${e}`:e,O.exitCode??=1,O.state=c.cleanupFailed,O.completedAt??=r.now(),k.open()},waitExit:()=>C.wait(),waitClose:()=>x.wait(),waitSettled:()=>k.wait()},A=(e,t)=>{0!==t.length&&(h.append(t),v.write(t),y?.(e,t))},j=(e,t)=>{if(null===e)return;const o=new TextDecoder("utf-8");e.on("data",e=>{A(t,o.decode(e,{stream:!0}))}),e.on("end",()=>{A(t,o.decode())})};j(w.stdout,"stdout"),j(w.stderr,"stderr");const E=(e,t)=>{if(O.exitObserved)return;const o=null!==t?i.signals[t]:void 0;O.exitCode=n({timedOut:!1,code:e,signalNumber:o}),O.exitObserved=!0,O.state===c.running&&(O.state=c.draining),C.open()};return w.on("exit",(e,t)=>{E(e,t)}),w.on("close",(e,i)=>{E(e,i),v.close(),(()=>{if(void 0!==g)try{O.pipeSegments=l(t(g,"utf8"))}catch{O.pipeSegments=void 0}finally{try{o(g)}catch{}}})(),O.closeObserved=!0,O.completedAt??=r.now(),x.open(),O.state!==c.stopping&&O.markCompleted()}),w.on("error",e=>{h.append(`无法启动进程: ${e.message}\n`),O.exitCode=O.exitCode??1,O.exitObserved=!0,O.state===c.running&&(O.state=c.draining),C.open()}),O}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { ChildProcess } from "node:child_process";
|
|
2
2
|
import type { BashStreamName } from "../exec.ts";
|
|
3
3
|
import type { ShellProfile } from "../profile.ts";
|
|
4
|
+
import type { ShellPipeCapability } from "../shell-pipe.ts";
|
|
4
5
|
import type { HeadTailBuffer } from "./head-tail-buffer.ts";
|
|
5
6
|
export type SessionDeltaHandler = (stream: BashStreamName, delta: string) => void;
|
|
6
7
|
export declare const SESSION_STATES: {
|
|
@@ -33,6 +34,9 @@ export interface ManagedSession {
|
|
|
33
34
|
terminationCause: SessionTerminationCause | undefined;
|
|
34
35
|
cleanupError: string | undefined;
|
|
35
36
|
lastUsedAt: number;
|
|
37
|
+
pipeSegments?: readonly number[] | undefined;
|
|
38
|
+
pipeCapability?: ShellPipeCapability | undefined;
|
|
39
|
+
dumpPath?: string | undefined;
|
|
36
40
|
beginPoll(onDelta?: SessionDeltaHandler): boolean;
|
|
37
41
|
endPoll(): void;
|
|
38
42
|
markStopping(cause: SessionTerminationCause): void;
|
|
@@ -51,6 +55,9 @@ export type SessionPollResult = {
|
|
|
51
55
|
readonly state: TerminalSessionState;
|
|
52
56
|
readonly terminationCause?: SessionTerminationCause;
|
|
53
57
|
readonly cleanupError?: string;
|
|
58
|
+
readonly pipeSegments?: readonly number[];
|
|
59
|
+
readonly pipeCapability?: ShellPipeCapability;
|
|
60
|
+
readonly dumpPath?: string;
|
|
54
61
|
} | {
|
|
55
62
|
readonly kind: "running";
|
|
56
63
|
readonly output: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{performance as
|
|
1
|
+
import{performance as e}from"node:perf_hooks";import{isTerminalSessionState as t}from"./types.js";export class SessionPollInProgressError extends Error{constructor(e){super(`会话 ${String(e)} 已有一个轮询窗口在运行`),this.name="SessionPollInProgressError"}}function o(e){const t=e?.reason;return t instanceof Error?t:new DOMException("string"==typeof t&&t.length>0?t:"The operation was aborted","AbortError")}export function throwIfSessionExecAborted(e){if(!0===e?.aborted)throw o(e)}function r(e,r,n){return r<=0||t(e.state)?Promise.resolve():new Promise((t,i)=>{let s=!1;const a=e=>{s||(s=!0,clearTimeout(d),n?.removeEventListener("abort",l),void 0!==e?i(e):t())},l=()=>a(o(n)),d=setTimeout(()=>a(),r);e.waitSettled().then(()=>a()),n?.addEventListener("abort",l,{once:!0}),!0===n?.aborted&&l()})}export async function pollUntilDeadline(o,n,i,s={}){if(!o.beginPoll(s.onDelta))throw new SessionPollInProgressError(o.id);try{throwIfSessionExecAborted(s.abortSignal),await r(o,n-e.now(),s.abortSignal),throwIfSessionExecAborted(s.abortSignal);const a=e.now();o.lastUsedAt=a;const l=o.state,d=t(l),p=d?o.buffer.snapshot(i):o.buffer.drain(i),u=(d?o.completedAt??a:a)-o.startedAt;return d?{kind:"exited",output:p.text,omitted:p.omitted,wallTimeMs:u,exitCode:o.exitCode??1,state:l,...o.terminationCause?{terminationCause:o.terminationCause}:{},...o.cleanupError?{cleanupError:o.cleanupError}:{},...void 0!==o.pipeSegments?{pipeSegments:o.pipeSegments}:{},...void 0!==o.pipeCapability?{pipeCapability:o.pipeCapability}:{},...void 0!==o.dumpPath?{dumpPath:o.dumpPath}:{}}:{kind:"running",output:p.text,omitted:p.omitted,wallTimeMs:u,sessionId:o.id}}finally{o.lastUsedAt=e.now(),o.endPoll()}}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { spawnSync as SpawnSync } from "node:child_process";
|
|
2
|
+
export declare const SIGPIPE_EXIT_CODE = 141;
|
|
3
|
+
export declare const PIPE_STATUS_ENV = "ROLL_PIPE_STATUS_FILE";
|
|
4
|
+
export declare const SHELL_PIPE_CAPABILITIES: readonly ["segments", "pipefail", "none"];
|
|
5
|
+
export type ShellPipeCapability = (typeof SHELL_PIPE_CAPABILITIES)[number];
|
|
6
|
+
export declare const PIPE_SEGMENT_ARRAYS: readonly ["PIPESTATUS", "pipestatus"];
|
|
7
|
+
export type PipeSegmentArray = (typeof PIPE_SEGMENT_ARRAYS)[number];
|
|
8
|
+
export interface ShellPipeProbe {
|
|
9
|
+
readonly capability: ShellPipeCapability;
|
|
10
|
+
readonly segmentArray?: PipeSegmentArray;
|
|
11
|
+
}
|
|
12
|
+
export declare function probeShellPipeCapability(shellPath: string, spawnSyncImpl: typeof SpawnSync): ShellPipeProbe;
|
|
13
|
+
export declare function parsePipeSegments(text: string): readonly number[] | undefined;
|
|
14
|
+
export declare function buildSegmentCaptureWrapper(command: string, segmentArray: PipeSegmentArray): string;
|
|
15
|
+
export interface PipelineVerdict {
|
|
16
|
+
readonly ok: boolean;
|
|
17
|
+
readonly effectiveExitCode: number;
|
|
18
|
+
readonly note?: string;
|
|
19
|
+
}
|
|
20
|
+
export declare const SIGPIPE_BENIGN_NOTE = "\u7BA1\u9053\u4E2D\u6709\u4E0A\u6E38\u9636\u6BB5\u88AB\u4E0B\u6E38\u63D0\u524D\u5173\u95ED\uFF08SIGPIPE\uFF0C\u9000\u51FA\u7801 141\uFF09\uFF0C\u6309\u826F\u6027\u5904\u7406\uFF1B\u4E0B\u6E38\u8F93\u51FA\u53EF\u80FD\u4E0D\u5B8C\u6574";
|
|
21
|
+
export declare const SIGPIPE_FALLBACK_NOTE = "\u9000\u51FA\u7801 141\uFF1A\u4E0A\u6E38\u88AB\u4E0B\u6E38\u63D0\u524D\u5173\u95ED\uFF08SIGPIPE\uFF09\uFF0C\u8F93\u51FA\u53EF\u80FD\u5B8C\u6574\uFF1B\u5F53\u524D shell \u65E0\u9010\u6BB5\u72B6\u6001\uFF0C\u672A\u89C6\u4E3A\u5931\u8D25";
|
|
22
|
+
export declare function evaluatePipelineExit(params: {
|
|
23
|
+
readonly exitCode: number;
|
|
24
|
+
readonly segments?: readonly number[];
|
|
25
|
+
readonly capability: ShellPipeCapability;
|
|
26
|
+
}): PipelineVerdict;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const SIGPIPE_EXIT_CODE=141;export const PIPE_STATUS_ENV="ROLL_PIPE_STATUS_FILE";export const SHELL_PIPE_CAPABILITIES=["segments","pipefail","none"];export const PIPE_SEGMENT_ARRAYS=["PIPESTATUS","pipestatus"];const e=2e3;export function probeShellPipeCapability(t,i){const n=i(t,["-c",'false | true; printf "%s|%s" "${PIPESTATUS[*]:-}" "${pipestatus[*]:-}"'],{encoding:"utf8",timeout:e});if(!n.error&&0===n.status){const e=n.stdout??"";if(e.startsWith("1 0"))return{capability:"segments",segmentArray:"PIPESTATUS"};if(e.endsWith("1 0")&&e.includes("|"))return{capability:"segments",segmentArray:"pipestatus"}}const o=i(t,["-c","( set -o pipefail ) 2>/dev/null && set -o pipefail; false | true"],{timeout:e});return o.error||0===o.status?{capability:"none"}:{capability:"pipefail"}}export function parsePipeSegments(e){const t=e.split(/\s+/u).filter(e=>e.length>0).map(e=>Number.parseInt(e,10));if(0!==t.length&&!t.some(e=>!Number.isFinite(e)))return t}export function buildSegmentCaptureWrapper(e,t){return`trap '${`__roll_pipe_status="\${${t}[*]:-}"`}; ${`[ -n "\${${PIPE_STATUS_ENV}:-}" ] && printf "%s\\n" "$__roll_pipe_status" >"\${${PIPE_STATUS_ENV}}" 2>/dev/null`}' EXIT; ${e}`}export const SIGPIPE_BENIGN_NOTE="管道中有上游阶段被下游提前关闭(SIGPIPE,退出码 141),按良性处理;下游输出可能不完整";export const SIGPIPE_FALLBACK_NOTE="退出码 141:上游被下游提前关闭(SIGPIPE),输出可能完整;当前 shell 无逐段状态,未视为失败";export function evaluatePipelineExit(e){const i=e.segments;if("segments"===e.capability&&void 0!==i&&i.length>0){const n=i[i.length-1]??e.exitCode;if(n!==e.exitCode)return t(e.exitCode);const o=i.slice(0,-1),s=o.every(e=>0===e||141===e),r=o.some(e=>141===e);if(0===n&&s)return{ok:!0,effectiveExitCode:0,...r?{note:SIGPIPE_BENIGN_NOTE}:{}};const p=o.find(e=>0!==e&&141!==e);return{ok:!1,effectiveExitCode:void 0!==p?p:n}}return t(e.exitCode)}function t(e){return 0===e?{ok:!0,effectiveExitCode:0}:141===e?{ok:!0,effectiveExitCode:141,note:SIGPIPE_FALLBACK_NOTE}:{ok:!1,effectiveExitCode:e}}
|
package/dist/bash/truncate.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export function truncateMiddle(t,e){const n=Array.from(t);if(n.length<=e)return{text:t,truncated:!1,removed:0};if(e<=0)return{text:"",truncated:!0,removed:n.length};const r=Math.ceil(e/2),
|
|
1
|
+
export function truncateMiddle(t,e){const n=Array.from(t);if(n.length<=e)return{text:t,truncated:!1,removed:0};if(e<=0)return{text:"",truncated:!0,removed:n.length};const r=Math.ceil(e/2),i=Math.floor(e/2),c=n.length-r-i,o=n.slice(0,r).join(""),l=n.slice(n.length-i).join("");return{text:`${o}\n…${String(c)} chars truncated(保留前 ${String(r)} 与后 ${String(i)} 字符,全文 ${String(n.length)} 字符)…\n${l}`,truncated:!0,removed:c}}
|
|
@@ -7,12 +7,14 @@ import type { ContextCompactionReason, ContextCompactionStrategy, SessionEvent,
|
|
|
7
7
|
import type { ToolPolicy } from "../types/policy.ts";
|
|
8
8
|
import { type AgentToolSource } from "../tool-bridge/build-tools.ts";
|
|
9
9
|
import { type AgentInstallToolCatalogEntry, type AgentInstallToolOutcome } from "../tool-bridge/agent-install-tool.ts";
|
|
10
|
+
import { type SessionFileToolsSettings } from "../tool-bridge/file-tools/index.ts";
|
|
10
11
|
import { type SessionBashSettings } from "../tool-bridge/bash-tool.ts";
|
|
11
12
|
import type { ShellProfile } from "../bash/profile.ts";
|
|
12
13
|
import type { CommandClassifier } from "../types/command-classification.ts";
|
|
13
14
|
import { type RedactedToolExecutionRecordSummary, type ToolExecutionRecord } from "../tool-bridge/tool-execution-record.ts";
|
|
14
|
-
import type { CommitCompactionInput, ListToolExecutionsOptions, ListTranscriptMessagesOptions, SequencedToolExecutionRecord } from "../store/thread-store.ts";
|
|
15
|
+
import type { AppendMessagesOptions, CommitCompactionInput, ListToolExecutionsOptions, ListTranscriptMessagesOptions, SequencedToolExecutionRecord } from "../store/thread-store.ts";
|
|
15
16
|
import { type CapabilityAgentOnboardingCatalogEntry, type CapabilityExternalDynamicContext, type CapabilityHostMode, type EffectiveCapabilityTurnContext, type EffectiveCapabilityManifest } from "./capability-manifest.ts";
|
|
17
|
+
import type { WorkspaceInstructionsSource } from "./workspace-instructions.ts";
|
|
16
18
|
import { type ArchivedTranscriptMessage, type CompactionCheckpoint } from "./compaction-checkpoint.ts";
|
|
17
19
|
import { type TranscriptReader } from "../tool-bridge/transcript-tool.ts";
|
|
18
20
|
import { type SessionUserInputRequestId } from "../interaction/user-input-interaction-manager.ts";
|
|
@@ -34,11 +36,12 @@ export interface AgentSessionOptions {
|
|
|
34
36
|
readonly maxSteps: number;
|
|
35
37
|
readonly policy?: ToolPolicy;
|
|
36
38
|
readonly initialMessages?: readonly ModelMessage[];
|
|
37
|
-
readonly onPersist?: (messages: readonly ModelMessage[]) => void;
|
|
39
|
+
readonly onPersist?: (messages: readonly ModelMessage[], options?: AppendMessagesOptions) => void;
|
|
38
40
|
readonly onReplace?: (messages: readonly ModelMessage[]) => void;
|
|
39
41
|
readonly onToolExecution?: (record: ToolExecutionRecord) => void;
|
|
40
42
|
readonly listToolExecutions?: (options?: ListToolExecutionsOptions) => readonly SequencedToolExecutionRecord[];
|
|
41
43
|
readonly getToolExecution?: (executionId: string) => SequencedToolExecutionRecord | undefined;
|
|
44
|
+
readonly recoverUncoveredToolExecutions?: () => readonly ModelMessage[];
|
|
42
45
|
readonly initialCheckpoint?: CompactionCheckpoint;
|
|
43
46
|
readonly listTranscriptMessages?: (options?: ListTranscriptMessagesOptions) => readonly ArchivedTranscriptMessage[];
|
|
44
47
|
readonly commitCompaction?: (input: CommitCompactionInput) => CompactionCheckpoint;
|
|
@@ -60,6 +63,8 @@ export interface AgentSessionOptions {
|
|
|
60
63
|
readonly capabilityContext?: AgentSessionCapabilityContext;
|
|
61
64
|
readonly resolveDynamicCapabilityContext?: (abortSignal: AbortSignal) => CapabilityExternalDynamicContext | Promise<CapabilityExternalDynamicContext>;
|
|
62
65
|
readonly skillLibrary?: SkillLibrary;
|
|
66
|
+
readonly workspaceInstructions?: WorkspaceInstructionsSource;
|
|
67
|
+
readonly fileTools?: SessionFileToolsSettings;
|
|
63
68
|
readonly bash?: SessionBashSettings;
|
|
64
69
|
readonly bashClassifier?: CommandClassifier;
|
|
65
70
|
readonly bashSession?: AgentSessionBashSession;
|
|
@@ -113,9 +118,11 @@ export declare class AgentSession {
|
|
|
113
118
|
private readonly onToolExecution;
|
|
114
119
|
private readonly listPersistedToolExecutions;
|
|
115
120
|
private readonly getPersistedToolExecution;
|
|
121
|
+
private readonly recoverPersistedToolExecutionContext;
|
|
116
122
|
private readonly listPersistedTranscriptMessages;
|
|
117
123
|
private readonly commitPersistedCompaction;
|
|
118
124
|
private readonly inMemoryToolExecutions;
|
|
125
|
+
private readonly uncoveredToolExecutions;
|
|
119
126
|
private readonly inMemoryTranscript;
|
|
120
127
|
private readonly legacyV1ActiveSnapshot;
|
|
121
128
|
private readonly compactionResources;
|
|
@@ -131,6 +138,9 @@ export declare class AgentSession {
|
|
|
131
138
|
private readonly policy;
|
|
132
139
|
private systemPrompt;
|
|
133
140
|
private readonly explicitSystemPrompt;
|
|
141
|
+
private lastExtraPrompt;
|
|
142
|
+
private readonly workspaceInstructions;
|
|
143
|
+
private appliedWorkspaceInstructions;
|
|
134
144
|
private capabilityContext;
|
|
135
145
|
private readonly resolveDynamicCapabilityContext;
|
|
136
146
|
private capabilityManifest;
|
|
@@ -157,10 +167,15 @@ export declare class AgentSession {
|
|
|
157
167
|
private closed;
|
|
158
168
|
private sessionUsage;
|
|
159
169
|
private lastInputTokens;
|
|
170
|
+
private lastStepOutputTokens;
|
|
171
|
+
private lastStepToolResultTokens;
|
|
172
|
+
private measuredMessageCount;
|
|
173
|
+
private promptOverhead;
|
|
160
174
|
private needsCompaction;
|
|
161
175
|
constructor(options: AgentSessionOptions);
|
|
162
176
|
private compileCapabilityManifest;
|
|
163
177
|
private compileSystemPrompt;
|
|
178
|
+
private syncWorkspaceInstructions;
|
|
164
179
|
private refreshCapabilityManifest;
|
|
165
180
|
setUserInputAvailable(available: boolean): void;
|
|
166
181
|
resolveUserInput(requestId: SessionUserInputRequestId, result: UserInputResult): boolean;
|
|
@@ -173,13 +188,19 @@ export declare class AgentSession {
|
|
|
173
188
|
compact(reason?: ContextCompactionReason): AsyncIterable<SessionEvent>;
|
|
174
189
|
private runTurn;
|
|
175
190
|
private persistMessages;
|
|
191
|
+
private recordPersistedMessagesInMemory;
|
|
192
|
+
private reconcileUncoveredToolExecutionContext;
|
|
176
193
|
private persistContextFailure;
|
|
194
|
+
private persistFailedTurn;
|
|
195
|
+
private failedTurnContextMessage;
|
|
196
|
+
private failedTurnDisplayMessage;
|
|
197
|
+
private appendInterruptedTurnMessages;
|
|
177
198
|
private persistToolExecution;
|
|
178
199
|
private rememberCompactionResources;
|
|
179
200
|
private retainCompactionResource;
|
|
180
201
|
private interactionDeadlineMs;
|
|
181
202
|
private requestApproval;
|
|
182
|
-
approve(approvalId: string): boolean;
|
|
203
|
+
approve(approvalId: string, scope?: "once" | "session"): boolean;
|
|
183
204
|
reject(approvalId: string, reason?: string): boolean;
|
|
184
205
|
getMessages(): readonly ModelMessage[];
|
|
185
206
|
getToolExecutions(options?: ListToolExecutionsOptions, includeRaw?: boolean): readonly SessionToolExecutionRecordView[];
|
|
@@ -190,6 +211,13 @@ export declare class AgentSession {
|
|
|
190
211
|
getSessionUsage(): SessionTokenUsage;
|
|
191
212
|
getSkillSummaries(): readonly SessionSkillSummary[];
|
|
192
213
|
setProviderOptions(providerOptions: SharedV4ProviderOptions | undefined): void;
|
|
214
|
+
private runAutoCompactionPasses;
|
|
215
|
+
private stopOnContextPressure;
|
|
216
|
+
private contextPressureTokens;
|
|
217
|
+
private promptOverheadTokens;
|
|
218
|
+
private currentCheckpointReminder;
|
|
219
|
+
private persistPausedTurnCancellation;
|
|
220
|
+
private compactionTargetTokens;
|
|
193
221
|
private shouldAutoCompact;
|
|
194
222
|
private listCompactionTranscriptEvidence;
|
|
195
223
|
private listCompactionToolEvidence;
|
|
@@ -213,7 +241,10 @@ export declare class AgentSession {
|
|
|
213
241
|
private cancellationDisplayMessage;
|
|
214
242
|
private cancellationContextMessage;
|
|
215
243
|
private emitCancellation;
|
|
244
|
+
private persistCancelledRecoveryTurn;
|
|
216
245
|
private persistCancelledTurn;
|
|
246
|
+
private cancellationRecordMessages;
|
|
247
|
+
private persistPendingToolCancellationsOrReport;
|
|
217
248
|
private persistPendingToolCancellations;
|
|
218
249
|
cancel(): boolean;
|
|
219
250
|
close(): Promise<void>;
|