aws-runtime-bridge 1.9.172 → 1.9.175
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 +126 -0
- package/dist/adapter/AcodeSdkAdapter.d.ts +5 -1
- package/dist/adapter/AcodeSdkAdapter.js +3 -3
- package/dist/adapter/types.d.ts +2 -0
- package/dist/index.js +1 -1
- package/dist/routes/bridge-temp-files.d.ts +1 -0
- package/dist/routes/bridge-temp-files.js +2 -0
- package/dist/routes/dashboard.js +35 -5
- package/dist/routes/file-browser.d.ts +4 -10
- package/dist/routes/file-browser.js +1 -1
- package/dist/routes/git.d.ts +42 -0
- package/dist/routes/git.js +34 -34
- package/dist/routes/sessions.js +1 -1
- package/dist/routes/tech-stack.d.ts +2 -0
- package/dist/routes/tech-stack.js +2 -0
- package/dist/routes/terminal.js +19 -19
- package/dist/services/agent-pty-manager.d.ts +2 -0
- package/dist/services/agent-pty-manager.js +5 -4
- package/dist/services/agent-startup-memory.js +4 -4
- package/dist/services/bridge-temp-files.d.ts +36 -0
- package/dist/services/bridge-temp-files.js +2 -0
- package/dist/services/fileSnapshotStore.d.ts +9 -0
- package/dist/services/fileSnapshotStore.js +1 -1
- package/dist/services/gitignore.d.ts +12 -0
- package/dist/services/gitignore.js +2 -0
- package/dist/services/log-retention.js +1 -1
- package/dist/services/open-doc-events.d.ts +21 -0
- package/dist/services/open-doc-events.js +2 -0
- package/dist/services/open-doc-registry.d.ts +24 -0
- package/dist/services/open-doc-registry.js +2 -0
- package/dist/services/request-invalid-dump.js +1 -1
- package/dist/services/runtime-resources-snapshot.js +2 -2
- package/dist/services/snapshot-retention.d.ts +7 -0
- package/dist/services/snapshot-retention.js +2 -0
- package/dist/services/tech-stack-scanner.d.ts +31 -0
- package/dist/services/tech-stack-scanner.js +2 -0
- package/dist/services/tunnel-client.d.ts +42 -0
- package/dist/services/tunnel-client.js +1 -1
- package/dist/services/workspaceTaskChangeWatcher.js +2 -2
- package/package/acode/dist/__tests__/summary-request-helper.d.ts +2 -0
- package/package/acode/dist/__tests__/summary-request-helper.js +2 -0
- package/package/acode/dist/cache-control.d.ts +26 -0
- package/package/acode/dist/cache-control.js +2 -0
- package/package/acode/dist/compaction.d.ts +35 -5
- package/package/acode/dist/compaction.js +19 -17
- package/package/acode/dist/microcompact.d.ts +57 -0
- package/package/acode/dist/microcompact.js +2 -0
- package/package/acode/dist/runtime.d.ts +4 -0
- package/package/acode/dist/runtime.js +40 -33
- package/package/acode/dist/token-estimator.d.ts +15 -0
- package/package/acode/dist/token-estimator.js +2 -0
- package/package/acode/dist/types.d.ts +13 -0
- package/package/aws-client-agent-mcp/dist/ability-market-tools.js +1 -1
- package/package/aws-client-agent-mcp/dist/agent-client.d.ts +15 -2
- package/package/aws-client-agent-mcp/dist/agent-client.js +1 -1
- package/package/aws-client-agent-mcp/dist/mcp-server.d.ts +5 -0
- package/package/aws-client-agent-mcp/dist/mcp-server.js +25 -23
- package/package/aws-client-agent-mcp/dist/mcp-tools.js +7 -7
- package/package/aws-client-agent-mcp/dist/memory-store.d.ts +21 -2
- package/package/aws-client-agent-mcp/dist/memory-store.js +27 -2
- package/package/aws-client-agent-mcp/dist/memory-tools.js +13 -9
- package/package/aws-client-agent-mcp/dist/server-memory-store.d.ts +1 -1
- package/package/aws-client-agent-mcp/dist/server-memory-store.js +1 -1
- package/package/aws-client-agent-mcp/dist/types.d.ts +51 -0
- package/package.json +1 -1
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import c from"node:fs/promises";import o from"node:path";import{getAutoRegisterConfigFilePath as N,getBridgeDataHome as
|
|
1
|
+
import c from"node:fs/promises";import o from"node:path";import{getAutoRegisterConfigFilePath as N,getBridgeDataHome as S,getRuntimeHomeDir as I}from"../config.js";import{createLogger as x}from"../utils/logger.js";import{sweepExpiredSnapshots as b}from"./fileSnapshotStore.js";import{getSnapshotRetentionDays as M,setSnapshotRetentionDays as O}from"./snapshot-retention.js";const w=x("log-retention"),m=7,j=7,_=6*60*60*1e3,$="Instance-ai-configuration-debug.log";let r=m,l=null,d=!1,y=!1,h=!1;function A(t,e){h||(h=!0,w.warn(`${t}${e instanceof Error?`: ${e.message}`:""}`))}function E(t){if(t==null||t===""||typeof t=="boolean")return m;const e=Number(t);return!Number.isFinite(e)||e<=0?m:Math.min(Math.floor(e),j)}function q(t){const e=E(t);return y=!0,e!==r&&(r=e,F()),r}function K(){return r}function Q(){r=m}function Z(){r=m,y=!1,l&&(clearInterval(l),l=null),d=!1,h=!1}function W(){const t=o.join(S(),"log");return{logDir:t,agentLogDir:o.join(t,"agent"),instanceAiDebugLogPath:o.join(z(),$)}}function z(){return String(process.env.AWS_TEST_HOME||"").trim()||String(process.env.AWS_RUNTIME_HOME_DIR||"").trim()||I()}async function D(t,e,i){try{const n=await c.stat(t);return n.mtimeMs>=e?!1:(await c.unlink(t),i.removedFiles+=1,i.bytesFreed+=n.size,!0)}catch(n){return n.code!=="ENOENT"&&(i.failures+=1,A("[log-retention] \u5220\u9664\u8FC7\u671F\u65E5\u5FD7\u5931\u8D25",n)),!1}}async function G(t,e,i){let n=o.normalize(t);const s=o.normalize(e);for(;n.startsWith(s)&&n!==s;){try{await c.rmdir(n),i.removedDirs+=1}catch{return}n=o.dirname(n)}}async function H(t,e,i){let n;try{n=await c.readdir(t)}catch{return}for(const s of n)!s.startsWith("lifecycle-")||!s.endsWith(".jsonl")||await D(o.join(t,s),e,i)}async function B(t,e,i){const n=o.join(t,"aws-mcp-node");let s;try{s=(await c.readdir(n,{withFileTypes:!0})).filter(u=>u.isDirectory()).map(u=>o.join(n,u.name))}catch{return}for(const g of s){let u;try{u=(await c.readdir(g,{withFileTypes:!0})).filter(a=>a.isDirectory()).map(a=>o.join(g,a.name))}catch{continue}for(const f of u){let a;try{a=(await c.readdir(f,{withFileTypes:!0})).filter(p=>p.isFile()).map(p=>o.join(f,p.name))}catch{continue}let L=!0;for(const T of a)await D(T,e,i)||(L=!1);L&&a.length>0&&await G(f,n,i)}let v;try{v=(await c.readdir(g,{withFileTypes:!0})).filter(a=>a.isFile()).map(a=>o.join(g,a.name))}catch{continue}for(const f of v)await D(f,e,i)}}async function P(t,e,i){await D(t,e,i)}function F(){const t=async()=>{const e={retentionDays:r,removedFiles:0,removedDirs:0,failures:0,bytesFreed:0},i=Date.now()-r*24*60*60*1e3,n=W();try{await H(n.logDir,i,e),await B(n.agentLogDir,i,e),await P(n.instanceAiDebugLogPath,i,e)}catch(s){A("[log-retention] \u6E05\u7406\u8FC7\u671F\u65E5\u5FD7\u51FA\u9519",s)}return await b(M()),(e.removedFiles>0||e.removedDirs>0)&&w.info(`[log-retention] \u6E05\u7406\u5B8C\u6210\uFF1A\u5220\u9664 ${e.removedFiles} \u4E2A\u6587\u4EF6 / ${e.removedDirs} \u4E2A\u76EE\u5F55\uFF0C\u91CA\u653E ${(e.bytesFreed/1024/1024).toFixed(1)} MB\uFF08\u4FDD\u7559 ${r} \u5929\uFF09`),e};return d||(d=!0,R=t().finally(()=>{d=!1})),R}let R=Promise.resolve({retentionDays:r,removedFiles:0,removedDirs:0,failures:0,bytesFreed:0});function ee(){if(l)return;const t=String(process.env.AWS_BRIDGE_LOG_RETENTION_DAYS||"").trim();t&&(r=E(t),y=!0),l=setInterval(()=>{F()},_),U().finally(()=>{F(),w.info(`[log-retention] \u65E5\u5FD7\u4FDD\u7559\u7B56\u7565\u5DF2\u542F\u52A8\uFF1A\u4FDD\u7559 ${r} \u5929\uFF0C\u6BCF ${_/36e5}h \u6E05\u7406\u4E00\u6B21`)})}async function U(){try{const t=await c.readFile(N(),"utf-8"),e=JSON.parse(t);e.logRetentionDays!==void 0&&!y&&(r=E(e.logRetentionDays)),e.snapshotRetentionDays!==void 0&&O(e.snapshotRetentionDays,!0)}catch{}}function te(){l&&(clearInterval(l),l=null)}export{m as DEFAULT_LOG_RETENTION_DAYS,K as getLogRetentionDays,W as getLogRetentionTargets,E as normalizeLogRetentionDays,Q as resetLogRetentionDaysForTest,q as setLogRetentionDays,ee as startLogRetention,te as stopLogRetention,Z as stopLogRetentionForTest,F as sweepExpiredLogs};
|
|
2
2
|
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
|
|
2
|
+
import type { OpenDocKind } from "./open-doc-registry.js";
|
|
3
|
+
|
|
4
|
+
export type OpenDocEvent = {
|
|
5
|
+
action: "open";
|
|
6
|
+
kind: OpenDocKind;
|
|
7
|
+
docId: string;
|
|
8
|
+
name: string;
|
|
9
|
+
detail?: string;
|
|
10
|
+
} | {
|
|
11
|
+
action: "close";
|
|
12
|
+
kind: OpenDocKind;
|
|
13
|
+
} | {
|
|
14
|
+
action: "delete";
|
|
15
|
+
kind: OpenDocKind;
|
|
16
|
+
docId: string;
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
export declare function normalizeSemanticToolName(raw: string | undefined): string;
|
|
20
|
+
|
|
21
|
+
export declare function resolveOpenDocEvent(toolName: string | undefined, args: Record<string, unknown> | undefined, result: unknown): OpenDocEvent | null;
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
const d={pencil_open_document:"pencil",pencil_close_document:"pencil",pencil_delete_document:"pencil",draw_open_document:"draw",draw_close_document:"draw",draw_delete_document:"draw",office_open_document:"office",office_close_document:"office",office_delete_document:"office"};function s(t){let e=String(t??"").trim().toLowerCase();if(!e)return"";const n=e.lastIndexOf("/");return n>=0&&(e=e.slice(n+1)),e.includes("__")&&(e=e.split("__").pop()??e),e}function p(t,e){if(t!=="call_tool"||!e)return null;const n=e.name;if(typeof n!="string"||!n.trim())return null;const r=e.arguments&&typeof e.arguments=="object"&&!Array.isArray(e.arguments)?e.arguments:{};return{innerName:s(n),innerArgs:r}}function a(t){const e=String(t??"").trim().replace(/\\/g,"/"),n=e.lastIndexOf("/");return n>=0?e.slice(n+1):e}function _(t){if(t&&typeof t=="object"&&!Array.isArray(t))return t;if(typeof t!="string")return null;try{const e=JSON.parse(t);return!e||typeof e!="object"||Array.isArray(e)?null:e}catch{return null}}function g(t,e,n){let r=s(t),c=e;if(r==="call_tool"){const u=p(r,e);if(!u)return null;r=u.innerName,c=u.innerArgs}const o=d[r];if(!o)return null;if(r.endsWith("_close_document"))return{action:"close",kind:o};const i=_(n),f=typeof i?.docId=="string"?i.docId.trim():typeof c?.docId=="string"?c.docId.trim():"";if(r.endsWith("_delete_document"))return f?{action:"delete",kind:o,docId:f}:null;if(!i||i.ok===!1)return null;const l=y(r,o,i,c);if(!l)return null;const m=o==="office"&&typeof i.kind=="string"&&i.kind.trim()?i.kind.trim():void 0;return{action:"open",kind:o,docId:f,name:l,...m?{detail:m}:{}}}function y(t,e,n,r){if(e!=="office"){const f=typeof n.name=="string"?n.name.trim():"";return f||(typeof r?.name=="string"?r.name.trim():"")}const c=typeof n.fileName=="string"?n.fileName.trim():"";if(c)return c;const o=typeof n.file=="string"?n.file.trim():"";if(o)return a(o);const i=typeof r?.file=="string"?r.file.trim():"";return i?a(i):""}export{s as normalizeSemanticToolName,g as resolveOpenDocEvent};
|
|
2
|
+
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
|
|
2
|
+
|
|
3
|
+
export type OpenDocKind = "pencil" | "draw" | "office";
|
|
4
|
+
|
|
5
|
+
export interface OpenDocEntry {
|
|
6
|
+
|
|
7
|
+
kind: OpenDocKind;
|
|
8
|
+
|
|
9
|
+
docId: string;
|
|
10
|
+
|
|
11
|
+
name: string;
|
|
12
|
+
|
|
13
|
+
detail?: string;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export declare function recordOpenDocument(agentId: string | undefined, entry: OpenDocEntry): void;
|
|
17
|
+
|
|
18
|
+
export declare function closeOpenDocument(agentId: string | undefined, kind: OpenDocKind): void;
|
|
19
|
+
|
|
20
|
+
export declare function removeOpenDocument(agentId: string | undefined, kind: OpenDocKind, docId: string): void;
|
|
21
|
+
|
|
22
|
+
export declare function listOpenDocuments(agentId: string | undefined): OpenDocEntry[];
|
|
23
|
+
|
|
24
|
+
export declare function clearOpenDocuments(agentId: string | undefined): void;
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
const o=new Map;function s(r,t){const e=String(r??"").trim();if(!e||!t.name.trim())return;let n=o.get(e);n||(n=new Map,o.set(e,n)),n.set(t.kind,{...t,docId:t.docId.trim(),name:t.name.trim()})}function f(r,t){const e=String(r??"").trim();e&&o.get(e)?.delete(t)}function g(r,t,e){const n=String(r??"").trim();if(!n)return;const c=e.trim();if(!c)return;const i=o.get(n)?.get(t);i&&i.docId&&i.docId===c&&o.get(n)?.delete(t)}function m(r){const t=String(r??"").trim();if(!t)return[];const e=o.get(t);if(!e)return[];const n=["pencil","draw","office"],c=[];for(const i of n){const u=e.get(i);u&&c.push(u)}return c}function d(r){const t=String(r??"").trim();t&&o.delete(t)}export{d as clearOpenDocuments,f as closeOpenDocument,m as listOpenDocuments,s as recordOpenDocument,g as removeOpenDocument};
|
|
2
|
+
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{createHash as T}from"node:crypto";import i from"node:fs/promises";import d from"node:path";import{getBridgeDataHome as v}from"../config.js";const p="acode-request-invalid-",I=20,h=10*6e4,_=8e3,w=2*1024*1024,u=800;let m=!1;const g=new Map;function C(){g.clear(),m=!1}function S(){return d.join(v(),"log")}function D(e){return T("sha1").update(e).digest("hex").slice(0,16)}function E(e){return new Date(e).toISOString().replace(/[:.]/g,"-")}function x(e){if(!Array.isArray(e))return{conversation:[],truncated:!1};try{if(JSON.stringify(e).length<=w)return{conversation:e,truncated:!1}}catch{}return{conversation:e.map(n=>{if(!n||typeof n!="object")return{value:String(n).slice(0,u)};const r=n,t=r.content;let o;if(typeof t=="string")o=t.slice(0,u);else if(t==null)o=t;else try{o=JSON.stringify(t).slice(0,u)}catch{o="[unserializable]"}return{role:r.role,tool_call_id:r.tool_call_id,tool_calls:Array.isArray(r.tool_calls)?r.tool_calls.map(c=>{const s=c;return{id:s?.id,type:s?.type,name:s?.name??s?.function?.name}}):void 0,contentPreview:o}}),truncated:!0}}async function O(e){try{const n=(await i.readdir(e)).filter(t=>t.startsWith(p)&&t.endsWith(".json")).sort(),r=n.length-I;if(r<=0)return;await Promise.all(n.slice(0,r).map(t=>i.rm(d.join(e,t),{force:!0})))}catch{}}async function M(e){const a=S(),n=D(e.errorText),r=Date.now(),t=g.get(e.sessionId);if(t&&t.fingerprint===n&&r-t.at<h)return t.file;const{conversation:o,truncated:c}=x(e.conversation),s=`${p}${E(r)}-${e.sessionId.slice(0,8)}.json`,l=d.join(a,s),y={timestamp:new Date(r).toISOString(),kind:"provider-request-invalid",sessionId:e.sessionId,agentId:e.agentId,model:e.model,attempt:e.attempt,errorText:e.errorText.slice(0,_),errorTextTruncated:e.errorText.length>_,messageCount:Array.isArray(e.conversation)?e.conversation.length:0,conversationTruncated:c,conversation:o,...e.extra?{extra:e.extra}:{}};try{return await i.mkdir(a,{recursive:!0}),await i.writeFile(l,JSON.stringify(y,null,2),"utf8"),g.set(e.sessionId,{fingerprint:n,file:l,at:r}),await O(a),l}catch(f){return m||(m=!0,console.warn(`[request-invalid-dump] \u4E0A\u4E0B\u6587\u5FEB\u7167\u5199\u5165\u5931\u8D25\uFF0C\u540E\u7EED\u5FEB\u7167\u5C06\u88AB\u4E22\u5F03: ${f instanceof Error?f.message:String(f)}`)),null}}export{M as dumpInvalidProviderRequest,S as getInvalidRequestDumpDir,C as resetInvalidRequestDumpStateForTest};
|
|
1
|
+
import{createHash as T}from"node:crypto";import i from"node:fs/promises";import d from"node:path";import{getBridgeDataHome as v}from"../config.js";const p="acode-request-invalid-",I=20,h=10*6e4,_=8e3,w=2*1024*1024,u=800;let m=!1;const g=new Map;function C(){g.clear(),m=!1}function S(){return d.join(v(),"log")}function D(e){return T("sha1").update(e).digest("hex").slice(0,16)}function E(e){return new Date(e).toISOString().replace(/[:.]/g,"-")}function x(e){if(!Array.isArray(e))return{conversation:[],truncated:!1};try{if(JSON.stringify(e).length<=w)return{conversation:e,truncated:!1}}catch{}return{conversation:e.map(n=>{if(!n||typeof n!="object")return{value:String(n).slice(0,u)};const r=n,t=r.content;let o;if(typeof t=="string")o=t.slice(0,u);else if(t==null)o=t;else try{o=JSON.stringify(t).slice(0,u)}catch{o="[unserializable]"}return{role:r.role,tool_call_id:r.tool_call_id,tool_calls:Array.isArray(r.tool_calls)?r.tool_calls.map(c=>{const s=c;return{id:s?.id,type:s?.type,name:s?.name??s?.function?.name}}):void 0,contentPreview:o}}),truncated:!0}}async function O(e){try{const n=(await i.readdir(e)).filter(t=>t.startsWith(p)&&t.endsWith(".json")).sort(),r=n.length-I;if(r<=0)return;await Promise.all(n.slice(0,r).map(t=>i.rm(d.join(e,t),{force:!0})))}catch{}}async function M(e){const a=S(),n=D(e.errorText),r=Date.now(),t=g.get(e.sessionId);if(t&&t.fingerprint===n&&r-t.at<h)return t.file;const{conversation:o,truncated:c}=x(e.conversation),s=`${p}${E(r)}-${e.sessionId.slice(0,8)}-${n.slice(0,8)}.json`,l=d.join(a,s),y={timestamp:new Date(r).toISOString(),kind:"provider-request-invalid",sessionId:e.sessionId,agentId:e.agentId,model:e.model,attempt:e.attempt,errorText:e.errorText.slice(0,_),errorTextTruncated:e.errorText.length>_,messageCount:Array.isArray(e.conversation)?e.conversation.length:0,conversationTruncated:c,conversation:o,...e.extra?{extra:e.extra}:{}};try{return await i.mkdir(a,{recursive:!0}),await i.writeFile(l,JSON.stringify(y,null,2),"utf8"),g.set(e.sessionId,{fingerprint:n,file:l,at:r}),await O(a),l}catch(f){return m||(m=!0,console.warn(`[request-invalid-dump] \u4E0A\u4E0B\u6587\u5FEB\u7167\u5199\u5165\u5931\u8D25\uFF0C\u540E\u7EED\u5FEB\u7167\u5C06\u88AB\u4E22\u5F03: ${f instanceof Error?f.message:String(f)}`)),null}}export{M as dumpInvalidProviderRequest,S as getInvalidRequestDumpDir,C as resetInvalidRequestDumpStateForTest};
|
|
2
2
|
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import
|
|
2
|
-
`)}async function
|
|
1
|
+
import m from"axios";import{getBrowserPool as f}from"../browser/browser-pool.js";import{resolveSchedulerBaseUrl as p}from"../config.js";import{ptySessions as g}from"../routes/pty.js";import{createLogger as $}from"../utils/logger.js";import{getAcodeBgManager as h}from"./acode-bg-manager.js";import{agentPtyManager as w}from"./agent-pty-manager.js";import{listOpenDocuments as b}from"./open-doc-registry.js";import{getRuntimeAccessToken as l}from"./runtime-binding.js";import{subAgentManager as k}from"./sub-agent-manager-instance.js";const i=$("runtime-resources"),S=3e3,a=20,y={pencil:"open pencil canvas",draw:"open draw diagram",office:"open office document"};function c(t,e){const n=String(t??"").replace(/\s+/g," ").trim();return n.length>e?`${n.slice(0,e)}\u2026`:n}function D(t){if(typeof t!="number"||!Number.isFinite(t)||t<=0)return"";const e=new Date(t),n=r=>String(r).padStart(2,"0");return`${n(e.getHours())}:${n(e.getMinutes())}`}async function v(t){try{const e=await h();return e?.listTasksWithReconcile?(await e.listTasksWithReconcile(t,"running")).filter(r=>r.status==="running").slice(0,a).map(r=>{const o=D(r.startedAt),s=r.description?c(r.description,60):c(r.commandPreview||r.command,80);return{kind:"background commands",text:`${r.taskId} \`${s}\`${o?` (since ${o})`:""}`}}):[]}catch(e){return i.warn(`collect background commands failed: ${e?.message}`),[]}}function x(t){try{const e=[];let n=[];try{n=w.listWaitingForInput(t)}catch(o){i.warn(`collect terminals waiting-input failed: ${o?.message}`)}const r=new Set(n);for(const o of g.values()){if(o.ownerUserId!==t||o.status!=="running")continue;if(e.length>=a)break;const s=c(o.title||o.shell,60),d=r.has(o.id)?"running, waiting for input":"running";e.push({kind:"terminals",text:`${o.id} ${s} (${d})`})}return e}catch(e){return i.warn(`collect terminals failed: ${e?.message}`),[]}}function A(t){try{return k.listActiveByParent(t).slice(0,a).map(n=>({kind:"sub-agents",text:`${n.subId} ${n.subagentType} "${c(n.description,60)}" (running)`}))}catch(e){return i.warn(`collect sub-agents failed: ${e?.message}`),[]}}function T(t){try{return f().listSessions(t).slice(0,a).map(n=>{const r=c(n.title||n.browserId,40),o=c(n.currentUrl,80);return{kind:"browsers",text:`${c(n.browserId,40)} "${r}"${o?` ${o}`:""}`}})}catch(e){return i.warn(`collect browsers failed: ${e?.message}`),[]}}function M(t){try{return b(t).map(e=>{const n=e.docId?`${e.docId} `:"",r=e.detail?` (${e.detail})`:"";return{kind:y[e.kind],text:`${n}${e.name}${r}`}})}catch(e){return i.warn(`collect open documents failed: ${e?.message}`),[]}}function u(t,e){if(!Array.isArray(e))return[];const n=[];for(const r of e){if(n.length>=a)break;const o=c(String(r?.name??r?.docId??""),60);if(!o)continue;const s=String(r?.permission??"").trim();n.push({kind:t,text:`${o}${s?` (${s})`:""}`})}return n}async function R(t){try{const{url:e}=p();if(!e)return[];const n=l(e)||l();if(!n)return[];const o=(await m.get(`${e}/api/runtime/agent-resources`,{params:{agentId:t},headers:{"X-Runtime-Token":n},timeout:S})).data??{};return[...u("office docs",o.officeDocs),...u("pencil docs",o.pencilDocs),...u("draw docs",o.drawDocs)]}catch(e){return i.warn(`collect java docs failed (office/pencil/draw omitted): agentId=${t}, error=${e?.message}`),[]}}function _(t){const e=new Map;for(const r of t){const o=e.get(r.kind);o?o.push(r.text):e.set(r.kind,[r.text])}const n=["[Runtime resources \u2014 live snapshot taken after context compaction.]","These already exist and are still running/available. Reuse them instead of creating duplicates","(do not start another dev server, open another browser, or redraw an existing document).","Details (output, page content, document body) are not included \u2014 query them when needed."];for(const[r,o]of e)n.push(`- ${r} (${o.length}): ${o.join("; ")}`);return n.join(`
|
|
2
|
+
`)}async function W(t){if(!t)return null;try{const[e,n]=await Promise.all([v(t),R(t)]),r=[...e,...x(t),...A(t),...T(t),...M(t),...n];if(r.length===0)return null;const o=_(r);return i.debug(`snapshot built for agentId=${t}: ${r.length} entries (${[...new Set(r.map(s=>s.kind))].join(", ")})`),o}catch(e){return i.warn(`build snapshot failed: ${e?.message}`),null}}export{W as buildRuntimeResourcesSnapshot};
|
|
3
3
|
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
const u=3650;let t=null,l=!1;function i(e,o=!1){if(o&&l)return;if(o||(l=!0),e==null||e===""){t=null;return}if(typeof e=="boolean"){t=null;return}const n=Number(e);if(!Number.isFinite(n)||n<=0){t=null;return}t=Math.min(Math.floor(n),3650)}function r(){return t}function s(){t=null,l=!1}export{r as getSnapshotRetentionDays,s as resetSnapshotRetentionForTest,i as setSnapshotRetentionDays};
|
|
2
|
+
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
|
|
2
|
+
|
|
3
|
+
export type LaunchStackType = "generic" | "java" | "python" | "node" | "go" | "php";
|
|
4
|
+
export interface TechStackCandidate {
|
|
5
|
+
|
|
6
|
+
id: string;
|
|
7
|
+
|
|
8
|
+
name: string;
|
|
9
|
+
type: LaunchStackType;
|
|
10
|
+
|
|
11
|
+
command: string;
|
|
12
|
+
|
|
13
|
+
cwd: string;
|
|
14
|
+
|
|
15
|
+
relativeCwd: string;
|
|
16
|
+
|
|
17
|
+
stack: string;
|
|
18
|
+
|
|
19
|
+
markers: string[];
|
|
20
|
+
confidence: "high" | "medium" | "low";
|
|
21
|
+
}
|
|
22
|
+
export interface TechStackScanResult {
|
|
23
|
+
workspacePath: string;
|
|
24
|
+
|
|
25
|
+
scannedDirs: number;
|
|
26
|
+
|
|
27
|
+
truncated: boolean;
|
|
28
|
+
candidates: TechStackCandidate[];
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export declare function scanTechStack(workspacePath: string): Promise<TechStackScanResult>;
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import N from"node:crypto";import{promises as k}from"node:fs";import d from"node:path";import{createLogger as R}from"../utils/logger.js";import{isIgnoredByGitIgnore as A,loadGitIgnoreRules as B}from"./gitignore.js";const w=R("tech-stack-scanner"),E=64*1024,T=4e3,C=2e3,F=5,M=new Set([".git",".svn",".hg",".idea",".vscode","node_modules","bower_components","vendor","target","dist","build","out","bin","obj",".gradle",".venv","venv","env","__pycache__",".mypy_cache",".pytest_cache",".next",".nuxt",".svelte-kit",".turbo",".cache","coverage"]);function q(e,n){return e==="."?n:`${e}/${n}`}async function g(e){try{const n=await k.open(e,"r");try{const t=await n.stat();if(!t.isFile())return null;const p=Math.min(t.size,E),o=Buffer.alloc(p);return await n.read(o,0,p,0),o.toString("utf8")}finally{await n.close()}}catch{return null}}async function D(e){try{return(await k.stat(e)).isFile()}catch{return!1}}function _(e){if(!e)return null;try{const n=JSON.parse(e);return n&&typeof n=="object"?n:null}catch{return null}}function L(e,n,t){return N.createHash("sha1").update(`${e}|${n}|${t}`).digest("hex").slice(0,12)}function I(e){return process.platform==="win32"?`${e}.cmd`:`./${e}`}function O(e,n,t){return n.has("mvnw")||n.has("mvnw.cmd")?`${I("mvnw")} ${t}`:`mvn ${t}`}function W(e,n){return e.has("gradlew")||e.has("gradlew.bat")?`${I("gradlew")} ${n}`:`gradle ${n}`}function G(e){if(!e)return"";const t=e.replace(/<parent>[\s\S]*?<\/parent>/gi,"").match(/<artifactId>\s*([^<\s]+)\s*<\/artifactId>/i);return t?t[1].trim():""}function J(e){if(!e)return"";const n=e.match(/rootProject\.name\s*=\s*['"]([^'"]+)['"]/);return n?n[1].trim():""}function X(e){if(!e)return"";const n=e.match(/\[package\][\s\S]*?(?=\n\[|$)/),p=(n?n[0]:e).match(/^\s*name\s*=\s*["']([^"']+)["']/m);return p?p[1].trim():""}function x(e){return d.basename(e)||"workspace"}function Y(e){return e.has("pnpm-lock.yaml")||e.has("pnpm-workspace.yaml")?{runner:"pnpm",runCommand:n=>`pnpm run ${n}`}:e.has("yarn.lock")?{runner:"yarn",runCommand:n=>`yarn run ${n}`}:e.has("bun.lockb")||e.has("bun.lock")?{runner:"bun",runCommand:n=>`bun run ${n}`}:{runner:"npm",runCommand:n=>`npm run ${n}`}}const K=["dev","develop","serve","start"];function z(e){for(const n of K)if(typeof e[n]=="string"&&e[n].trim())return n;return null}function H(e,n){return e.has("uv.lock")?"uv run ":n&&/\[tool\.poetry\]/i.test(n)?"poetry run ":""}function m(e){const{facts:n,stack:t,type:p,command:o,name:i,markers:h,confidence:f}=e;return{id:L(n.relativeDir,t,o),name:i||x(n.absoluteDir),type:p,command:o,cwd:n.absoluteDir,relativeCwd:n.relativeDir,stack:t,markers:h,confidence:f}}async function Q(e){const{absoluteDir:n,entryNames:t,subdirectories:p}=e,o=[],i=x(n);if(t.has("pom.xml")){const a=await g(d.join(n,"pom.xml")),s=G(a)||i,c=!!(a&&/spring-boot/i.test(a));o.push(m({facts:e,stack:c?"spring-boot":"maven",type:"java",command:O(n,t,c?"spring-boot:run":"-DskipTests package"),name:s,markers:["pom.xml"],confidence:c?"high":"medium"}))}else if(t.has("build.gradle")||t.has("build.gradle.kts")){const a=t.has("build.gradle.kts")?"build.gradle.kts":"build.gradle",s=await g(d.join(n,a)),c=J(s)||i,r=!!(s&&/org\.springframework\.boot/i.test(s));o.push(m({facts:e,stack:r?"spring-boot":"gradle",type:"java",command:W(t,r?"bootRun":"build"),name:c,markers:[a],confidence:r?"high":"medium"}))}if(t.has("package.json")){const a=_(await g(d.join(n,"package.json"))),s=a&&typeof a.scripts=="object"&&a.scripts!==null?a.scripts:{},c=z(s);if(c){const{runCommand:r}=Y(t),l=a&&typeof a.name=="string"?a.name.trim():"";o.push(m({facts:e,stack:"node",type:"node",command:r(c),name:l||i,markers:["package.json"],confidence:"high"}))}}if(t.has("manage.py"))o.push(m({facts:e,stack:"django",type:"python",command:"python manage.py runserver",name:`${i} (Django)`,markers:["manage.py"],confidence:"high"}));else if(t.has("pyproject.toml")||t.has("requirements.txt")||t.has("setup.py")){const a=t.has("pyproject.toml")?await g(d.join(n,"pyproject.toml")):null,s=H(t,a),c=t.has("pyproject.toml")?"pyproject.toml":t.has("requirements.txt")?"requirements.txt":"setup.py";!!(a&&/fastapi/i.test(a))&&t.has("main.py")?o.push(m({facts:e,stack:"fastapi",type:"python",command:`${s}uvicorn main:app --reload`,name:`${i} (FastAPI)`,markers:[c,"main.py"],confidence:"high"})):t.has("main.py")?o.push(m({facts:e,stack:"python",type:"python",command:`${s}python main.py`,name:i,markers:[c,"main.py"],confidence:"medium"})):t.has("app.py")&&o.push(m({facts:e,stack:"python",type:"python",command:`${s}python app.py`,name:i,markers:[c,"app.py"],confidence:"medium"}))}if(t.has("go.mod")){if(t.has("main.go"))o.push(m({facts:e,stack:"go",type:"go",command:"go run .",name:i,markers:["go.mod","main.go"],confidence:"high"}));else if(p.includes("cmd")){const a=d.join(n,"cmd");let s=[];try{s=await k.readdir(a,{withFileTypes:!0})}catch{s=[]}const c=s.filter(r=>r.isDirectory()).map(r=>r.name).sort().slice(0,F);for(const r of c)await D(d.join(a,r,"main.go"))&&o.push(m({facts:e,stack:"go",type:"go",command:`go run ./cmd/${r}`,name:`${i}/${r}`,markers:["go.mod",`cmd/${r}/main.go`],confidence:"high"}))}}if(t.has("composer.json")){const a=_(await g(d.join(n,"composer.json"))),s=a&&typeof a.name=="string"?a.name.trim():"";!!(a&&(/laravel\/framework/i.test(JSON.stringify(a.require??{}))||/laravel\/framework/i.test(JSON.stringify(a["require-dev"]??{}))))&&t.has("artisan")?o.push(m({facts:e,stack:"laravel",type:"php",command:"php artisan serve",name:s||i,markers:["composer.json","artisan"],confidence:"high"})):e.directoryNames.has("public")&&e.directoryNames.has("bin")?o.push(m({facts:e,stack:"symfony",type:"php",command:"php -S localhost:8000 -t public",name:s||i,markers:["composer.json"],confidence:"medium"})):t.has("index.php")&&o.push(m({facts:e,stack:"php",type:"php",command:"php -S localhost:8000",name:s||i,markers:["composer.json","index.php"],confidence:"medium"}))}else t.has("index.php")&&o.push(m({facts:e,stack:"php",type:"php",command:"php -S localhost:8000",name:i,markers:["index.php"],confidence:"low"}));if(t.has("Cargo.toml")){const a=await g(d.join(n,"Cargo.toml")),s=!!(a&&/^\s*\[package\]/m.test(a)),c=!!(a&&/^\s*\[\[bin\]\]/m.test(a)||await D(d.join(n,"src","main.rs")));if(s&&c){const r=X(a);o.push(m({facts:e,stack:"cargo",type:"generic",command:"cargo run",name:r||i,markers:["Cargo.toml"],confidence:"medium"}))}}const h=t.has("deno.json")?"deno.json":t.has("deno.jsonc")?"deno.jsonc":"";if(h){const a=await g(d.join(n,h));a&&/["']?start["']?\s*:/.test(a)&&o.push(m({facts:e,stack:"deno",type:"generic",command:"deno task start",name:i,markers:[h],confidence:"medium"}))}const f=["docker-compose.yml","docker-compose.yaml","compose.yml","compose.yaml"].find(a=>t.has(a));return f&&o.push(m({facts:e,stack:"docker-compose",type:"generic",command:"docker compose up",name:`${i} (compose)`,markers:[f],confidence:"medium"})),o}function U(e,n,t,p){return M.has(t.toLowerCase())?!0:p.length===0?!1:A(n,!0,p)}async function ae(e){const n=String(e||"").trim();if(!n)throw new Error("workspacePath is required");const t=d.resolve(n);if(!(await k.stat(t)).isDirectory())throw new Error(`Workspace path is not a directory: ${t}`);const o=await B(t),i=[];let h=0,f=!1;const a=[[t,"."]];for(;a.length>0;){if(h>=T){f=!0;break}const r=a.shift();if(!r)break;const[l,v]=r;h+=1;let y=[];try{y=await k.readdir(l,{withFileTypes:!0})}catch(u){w.warn(`[scan] readdir failed: dir=${l} error=${u.message}`);continue}y.length>C&&(f=!0,y=y.slice(0,C));const b=new Set,j=new Set,$=[];for(const u of y)if(u.isDirectory()){j.add(u.name);const S=q(v,u.name);if(U(t,S,u.name,o))continue;$.push(u.name),a.push([d.join(l,u.name),S])}else u.isFile()&&b.add(u.name);const P={absoluteDir:l,relativeDir:v,entryNames:b,directoryNames:j,subdirectories:$};try{i.push(...await Q(P))}catch(u){w.warn(`[scan] detect failed: dir=${l} error=${u.message}`)}}const s=new Set,c=i.filter(r=>s.has(r.id)?!1:(s.add(r.id),!0));return c.sort((r,l)=>r.relativeCwd!==l.relativeCwd?r.relativeCwd.localeCompare(l.relativeCwd):r.stack.localeCompare(l.stack)),w.info(`[scan] workspace=${t} dirs=${h} candidates=${c.length} truncated=${f}`),{workspacePath:t,scannedDirs:h,truncated:f,candidates:c}}export{ae as scanTechStack};
|
|
2
|
+
|
|
@@ -1,4 +1,36 @@
|
|
|
1
1
|
|
|
2
|
+
import WebSocket from "ws";
|
|
3
|
+
interface LocalStream {
|
|
4
|
+
ws: WebSocket;
|
|
5
|
+
|
|
6
|
+
pending: Array<{
|
|
7
|
+
data: Buffer;
|
|
8
|
+
bin: boolean;
|
|
9
|
+
}>;
|
|
10
|
+
}
|
|
11
|
+
interface TunnelState {
|
|
12
|
+
|
|
13
|
+
serverUrl: string;
|
|
14
|
+
instanceId: string;
|
|
15
|
+
ws?: WebSocket;
|
|
16
|
+
|
|
17
|
+
streams: Map<string, LocalStream>;
|
|
18
|
+
|
|
19
|
+
pendingReqChunks: Map<string, PendingRequestChunks>;
|
|
20
|
+
timer?: NodeJS.Timeout;
|
|
21
|
+
reconnectTimer?: NodeJS.Timeout;
|
|
22
|
+
|
|
23
|
+
reconnectAttempts?: number;
|
|
24
|
+
shuttingDown: boolean;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
interface PendingRequestChunks {
|
|
28
|
+
method: string;
|
|
29
|
+
path: string;
|
|
30
|
+
headers?: Record<string, string[]>;
|
|
31
|
+
parts: Buffer[];
|
|
32
|
+
timer: NodeJS.Timeout;
|
|
33
|
+
}
|
|
2
34
|
|
|
3
35
|
export declare function startTunnelClient(serverUrl: string, instanceId: string): void;
|
|
4
36
|
|
|
@@ -7,3 +39,13 @@ export declare function stopTunnelClient(): void;
|
|
|
7
39
|
export declare function stopTunnelClientForServer(serverUrl: string): void;
|
|
8
40
|
|
|
9
41
|
export declare function stopTunnelClientsExcept(serverUrls: string[]): void;
|
|
42
|
+
|
|
43
|
+
export declare const __tunnelClientTestHooks: {
|
|
44
|
+
createState(serverUrl?: string, instanceId?: string): TunnelState;
|
|
45
|
+
dispatch(state: TunnelState, msg: Record<string, unknown>): void;
|
|
46
|
+
|
|
47
|
+
pendingChunkIds(state: TunnelState): string[];
|
|
48
|
+
|
|
49
|
+
cleanup(state: TunnelState): void;
|
|
50
|
+
};
|
|
51
|
+
export {};
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import
|
|
1
|
+
import O,{AxiosError as x}from"axios";import g from"ws";import{getActiveBridgeHttpPort as R}from"../config.js";import{logger as s}from"../utils/logger.js";import{loadConfigs as L,loadPrimaryLifecycleConfig as P}from"./auto-register.js";import{getRuntimeAccessToken as W,normalizeSchedulerBaseUrl as C}from"./runtime-binding.js";const $=15e3,G=5e3,H=3e4,A=.2,J=200,K=1*1024*1024,X=4001,Y=768*1024,j=384*1024,z=5*6e4,p=new Map;function F(e){const n=e.serverUrl,r=e.instanceId;if(!n||!r)return null;try{const t=new URL(n),o=t.protocol==="https:"?"wss:":"ws:",u=W(n),l=L().find(h=>C(h.serverUrl)===n)||P(),i=u||l.userKey;if(u?s.debug("[TunnelClient] \u4F7F\u7528 runtime access token \u8FDE\u63A5\u96A7\u9053"):l.userKey&&s.warn("[TunnelClient] getRuntimeAccessToken \u8FD4\u56DE\u7A7A\uFF0C\u56DE\u9000\u5230 userKey\uFF08\u975E runtime token\uFF0C\u9274\u6743\u53EF\u80FD\u5931\u8D25\uFF09: targetUrl=",n),!i)return s.warn("[TunnelClient] \u7F3A\u5C11 runtime token\uFF0C\u65E0\u6CD5\u5EFA\u7ACB\u96A7\u9053: targetUrl=",n),null;const f=new URLSearchParams({instanceId:r});return{url:`${o}//${t.host}/ws/bridge-tunnel?${f.toString()}`,token:i}}catch(t){return s.warn("[TunnelClient] \u65E0\u6CD5\u89E3\u6790 serverUrl:",String(t)),null}}function le(e,n){const r=C(e);if(!r){s.warn("[TunnelClient] serverUrl \u65E0\u6548\uFF0C\u65E0\u6CD5\u542F\u52A8\u96A7\u9053:",e);return}const t=p.get(r);t&&(t.shuttingDown=!0,S(t),p.delete(r));const o={serverUrl:r,instanceId:n,streams:new Map,pendingReqChunks:new Map,shuttingDown:!1};p.set(r,o),B(o)}function de(){for(const e of p.values())e.shuttingDown=!0,S(e);p.clear()}function fe(e){const n=C(e);if(!n)return;const r=p.get(n);r&&(r.shuttingDown=!0,S(r),p.delete(n),s.info(`[TunnelClient] tunnel stopped: ${n}`))}function ae(e){const n=new Set(e.map(r=>C(r)).filter(r=>!!r));for(const[r,t]of p.entries())n.has(r)||(s.info(`[TunnelClient] serverUrl \u5DF2\u4E0D\u5728\u914D\u7F6E\u4E2D\uFF0C\u505C\u6B62\u65E7\u96A7\u9053: ${r}`),t.shuttingDown=!0,S(t),p.delete(r))}function S(e){e.timer&&(clearInterval(e.timer),e.timer=void 0),e.reconnectTimer&&(clearTimeout(e.reconnectTimer),e.reconnectTimer=void 0);for(const[n,r]of e.streams.entries()){try{r.ws.close(1e3,"tunnel client stopped")}catch{}e.streams.delete(n)}if(e.ws){e.ws.removeAllListeners();try{e.ws.close(1e3,"tunnel client stopped")}catch{}e.ws=void 0}}function B(e){if(e.shuttingDown)return;const n=e.instanceId;if(!n)return;const r=F(e);if(!r){b(e);return}s.info("[TunnelClient] \u8FDE\u63A5\u96A7\u9053\u670D\u52A1\u7AEF:",r.url);const t=new g(r.url,{handshakeTimeout:15e3,headers:{"X-Runtime-Token":r.token}});e.ws=t,t.on("open",()=>{s.info("[TunnelClient] \u96A7\u9053\u8FDE\u63A5\u5DF2\u5EFA\u7ACB: server=",e.serverUrl,"instanceId=",n),e.reconnectTimer&&clearTimeout(e.reconnectTimer),e.reconnectTimer=void 0,e.reconnectAttempts=0,e.timer=setInterval(()=>{t.readyState===g.OPEN&&t.send(JSON.stringify({t:"ping"}))},$)}),t.on("unexpected-response",(o,u)=>{s.error("[TunnelClient] \u670D\u52A1\u7AEF\u62D2\u7EDD\u8FDE\u63A5\uFF08\u975E 101 \u54CD\u5E94\uFF09: server=",e.serverUrl,"statusCode=",u.statusCode,"statusMessage=",u.statusMessage)}),t.on("upgrade",o=>{s.debug("[TunnelClient] \u6536\u5230\u5347\u7EA7\u54CD\u5E94: statusCode=",o.statusCode)}),t.on("message",o=>{let u;typeof o=="string"?u=o:Buffer.isBuffer(o)?u=o.toString("utf-8"):u=Buffer.from(o).toString("utf-8");try{const l=JSON.parse(u);M(e,l)}catch(l){s.warn("[TunnelClient] \u89E3\u6790\u96A7\u9053\u6D88\u606F\u5931\u8D25:",String(l))}}),t.on("close",(o,u)=>{if(s.warn("[TunnelClient] \u96A7\u9053\u8FDE\u63A5\u5173\u95ED: server=",e.serverUrl,"code=",o,"reason=",String(u)),k(e),o===X){s.warn("[TunnelClient] \u9274\u6743\u5931\u8D25\uFF084001\uFF09\uFF0C\u505C\u6B62\u81EA\u52A8\u91CD\u8FDE\uFF1B\u5F85\u91CD\u65B0\u6CE8\u518C\u540E\u518D\u542F\u52A8\u96A7\u9053: server=",e.serverUrl);return}b(e)}),t.on("error",o=>{s.warn("[TunnelClient] \u96A7\u9053\u8FDE\u63A5\u9519\u8BEF: server=",e.serverUrl,"err=",o.message,"code=",o.code),k(e),b(e)})}function k(e){e.timer&&(clearInterval(e.timer),e.timer=void 0);for(const[n,r]of e.streams.entries()){try{r.ws.close(1011,"tunnel disconnected")}catch{}e.streams.delete(n)}for(const n of Array.from(e.pendingReqChunks.keys()))E(e,n);e.ws=void 0}function b(e){if(e.shuttingDown||e.reconnectTimer)return;const n=(e.reconnectAttempts??0)+1;e.reconnectAttempts=n;const r=Math.min(G*Math.pow(2,n-1),H),t=1-A+Math.random()*A*2,o=Math.round(r*t);s.debug("[TunnelClient] \u8BA1\u5212\u91CD\u8FDE: server=",e.serverUrl,"attempt=",n,"delayMs=",o),e.reconnectTimer=setTimeout(()=>{e.reconnectTimer=void 0,B(e)},o)}function M(e,n){switch(n.t){case"req":n.chunked?V(e,n):U(e,n);break;case"reqchunk":Q(e,n);break;case"reqend":Z(e,n);break;case"wsopen":ee(e,n);break;case"wsmsg":ne(e,n);break;case"wsclose":re(e,n);break;case"ping":d(e,{t:"pong"});break;case"pong":break;default:s.debug("[TunnelClient] \u672A\u77E5\u6D88\u606F\u7C7B\u578B: t=",n.t)}}function V(e,n){E(e,n.id);const r=setTimeout(()=>{s.warn("[TunnelClient] \u8BF7\u6C42\u4F53\u62C6\u5E27\u8D85\u65F6\uFF0C\u4E22\u5F03\u534A\u5305:",n.id),e.pendingReqChunks.delete(n.id)},z);r.unref?.(),e.pendingReqChunks.set(n.id,{method:n.method||"GET",path:n.path||"/",headers:n.headers,parts:[],timer:r})}function Q(e,n){const r=e.pendingReqChunks.get(n.id);if(!r){s.debug("[TunnelClient] \u6536\u5230\u65E0\u4E3B reqchunk\uFF0C\u5DF2\u5FFD\u7565:",n.id);return}n.d&&r.parts.push(Buffer.from(n.d,"base64"))}async function Z(e,n){const r=e.pendingReqChunks.get(n.id);if(!r){s.debug("[TunnelClient] \u6536\u5230\u65E0\u4E3B reqend\uFF0C\u5DF2\u5FFD\u7565:",n.id);return}E(e,n.id);const t=Buffer.concat(r.parts);await U(e,{t:"req",id:n.id,method:r.method,path:r.path,headers:r.headers,body:t.length>0?t.toString("base64"):null})}function E(e,n){const r=e.pendingReqChunks.get(n);r&&(clearTimeout(r.timer),e.pendingReqChunks.delete(n))}async function U(e,n){const r=n.id,t=n.method||"GET",o=n.path||"/",u=`http://127.0.0.1:${R()}${o}`;try{const l=n.body?Buffer.from(n.body,"base64"):void 0,i={};if(n.headers)for(const[a,c]of Object.entries(n.headers))c&&c.length>0&&(i[a]=c[0]);i["x-bridge-tunnel-source"]=e.serverUrl;const f=await O.request({url:u,method:t,headers:i,data:l,timeout:0,responseType:"stream",validateStatus:()=>!0}),h={};for(const[a,c]of Object.entries(f.headers))c!==void 0&&(h[a]=Array.isArray(c)?c:[String(c)]);const v=f.data,I=String(h["content-type"]?.[0]||"").toLowerCase().includes("text/event-stream"),m=[];let w=0,T=!1,y=!1;try{if(v)for await(const a of v){const c=Buffer.isBuffer(a)?a:Buffer.from(a);if(c.length!==0){if(T){if(!_(e,r,c))return}else if(I){if(T=!0,y=!0,!d(e,{t:"res",id:r,status:f.status,headers:h,body:null,chunked:!0})||!_(e,r,c))return}else if(m.push(c),w+=c.length,w>Y){if(T=!0,y=!0,!d(e,{t:"res",id:r,status:f.status,headers:h,body:null,chunked:!0}))return;for(const D of m)if(!_(e,r,D))return;m.length=0,w=0}}}}catch(a){const c=a instanceof Error?a.message:String(a);s.warn("[TunnelClient] \u672C\u5730\u6D41\u8BFB\u53D6\u4E2D\u65AD:",t,o,"->",c),y?d(e,{t:"resend",id:r,error:c}):d(e,{t:"res",id:r,status:502,headers:{"content-type":["text/plain; charset=utf-8"]},body:Buffer.from(c).toString("base64")});return}if(T){d(e,{t:"resend",id:r});return}const N=w>0?Buffer.concat(m).toString("base64"):"";d(e,{t:"res",id:r,status:f.status,headers:h,body:N||null})}catch(l){const i=l instanceof x?l.message:String(l);s.warn("[TunnelClient] \u672C\u5730\u8F6C\u53D1\u5931\u8D25:",t,o,"->",i),d(e,{t:"res",id:r,status:502,headers:{"content-type":["text/plain; charset=utf-8"]},body:Buffer.from(i).toString("base64")})}}function _(e,n,r){let t=0;for(;t<r.length;){const o=r.subarray(t,t+j);if(!d(e,{t:"reschunk",id:n,d:o.toString("base64")}))return!1;t+=o.length}return!0}function ee(e,n){const r=n.id,t=n.path||"/",o=`ws://127.0.0.1:${R()}${t}`;let u;try{u=new g(o,{handshakeTimeout:1e4})}catch(i){s.warn("[TunnelClient] \u672C\u5730 WS \u8FDE\u63A5\u5931\u8D25:",String(i)),d(e,{t:"wsclose",id:r,code:1011,reason:"local ws connect failed"});return}const l={ws:u,pending:[]};e.streams.set(r,l),u.on("open",()=>{for(const i of l.pending)q(l,i.data,i.bin);l.pending=[],d(e,{t:"wsopened",id:r})}),u.on("message",(i,f)=>{const h=Buffer.isBuffer(i)?i:Buffer.from(i);f&&e.ws&&e.ws.bufferedAmount>K||d(e,{t:"wsmsg",id:r,bin:f,d:h.toString("base64")})}),u.on("close",(i,f)=>{e.streams.delete(r),d(e,{t:"wsclose",id:r,code:i,reason:String(f)})}),u.on("error",i=>{s.warn("[TunnelClient] \u672C\u5730 WS \u9519\u8BEF: id=",r,"err=",i.message),e.streams.delete(r);try{u.close(1011,i.message)}catch{}d(e,{t:"wsclose",id:r,code:1011,reason:i.message})})}function q(e,n,r){r?e.ws.send(n):e.ws.send(n.toString("utf-8"))}function ne(e,n){const r=e.streams.get(n.id);if(!r)return;const t=n.d?Buffer.from(n.d,"base64"):Buffer.alloc(0);if(r.ws.readyState!==g.OPEN){r.pending.length>=J&&(r.pending.shift(),s.warn("[TunnelClient] \u672C\u5730 WS \u672A\u5C31\u7EEA\uFF0C\u6392\u961F\u6D88\u606F\u8D85\u4E0A\u9650\uFF0C\u4E22\u5F03\u6700\u65E7\u4E00\u6761: id=",n.id)),r.pending.push({data:t,bin:!!n.bin});return}q(r,t,!!n.bin)}function re(e,n){const r=e.streams.get(n.id);if(r){e.streams.delete(n.id);try{r.ws.close(n.code??1e3,n.reason||"")}catch{}}}function d(e,n){if(!e.ws||e.ws.readyState!==g.OPEN)return!1;try{return e.ws.send(JSON.stringify(n)),!0}catch(r){return s.warn("[TunnelClient] sendJson \u5931\u8D25:",String(r)),!1}}const he={createState(e="http://server.test",n="test-instance"){return{serverUrl:e,instanceId:n,streams:new Map,pendingReqChunks:new Map,shuttingDown:!1}},dispatch(e,n){M(e,n)},pendingChunkIds(e){return Array.from(e.pendingReqChunks.keys())},cleanup(e){k(e)}};export{he as __tunnelClientTestHooks,le as startTunnelClient,de as stopTunnelClient,fe as stopTunnelClientForServer,ae as stopTunnelClientsExcept};
|
|
2
2
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{createHash as
|
|
1
|
+
import{createHash as E}from"node:crypto";import{promises as r}from"node:fs";import c from"node:path";import X from"axios";import*as J from"diff";import{resolveSchedulerBaseUrl as V,getRuntimeHomeDir as C}from"../config.js";import{createLogger as Z}from"../utils/logger.js";import{getChangeCacheRetentionDays as $,setChangeCacheRetentionDays as q}from"./change-cache-retention.js";import{getSnapshotRetentionDays as T,setSnapshotRetentionDays as Q}from"./snapshot-retention.js";import{sweepExpiredSnapshots as Y}from"./fileSnapshotStore.js";import{getRuntimeAccessToken as L}from"./runtime-binding.js";const h=Z("workspace-task-change-watcher"),ee=10*1024*1024,te=".agentswork/change-cache",m="change-cache",ne=60*60*1e3,ae=24*60*60*1e3;let l=null,b=!1,y="",p=null;const g=new Map,d=new Map;let R=!1;function me(e){l&&l.taskNodeId!==e.taskNodeId&&z().catch(()=>{}),l=e,h.info(`Task context set: agent=${e.agentId}, taskInstance=${e.taskInstanceId}, node=${e.taskNodeId}`)}function ye(){l&&(h.info(`Task context cleared: agent=${l.agentId}`),z().catch(()=>{})),l=null}function ke(){return l}function De(){return l!==null}async function Ie(e){const t=c.resolve(e.trim());try{if(!(await r.stat(t)).isDirectory())throw new Error(`Not a directory: ${t}`)}catch{throw new Error(`Workspace path does not exist or inaccessible: ${t}`)}if(p){try{p.close()}catch{}p=null}y=t,b=!0,h.info(`Workspace path set (fs.watch disabled, using tool interception only): ${y}`)}async function Ee(){if(b=!1,p){try{p.close()}catch{}p=null}g.clear(),d.clear(),y="",h.info("Workspace watch stopped")}function F(e,t,a){return E("sha256").update(`${e||"no-task"}:${t}:${a}`,"utf-8").digest("hex").slice(0,32)}function N(e){return E("sha256").update(c.resolve(e),"utf-8").digest("hex").slice(0,16)}function k(e){return c.join(C(),".aws-bridge",m,N(e))}function oe(e){return c.join(C(),m,N(e))}function W(e){return c.join(e,te)}const j=new Set;async function _(e){if(!j.has(e)){j.add(e);try{const t=W(e),a=k(e);await r.access(t),await r.mkdir(c.dirname(a),{recursive:!0}),await r.rename(t,a),h.info(`Migrated legacy change-cache: ${t} -> ${a}`)}catch{}}}async function v(e,t,a){if(a===null)return;await _(e);const o=k(e);await r.mkdir(o,{recursive:!0});const n=c.join(o,`${t}.before`);await r.writeFile(n,a,"utf-8"),B(),h.debug(`Saved beforeContent cache: ${n}`)}async function M(e,t,a,o){const n=J.createPatch("file",a,o);await _(e);const i=k(e);await r.mkdir(i,{recursive:!0});const f=c.join(i,`${t}.diff`);await r.writeFile(f,n,"utf-8"),B(),h.debug(`Saved diff cache: ${f}`)}async function U(e,t){const a=[c.join(k(e),t),c.join(oe(e),t),c.join(W(e),t)];for(const o of a)try{return await r.readFile(o,"utf-8")}catch{}return null}async function $e(e,t){return U(e,`${t}.before`)}async function Te(e,t){return U(e,`${t}.diff`)}let x=0,S=null,A=Promise.resolve();function P(){return A=A.then(()=>ie()),A}async function ie(){const e=$();if(!(e===null||e<=0))try{const t=[c.join(C(),".aws-bridge",m),c.join(C(),m)],a=Date.now()-e*24*60*60*1e3;let o=0;for(const n of t){let i=[];try{i=(await r.readdir(n)).filter(f=>!f.startsWith("."))}catch{continue}for(const f of i){const s=c.join(n,f);try{const u=await r.readdir(s);let w=!0;for(const I of u){if(!I.endsWith(".diff")&&!I.endsWith(".before")){w=!1;continue}const H=c.join(s,I);try{(await r.stat(H)).mtimeMs<a?(await r.unlink(H),o++):w=!1}catch{w=!1}}w&&await r.rmdir(s).catch(()=>{})}catch{}}}o>0&&h.info(`Change-cache TTL sweep: removed ${o} expired file(s), retentionDays=${e}`)}catch(t){h.warn(`Change-cache TTL sweep failed: ${t.message}`)}}function B(){const e=Date.now();e-x>=ne&&(x=e,P().catch(()=>{})),S||(S=setInterval(()=>{P().catch(()=>{})},ae),S.unref?.())}async function O(e){try{return(await r.stat(e)).size>ee?null:await r.readFile(e,"utf-8")}catch{return null}}function D(e){return e===null?null:E("sha256").update(e,"utf-8").digest("hex").slice(0,16)}async function se(e){const t=g.get(e);if(!t)return;g.delete(e),t.timer&&clearTimeout(t.timer);const a=l;if(!a){if(t.operation==="DELETE")d.delete(e);else{const u=await O(e);u!==null&&d.set(e,u)}return}const o=c.relative(a.workspacePath,e).replace(/\\/g,"/");if(o.startsWith(".."))return;let n=t.beforeContent,i=null;t.operation==="DELETE"?(n=n??d.get(e)??null,i=null):(i=await O(e),t.operation==="UPDATE"&&n===null&&(n=d.get(e)??null)),t.operation==="DELETE"?d.delete(e):d.set(e,i);const f=new Date().toISOString(),s=F(a.taskInstanceId,o,f);t.operation==="UPDATE"&&n!==null&&i!==null?await M(a.workspacePath,s,n,i):t.operation==="DELETE"&&await v(a.workspacePath,s,n),await K(a,{workspacePath:a.workspacePath,filePath:o,operation:t.operation,beforeContent:n,afterContent:i,beforeHash:D(n),afterHash:D(i),timestamp:f,reason:G(t.operation,n,i)},s)}async function K(e,t,a){try{const o=V().url,n=L(o)||L();if(!n){h.warn("Cannot send change record: no auth token");return}const i=JSON.stringify({toolRecorded:!0,cacheKey:a,timestamp:t.timestamp}),s=(await X.post(`${o}/api/runtime/callback/task-file-changed`,{agentId:e.agentId,taskInstanceId:e.taskInstanceId,taskNodeId:e.taskNodeId,tenantId:e.tenantId,operation:t.operation,targetType:"FILE",targetPath:t.filePath,beforeHash:t.beforeHash,afterHash:t.afterHash,metadata:i,reason:t.reason,workspacePath:e.workspacePath},{headers:{"X-Runtime-Token":n},timeout:1e4})).data;if(s?.ignored===!0?h.warn(`Change record ignored by server: ${t.filePath} (${t.operation}), reason: ${String(s.reason??"unknown")}`):h.info(`Change record sent: ${t.filePath} (${t.operation})`),s&&s.changeCacheRetentionDays!==void 0){const u=$();q(s.changeCacheRetentionDays),u!==$()&&(x=0,P().catch(()=>{}))}if(s&&s.snapshotRetentionDays!==void 0){const u=T();Q(s.snapshotRetentionDays),u!==T()&&Y(T()).catch(()=>{})}}catch(o){h.warn(`Failed to send change record: ${o.message}`)}}async function z(){if(R)return;R=!0;const e=Array.from(g.keys());for(const t of e)try{await se(t)}catch{}R=!1}function be(){return g.size}function Re(){return b&&p!==null}function ve(){return y}function G(e,t,a){const o=t?t.split(`
|
|
2
2
|
`).length:0,n=a?a.split(`
|
|
3
|
-
`).length:0;if(e==="CREATE")return`\u521B\u5EFA\u6587\u4EF6\uFF0C\u5171 ${n} \u884C`;if(e==="DELETE")return`\u5220\u9664\u6587\u4EF6\uFF0C\u539F ${o} \u884C`;if(o===n)return`\u4FEE\u6539\u6587\u4EF6\uFF08\u884C\u6570\u4E0D\u53D8\uFF0C${n} \u884C\uFF09`;const i=n-o;return`\u4FEE\u6539\u6587\u4EF6\uFF1A${o} \u884C -> ${n} \u884C\uFF08${i>0?"+":""}${i} \u884C\uFF09`}async function
|
|
3
|
+
`).length:0;if(e==="CREATE")return`\u521B\u5EFA\u6587\u4EF6\uFF0C\u5171 ${n} \u884C`;if(e==="DELETE")return`\u5220\u9664\u6587\u4EF6\uFF0C\u539F ${o} \u884C`;if(o===n)return`\u4FEE\u6539\u6587\u4EF6\uFF08\u884C\u6570\u4E0D\u53D8\uFF0C${n} \u884C\uFF09`;const i=n-o;return`\u4FEE\u6539\u6587\u4EF6\uFF1A${o} \u884C -> ${n} \u884C\uFF08${i>0?"+":""}${i} \u884C\uFF09`}async function xe(e){const t=l,a=e.agentId||t?.agentId,o=e.workspacePath||t?.workspacePath;if(!a||!o){h.warn(`Agent file change skipped (no identity): ${e.filePath} (${e.operation})`);return}h.info(`Recording agent file change: ${e.filePath} (${e.operation}), taskNode=${t?.taskNodeId??"(no task)"}`);const n=t??{agentId:a,taskInstanceId:"",taskNodeId:"",tenantId:"",workspacePath:o,projectId:""},i=new Date().toISOString(),f=F(n.taskInstanceId,e.filePath,i);e.operation==="UPDATE"&&e.beforeContent!==null&&e.afterContent!==null?(await M(n.workspacePath,f,e.beforeContent,e.afterContent),await v(n.workspacePath,f,e.beforeContent)):e.operation==="DELETE"&&await v(n.workspacePath,f,e.beforeContent);const s=e.reason?.trim()||G(e.operation,e.beforeContent,e.afterContent);await K(n,{workspacePath:n.workspacePath,filePath:e.filePath,operation:e.operation,beforeContent:e.beforeContent,afterContent:e.afterContent,beforeHash:D(e.beforeContent),afterHash:D(e.afterContent),timestamp:i,reason:s},f)}export{ye as clearTaskContext,be as getPendingChangeCountForTest,ke as getTaskContext,ve as getWorkspaceRoot,De as hasActiveTask,Re as isWatching,$e as readBeforeContentFromCache,Te as readDiffFromCache,xe as recordAgentFileChange,me as setTaskContext,Ie as startWatching,Ee as stopWatching,P as sweepExpiredChangeCache};
|
|
4
4
|
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
|
|
2
|
+
|
|
3
|
+
export type CacheControlMode = "off" | "message" | "content-block";
|
|
4
|
+
|
|
5
|
+
export interface CacheControlMessage {
|
|
6
|
+
role: string;
|
|
7
|
+
content?: unknown;
|
|
8
|
+
[key: string]: unknown;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export declare function asCacheControlMessages(messages: readonly unknown[]): CacheControlMessage[];
|
|
12
|
+
|
|
13
|
+
export interface CacheControlInjection {
|
|
14
|
+
|
|
15
|
+
index: number;
|
|
16
|
+
|
|
17
|
+
message: CacheControlMessage;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export declare function findPreviousNonSystemMessageIndex(messages: readonly CacheControlMessage[], startIndex: number): number | undefined;
|
|
21
|
+
|
|
22
|
+
export declare function clearNonSystemMessageCacheControl(messages: CacheControlMessage[]): void;
|
|
23
|
+
|
|
24
|
+
export declare function injectCacheControl(messages: CacheControlMessage[], mode: CacheControlMode | undefined, options?: {
|
|
25
|
+
skipCacheWrite?: boolean;
|
|
26
|
+
}): CacheControlInjection | undefined;
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
function s(e){return e}function l(e,n){for(let t=Math.min(n,e.length-1);t>=0;t-=1)if(e[t]?.role!=="system")return t}function h(e){for(let n=0;n<e.length;n+=1){const t=e[n];if(t.role==="system"||!("cache_control"in t))continue;const{cache_control:a,...r}=t;e[n]=r}}function x(e,n,t={}){if(!n||n==="off"||e.length===0)return;h(e);const a=l(e,e.length-1);if(a===void 0)return;const r=t.skipCacheWrite===!0?l(e,a-1):a;if(r===void 0)return;const c=e[r],i={type:"ephemeral"};if(n==="message")return{index:r,message:{...c,cache_control:{...i}}};const u=c.content;if(typeof u=="string")return{index:r,message:{...c,content:[{type:"text",text:u,cache_control:{...i}}]}};if(Array.isArray(u)){const o=u.map(d=>({...d}));if(o.length===0)return o.push({type:"text",text:"",cache_control:{...i}}),{index:r,message:{...c,content:o}};const f=o.length-1;return o[f]={...o[f],cache_control:{...i}},{index:r,message:{...c,content:o}}}return{index:r,message:{...c,cache_control:{...i}}}}export{s as asCacheControlMessages,h as clearNonSystemMessageCacheControl,l as findPreviousNonSystemMessageIndex,x as injectCacheControl};
|
|
2
|
+
|
|
@@ -15,6 +15,16 @@ export declare const RUNTIME_RESOURCES_PREFIX = "ACode runtime resources:";
|
|
|
15
15
|
export declare const RUNTIME_INSTRUCTIONS_PREFIX = "[Runtime Instructions]";
|
|
16
16
|
|
|
17
17
|
export declare const COMPACTION_LLM_PROMPT_TEMPLATE: string;
|
|
18
|
+
|
|
19
|
+
export { ESTIMATION_CJK_CHARS_PER_TOKEN } from "./token-estimator.js";
|
|
20
|
+
|
|
21
|
+
export { ESTIMATION_ASCII_CHARS_PER_TOKEN } from "./token-estimator.js";
|
|
22
|
+
|
|
23
|
+
export { ESTIMATION_SAFE_PADDING } from "./token-estimator.js";
|
|
24
|
+
|
|
25
|
+
export { ESTIMATION_IMAGE_TOKENS } from "./token-estimator.js";
|
|
26
|
+
|
|
27
|
+
export { ESTIMATION_TOOL_OVERHEAD } from "./token-estimator.js";
|
|
18
28
|
interface ChatMessageLike {
|
|
19
29
|
role: "system" | "user" | "assistant" | "tool";
|
|
20
30
|
content: string | unknown[] | null;
|
|
@@ -56,11 +66,15 @@ export interface CompactionResult {
|
|
|
56
66
|
|
|
57
67
|
downsampleCount?: number;
|
|
58
68
|
|
|
69
|
+
droppedMessages?: number;
|
|
70
|
+
|
|
59
71
|
noSummary?: boolean;
|
|
60
72
|
|
|
61
73
|
reachedTarget?: boolean;
|
|
62
74
|
|
|
63
75
|
retryAttempts?: number;
|
|
76
|
+
|
|
77
|
+
contextTokensAfter?: number;
|
|
64
78
|
}
|
|
65
79
|
|
|
66
80
|
export type CompactionLevel = 1 | 2 | 3 | 4;
|
|
@@ -136,11 +150,24 @@ export interface CompactionPhaseEvent {
|
|
|
136
150
|
reason?: string;
|
|
137
151
|
}
|
|
138
152
|
|
|
153
|
+
export interface SummaryRequestMessage {
|
|
154
|
+
role: "system" | "user" | "assistant" | "tool";
|
|
155
|
+
content: string | unknown[] | null;
|
|
156
|
+
tool_call_id?: string;
|
|
157
|
+
tool_calls?: unknown[];
|
|
158
|
+
}
|
|
159
|
+
|
|
139
160
|
export type LLMSummarizer = (input: {
|
|
140
|
-
|
|
161
|
+
|
|
162
|
+
messages: readonly SummaryRequestMessage[];
|
|
163
|
+
|
|
164
|
+
prefixMessages?: readonly SummaryRequestMessage[];
|
|
165
|
+
|
|
141
166
|
messageCount: number;
|
|
142
167
|
contextLimit: number;
|
|
143
168
|
|
|
169
|
+
reasoningText?: string;
|
|
170
|
+
|
|
144
171
|
previousSummary?: string;
|
|
145
172
|
|
|
146
173
|
anchors?: FidelityAnchors;
|
|
@@ -189,14 +216,14 @@ export declare function lookupModelLimits(modelName: string, configOverrides?: {
|
|
|
189
216
|
maxOutput: number;
|
|
190
217
|
};
|
|
191
218
|
|
|
192
|
-
export
|
|
193
|
-
|
|
194
|
-
export declare function estimateTokens(text: string): number;
|
|
219
|
+
export { estimateTextTokens, estimateTokens } from "./token-estimator.js";
|
|
195
220
|
|
|
196
221
|
export declare function conversationSizeBytes(messages: readonly ChatMessageLike[]): number;
|
|
197
222
|
|
|
198
223
|
export declare function estimateConversationTokens(messages: readonly ChatMessageLike[]): number;
|
|
199
224
|
|
|
225
|
+
export declare function estimateContextTokens(messages: readonly ChatMessageLike[], toolsTokens?: number): number;
|
|
226
|
+
|
|
200
227
|
export declare function conversationSizeKB(messages: readonly ChatMessageLike[]): number;
|
|
201
228
|
|
|
202
229
|
export declare function isOverflow(messages: readonly ChatMessageLike[], contextLimit: number, _maxOutput?: number): boolean;
|
|
@@ -231,6 +258,8 @@ export declare function summarizeConversation(messages: ChatMessageLike[], optio
|
|
|
231
258
|
|
|
232
259
|
includeReasoning?: boolean;
|
|
233
260
|
|
|
261
|
+
prefixMessages?: readonly SummaryRequestMessage[];
|
|
262
|
+
|
|
234
263
|
stats?: {
|
|
235
264
|
downsampleCount: number;
|
|
236
265
|
droppedMessages: number;
|
|
@@ -255,6 +284,7 @@ export declare function performCompaction(messages: ChatMessageLike[], contextLi
|
|
|
255
284
|
|
|
256
285
|
retryPolicy?: SummaryRetryPolicy;
|
|
257
286
|
|
|
287
|
+
prefixMessages?: readonly SummaryRequestMessage[];
|
|
288
|
+
|
|
258
289
|
allowRuleFallback?: boolean;
|
|
259
290
|
}): Promise<CompactionResult>;
|
|
260
|
-
export {};
|