@hold-rein/plugins-base 0.0.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/plugin-id.d.ts +2 -0
- package/dist/plugin-id.d.ts.map +1 -0
- package/dist/server/routes/index.d.ts +4 -0
- package/dist/server/routes/index.d.ts.map +1 -0
- package/dist/server/tools/index.d.ts +2 -0
- package/dist/server/tools/index.d.ts.map +1 -0
- package/dist/server/tools/shell-exec-tool/index.d.ts +10 -0
- package/dist/server/tools/shell-exec-tool/index.d.ts.map +1 -0
- package/dist/server/tools/shell-exec-tool/shell-command-risk.d.ts +3 -0
- package/dist/server/tools/shell-exec-tool/shell-command-risk.d.ts.map +1 -0
- package/dist/server/tools/shell-exec-tool/shell-process-manager.d.ts +50 -0
- package/dist/server/tools/shell-exec-tool/shell-process-manager.d.ts.map +1 -0
- package/dist/server.cjs +5 -0
- package/dist/server.cjs.map +1 -0
- package/dist/server.d.ts +4 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +401 -0
- package/dist/server.js.map +1 -0
- package/dist/style.css +1 -0
- package/dist/web/right-panels/index.d.ts +2 -0
- package/dist/web/right-panels/index.d.ts.map +1 -0
- package/dist/web/right-panels/shell-processes/ShellProcessesPanel.d.ts +7 -0
- package/dist/web/right-panels/shell-processes/ShellProcessesPanel.d.ts.map +1 -0
- package/dist/web/right-panels/shell-processes/createShellProcesses.d.ts +7 -0
- package/dist/web/right-panels/shell-processes/createShellProcesses.d.ts.map +1 -0
- package/dist/web/right-panels/shell-processes/index.d.ts +4 -0
- package/dist/web/right-panels/shell-processes/index.d.ts.map +1 -0
- package/dist/web/tools/index.d.ts +3 -0
- package/dist/web/tools/index.d.ts.map +1 -0
- package/dist/web/tools/shell-exec-tool/icon.d.ts +6 -0
- package/dist/web/tools/shell-exec-tool/icon.d.ts.map +1 -0
- package/dist/web/tools/shell-exec-tool/index.d.ts +4 -0
- package/dist/web/tools/shell-exec-tool/index.d.ts.map +1 -0
- package/dist/web/tools/sub-agent/call-subagent.d.ts +4 -0
- package/dist/web/tools/sub-agent/call-subagent.d.ts.map +1 -0
- package/dist/web/tools/sub-agent/index.d.ts +3 -0
- package/dist/web/tools/sub-agent/index.d.ts.map +1 -0
- package/dist/web/tools/sub-agent/revoke-subagent.d.ts +4 -0
- package/dist/web/tools/sub-agent/revoke-subagent.d.ts.map +1 -0
- package/dist/web.d.ts +4 -0
- package/dist/web.d.ts.map +1 -0
- package/dist/web.umd.cjs +3 -0
- package/dist/web.umd.cjs.map +1 -0
- package/package.json +60 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plugin-id.d.ts","sourceRoot":"","sources":["../src/plugin-id.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,SAAS,mBAAmB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/server/routes/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAA;AAEhC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAA;AAQ5D,MAAM,CAAC,OAAO,UAAU,YAAY,CAAC,OAAO,EAAE,YAAY,CAAC,YAAY,GAAG,MAAM,CA4D/E"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/server/tools/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,mBAAmB,EACnB,mBAAmB,EACnB,mBAAmB,EACpB,MAAM,mBAAmB,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { ExecutionEnv } from "@earendil-works/pi-agent-core";
|
|
2
|
+
import type { ServerPlugin } from "@hold-rein/plugin-server";
|
|
3
|
+
interface CreateShellExecToolOptions {
|
|
4
|
+
readonly taskId?: string;
|
|
5
|
+
}
|
|
6
|
+
export declare function createShellExecTool(env: ExecutionEnv, options?: CreateShellExecToolOptions): ServerPlugin.PluginTool;
|
|
7
|
+
export declare function createShellReadTool(): ServerPlugin.PluginTool;
|
|
8
|
+
export declare function createShellKillTool(): ServerPlugin.PluginTool;
|
|
9
|
+
export {};
|
|
10
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/server/tools/shell-exec-tool/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAElE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAmC7D,UAAU,0BAA0B;IAClC,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED,wBAAgB,mBAAmB,CACjC,GAAG,EAAE,YAAY,EACjB,OAAO,GAAE,0BAA+B,GACvC,YAAY,CAAC,UAAU,CAgGzB;AAED,wBAAgB,mBAAmB,IAAI,YAAY,CAAC,UAAU,CA0B7D;AAED,wBAAgB,mBAAmB,IAAI,YAAY,CAAC,UAAU,CAiC7D"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"shell-command-risk.d.ts","sourceRoot":"","sources":["../../../../src/server/tools/shell-exec-tool/shell-command-risk.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,gBAAgB,GAAG,MAAM,GAAG,QAAQ,GAAG,WAAW,CAAC;AAoB/D,wBAAgB,wBAAwB,CAAC,OAAO,EAAE,MAAM,GAAG,gBAAgB,CAU1E"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
export type ShellProcessStatus = "running" | "completed" | "failed" | "killed";
|
|
2
|
+
export interface ShellProcessRecord {
|
|
3
|
+
readonly command: string;
|
|
4
|
+
readonly cwd: string;
|
|
5
|
+
readonly endedAt?: string;
|
|
6
|
+
readonly exitCode?: number;
|
|
7
|
+
readonly id: string;
|
|
8
|
+
readonly startedAt: string;
|
|
9
|
+
readonly status: ShellProcessStatus;
|
|
10
|
+
readonly stderr: string;
|
|
11
|
+
readonly stdout: string;
|
|
12
|
+
readonly taskId?: string;
|
|
13
|
+
readonly toolCallId: string;
|
|
14
|
+
readonly truncated: boolean;
|
|
15
|
+
}
|
|
16
|
+
export type ShellProcessEvent = {
|
|
17
|
+
readonly record: ShellProcessRecord;
|
|
18
|
+
readonly type: "shell_end" | "shell_start";
|
|
19
|
+
} | {
|
|
20
|
+
readonly chunk: string;
|
|
21
|
+
readonly record: ShellProcessRecord;
|
|
22
|
+
readonly type: "shell_stderr" | "shell_stdout";
|
|
23
|
+
};
|
|
24
|
+
export type ShellProcessEventListener = (event: ShellProcessEvent) => void;
|
|
25
|
+
export interface RegisterShellProcessInput {
|
|
26
|
+
readonly command: string;
|
|
27
|
+
readonly controller: AbortController;
|
|
28
|
+
readonly cwd: string;
|
|
29
|
+
readonly taskId?: string;
|
|
30
|
+
readonly toolCallId: string;
|
|
31
|
+
}
|
|
32
|
+
export declare class ShellProcessManager {
|
|
33
|
+
private readonly listeners;
|
|
34
|
+
private readonly records;
|
|
35
|
+
appendStderr(id: string, chunk: string): void;
|
|
36
|
+
appendStdout(id: string, chunk: string): void;
|
|
37
|
+
clear(): void;
|
|
38
|
+
complete(id: string, exitCode: number): void;
|
|
39
|
+
fail(id: string): void;
|
|
40
|
+
get(id: string): ShellProcessRecord | undefined;
|
|
41
|
+
kill(id: string): ShellProcessRecord | undefined;
|
|
42
|
+
killByTask(taskId: string): ShellProcessRecord[];
|
|
43
|
+
killAndRemoveByTask(taskId: string): ShellProcessRecord[];
|
|
44
|
+
list(taskId?: string): ShellProcessRecord[];
|
|
45
|
+
register(input: RegisterShellProcessInput): ShellProcessRecord;
|
|
46
|
+
subscribe(listener: ShellProcessEventListener): () => void;
|
|
47
|
+
private notify;
|
|
48
|
+
}
|
|
49
|
+
export declare const shellProcessManager: ShellProcessManager;
|
|
50
|
+
//# sourceMappingURL=shell-process-manager.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"shell-process-manager.d.ts","sourceRoot":"","sources":["../../../../src/server/tools/shell-exec-tool/shell-process-manager.ts"],"names":[],"mappings":"AAIA,MAAM,MAAM,kBAAkB,GAAG,SAAS,GAAG,WAAW,GAAG,QAAQ,GAAG,QAAQ,CAAC;AAE/E,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,MAAM,EAAE,kBAAkB,CAAC;IACpC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;CAC7B;AAED,MAAM,MAAM,iBAAiB,GACzB;IACA,QAAQ,CAAC,MAAM,EAAE,kBAAkB,CAAC;IACpC,QAAQ,CAAC,IAAI,EAAE,WAAW,GAAG,aAAa,CAAC;CAC5C,GACC;IACA,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,MAAM,EAAE,kBAAkB,CAAC;IACpC,QAAQ,CAAC,IAAI,EAAE,cAAc,GAAG,cAAc,CAAC;CAChD,CAAC;AAEJ,MAAM,MAAM,yBAAyB,GAAG,CAAC,KAAK,EAAE,iBAAiB,KAAK,IAAI,CAAC;AAkB3E,MAAM,WAAW,yBAAyB;IACxC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,UAAU,EAAE,eAAe,CAAC;IACrC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;CAC7B;AAED,qBAAa,mBAAmB;IAC9B,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAwC;IAElE,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAgD;IAExE,YAAY,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI;IAiB7C,YAAY,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI;IAiB7C,KAAK,IAAI,IAAI;IAIb,QAAQ,CAAC,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI;IAgB5C,IAAI,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI;IAetB,GAAG,CAAC,EAAE,EAAE,MAAM,GAAG,kBAAkB,GAAG,SAAS;IAM/C,IAAI,CAAC,EAAE,EAAE,MAAM,GAAG,kBAAkB,GAAG,SAAS;IAoBhD,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,kBAAkB,EAAE;IAOhD,mBAAmB,CAAC,MAAM,EAAE,MAAM,GAAG,kBAAkB,EAAE;IAWzD,IAAI,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,kBAAkB,EAAE;IAM3C,QAAQ,CAAC,KAAK,EAAE,yBAAyB,GAAG,kBAAkB;IA2B9D,SAAS,CAAC,QAAQ,EAAE,yBAAyB,GAAG,MAAM,IAAI;IAQ1D,OAAO,CAAC,MAAM;CAKf;AAED,eAAO,MAAM,mBAAmB,qBAA4B,CAAC"}
|
package/dist/server.cjs
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
"use strict";var A=Object.defineProperty;var v=(t,s,e)=>s in t?A(t,s,{enumerable:!0,configurable:!0,writable:!0,value:e}):t[s]=e;var I=(t,s,e)=>v(t,typeof s!="symbol"?s+"":s,e);const x=require("express"),C=require("node:crypto"),d=require("@earendil-works/pi-ai"),y=2e5;class R{constructor(){I(this,"listeners",new Set);I(this,"records",new Map)}appendStderr(s,e){const n=this.records.get(s);if(!n)return;const r=b(n.stderr,e);n.stderr=r.value,n.truncated||(n.truncated=r.truncated),this.notify({chunk:e,record:l(n),type:"shell_stderr"})}appendStdout(s,e){const n=this.records.get(s);if(!n)return;const r=b(n.stdout,e);n.stdout=r.value,n.truncated||(n.truncated=r.truncated),this.notify({chunk:e,record:l(n),type:"shell_stdout"})}clear(){this.records.clear()}complete(s,e){const n=this.records.get(s);!n||n.status==="killed"||(n.endedAt=new Date().toISOString(),n.exitCode=e,n.status=e===0?"completed":"failed",this.notify({record:l(n),type:"shell_end"}))}fail(s){const e=this.records.get(s);!e||e.status==="killed"||(e.endedAt=new Date().toISOString(),e.status="failed",this.notify({record:l(e),type:"shell_end"}))}get(s){const e=this.records.get(s);return e?l(e):void 0}kill(s){const e=this.records.get(s);if(e)return e.status==="running"&&(e.controller.abort(),e.endedAt=new Date().toISOString(),e.status="killed",this.notify({record:l(e),type:"shell_end"})),l(e)}killByTask(s){return this.list(s).filter(e=>e.status==="running").map(e=>this.kill(e.id)).filter(e=>e!==void 0)}killAndRemoveByTask(s){return this.list(s).map(n=>{const r=this.kill(n.id)??n;return this.records.delete(n.id),r})}list(s){return Array.from(this.records.values()).filter(e=>s===void 0||e.taskId===s).map(l)}register(s){const e=`shell_${C.randomUUID()}`,n={command:s.command,controller:s.controller,cwd:s.cwd,id:e,startedAt:new Date().toISOString(),status:"running",stderr:"",stdout:"",...s.taskId?{taskId:s.taskId}:{},toolCallId:s.toolCallId,truncated:!1};this.records.set(e,n);const r=l(n);return this.notify({record:r,type:"shell_start"}),r}subscribe(s){return this.listeners.add(s),()=>{this.listeners.delete(s)}}notify(s){for(const e of this.listeners)e(s)}}const o=new R;function b(t,s){const e=`${t}${s}`;return e.length<=y?{truncated:!1,value:e}:{truncated:!0,value:e.slice(e.length-y)}}function l(t){return{command:t.command,cwd:t.cwd,...t.endedAt?{endedAt:t.endedAt}:{},...t.exitCode===void 0?{}:{exitCode:t.exitCode},id:t.id,startedAt:t.startedAt,status:t.status,stderr:t.stderr,stdout:t.stdout,...t.taskId?{taskId:t.taskId}:{},toolCallId:t.toolCallId,truncated:t.truncated}}function O(t){const s=x.Router();return s.get("/shells",(e,n)=>{const r=typeof e.query.taskId=="string"?e.query.taskId:void 0;n.status(200),n.setHeader("Cache-Control","no-cache, no-transform"),n.setHeader("Connection","keep-alive"),n.setHeader("Content-Type","application/x-ndjson; charset=utf-8"),n.flushHeaders();for(const i of N(o.list(r)))w(n,i);const a=o.subscribe(i=>{r!==void 0&&i.record.taskId!==r||w(n,i)});e.on("close",()=>{a()})}),s.get("/shells/:shellId",(e,n)=>{const r=o.get(e.params.shellId);if(!r){t.sendError(n,t.RESPONSE_CODE_DEFINITIONS.notFound);return}t.sendSuccess(n,r)}),s.post("/shells/:shellId/kill",(e,n)=>{const r=o.kill(e.params.shellId);if(!r){t.sendError(n,t.RESPONSE_CODE_DEFINITIONS.notFound);return}t.sendSuccess(n,r)}),s}function N(t){return t.flatMap(s=>[{record:s,type:"shell_start"},...s.stdout?[{chunk:s.stdout,record:s,type:"shell_stdout"}]:[],...s.stderr?[{chunk:s.stderr,record:s,type:"shell_stderr"}]:[],...s.status==="running"?[]:[{record:s,type:"shell_end"}]])}function w(t,s){t.write(`${JSON.stringify(s)}
|
|
2
|
+
`)}const P=[/\brm\b/u,/\brm\s+(-[^\s]*r[^\s]*f|-{1,2}recursive\b.*-{1,2}force\b)/u,/\bgit\s+reset\s+--hard\b/u,/\bsudo\b/u,/\bchmod\s+777\b/u],D=[/>/u,/\bmv\b/u,/\bcp\b/u,/\btouch\b/u,/\bmkdir\b/u,/\bgit\s+(add|commit|push|switch|checkout|branch)\b/u,/\b(pnpm|npm|yarn)\s+(install|add|remove)\b/u];function M(t){return P.some(s=>s.test(t))?"dangerous":D.some(s=>s.test(t))?"writes":"safe"}const _=2e4,$=60,L=d.Type.Object({command:d.Type.String({description:"Shell command to execute."}),cwd:d.Type.Optional(d.Type.String({description:"Working directory for the command."})),timeoutSeconds:d.Type.Optional(d.Type.Number({description:"Command timeout in seconds."}))}),U=d.Type.Object({shellId:d.Type.String({description:"Registered shell command id."})}),H=d.Type.Object({shellId:d.Type.String({description:"Registered shell command id."})});function q(t,s={}){return{name:"shell_exec",label:"Shell Exec",description:"Run a shell command in the configured workspace.",parameters:L,beforeExecute({event:e,requestApproval:n}){const r=e.input,a=typeof r.command=="string"?r.command:"";if(M(a)!=="safe")return n(`Allowed to execute the command: ${r.command}`)},async execute(e,n,r){const a=n,i=a.cwd??t.cwd,k=new AbortController,u=o.register({command:a.command,controller:k,cwd:i,...s.taskId?{taskId:s.taskId}:{},toolCallId:e}),p=()=>{o.kill(u.id)};r&&(r.aborted?p():r.addEventListener("abort",p,{once:!0}));const g=t.exec(a.command,{abortSignal:k.signal,cwd:i,onStderr:c=>{o.appendStderr(u.id,c)},onStdout:c=>{o.appendStdout(u.id,c)}}).then(c=>{if(!c.ok)throw o.fail(u.id),c.error;return o.complete(u.id,c.value.exitCode),c.value}).finally(()=>{r==null||r.removeEventListener("abort",p)}),E=await G(g,(a.timeoutSeconds??$)*1e3),m=o.get(u.id)??u;return E.status==="completed"?{content:[{type:"text",text:f(m)}],details:h(m)}:(g.catch(()=>{}),{content:[{type:"text",text:f(m)}],details:h(m)})},executionMode:"sequential"}}function F(){return{name:"shell_read",label:"Shell Read",description:"Read output and status for a registered shell command.",parameters:U,async execute(t,s){const e=s,n=o.get(e.shellId);if(!n)throw new Error(`Unknown shell command: ${e.shellId}`);return{content:[{type:"text",text:f(n)}],details:h(n)}},executionMode:"sequential"}}function j(){return{name:"shell_kill",label:"Shell Kill",description:"Stop a registered running shell command.",parameters:H,beforeExecute({event:t,requestApproval:s}){const e=t.input;return s(`Allowed to stop shell command: ${e.shellId??"unknown"}`)},async execute(t,s){const e=s,n=o.kill(e.shellId);if(!n)throw new Error(`Unknown shell command: ${e.shellId}`);return{content:[{type:"text",text:f(n)}],details:h(n)}},executionMode:"sequential"}}async function G(t,s){return await Promise.race([t.then(()=>({status:"completed"})),new Promise(e=>{setTimeout(()=>{e({status:"running"})},s)})])}function h(t){return{command:t.command,cwd:t.cwd,...t.endedAt?{endedAt:t.endedAt}:{},...t.exitCode===void 0?{}:{exitCode:t.exitCode},shellId:t.id,status:t.status,stderrLength:t.stderr.length,stdoutLength:t.stdout.length,...t.taskId?{taskId:t.taskId}:{},truncated:t.truncated}}function f(t){return[`shellId: ${t.id}`,`status: ${t.status}`,`cwd: ${t.cwd}`,`command: ${t.command}`,...t.exitCode===void 0?[]:[`exitCode: ${t.exitCode}`],"","stdout:",T(t.stdout),"","stderr:",T(t.stderr)].join(`
|
|
3
|
+
`)}function T(t){return t.length<=_?t:`${t.slice(0,_)}
|
|
4
|
+
[output truncated]`}const B="__base__plugin",K=3600*1e3,S=new Map,W={id:B,registerRoutes:O,contributionResolver:t=>({tools:[q(t.env,{taskId:t.taskId}),F(),j()],onAgentEnd:()=>{var n;if(t.agentName!=="main")return;const s=S.get(t.taskId);s&&clearTimeout(s);const e=setTimeout(()=>{S.delete(t.taskId),o.killAndRemoveByTask(t.taskId)},K);S.set(t.taskId,e),(n=e.unref)==null||n.call(e)}})};module.exports=W;
|
|
5
|
+
//# sourceMappingURL=server.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.cjs","sources":["../src/server/tools/shell-exec-tool/shell-process-manager.ts","../src/server/routes/index.ts","../src/server/tools/shell-exec-tool/shell-command-risk.ts","../src/server/tools/shell-exec-tool/index.ts","../src/plugin-id.ts","../src/server.ts"],"sourcesContent":["import { randomUUID } from \"node:crypto\";\n\nconst MAX_STREAM_LENGTH = 200_000;\n\nexport type ShellProcessStatus = \"running\" | \"completed\" | \"failed\" | \"killed\";\n\nexport interface ShellProcessRecord {\n readonly command: string;\n readonly cwd: string;\n readonly endedAt?: string;\n readonly exitCode?: number;\n readonly id: string;\n readonly startedAt: string;\n readonly status: ShellProcessStatus;\n readonly stderr: string;\n readonly stdout: string;\n readonly taskId?: string;\n readonly toolCallId: string;\n readonly truncated: boolean;\n}\n\nexport type ShellProcessEvent =\n | {\n readonly record: ShellProcessRecord;\n readonly type: \"shell_end\" | \"shell_start\";\n }\n | {\n readonly chunk: string;\n readonly record: ShellProcessRecord;\n readonly type: \"shell_stderr\" | \"shell_stdout\";\n };\n\nexport type ShellProcessEventListener = (event: ShellProcessEvent) => void;\n\ninterface MutableShellProcessRecord {\n command: string;\n controller: AbortController;\n cwd: string;\n endedAt?: string;\n exitCode?: number;\n id: string;\n startedAt: string;\n status: ShellProcessStatus;\n stderr: string;\n stdout: string;\n taskId?: string;\n toolCallId: string;\n truncated: boolean;\n}\n\nexport interface RegisterShellProcessInput {\n readonly command: string;\n readonly controller: AbortController;\n readonly cwd: string;\n readonly taskId?: string;\n readonly toolCallId: string;\n}\n\nexport class ShellProcessManager {\n private readonly listeners = new Set<ShellProcessEventListener>();\n\n private readonly records = new Map<string, MutableShellProcessRecord>();\n\n appendStderr(id: string, chunk: string): void {\n const record = this.records.get(id);\n\n if (!record) {\n return;\n }\n\n const next = appendBounded(record.stderr, chunk);\n record.stderr = next.value;\n record.truncated ||= next.truncated;\n this.notify({\n chunk,\n record: toShellProcessRecord(record),\n type: \"shell_stderr\"\n });\n }\n\n appendStdout(id: string, chunk: string): void {\n const record = this.records.get(id);\n\n if (!record) {\n return;\n }\n\n const next = appendBounded(record.stdout, chunk);\n record.stdout = next.value;\n record.truncated ||= next.truncated;\n this.notify({\n chunk,\n record: toShellProcessRecord(record),\n type: \"shell_stdout\"\n });\n }\n\n clear(): void {\n this.records.clear();\n }\n\n complete(id: string, exitCode: number): void {\n const record = this.records.get(id);\n\n if (!record || record.status === \"killed\") {\n return;\n }\n\n record.endedAt = new Date().toISOString();\n record.exitCode = exitCode;\n record.status = exitCode === 0 ? \"completed\" : \"failed\";\n this.notify({\n record: toShellProcessRecord(record),\n type: \"shell_end\"\n });\n }\n\n fail(id: string): void {\n const record = this.records.get(id);\n\n if (!record || record.status === \"killed\") {\n return;\n }\n\n record.endedAt = new Date().toISOString();\n record.status = \"failed\";\n this.notify({\n record: toShellProcessRecord(record),\n type: \"shell_end\"\n });\n }\n\n get(id: string): ShellProcessRecord | undefined {\n const record = this.records.get(id);\n\n return record ? toShellProcessRecord(record) : undefined;\n }\n\n kill(id: string): ShellProcessRecord | undefined {\n const record = this.records.get(id);\n\n if (!record) {\n return undefined;\n }\n\n if (record.status === \"running\") {\n record.controller.abort();\n record.endedAt = new Date().toISOString();\n record.status = \"killed\";\n this.notify({\n record: toShellProcessRecord(record),\n type: \"shell_end\"\n });\n }\n\n return toShellProcessRecord(record);\n }\n\n killByTask(taskId: string): ShellProcessRecord[] {\n return this.list(taskId)\n .filter((record) => record.status === \"running\")\n .map((record) => this.kill(record.id))\n .filter((record): record is ShellProcessRecord => record !== undefined);\n }\n\n killAndRemoveByTask(taskId: string): ShellProcessRecord[] {\n const taskRecords = this.list(taskId);\n\n return taskRecords\n .map((record) => {\n const killedRecord = this.kill(record.id) ?? record;\n this.records.delete(record.id);\n return killedRecord;\n });\n }\n\n list(taskId?: string): ShellProcessRecord[] {\n return Array.from(this.records.values())\n .filter((record) => taskId === undefined || record.taskId === taskId)\n .map(toShellProcessRecord);\n }\n\n register(input: RegisterShellProcessInput): ShellProcessRecord {\n const id = `shell_${randomUUID()}`;\n const record: MutableShellProcessRecord = {\n command: input.command,\n controller: input.controller,\n cwd: input.cwd,\n id,\n startedAt: new Date().toISOString(),\n status: \"running\",\n stderr: \"\",\n stdout: \"\",\n ...(input.taskId ? { taskId: input.taskId } : {}),\n toolCallId: input.toolCallId,\n truncated: false\n };\n\n this.records.set(id, record);\n\n const shellRecord = toShellProcessRecord(record);\n this.notify({\n record: shellRecord,\n type: \"shell_start\"\n });\n\n return shellRecord;\n }\n\n subscribe(listener: ShellProcessEventListener): () => void {\n this.listeners.add(listener);\n\n return () => {\n this.listeners.delete(listener);\n };\n }\n\n private notify(event: ShellProcessEvent): void {\n for (const listener of this.listeners) {\n listener(event);\n }\n }\n}\n\nexport const shellProcessManager = new ShellProcessManager();\n\nfunction appendBounded(current: string, chunk: string): {\n truncated: boolean;\n value: string;\n} {\n const value = `${current}${chunk}`;\n\n if (value.length <= MAX_STREAM_LENGTH) {\n return { truncated: false, value };\n }\n\n return {\n truncated: true,\n value: value.slice(value.length - MAX_STREAM_LENGTH)\n };\n}\n\nfunction toShellProcessRecord(\n record: MutableShellProcessRecord\n): ShellProcessRecord {\n return {\n command: record.command,\n cwd: record.cwd,\n ...(record.endedAt ? { endedAt: record.endedAt } : {}),\n ...(record.exitCode === undefined ? {} : { exitCode: record.exitCode }),\n id: record.id,\n startedAt: record.startedAt,\n status: record.status,\n stderr: record.stderr,\n stdout: record.stdout,\n ...(record.taskId ? { taskId: record.taskId } : {}),\n toolCallId: record.toolCallId,\n truncated: record.truncated\n };\n}\n","import { Router } from 'express'\nimport type { Request, Response } from 'express'\nimport type { ServerPlugin } from '@hold-rein/plugin-server'\n\nimport {\n shellProcessManager,\n type ShellProcessEvent,\n type ShellProcessRecord\n} from '../tools/shell-exec-tool/shell-process-manager'\n\nexport default function createRouter(context: ServerPlugin.RouteContext): Router {\n const router = Router()\n\n router.get('/shells', (request: Request, response: Response) => {\n const taskId = typeof request.query.taskId === 'string'\n ? request.query.taskId\n : undefined\n\n response.status(200)\n response.setHeader('Cache-Control', 'no-cache, no-transform')\n response.setHeader('Connection', 'keep-alive')\n response.setHeader('Content-Type', 'application/x-ndjson; charset=utf-8')\n response.flushHeaders()\n\n for (const event of createShellSnapshotEvents(shellProcessManager.list(taskId))) {\n writeJsonLine(response, event)\n }\n\n const unsubscribe = shellProcessManager.subscribe((event) => {\n if (taskId !== undefined && event.record.taskId !== taskId) {\n return\n }\n\n writeJsonLine(response, event)\n })\n\n request.on('close', () => {\n unsubscribe()\n })\n })\n\n router.get('/shells/:shellId', (\n request: Request<{ shellId: string }>,\n response: Response\n ) => {\n const record = shellProcessManager.get(request.params.shellId)\n\n if (!record) {\n context.sendError(response, context.RESPONSE_CODE_DEFINITIONS.notFound)\n return\n }\n\n context.sendSuccess(response, record)\n })\n\n router.post('/shells/:shellId/kill', (\n request: Request<{ shellId: string }>,\n response: Response\n ) => {\n const record = shellProcessManager.kill(request.params.shellId)\n\n if (!record) {\n context.sendError(response, context.RESPONSE_CODE_DEFINITIONS.notFound)\n return\n }\n\n context.sendSuccess(response, record)\n })\n\n return router\n}\n\nfunction createShellSnapshotEvents(\n records: readonly ShellProcessRecord[]\n): ShellProcessEvent[] {\n return records.flatMap((record) => [\n {\n record,\n type: 'shell_start' as const\n },\n ...(record.stdout\n ? [{\n chunk: record.stdout,\n record,\n type: 'shell_stdout' as const\n }]\n : []),\n ...(record.stderr\n ? [{\n chunk: record.stderr,\n record,\n type: 'shell_stderr' as const\n }]\n : []),\n ...(record.status === 'running'\n ? []\n : [{\n record,\n type: 'shell_end' as const\n }])\n ])\n}\n\nfunction writeJsonLine(response: Response, event: ShellProcessEvent): void {\n response.write(`${JSON.stringify(event)}\\n`)\n}\n","export type ShellCommandRisk = \"safe\" | \"writes\" | \"dangerous\";\n\nconst DANGEROUS_PATTERNS = [\n /\\brm\\b/u,\n /\\brm\\s+(-[^\\s]*r[^\\s]*f|-{1,2}recursive\\b.*-{1,2}force\\b)/u,\n /\\bgit\\s+reset\\s+--hard\\b/u,\n /\\bsudo\\b/u,\n /\\bchmod\\s+777\\b/u\n];\n\nconst WRITE_PATTERNS = [\n />/u,\n /\\bmv\\b/u,\n /\\bcp\\b/u,\n /\\btouch\\b/u,\n /\\bmkdir\\b/u,\n /\\bgit\\s+(add|commit|push|switch|checkout|branch)\\b/u,\n /\\b(pnpm|npm|yarn)\\s+(install|add|remove)\\b/u\n];\n\nexport function classifyShellCommandRisk(command: string): ShellCommandRisk {\n if (DANGEROUS_PATTERNS.some((pattern) => pattern.test(command))) {\n return \"dangerous\";\n }\n\n if (WRITE_PATTERNS.some((pattern) => pattern.test(command))) {\n return \"writes\";\n }\n\n return \"safe\";\n}\n","import type { ExecutionEnv } from \"@earendil-works/pi-agent-core\";\nimport { Type, type Static } from \"@earendil-works/pi-ai\";\nimport type { ServerPlugin } from \"@hold-rein/plugin-server\";\n\nimport { classifyShellCommandRisk } from \"./shell-command-risk\";\nimport {\n shellProcessManager,\n type ShellProcessRecord\n} from \"./shell-process-manager\";\n\nconst MAX_OUTPUT_LENGTH = 20_000;\nconst DEFAULT_WAIT_TIMEOUT_SECONDS = 60;\n\nconst shellExecParameters = Type.Object({\n command: Type.String({ description: \"Shell command to execute.\" }),\n cwd: Type.Optional(\n Type.String({ description: \"Working directory for the command.\" })\n ),\n timeoutSeconds: Type.Optional(\n Type.Number({ description: \"Command timeout in seconds.\" })\n )\n});\n\ntype ShellExecParameters = Static<typeof shellExecParameters>;\n\nconst shellReadParameters = Type.Object({\n shellId: Type.String({ description: \"Registered shell command id.\" })\n});\n\ntype ShellReadParameters = Static<typeof shellReadParameters>;\n\nconst shellKillParameters = Type.Object({\n shellId: Type.String({ description: \"Registered shell command id.\" })\n});\n\ntype ShellKillParameters = Static<typeof shellKillParameters>;\n\ninterface CreateShellExecToolOptions {\n readonly taskId?: string;\n}\n\nexport function createShellExecTool(\n env: ExecutionEnv,\n options: CreateShellExecToolOptions = {}\n): ServerPlugin.PluginTool {\n return {\n name: \"shell_exec\",\n label: \"Shell Exec\",\n description: \"Run a shell command in the configured workspace.\",\n parameters: shellExecParameters,\n beforeExecute({ event, requestApproval }) {\n const params = event.input as Partial<ShellExecParameters>;\n const command = typeof params.command === \"string\" ? params.command : \"\";\n const risk = classifyShellCommandRisk(command);\n\n if (risk === \"safe\") {\n return undefined;\n }\n\n return requestApproval(`Allowed to execute the command: ${params.command}`);\n },\n async execute(_toolCallId, rawParams, signal) {\n const params = rawParams as ShellExecParameters;\n const cwd = params.cwd ?? env.cwd;\n const controller = new AbortController();\n const shell = shellProcessManager.register({\n command: params.command,\n controller,\n cwd,\n ...(options.taskId ? { taskId: options.taskId } : {}),\n toolCallId: _toolCallId\n });\n const onAbort = () => {\n shellProcessManager.kill(shell.id);\n };\n\n if (signal) {\n if (signal.aborted) {\n onAbort();\n } else {\n signal.addEventListener(\"abort\", onAbort, { once: true });\n }\n }\n\n const execPromise = env\n .exec(params.command, {\n abortSignal: controller.signal,\n cwd,\n onStderr: (chunk) => {\n shellProcessManager.appendStderr(shell.id, chunk);\n },\n onStdout: (chunk) => {\n shellProcessManager.appendStdout(shell.id, chunk);\n }\n })\n .then((result) => {\n if (!result.ok) {\n shellProcessManager.fail(shell.id);\n throw result.error;\n }\n\n shellProcessManager.complete(shell.id, result.value.exitCode);\n\n return result.value;\n })\n .finally(() => {\n signal?.removeEventListener(\"abort\", onAbort);\n });\n const waitResult = await waitForShellResult(\n execPromise,\n (params.timeoutSeconds ?? DEFAULT_WAIT_TIMEOUT_SECONDS) * 1000\n );\n const record = shellProcessManager.get(shell.id) ?? shell;\n\n if (waitResult.status === \"completed\") {\n return {\n content: [\n {\n type: \"text\",\n text: formatShellOutput(record)\n }\n ],\n details: toShellDetails(record)\n };\n }\n\n execPromise.catch(() => undefined);\n\n return {\n content: [\n {\n type: \"text\",\n text: formatShellOutput(record)\n }\n ],\n details: toShellDetails(record)\n };\n },\n executionMode: \"sequential\"\n };\n}\n\nexport function createShellReadTool(): ServerPlugin.PluginTool {\n return {\n name: \"shell_read\",\n label: \"Shell Read\",\n description: \"Read output and status for a registered shell command.\",\n parameters: shellReadParameters,\n async execute(_toolCallId, rawParams) {\n const params = rawParams as ShellReadParameters;\n const record = shellProcessManager.get(params.shellId);\n\n if (!record) {\n throw new Error(`Unknown shell command: ${params.shellId}`);\n }\n\n return {\n content: [\n {\n type: \"text\",\n text: formatShellOutput(record)\n }\n ],\n details: toShellDetails(record)\n };\n },\n executionMode: \"sequential\"\n };\n}\n\nexport function createShellKillTool(): ServerPlugin.PluginTool {\n return {\n name: \"shell_kill\",\n label: \"Shell Kill\",\n description: \"Stop a registered running shell command.\",\n parameters: shellKillParameters,\n beforeExecute({ event, requestApproval }) {\n const params = event.input as Partial<ShellKillParameters>;\n\n return requestApproval(\n `Allowed to stop shell command: ${params.shellId ?? \"unknown\"}`\n );\n },\n async execute(_toolCallId, rawParams) {\n const params = rawParams as ShellKillParameters;\n const record = shellProcessManager.kill(params.shellId);\n\n if (!record) {\n throw new Error(`Unknown shell command: ${params.shellId}`);\n }\n\n return {\n content: [\n {\n type: \"text\",\n text: formatShellOutput(record)\n }\n ],\n details: toShellDetails(record)\n };\n },\n executionMode: \"sequential\"\n };\n}\n\nasync function waitForShellResult<T>(\n promise: Promise<T>,\n timeoutMs: number\n): Promise<{ status: \"completed\" } | { status: \"running\" }> {\n return await Promise.race([\n promise.then(() => ({ status: \"completed\" as const })),\n new Promise<{ status: \"running\" }>((resolve) => {\n setTimeout(() => {\n resolve({ status: \"running\" });\n }, timeoutMs);\n })\n ]);\n}\n\nfunction toShellDetails(record: ShellProcessRecord) {\n return {\n command: record.command,\n cwd: record.cwd,\n ...(record.endedAt ? { endedAt: record.endedAt } : {}),\n ...(record.exitCode === undefined ? {} : { exitCode: record.exitCode }),\n shellId: record.id,\n status: record.status,\n stderrLength: record.stderr.length,\n stdoutLength: record.stdout.length,\n ...(record.taskId ? { taskId: record.taskId } : {}),\n truncated: record.truncated\n };\n}\n\nfunction formatShellOutput(input: ShellProcessRecord): string {\n return [\n `shellId: ${input.id}`,\n `status: ${input.status}`,\n `cwd: ${input.cwd}`,\n `command: ${input.command}`,\n ...(input.exitCode === undefined ? [] : [`exitCode: ${input.exitCode}`]),\n \"\",\n \"stdout:\",\n truncateOutput(input.stdout),\n \"\",\n \"stderr:\",\n truncateOutput(input.stderr)\n ].join(\"\\n\");\n}\n\nfunction truncateOutput(output: string): string {\n if (output.length <= MAX_OUTPUT_LENGTH) {\n return output;\n }\n\n return `${output.slice(0, MAX_OUTPUT_LENGTH)}\\n[output truncated]`;\n}\n","export const PLUGIN_ID = \"__base__plugin\";\n","import type { ServerPlugin } from \"@hold-rein/plugin-server\";\nimport createRouter from './server/routes'\nimport {\n createShellExecTool,\n createShellKillTool,\n createShellReadTool\n} from './server/tools'\nimport { shellProcessManager } from './server/tools/shell-exec-tool/shell-process-manager'\n\nimport { PLUGIN_ID } from \"./plugin-id\";\n\nconst MAIN_AGENT_SHELL_CLEANUP_DELAY_MS = 60 * 60 * 1000\n\nconst shellCleanupTimers = new Map<string, ReturnType<typeof setTimeout>>()\n\nconst baseServerPlugin: ServerPlugin.Plugin = {\n id: PLUGIN_ID,\n registerRoutes: createRouter,\n contributionResolver: (context) => {\n return {\n tools: [\n createShellExecTool(context.env, { taskId: context.taskId }),\n createShellReadTool(),\n createShellKillTool()\n ],\n onAgentEnd: () => {\n if (context.agentName !== 'main') {\n return undefined\n }\n\n const existingTimer = shellCleanupTimers.get(context.taskId)\n\n if (existingTimer) {\n clearTimeout(existingTimer)\n }\n\n const timer = setTimeout(() => {\n shellCleanupTimers.delete(context.taskId)\n shellProcessManager.killAndRemoveByTask(context.taskId)\n }, MAIN_AGENT_SHELL_CLEANUP_DELAY_MS)\n\n shellCleanupTimers.set(context.taskId, timer)\n ;(timer as { unref?: () => void }).unref?.()\n\n return undefined\n }\n }\n }\n};\n\nexport default baseServerPlugin;\n"],"names":["MAX_STREAM_LENGTH","ShellProcessManager","__publicField","id","chunk","record","next","appendBounded","toShellProcessRecord","exitCode","taskId","killedRecord","input","randomUUID","shellRecord","listener","event","shellProcessManager","current","value","createRouter","context","router","Router","request","response","createShellSnapshotEvents","writeJsonLine","unsubscribe","records","DANGEROUS_PATTERNS","WRITE_PATTERNS","classifyShellCommandRisk","command","pattern","MAX_OUTPUT_LENGTH","DEFAULT_WAIT_TIMEOUT_SECONDS","shellExecParameters","Type","shellReadParameters","shellKillParameters","createShellExecTool","env","options","requestApproval","params","_toolCallId","rawParams","signal","cwd","controller","shell","onAbort","execPromise","result","waitResult","waitForShellResult","formatShellOutput","toShellDetails","createShellReadTool","createShellKillTool","promise","timeoutMs","resolve","truncateOutput","output","PLUGIN_ID","MAIN_AGENT_SHELL_CLEANUP_DELAY_MS","shellCleanupTimers","baseServerPlugin","existingTimer","timer","_a"],"mappings":"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"}
|
package/dist/server.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAe7D,QAAA,MAAM,gBAAgB,EAAE,YAAY,CAAC,MAiCpC,CAAC;AAEF,eAAe,gBAAgB,CAAC"}
|
package/dist/server.js
ADDED
|
@@ -0,0 +1,401 @@
|
|
|
1
|
+
var A = Object.defineProperty;
|
|
2
|
+
var T = (t, s, e) => s in t ? A(t, s, { enumerable: !0, configurable: !0, writable: !0, value: e }) : t[s] = e;
|
|
3
|
+
var I = (t, s, e) => T(t, typeof s != "symbol" ? s + "" : s, e);
|
|
4
|
+
import { Router as C } from "express";
|
|
5
|
+
import { randomUUID as x } from "node:crypto";
|
|
6
|
+
import { Type as d } from "@earendil-works/pi-ai";
|
|
7
|
+
const b = 2e5;
|
|
8
|
+
class R {
|
|
9
|
+
constructor() {
|
|
10
|
+
I(this, "listeners", /* @__PURE__ */ new Set());
|
|
11
|
+
I(this, "records", /* @__PURE__ */ new Map());
|
|
12
|
+
}
|
|
13
|
+
appendStderr(s, e) {
|
|
14
|
+
const n = this.records.get(s);
|
|
15
|
+
if (!n)
|
|
16
|
+
return;
|
|
17
|
+
const r = w(n.stderr, e);
|
|
18
|
+
n.stderr = r.value, n.truncated || (n.truncated = r.truncated), this.notify({
|
|
19
|
+
chunk: e,
|
|
20
|
+
record: l(n),
|
|
21
|
+
type: "shell_stderr"
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
appendStdout(s, e) {
|
|
25
|
+
const n = this.records.get(s);
|
|
26
|
+
if (!n)
|
|
27
|
+
return;
|
|
28
|
+
const r = w(n.stdout, e);
|
|
29
|
+
n.stdout = r.value, n.truncated || (n.truncated = r.truncated), this.notify({
|
|
30
|
+
chunk: e,
|
|
31
|
+
record: l(n),
|
|
32
|
+
type: "shell_stdout"
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
clear() {
|
|
36
|
+
this.records.clear();
|
|
37
|
+
}
|
|
38
|
+
complete(s, e) {
|
|
39
|
+
const n = this.records.get(s);
|
|
40
|
+
!n || n.status === "killed" || (n.endedAt = (/* @__PURE__ */ new Date()).toISOString(), n.exitCode = e, n.status = e === 0 ? "completed" : "failed", this.notify({
|
|
41
|
+
record: l(n),
|
|
42
|
+
type: "shell_end"
|
|
43
|
+
}));
|
|
44
|
+
}
|
|
45
|
+
fail(s) {
|
|
46
|
+
const e = this.records.get(s);
|
|
47
|
+
!e || e.status === "killed" || (e.endedAt = (/* @__PURE__ */ new Date()).toISOString(), e.status = "failed", this.notify({
|
|
48
|
+
record: l(e),
|
|
49
|
+
type: "shell_end"
|
|
50
|
+
}));
|
|
51
|
+
}
|
|
52
|
+
get(s) {
|
|
53
|
+
const e = this.records.get(s);
|
|
54
|
+
return e ? l(e) : void 0;
|
|
55
|
+
}
|
|
56
|
+
kill(s) {
|
|
57
|
+
const e = this.records.get(s);
|
|
58
|
+
if (e)
|
|
59
|
+
return e.status === "running" && (e.controller.abort(), e.endedAt = (/* @__PURE__ */ new Date()).toISOString(), e.status = "killed", this.notify({
|
|
60
|
+
record: l(e),
|
|
61
|
+
type: "shell_end"
|
|
62
|
+
})), l(e);
|
|
63
|
+
}
|
|
64
|
+
killByTask(s) {
|
|
65
|
+
return this.list(s).filter((e) => e.status === "running").map((e) => this.kill(e.id)).filter((e) => e !== void 0);
|
|
66
|
+
}
|
|
67
|
+
killAndRemoveByTask(s) {
|
|
68
|
+
return this.list(s).map((n) => {
|
|
69
|
+
const r = this.kill(n.id) ?? n;
|
|
70
|
+
return this.records.delete(n.id), r;
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
list(s) {
|
|
74
|
+
return Array.from(this.records.values()).filter((e) => s === void 0 || e.taskId === s).map(l);
|
|
75
|
+
}
|
|
76
|
+
register(s) {
|
|
77
|
+
const e = `shell_${x()}`, n = {
|
|
78
|
+
command: s.command,
|
|
79
|
+
controller: s.controller,
|
|
80
|
+
cwd: s.cwd,
|
|
81
|
+
id: e,
|
|
82
|
+
startedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
83
|
+
status: "running",
|
|
84
|
+
stderr: "",
|
|
85
|
+
stdout: "",
|
|
86
|
+
...s.taskId ? { taskId: s.taskId } : {},
|
|
87
|
+
toolCallId: s.toolCallId,
|
|
88
|
+
truncated: !1
|
|
89
|
+
};
|
|
90
|
+
this.records.set(e, n);
|
|
91
|
+
const r = l(n);
|
|
92
|
+
return this.notify({
|
|
93
|
+
record: r,
|
|
94
|
+
type: "shell_start"
|
|
95
|
+
}), r;
|
|
96
|
+
}
|
|
97
|
+
subscribe(s) {
|
|
98
|
+
return this.listeners.add(s), () => {
|
|
99
|
+
this.listeners.delete(s);
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
notify(s) {
|
|
103
|
+
for (const e of this.listeners)
|
|
104
|
+
e(s);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
const o = new R();
|
|
108
|
+
function w(t, s) {
|
|
109
|
+
const e = `${t}${s}`;
|
|
110
|
+
return e.length <= b ? { truncated: !1, value: e } : {
|
|
111
|
+
truncated: !0,
|
|
112
|
+
value: e.slice(e.length - b)
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
function l(t) {
|
|
116
|
+
return {
|
|
117
|
+
command: t.command,
|
|
118
|
+
cwd: t.cwd,
|
|
119
|
+
...t.endedAt ? { endedAt: t.endedAt } : {},
|
|
120
|
+
...t.exitCode === void 0 ? {} : { exitCode: t.exitCode },
|
|
121
|
+
id: t.id,
|
|
122
|
+
startedAt: t.startedAt,
|
|
123
|
+
status: t.status,
|
|
124
|
+
stderr: t.stderr,
|
|
125
|
+
stdout: t.stdout,
|
|
126
|
+
...t.taskId ? { taskId: t.taskId } : {},
|
|
127
|
+
toolCallId: t.toolCallId,
|
|
128
|
+
truncated: t.truncated
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
function O(t) {
|
|
132
|
+
const s = C();
|
|
133
|
+
return s.get("/shells", (e, n) => {
|
|
134
|
+
const r = typeof e.query.taskId == "string" ? e.query.taskId : void 0;
|
|
135
|
+
n.status(200), n.setHeader("Cache-Control", "no-cache, no-transform"), n.setHeader("Connection", "keep-alive"), n.setHeader("Content-Type", "application/x-ndjson; charset=utf-8"), n.flushHeaders();
|
|
136
|
+
for (const i of N(o.list(r)))
|
|
137
|
+
y(n, i);
|
|
138
|
+
const a = o.subscribe((i) => {
|
|
139
|
+
r !== void 0 && i.record.taskId !== r || y(n, i);
|
|
140
|
+
});
|
|
141
|
+
e.on("close", () => {
|
|
142
|
+
a();
|
|
143
|
+
});
|
|
144
|
+
}), s.get("/shells/:shellId", (e, n) => {
|
|
145
|
+
const r = o.get(e.params.shellId);
|
|
146
|
+
if (!r) {
|
|
147
|
+
t.sendError(n, t.RESPONSE_CODE_DEFINITIONS.notFound);
|
|
148
|
+
return;
|
|
149
|
+
}
|
|
150
|
+
t.sendSuccess(n, r);
|
|
151
|
+
}), s.post("/shells/:shellId/kill", (e, n) => {
|
|
152
|
+
const r = o.kill(e.params.shellId);
|
|
153
|
+
if (!r) {
|
|
154
|
+
t.sendError(n, t.RESPONSE_CODE_DEFINITIONS.notFound);
|
|
155
|
+
return;
|
|
156
|
+
}
|
|
157
|
+
t.sendSuccess(n, r);
|
|
158
|
+
}), s;
|
|
159
|
+
}
|
|
160
|
+
function N(t) {
|
|
161
|
+
return t.flatMap((s) => [
|
|
162
|
+
{
|
|
163
|
+
record: s,
|
|
164
|
+
type: "shell_start"
|
|
165
|
+
},
|
|
166
|
+
...s.stdout ? [{
|
|
167
|
+
chunk: s.stdout,
|
|
168
|
+
record: s,
|
|
169
|
+
type: "shell_stdout"
|
|
170
|
+
}] : [],
|
|
171
|
+
...s.stderr ? [{
|
|
172
|
+
chunk: s.stderr,
|
|
173
|
+
record: s,
|
|
174
|
+
type: "shell_stderr"
|
|
175
|
+
}] : [],
|
|
176
|
+
...s.status === "running" ? [] : [{
|
|
177
|
+
record: s,
|
|
178
|
+
type: "shell_end"
|
|
179
|
+
}]
|
|
180
|
+
]);
|
|
181
|
+
}
|
|
182
|
+
function y(t, s) {
|
|
183
|
+
t.write(`${JSON.stringify(s)}
|
|
184
|
+
`);
|
|
185
|
+
}
|
|
186
|
+
const P = [
|
|
187
|
+
/\brm\b/u,
|
|
188
|
+
/\brm\s+(-[^\s]*r[^\s]*f|-{1,2}recursive\b.*-{1,2}force\b)/u,
|
|
189
|
+
/\bgit\s+reset\s+--hard\b/u,
|
|
190
|
+
/\bsudo\b/u,
|
|
191
|
+
/\bchmod\s+777\b/u
|
|
192
|
+
], D = [
|
|
193
|
+
/>/u,
|
|
194
|
+
/\bmv\b/u,
|
|
195
|
+
/\bcp\b/u,
|
|
196
|
+
/\btouch\b/u,
|
|
197
|
+
/\bmkdir\b/u,
|
|
198
|
+
/\bgit\s+(add|commit|push|switch|checkout|branch)\b/u,
|
|
199
|
+
/\b(pnpm|npm|yarn)\s+(install|add|remove)\b/u
|
|
200
|
+
];
|
|
201
|
+
function M(t) {
|
|
202
|
+
return P.some((s) => s.test(t)) ? "dangerous" : D.some((s) => s.test(t)) ? "writes" : "safe";
|
|
203
|
+
}
|
|
204
|
+
const _ = 2e4, $ = 60, L = d.Object({
|
|
205
|
+
command: d.String({ description: "Shell command to execute." }),
|
|
206
|
+
cwd: d.Optional(
|
|
207
|
+
d.String({ description: "Working directory for the command." })
|
|
208
|
+
),
|
|
209
|
+
timeoutSeconds: d.Optional(
|
|
210
|
+
d.Number({ description: "Command timeout in seconds." })
|
|
211
|
+
)
|
|
212
|
+
}), U = d.Object({
|
|
213
|
+
shellId: d.String({ description: "Registered shell command id." })
|
|
214
|
+
}), H = d.Object({
|
|
215
|
+
shellId: d.String({ description: "Registered shell command id." })
|
|
216
|
+
});
|
|
217
|
+
function F(t, s = {}) {
|
|
218
|
+
return {
|
|
219
|
+
name: "shell_exec",
|
|
220
|
+
label: "Shell Exec",
|
|
221
|
+
description: "Run a shell command in the configured workspace.",
|
|
222
|
+
parameters: L,
|
|
223
|
+
beforeExecute({ event: e, requestApproval: n }) {
|
|
224
|
+
const r = e.input, a = typeof r.command == "string" ? r.command : "";
|
|
225
|
+
if (M(a) !== "safe")
|
|
226
|
+
return n(`Allowed to execute the command: ${r.command}`);
|
|
227
|
+
},
|
|
228
|
+
async execute(e, n, r) {
|
|
229
|
+
const a = n, i = a.cwd ?? t.cwd, k = new AbortController(), u = o.register({
|
|
230
|
+
command: a.command,
|
|
231
|
+
controller: k,
|
|
232
|
+
cwd: i,
|
|
233
|
+
...s.taskId ? { taskId: s.taskId } : {},
|
|
234
|
+
toolCallId: e
|
|
235
|
+
}), p = () => {
|
|
236
|
+
o.kill(u.id);
|
|
237
|
+
};
|
|
238
|
+
r && (r.aborted ? p() : r.addEventListener("abort", p, { once: !0 }));
|
|
239
|
+
const g = t.exec(a.command, {
|
|
240
|
+
abortSignal: k.signal,
|
|
241
|
+
cwd: i,
|
|
242
|
+
onStderr: (c) => {
|
|
243
|
+
o.appendStderr(u.id, c);
|
|
244
|
+
},
|
|
245
|
+
onStdout: (c) => {
|
|
246
|
+
o.appendStdout(u.id, c);
|
|
247
|
+
}
|
|
248
|
+
}).then((c) => {
|
|
249
|
+
if (!c.ok)
|
|
250
|
+
throw o.fail(u.id), c.error;
|
|
251
|
+
return o.complete(u.id, c.value.exitCode), c.value;
|
|
252
|
+
}).finally(() => {
|
|
253
|
+
r == null || r.removeEventListener("abort", p);
|
|
254
|
+
}), v = await B(
|
|
255
|
+
g,
|
|
256
|
+
(a.timeoutSeconds ?? $) * 1e3
|
|
257
|
+
), m = o.get(u.id) ?? u;
|
|
258
|
+
return v.status === "completed" ? {
|
|
259
|
+
content: [
|
|
260
|
+
{
|
|
261
|
+
type: "text",
|
|
262
|
+
text: f(m)
|
|
263
|
+
}
|
|
264
|
+
],
|
|
265
|
+
details: h(m)
|
|
266
|
+
} : (g.catch(() => {
|
|
267
|
+
}), {
|
|
268
|
+
content: [
|
|
269
|
+
{
|
|
270
|
+
type: "text",
|
|
271
|
+
text: f(m)
|
|
272
|
+
}
|
|
273
|
+
],
|
|
274
|
+
details: h(m)
|
|
275
|
+
});
|
|
276
|
+
},
|
|
277
|
+
executionMode: "sequential"
|
|
278
|
+
};
|
|
279
|
+
}
|
|
280
|
+
function j() {
|
|
281
|
+
return {
|
|
282
|
+
name: "shell_read",
|
|
283
|
+
label: "Shell Read",
|
|
284
|
+
description: "Read output and status for a registered shell command.",
|
|
285
|
+
parameters: U,
|
|
286
|
+
async execute(t, s) {
|
|
287
|
+
const e = s, n = o.get(e.shellId);
|
|
288
|
+
if (!n)
|
|
289
|
+
throw new Error(`Unknown shell command: ${e.shellId}`);
|
|
290
|
+
return {
|
|
291
|
+
content: [
|
|
292
|
+
{
|
|
293
|
+
type: "text",
|
|
294
|
+
text: f(n)
|
|
295
|
+
}
|
|
296
|
+
],
|
|
297
|
+
details: h(n)
|
|
298
|
+
};
|
|
299
|
+
},
|
|
300
|
+
executionMode: "sequential"
|
|
301
|
+
};
|
|
302
|
+
}
|
|
303
|
+
function G() {
|
|
304
|
+
return {
|
|
305
|
+
name: "shell_kill",
|
|
306
|
+
label: "Shell Kill",
|
|
307
|
+
description: "Stop a registered running shell command.",
|
|
308
|
+
parameters: H,
|
|
309
|
+
beforeExecute({ event: t, requestApproval: s }) {
|
|
310
|
+
const e = t.input;
|
|
311
|
+
return s(
|
|
312
|
+
`Allowed to stop shell command: ${e.shellId ?? "unknown"}`
|
|
313
|
+
);
|
|
314
|
+
},
|
|
315
|
+
async execute(t, s) {
|
|
316
|
+
const e = s, n = o.kill(e.shellId);
|
|
317
|
+
if (!n)
|
|
318
|
+
throw new Error(`Unknown shell command: ${e.shellId}`);
|
|
319
|
+
return {
|
|
320
|
+
content: [
|
|
321
|
+
{
|
|
322
|
+
type: "text",
|
|
323
|
+
text: f(n)
|
|
324
|
+
}
|
|
325
|
+
],
|
|
326
|
+
details: h(n)
|
|
327
|
+
};
|
|
328
|
+
},
|
|
329
|
+
executionMode: "sequential"
|
|
330
|
+
};
|
|
331
|
+
}
|
|
332
|
+
async function B(t, s) {
|
|
333
|
+
return await Promise.race([
|
|
334
|
+
t.then(() => ({ status: "completed" })),
|
|
335
|
+
new Promise((e) => {
|
|
336
|
+
setTimeout(() => {
|
|
337
|
+
e({ status: "running" });
|
|
338
|
+
}, s);
|
|
339
|
+
})
|
|
340
|
+
]);
|
|
341
|
+
}
|
|
342
|
+
function h(t) {
|
|
343
|
+
return {
|
|
344
|
+
command: t.command,
|
|
345
|
+
cwd: t.cwd,
|
|
346
|
+
...t.endedAt ? { endedAt: t.endedAt } : {},
|
|
347
|
+
...t.exitCode === void 0 ? {} : { exitCode: t.exitCode },
|
|
348
|
+
shellId: t.id,
|
|
349
|
+
status: t.status,
|
|
350
|
+
stderrLength: t.stderr.length,
|
|
351
|
+
stdoutLength: t.stdout.length,
|
|
352
|
+
...t.taskId ? { taskId: t.taskId } : {},
|
|
353
|
+
truncated: t.truncated
|
|
354
|
+
};
|
|
355
|
+
}
|
|
356
|
+
function f(t) {
|
|
357
|
+
return [
|
|
358
|
+
`shellId: ${t.id}`,
|
|
359
|
+
`status: ${t.status}`,
|
|
360
|
+
`cwd: ${t.cwd}`,
|
|
361
|
+
`command: ${t.command}`,
|
|
362
|
+
...t.exitCode === void 0 ? [] : [`exitCode: ${t.exitCode}`],
|
|
363
|
+
"",
|
|
364
|
+
"stdout:",
|
|
365
|
+
E(t.stdout),
|
|
366
|
+
"",
|
|
367
|
+
"stderr:",
|
|
368
|
+
E(t.stderr)
|
|
369
|
+
].join(`
|
|
370
|
+
`);
|
|
371
|
+
}
|
|
372
|
+
function E(t) {
|
|
373
|
+
return t.length <= _ ? t : `${t.slice(0, _)}
|
|
374
|
+
[output truncated]`;
|
|
375
|
+
}
|
|
376
|
+
const q = "__base__plugin", K = 3600 * 1e3, S = /* @__PURE__ */ new Map(), z = {
|
|
377
|
+
id: q,
|
|
378
|
+
registerRoutes: O,
|
|
379
|
+
contributionResolver: (t) => ({
|
|
380
|
+
tools: [
|
|
381
|
+
F(t.env, { taskId: t.taskId }),
|
|
382
|
+
j(),
|
|
383
|
+
G()
|
|
384
|
+
],
|
|
385
|
+
onAgentEnd: () => {
|
|
386
|
+
var n;
|
|
387
|
+
if (t.agentName !== "main")
|
|
388
|
+
return;
|
|
389
|
+
const s = S.get(t.taskId);
|
|
390
|
+
s && clearTimeout(s);
|
|
391
|
+
const e = setTimeout(() => {
|
|
392
|
+
S.delete(t.taskId), o.killAndRemoveByTask(t.taskId);
|
|
393
|
+
}, K);
|
|
394
|
+
S.set(t.taskId, e), (n = e.unref) == null || n.call(e);
|
|
395
|
+
}
|
|
396
|
+
})
|
|
397
|
+
};
|
|
398
|
+
export {
|
|
399
|
+
z as default
|
|
400
|
+
};
|
|
401
|
+
//# sourceMappingURL=server.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.js","sources":["../src/server/tools/shell-exec-tool/shell-process-manager.ts","../src/server/routes/index.ts","../src/server/tools/shell-exec-tool/shell-command-risk.ts","../src/server/tools/shell-exec-tool/index.ts","../src/plugin-id.ts","../src/server.ts"],"sourcesContent":["import { randomUUID } from \"node:crypto\";\n\nconst MAX_STREAM_LENGTH = 200_000;\n\nexport type ShellProcessStatus = \"running\" | \"completed\" | \"failed\" | \"killed\";\n\nexport interface ShellProcessRecord {\n readonly command: string;\n readonly cwd: string;\n readonly endedAt?: string;\n readonly exitCode?: number;\n readonly id: string;\n readonly startedAt: string;\n readonly status: ShellProcessStatus;\n readonly stderr: string;\n readonly stdout: string;\n readonly taskId?: string;\n readonly toolCallId: string;\n readonly truncated: boolean;\n}\n\nexport type ShellProcessEvent =\n | {\n readonly record: ShellProcessRecord;\n readonly type: \"shell_end\" | \"shell_start\";\n }\n | {\n readonly chunk: string;\n readonly record: ShellProcessRecord;\n readonly type: \"shell_stderr\" | \"shell_stdout\";\n };\n\nexport type ShellProcessEventListener = (event: ShellProcessEvent) => void;\n\ninterface MutableShellProcessRecord {\n command: string;\n controller: AbortController;\n cwd: string;\n endedAt?: string;\n exitCode?: number;\n id: string;\n startedAt: string;\n status: ShellProcessStatus;\n stderr: string;\n stdout: string;\n taskId?: string;\n toolCallId: string;\n truncated: boolean;\n}\n\nexport interface RegisterShellProcessInput {\n readonly command: string;\n readonly controller: AbortController;\n readonly cwd: string;\n readonly taskId?: string;\n readonly toolCallId: string;\n}\n\nexport class ShellProcessManager {\n private readonly listeners = new Set<ShellProcessEventListener>();\n\n private readonly records = new Map<string, MutableShellProcessRecord>();\n\n appendStderr(id: string, chunk: string): void {\n const record = this.records.get(id);\n\n if (!record) {\n return;\n }\n\n const next = appendBounded(record.stderr, chunk);\n record.stderr = next.value;\n record.truncated ||= next.truncated;\n this.notify({\n chunk,\n record: toShellProcessRecord(record),\n type: \"shell_stderr\"\n });\n }\n\n appendStdout(id: string, chunk: string): void {\n const record = this.records.get(id);\n\n if (!record) {\n return;\n }\n\n const next = appendBounded(record.stdout, chunk);\n record.stdout = next.value;\n record.truncated ||= next.truncated;\n this.notify({\n chunk,\n record: toShellProcessRecord(record),\n type: \"shell_stdout\"\n });\n }\n\n clear(): void {\n this.records.clear();\n }\n\n complete(id: string, exitCode: number): void {\n const record = this.records.get(id);\n\n if (!record || record.status === \"killed\") {\n return;\n }\n\n record.endedAt = new Date().toISOString();\n record.exitCode = exitCode;\n record.status = exitCode === 0 ? \"completed\" : \"failed\";\n this.notify({\n record: toShellProcessRecord(record),\n type: \"shell_end\"\n });\n }\n\n fail(id: string): void {\n const record = this.records.get(id);\n\n if (!record || record.status === \"killed\") {\n return;\n }\n\n record.endedAt = new Date().toISOString();\n record.status = \"failed\";\n this.notify({\n record: toShellProcessRecord(record),\n type: \"shell_end\"\n });\n }\n\n get(id: string): ShellProcessRecord | undefined {\n const record = this.records.get(id);\n\n return record ? toShellProcessRecord(record) : undefined;\n }\n\n kill(id: string): ShellProcessRecord | undefined {\n const record = this.records.get(id);\n\n if (!record) {\n return undefined;\n }\n\n if (record.status === \"running\") {\n record.controller.abort();\n record.endedAt = new Date().toISOString();\n record.status = \"killed\";\n this.notify({\n record: toShellProcessRecord(record),\n type: \"shell_end\"\n });\n }\n\n return toShellProcessRecord(record);\n }\n\n killByTask(taskId: string): ShellProcessRecord[] {\n return this.list(taskId)\n .filter((record) => record.status === \"running\")\n .map((record) => this.kill(record.id))\n .filter((record): record is ShellProcessRecord => record !== undefined);\n }\n\n killAndRemoveByTask(taskId: string): ShellProcessRecord[] {\n const taskRecords = this.list(taskId);\n\n return taskRecords\n .map((record) => {\n const killedRecord = this.kill(record.id) ?? record;\n this.records.delete(record.id);\n return killedRecord;\n });\n }\n\n list(taskId?: string): ShellProcessRecord[] {\n return Array.from(this.records.values())\n .filter((record) => taskId === undefined || record.taskId === taskId)\n .map(toShellProcessRecord);\n }\n\n register(input: RegisterShellProcessInput): ShellProcessRecord {\n const id = `shell_${randomUUID()}`;\n const record: MutableShellProcessRecord = {\n command: input.command,\n controller: input.controller,\n cwd: input.cwd,\n id,\n startedAt: new Date().toISOString(),\n status: \"running\",\n stderr: \"\",\n stdout: \"\",\n ...(input.taskId ? { taskId: input.taskId } : {}),\n toolCallId: input.toolCallId,\n truncated: false\n };\n\n this.records.set(id, record);\n\n const shellRecord = toShellProcessRecord(record);\n this.notify({\n record: shellRecord,\n type: \"shell_start\"\n });\n\n return shellRecord;\n }\n\n subscribe(listener: ShellProcessEventListener): () => void {\n this.listeners.add(listener);\n\n return () => {\n this.listeners.delete(listener);\n };\n }\n\n private notify(event: ShellProcessEvent): void {\n for (const listener of this.listeners) {\n listener(event);\n }\n }\n}\n\nexport const shellProcessManager = new ShellProcessManager();\n\nfunction appendBounded(current: string, chunk: string): {\n truncated: boolean;\n value: string;\n} {\n const value = `${current}${chunk}`;\n\n if (value.length <= MAX_STREAM_LENGTH) {\n return { truncated: false, value };\n }\n\n return {\n truncated: true,\n value: value.slice(value.length - MAX_STREAM_LENGTH)\n };\n}\n\nfunction toShellProcessRecord(\n record: MutableShellProcessRecord\n): ShellProcessRecord {\n return {\n command: record.command,\n cwd: record.cwd,\n ...(record.endedAt ? { endedAt: record.endedAt } : {}),\n ...(record.exitCode === undefined ? {} : { exitCode: record.exitCode }),\n id: record.id,\n startedAt: record.startedAt,\n status: record.status,\n stderr: record.stderr,\n stdout: record.stdout,\n ...(record.taskId ? { taskId: record.taskId } : {}),\n toolCallId: record.toolCallId,\n truncated: record.truncated\n };\n}\n","import { Router } from 'express'\nimport type { Request, Response } from 'express'\nimport type { ServerPlugin } from '@hold-rein/plugin-server'\n\nimport {\n shellProcessManager,\n type ShellProcessEvent,\n type ShellProcessRecord\n} from '../tools/shell-exec-tool/shell-process-manager'\n\nexport default function createRouter(context: ServerPlugin.RouteContext): Router {\n const router = Router()\n\n router.get('/shells', (request: Request, response: Response) => {\n const taskId = typeof request.query.taskId === 'string'\n ? request.query.taskId\n : undefined\n\n response.status(200)\n response.setHeader('Cache-Control', 'no-cache, no-transform')\n response.setHeader('Connection', 'keep-alive')\n response.setHeader('Content-Type', 'application/x-ndjson; charset=utf-8')\n response.flushHeaders()\n\n for (const event of createShellSnapshotEvents(shellProcessManager.list(taskId))) {\n writeJsonLine(response, event)\n }\n\n const unsubscribe = shellProcessManager.subscribe((event) => {\n if (taskId !== undefined && event.record.taskId !== taskId) {\n return\n }\n\n writeJsonLine(response, event)\n })\n\n request.on('close', () => {\n unsubscribe()\n })\n })\n\n router.get('/shells/:shellId', (\n request: Request<{ shellId: string }>,\n response: Response\n ) => {\n const record = shellProcessManager.get(request.params.shellId)\n\n if (!record) {\n context.sendError(response, context.RESPONSE_CODE_DEFINITIONS.notFound)\n return\n }\n\n context.sendSuccess(response, record)\n })\n\n router.post('/shells/:shellId/kill', (\n request: Request<{ shellId: string }>,\n response: Response\n ) => {\n const record = shellProcessManager.kill(request.params.shellId)\n\n if (!record) {\n context.sendError(response, context.RESPONSE_CODE_DEFINITIONS.notFound)\n return\n }\n\n context.sendSuccess(response, record)\n })\n\n return router\n}\n\nfunction createShellSnapshotEvents(\n records: readonly ShellProcessRecord[]\n): ShellProcessEvent[] {\n return records.flatMap((record) => [\n {\n record,\n type: 'shell_start' as const\n },\n ...(record.stdout\n ? [{\n chunk: record.stdout,\n record,\n type: 'shell_stdout' as const\n }]\n : []),\n ...(record.stderr\n ? [{\n chunk: record.stderr,\n record,\n type: 'shell_stderr' as const\n }]\n : []),\n ...(record.status === 'running'\n ? []\n : [{\n record,\n type: 'shell_end' as const\n }])\n ])\n}\n\nfunction writeJsonLine(response: Response, event: ShellProcessEvent): void {\n response.write(`${JSON.stringify(event)}\\n`)\n}\n","export type ShellCommandRisk = \"safe\" | \"writes\" | \"dangerous\";\n\nconst DANGEROUS_PATTERNS = [\n /\\brm\\b/u,\n /\\brm\\s+(-[^\\s]*r[^\\s]*f|-{1,2}recursive\\b.*-{1,2}force\\b)/u,\n /\\bgit\\s+reset\\s+--hard\\b/u,\n /\\bsudo\\b/u,\n /\\bchmod\\s+777\\b/u\n];\n\nconst WRITE_PATTERNS = [\n />/u,\n /\\bmv\\b/u,\n /\\bcp\\b/u,\n /\\btouch\\b/u,\n /\\bmkdir\\b/u,\n /\\bgit\\s+(add|commit|push|switch|checkout|branch)\\b/u,\n /\\b(pnpm|npm|yarn)\\s+(install|add|remove)\\b/u\n];\n\nexport function classifyShellCommandRisk(command: string): ShellCommandRisk {\n if (DANGEROUS_PATTERNS.some((pattern) => pattern.test(command))) {\n return \"dangerous\";\n }\n\n if (WRITE_PATTERNS.some((pattern) => pattern.test(command))) {\n return \"writes\";\n }\n\n return \"safe\";\n}\n","import type { ExecutionEnv } from \"@earendil-works/pi-agent-core\";\nimport { Type, type Static } from \"@earendil-works/pi-ai\";\nimport type { ServerPlugin } from \"@hold-rein/plugin-server\";\n\nimport { classifyShellCommandRisk } from \"./shell-command-risk\";\nimport {\n shellProcessManager,\n type ShellProcessRecord\n} from \"./shell-process-manager\";\n\nconst MAX_OUTPUT_LENGTH = 20_000;\nconst DEFAULT_WAIT_TIMEOUT_SECONDS = 60;\n\nconst shellExecParameters = Type.Object({\n command: Type.String({ description: \"Shell command to execute.\" }),\n cwd: Type.Optional(\n Type.String({ description: \"Working directory for the command.\" })\n ),\n timeoutSeconds: Type.Optional(\n Type.Number({ description: \"Command timeout in seconds.\" })\n )\n});\n\ntype ShellExecParameters = Static<typeof shellExecParameters>;\n\nconst shellReadParameters = Type.Object({\n shellId: Type.String({ description: \"Registered shell command id.\" })\n});\n\ntype ShellReadParameters = Static<typeof shellReadParameters>;\n\nconst shellKillParameters = Type.Object({\n shellId: Type.String({ description: \"Registered shell command id.\" })\n});\n\ntype ShellKillParameters = Static<typeof shellKillParameters>;\n\ninterface CreateShellExecToolOptions {\n readonly taskId?: string;\n}\n\nexport function createShellExecTool(\n env: ExecutionEnv,\n options: CreateShellExecToolOptions = {}\n): ServerPlugin.PluginTool {\n return {\n name: \"shell_exec\",\n label: \"Shell Exec\",\n description: \"Run a shell command in the configured workspace.\",\n parameters: shellExecParameters,\n beforeExecute({ event, requestApproval }) {\n const params = event.input as Partial<ShellExecParameters>;\n const command = typeof params.command === \"string\" ? params.command : \"\";\n const risk = classifyShellCommandRisk(command);\n\n if (risk === \"safe\") {\n return undefined;\n }\n\n return requestApproval(`Allowed to execute the command: ${params.command}`);\n },\n async execute(_toolCallId, rawParams, signal) {\n const params = rawParams as ShellExecParameters;\n const cwd = params.cwd ?? env.cwd;\n const controller = new AbortController();\n const shell = shellProcessManager.register({\n command: params.command,\n controller,\n cwd,\n ...(options.taskId ? { taskId: options.taskId } : {}),\n toolCallId: _toolCallId\n });\n const onAbort = () => {\n shellProcessManager.kill(shell.id);\n };\n\n if (signal) {\n if (signal.aborted) {\n onAbort();\n } else {\n signal.addEventListener(\"abort\", onAbort, { once: true });\n }\n }\n\n const execPromise = env\n .exec(params.command, {\n abortSignal: controller.signal,\n cwd,\n onStderr: (chunk) => {\n shellProcessManager.appendStderr(shell.id, chunk);\n },\n onStdout: (chunk) => {\n shellProcessManager.appendStdout(shell.id, chunk);\n }\n })\n .then((result) => {\n if (!result.ok) {\n shellProcessManager.fail(shell.id);\n throw result.error;\n }\n\n shellProcessManager.complete(shell.id, result.value.exitCode);\n\n return result.value;\n })\n .finally(() => {\n signal?.removeEventListener(\"abort\", onAbort);\n });\n const waitResult = await waitForShellResult(\n execPromise,\n (params.timeoutSeconds ?? DEFAULT_WAIT_TIMEOUT_SECONDS) * 1000\n );\n const record = shellProcessManager.get(shell.id) ?? shell;\n\n if (waitResult.status === \"completed\") {\n return {\n content: [\n {\n type: \"text\",\n text: formatShellOutput(record)\n }\n ],\n details: toShellDetails(record)\n };\n }\n\n execPromise.catch(() => undefined);\n\n return {\n content: [\n {\n type: \"text\",\n text: formatShellOutput(record)\n }\n ],\n details: toShellDetails(record)\n };\n },\n executionMode: \"sequential\"\n };\n}\n\nexport function createShellReadTool(): ServerPlugin.PluginTool {\n return {\n name: \"shell_read\",\n label: \"Shell Read\",\n description: \"Read output and status for a registered shell command.\",\n parameters: shellReadParameters,\n async execute(_toolCallId, rawParams) {\n const params = rawParams as ShellReadParameters;\n const record = shellProcessManager.get(params.shellId);\n\n if (!record) {\n throw new Error(`Unknown shell command: ${params.shellId}`);\n }\n\n return {\n content: [\n {\n type: \"text\",\n text: formatShellOutput(record)\n }\n ],\n details: toShellDetails(record)\n };\n },\n executionMode: \"sequential\"\n };\n}\n\nexport function createShellKillTool(): ServerPlugin.PluginTool {\n return {\n name: \"shell_kill\",\n label: \"Shell Kill\",\n description: \"Stop a registered running shell command.\",\n parameters: shellKillParameters,\n beforeExecute({ event, requestApproval }) {\n const params = event.input as Partial<ShellKillParameters>;\n\n return requestApproval(\n `Allowed to stop shell command: ${params.shellId ?? \"unknown\"}`\n );\n },\n async execute(_toolCallId, rawParams) {\n const params = rawParams as ShellKillParameters;\n const record = shellProcessManager.kill(params.shellId);\n\n if (!record) {\n throw new Error(`Unknown shell command: ${params.shellId}`);\n }\n\n return {\n content: [\n {\n type: \"text\",\n text: formatShellOutput(record)\n }\n ],\n details: toShellDetails(record)\n };\n },\n executionMode: \"sequential\"\n };\n}\n\nasync function waitForShellResult<T>(\n promise: Promise<T>,\n timeoutMs: number\n): Promise<{ status: \"completed\" } | { status: \"running\" }> {\n return await Promise.race([\n promise.then(() => ({ status: \"completed\" as const })),\n new Promise<{ status: \"running\" }>((resolve) => {\n setTimeout(() => {\n resolve({ status: \"running\" });\n }, timeoutMs);\n })\n ]);\n}\n\nfunction toShellDetails(record: ShellProcessRecord) {\n return {\n command: record.command,\n cwd: record.cwd,\n ...(record.endedAt ? { endedAt: record.endedAt } : {}),\n ...(record.exitCode === undefined ? {} : { exitCode: record.exitCode }),\n shellId: record.id,\n status: record.status,\n stderrLength: record.stderr.length,\n stdoutLength: record.stdout.length,\n ...(record.taskId ? { taskId: record.taskId } : {}),\n truncated: record.truncated\n };\n}\n\nfunction formatShellOutput(input: ShellProcessRecord): string {\n return [\n `shellId: ${input.id}`,\n `status: ${input.status}`,\n `cwd: ${input.cwd}`,\n `command: ${input.command}`,\n ...(input.exitCode === undefined ? [] : [`exitCode: ${input.exitCode}`]),\n \"\",\n \"stdout:\",\n truncateOutput(input.stdout),\n \"\",\n \"stderr:\",\n truncateOutput(input.stderr)\n ].join(\"\\n\");\n}\n\nfunction truncateOutput(output: string): string {\n if (output.length <= MAX_OUTPUT_LENGTH) {\n return output;\n }\n\n return `${output.slice(0, MAX_OUTPUT_LENGTH)}\\n[output truncated]`;\n}\n","export const PLUGIN_ID = \"__base__plugin\";\n","import type { ServerPlugin } from \"@hold-rein/plugin-server\";\nimport createRouter from './server/routes'\nimport {\n createShellExecTool,\n createShellKillTool,\n createShellReadTool\n} from './server/tools'\nimport { shellProcessManager } from './server/tools/shell-exec-tool/shell-process-manager'\n\nimport { PLUGIN_ID } from \"./plugin-id\";\n\nconst MAIN_AGENT_SHELL_CLEANUP_DELAY_MS = 60 * 60 * 1000\n\nconst shellCleanupTimers = new Map<string, ReturnType<typeof setTimeout>>()\n\nconst baseServerPlugin: ServerPlugin.Plugin = {\n id: PLUGIN_ID,\n registerRoutes: createRouter,\n contributionResolver: (context) => {\n return {\n tools: [\n createShellExecTool(context.env, { taskId: context.taskId }),\n createShellReadTool(),\n createShellKillTool()\n ],\n onAgentEnd: () => {\n if (context.agentName !== 'main') {\n return undefined\n }\n\n const existingTimer = shellCleanupTimers.get(context.taskId)\n\n if (existingTimer) {\n clearTimeout(existingTimer)\n }\n\n const timer = setTimeout(() => {\n shellCleanupTimers.delete(context.taskId)\n shellProcessManager.killAndRemoveByTask(context.taskId)\n }, MAIN_AGENT_SHELL_CLEANUP_DELAY_MS)\n\n shellCleanupTimers.set(context.taskId, timer)\n ;(timer as { unref?: () => void }).unref?.()\n\n return undefined\n }\n }\n }\n};\n\nexport default baseServerPlugin;\n"],"names":["MAX_STREAM_LENGTH","ShellProcessManager","__publicField","id","chunk","record","next","appendBounded","toShellProcessRecord","exitCode","taskId","killedRecord","input","randomUUID","shellRecord","listener","event","shellProcessManager","current","value","createRouter","context","router","Router","request","response","createShellSnapshotEvents","writeJsonLine","unsubscribe","records","DANGEROUS_PATTERNS","WRITE_PATTERNS","classifyShellCommandRisk","command","pattern","MAX_OUTPUT_LENGTH","DEFAULT_WAIT_TIMEOUT_SECONDS","shellExecParameters","Type","shellReadParameters","shellKillParameters","createShellExecTool","env","options","requestApproval","params","_toolCallId","rawParams","signal","cwd","controller","shell","onAbort","execPromise","result","waitResult","waitForShellResult","formatShellOutput","toShellDetails","createShellReadTool","createShellKillTool","promise","timeoutMs","resolve","truncateOutput","output","PLUGIN_ID","MAIN_AGENT_SHELL_CLEANUP_DELAY_MS","shellCleanupTimers","baseServerPlugin","existingTimer","timer","_a"],"mappings":"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"}
|
package/dist/style.css
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
.shell-processes-panel{display:flex;flex-direction:column;gap:8px;min-height:0}.shell-processes-toolbar{align-items:center;display:flex;gap:8px;justify-content:space-between}.shell-processes-title{color:var(--app-color-text);font-size:13px;font-weight:600;line-height:1.4}.shell-processes-empty{align-items:center;color:var(--app-color-text-secondary);display:flex;justify-content:center;min-height:160px}.shell-processes-list{display:flex;flex-direction:column;gap:8px}.shell-processes-item{border:1px solid var(--app-color-border-secondary);border-radius:6px;display:flex;flex-direction:column;gap:6px;padding:8px}.shell-processes-item-header{align-items:center;display:flex;gap:8px;justify-content:space-between}.shell-processes-item-title{align-items:center;background:none;border:0;color:var(--app-color-text);cursor:pointer;display:flex;flex:1;gap:6px;min-width:0;padding:0;text-align:start}.shell-processes-item-title .anticon{color:var(--app-color-text-tertiary);flex:0 0 auto;font-size:10px;line-height:1.68}.shell-processes-command{color:var(--app-color-text);font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;font-size:12px;line-height:1.4;overflow-wrap:anywhere}.shell-processes-meta{color:var(--app-color-text-tertiary);font-size:11px;line-height:1.4;overflow-wrap:anywhere}.shell-processes-output{background:var(--app-color-fill-tertiary);border-radius:4px;color:var(--app-color-text-secondary);font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;font-size:11px;line-height:1.45;margin:0;max-height:180px;overflow:auto;padding:8px;white-space:pre-wrap}.shell-processes-status{margin-inline-end:0}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/web/right-panels/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { WebPlugin } from "@hold-rein/plugin-web";
|
|
2
|
+
import "./shell-processes.css";
|
|
3
|
+
export interface ShellProcessesPanelProps extends WebPlugin.RightPanelProps {
|
|
4
|
+
readonly request: WebPlugin.RuntimeContext["request"];
|
|
5
|
+
}
|
|
6
|
+
export declare function ShellProcessesPanel({ request, taskId }: ShellProcessesPanelProps): import("react/jsx-runtime").JSX.Element;
|
|
7
|
+
//# sourceMappingURL=ShellProcessesPanel.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ShellProcessesPanel.d.ts","sourceRoot":"","sources":["../../../../src/web/right-panels/shell-processes/ShellProcessesPanel.tsx"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAGvD,OAAO,uBAAuB,CAAC;AA8B/B,MAAM,WAAW,wBAAyB,SAAQ,SAAS,CAAC,eAAe;IACzE,QAAQ,CAAC,OAAO,EAAE,SAAS,CAAC,cAAc,CAAC,SAAS,CAAC,CAAC;CACvD;AAED,wBAAgB,mBAAmB,CAAC,EAClC,OAAO,EACP,MAAM,EACP,EAAE,wBAAwB,2CA0J1B"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { WebPlugin } from "@hold-rein/plugin-web";
|
|
2
|
+
interface CreateShellProcessesOptions {
|
|
3
|
+
readonly request: WebPlugin.RuntimeContext["request"];
|
|
4
|
+
}
|
|
5
|
+
export declare function createShellProcesses({ request }: CreateShellProcessesOptions): WebPlugin.RightPanel;
|
|
6
|
+
export {};
|
|
7
|
+
//# sourceMappingURL=createShellProcesses.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"createShellProcesses.d.ts","sourceRoot":"","sources":["../../../../src/web/right-panels/shell-processes/createShellProcesses.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAIvD,UAAU,2BAA2B;IACnC,QAAQ,CAAC,OAAO,EAAE,SAAS,CAAC,cAAc,CAAC,SAAS,CAAC,CAAC;CACvD;AAED,wBAAgB,oBAAoB,CAAC,EACnC,OAAO,EACR,EAAE,2BAA2B,GAAG,SAAS,CAAC,UAAU,CAYpD"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/web/right-panels/shell-processes/index.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAC9D,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAC5D,YAAY,EAAE,wBAAwB,EAAE,MAAM,uBAAuB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/web/tools/index.ts"],"names":[],"mappings":"AAAA,cAAc,mBAAmB,CAAA;AACjC,cAAc,aAAa,CAAA"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import Icon from '@ant-design/icons';
|
|
2
|
+
import type { GetProps } from 'antd';
|
|
3
|
+
type CustomIconComponentProps = GetProps<typeof Icon>;
|
|
4
|
+
export default function TerminalIcon(props: Partial<CustomIconComponentProps>): import("react/jsx-runtime").JSX.Element;
|
|
5
|
+
export {};
|
|
6
|
+
//# sourceMappingURL=icon.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"icon.d.ts","sourceRoot":"","sources":["../../../../src/web/tools/shell-exec-tool/icon.tsx"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,mBAAmB,CAAA;AACpC,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,MAAM,CAAA;AAUpC,KAAK,wBAAwB,GAAG,QAAQ,CAAC,OAAO,IAAI,CAAC,CAAC;AAEtD,MAAM,CAAC,OAAO,UAAU,YAAY,CAAC,KAAK,EAAE,OAAO,CAAC,wBAAwB,CAAC,2CAE5E"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { WebPlugin } from '@hold-rein/plugin-web';
|
|
2
|
+
export declare function ShellExecToolRender(props: WebPlugin.ToolRenderProps): import("react/jsx-runtime").JSX.Element;
|
|
3
|
+
export declare const shellExecTool: WebPlugin.ToolRender;
|
|
4
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/web/tools/shell-exec-tool/index.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAA;AAGtD,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,SAAS,CAAC,eAAe,2CAMnE;AAED,eAAO,MAAM,aAAa,EAAE,SAAS,CAAC,UAGrC,CAAA"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { WebPlugin } from '@hold-rein/plugin-web';
|
|
2
|
+
export declare function CallSubagentToolRender(props: WebPlugin.ToolRenderProps): import("react/jsx-runtime").JSX.Element;
|
|
3
|
+
export declare const callSubagentTool: WebPlugin.ToolRender;
|
|
4
|
+
//# sourceMappingURL=call-subagent.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"call-subagent.d.ts","sourceRoot":"","sources":["../../../../src/web/tools/sub-agent/call-subagent.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAA;AAEtD,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,SAAS,CAAC,eAAe,2CAMtE;AAED,eAAO,MAAM,gBAAgB,EAAE,SAAS,CAAC,UAGxC,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/web/tools/sub-agent/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAA;AAClD,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAA"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { WebPlugin } from '@hold-rein/plugin-web';
|
|
2
|
+
export declare function RevokeSubagentToolRender(props: WebPlugin.ToolRenderProps): import("react/jsx-runtime").JSX.Element;
|
|
3
|
+
export declare const revokeSubagentTool: WebPlugin.ToolRender;
|
|
4
|
+
//# sourceMappingURL=revoke-subagent.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"revoke-subagent.d.ts","sourceRoot":"","sources":["../../../../src/web/tools/sub-agent/revoke-subagent.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAA;AAEtD,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,SAAS,CAAC,eAAe,2CAMxE;AAED,eAAO,MAAM,kBAAkB,EAAE,SAAS,CAAC,UAG1C,CAAA"}
|
package/dist/web.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"web.d.ts","sourceRoot":"","sources":["../src/web.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAA;AAStD,QAAA,MAAM,aAAa,EAAE,SAAS,CAAC,MAY9B,CAAA;AAED,eAAe,aAAa,CAAA"}
|
package/dist/web.umd.cjs
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
(function(e,n){typeof exports=="object"&&typeof module<"u"?module.exports=n(require("react/jsx-runtime"),require("@ant-design/icons"),require("antd"),require("react")):typeof define=="function"&&define.amd?define(["react/jsx-runtime","@ant-design/icons","antd","react"],n):(e=typeof globalThis<"u"?globalThis:e||self,e.HoldReinBasePlugin=n(e.jsxRuntime,e.Icon,e.antd,e.react))})(this,(function(e,n,i,u){"use strict";function x(){return e.jsx("svg",{viewBox:"0 0 1024 1024",version:"1.1",xmlns:"http://www.w3.org/2000/svg",width:"1em",height:"1em",fill:"currentColor",children:e.jsx("path",{d:"M810.666667 1024 213.333333 1024c-119.466667 0-213.333333-93.866667-213.333333-213.333333L0 213.333333c0-119.466667 93.866667-213.333333 213.333333-213.333333l597.333333 0c119.466667 0 213.333333 93.866667 213.333333 213.333333l0 597.333333C1024 930.133333 930.133333 1024 810.666667 1024zM213.333333 85.333333C140.8 85.333333 85.333333 140.8 85.333333 213.333333l0 597.333333c0 72.533333 55.466667 128 128 128l597.333333 0c72.533333 0 128-55.466667 128-128L938.666667 213.333333c0-72.533333-55.466667-128-128-128L213.333333 85.333333zM384 426.666667c-12.8 0-21.333333-4.266667-29.866667-12.8l-128-128c-17.066667-17.066667-17.066667-42.666667 0-59.733333s42.666667-17.066667 59.733333 0l128 128c17.066667 17.066667 17.066667 42.666667 0 59.733333C405.333333 422.4 396.8 426.666667 384 426.666667zM256 554.666667c-12.8 0-21.333333-4.266667-29.866667-12.8-17.066667-17.066667-17.066667-42.666667 0-59.733333l128-128c17.066667-17.066667 42.666667-17.066667 59.733333 0s17.066667 42.666667 0 59.733333l-128 128C277.333333 550.4 268.8 554.666667 256 554.666667zM640 554.666667l-170.666667 0c-25.6 0-42.666667-17.066667-42.666667-42.666667s17.066667-42.666667 42.666667-42.666667l170.666667 0c25.6 0 42.666667 17.066667 42.666667 42.666667S665.6 554.666667 640 554.666667z"})})}function E(s){return e.jsx(n,{component:x,...s})}function T(s){return e.jsx(s.DefaultToolRender,{title:"执行命令",icon:e.jsx(E,{}),children:s.renderDefaultChildren()})}const v={Render:T,toolName:"shell_exec"};function N(s){return e.jsx(s.DefaultToolRender,{title:"启动子智能体",icon:e.jsx(n.ToolOutlined,{}),children:s.renderDefaultChildren()})}const y={Render:N,toolName:"call_subagent"};function w(s){return e.jsx(s.DefaultToolRender,{title:"重启子智能体",icon:e.jsx(n.ToolOutlined,{}),children:s.renderDefaultChildren()})}const C={Render:w,toolName:"revoke_subagent"},S="__base__plugin";function m({request:s,taskId:t}){const[o,a]=u.useState([]),[r,c]=u.useState(new Set),[h,p]=u.useState(!1),[A,j]=u.useState(0),[B,b]=u.useState(""),I=u.useCallback(()=>{j(l=>l+1)},[]);u.useEffect(()=>{if(!t){a([]);return}const l=new AbortController;let d=!0;return p(!0),a([]),P(t,l.signal,()=>{d&&p(!1)},f=>{d&&a(G=>_(G,f))}).finally(()=>{d&&p(!1)}),()=>{d=!1,l.abort()}},[A,t]);const $=u.useCallback(async l=>{b(l);try{await s({method:"POST",path:`/plugin/${S}/shells/${l}/kill`})}finally{b("")}},[s]),q=u.useCallback(l=>{c(d=>{const f=new Set(d);return f.has(l)?f.delete(l):f.add(l),f})},[]);return t?e.jsxs("div",{className:"shell-processes-panel",children:[e.jsxs("div",{className:"shell-processes-toolbar",children:[e.jsx("span",{className:"shell-processes-title",children:"Shells"}),e.jsx(i.Tooltip,{title:"Refresh",children:e.jsx(i.Button,{"aria-label":"Refresh shells",icon:e.jsx(n.SyncOutlined,{spin:h}),onClick:()=>{I()},size:"small",type:"text"})})]}),o.length===0?e.jsx("div",{className:"shell-processes-empty",children:e.jsx(i.Empty,{description:"No shell commands",image:i.Empty.PRESENTED_IMAGE_SIMPLE})}):e.jsx("div",{className:"shell-processes-list",children:o.map(l=>{const d=l.status==="running"||r.has(l.id);return e.jsxs("article",{className:"shell-processes-item",children:[e.jsxs("div",{className:"shell-processes-item-header",children:[e.jsxs("button",{"aria-expanded":d,className:"shell-processes-item-title",onClick:()=>{q(l.id)},type:"button",children:[d?e.jsx(n.DownOutlined,{}):e.jsx(n.RightOutlined,{}),e.jsx("code",{className:"shell-processes-command",children:l.command})]}),e.jsxs(i.Space,{size:4,children:[e.jsx(i.Tag,{className:"shell-processes-status",children:l.status}),l.status==="running"?e.jsx(i.Tooltip,{title:"Stop",children:e.jsx(i.Button,{"aria-label":"Stop shell",danger:!0,icon:e.jsx(n.StopOutlined,{}),loading:B===l.id,onClick:()=>{$(l.id)},size:"small",type:"text"})}):null]})]}),d?e.jsxs(e.Fragment,{children:[e.jsx("div",{className:"shell-processes-meta",children:l.cwd}),e.jsx("pre",{className:"shell-processes-output",children:D(l)})]}):null]},l.id)})})]}):e.jsx("div",{className:"shell-processes-empty",children:e.jsx(i.Empty,{description:"No task selected",image:i.Empty.PRESENTED_IMAGE_SIMPLE})})}function D(s){return k(s).trim()||"(no output)"}async function P(s,t,o,a){var r;try{const c=await fetch(M(s),{signal:t}),h=(r=c.body)==null?void 0:r.getReader();if(o(),!c.ok||!h)return;await O(h,t,a)}catch(c){if(!z(c))throw c}}async function O(s,t,o){const a=new TextDecoder;let r="";for(;!t.aborted;){const c=await s.read();if(c.done)break;r+=a.decode(c.value,{stream:!0});const h=r.split(`
|
|
2
|
+
`);r=h.pop()??"";for(const p of h)p.trim()&&o(JSON.parse(p))}}function _(s,t){const o=t.record,a=s.findIndex(r=>r.id===o.id);return g(a===-1?[...s,o]:s.map((r,c)=>c===a?o:r))}function k(s){return[s.stdout,s.stderr].filter(Boolean).join("")}function g(s){return[...s].sort((t,o)=>Date.parse(o.startedAt)-Date.parse(t.startedAt))}function M(s){return`/plugin/${S}/shells?taskId=${encodeURIComponent(s)}`}function z(s){return s instanceof DOMException&&s.name==="AbortError"}function L({request:s}){return{id:"shell-processes",icon:e.jsx(n.CodeOutlined,{"aria-hidden":"true"}),title:"Shell commands",Render:t=>e.jsx(m,{...t,request:s})}}return{id:S,contributionResolver:({request:s})=>({toolRenders:[v,y,C],rightPanels:[L({request:s})]})}}));
|
|
3
|
+
//# sourceMappingURL=web.umd.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"web.umd.cjs","sources":["../src/web/tools/shell-exec-tool/icon.tsx","../src/web/tools/shell-exec-tool/index.tsx","../src/web/tools/sub-agent/call-subagent.tsx","../src/web/tools/sub-agent/revoke-subagent.tsx","../src/plugin-id.ts","../src/web/right-panels/shell-processes/ShellProcessesPanel.tsx","../src/web/right-panels/shell-processes/createShellProcesses.tsx","../src/web.ts"],"sourcesContent":["import Icon from '@ant-design/icons'\nimport type { GetProps } from 'antd'\n\nfunction TerminalSvg() {\n return (\n <svg viewBox=\"0 0 1024 1024\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\" width='1em' height='1em' fill='currentColor'>\n <path d=\"M810.666667 1024 213.333333 1024c-119.466667 0-213.333333-93.866667-213.333333-213.333333L0 213.333333c0-119.466667 93.866667-213.333333 213.333333-213.333333l597.333333 0c119.466667 0 213.333333 93.866667 213.333333 213.333333l0 597.333333C1024 930.133333 930.133333 1024 810.666667 1024zM213.333333 85.333333C140.8 85.333333 85.333333 140.8 85.333333 213.333333l0 597.333333c0 72.533333 55.466667 128 128 128l597.333333 0c72.533333 0 128-55.466667 128-128L938.666667 213.333333c0-72.533333-55.466667-128-128-128L213.333333 85.333333zM384 426.666667c-12.8 0-21.333333-4.266667-29.866667-12.8l-128-128c-17.066667-17.066667-17.066667-42.666667 0-59.733333s42.666667-17.066667 59.733333 0l128 128c17.066667 17.066667 17.066667 42.666667 0 59.733333C405.333333 422.4 396.8 426.666667 384 426.666667zM256 554.666667c-12.8 0-21.333333-4.266667-29.866667-12.8-17.066667-17.066667-17.066667-42.666667 0-59.733333l128-128c17.066667-17.066667 42.666667-17.066667 59.733333 0s17.066667 42.666667 0 59.733333l-128 128C277.333333 550.4 268.8 554.666667 256 554.666667zM640 554.666667l-170.666667 0c-25.6 0-42.666667-17.066667-42.666667-42.666667s17.066667-42.666667 42.666667-42.666667l170.666667 0c25.6 0 42.666667 17.066667 42.666667 42.666667S665.6 554.666667 640 554.666667z\"/>\n </svg>\n )\n}\n\ntype CustomIconComponentProps = GetProps<typeof Icon>;\n\nexport default function TerminalIcon(props: Partial<CustomIconComponentProps>) {\n return <Icon component={TerminalSvg} {...props} />\n}\n","import type { WebPlugin } from '@hold-rein/plugin-web'\nimport TerminalIcon from './icon'\n\nexport function ShellExecToolRender(props: WebPlugin.ToolRenderProps) {\n return (\n <props.DefaultToolRender title='执行命令' icon={<TerminalIcon />}>\n { props.renderDefaultChildren() }\n </props.DefaultToolRender>\n )\n}\n\nexport const shellExecTool: WebPlugin.ToolRender = {\n Render: ShellExecToolRender,\n toolName: 'shell_exec'\n}\n","import { ToolOutlined } from '@ant-design/icons'\nimport type { WebPlugin } from '@hold-rein/plugin-web'\n\nexport function CallSubagentToolRender(props: WebPlugin.ToolRenderProps) {\n return (\n <props.DefaultToolRender title='启动子智能体' icon={<ToolOutlined />}>\n { props.renderDefaultChildren() }\n </props.DefaultToolRender>\n )\n}\n\nexport const callSubagentTool: WebPlugin.ToolRender = {\n Render: CallSubagentToolRender,\n toolName: 'call_subagent'\n}\n","import { ToolOutlined } from '@ant-design/icons'\nimport type { WebPlugin } from '@hold-rein/plugin-web'\n\nexport function RevokeSubagentToolRender(props: WebPlugin.ToolRenderProps) {\n return (\n <props.DefaultToolRender title='重启子智能体' icon={<ToolOutlined />}>\n { props.renderDefaultChildren() }\n </props.DefaultToolRender>\n )\n}\n\nexport const revokeSubagentTool: WebPlugin.ToolRender = {\n Render: RevokeSubagentToolRender,\n toolName: 'revoke_subagent'\n}\n","export const PLUGIN_ID = \"__base__plugin\";\n","import {\n DownOutlined,\n RightOutlined,\n StopOutlined,\n SyncOutlined\n} from \"@ant-design/icons\";\nimport { Button, Empty, Space, Tag, Tooltip } from \"antd\";\nimport { useCallback, useEffect, useState } from \"react\";\nimport type { WebPlugin } from \"@hold-rein/plugin-web\";\nimport { PLUGIN_ID } from '../../../plugin-id'\n\nimport \"./shell-processes.css\";\n\ntype ShellProcessStatus = \"running\" | \"completed\" | \"failed\" | \"killed\";\n\ninterface ShellProcessRecord {\n readonly command: string;\n readonly cwd: string;\n readonly endedAt?: string;\n readonly exitCode?: number;\n readonly id: string;\n readonly startedAt: string;\n readonly status: ShellProcessStatus;\n readonly stderr: string;\n readonly stdout: string;\n readonly taskId?: string;\n readonly toolCallId: string;\n readonly truncated: boolean;\n}\n\ntype ShellProcessEvent =\n | {\n readonly record: ShellProcessRecord;\n readonly type: \"shell_end\" | \"shell_start\";\n }\n | {\n readonly chunk: string;\n readonly record: ShellProcessRecord;\n readonly type: \"shell_stderr\" | \"shell_stdout\";\n };\n\nexport interface ShellProcessesPanelProps extends WebPlugin.RightPanelProps {\n readonly request: WebPlugin.RuntimeContext[\"request\"];\n}\n\nexport function ShellProcessesPanel({\n request,\n taskId\n}: ShellProcessesPanelProps) {\n const [items, setItems] = useState<ShellProcessRecord[]>([]);\n const [expandedIds, setExpandedIds] = useState<ReadonlySet<string>>(new Set());\n const [loading, setLoading] = useState(false);\n const [reconnectIndex, setReconnectIndex] = useState(0);\n const [stoppingId, setStoppingId] = useState<string>(\"\");\n\n const reconnect = useCallback(() => {\n setReconnectIndex((current) => current + 1);\n }, []);\n\n useEffect(() => {\n if (!taskId) {\n setItems([]);\n return undefined;\n }\n\n const controller = new AbortController();\n let active = true;\n\n setLoading(true);\n setItems([]);\n void listenForShells(taskId, controller.signal, () => {\n if (active) {\n setLoading(false);\n }\n }, (event) => {\n if (!active) {\n return;\n }\n\n setItems((current) => applyShellEvent(current, event));\n }).finally(() => {\n if (active) {\n setLoading(false);\n }\n });\n\n return () => {\n active = false;\n controller.abort();\n };\n }, [reconnectIndex, taskId]);\n\n const stopShell = useCallback(\n async (shellId: string) => {\n setStoppingId(shellId);\n try {\n await request({\n method: \"POST\",\n path: `/plugin/${PLUGIN_ID}/shells/${shellId}/kill`\n });\n } finally {\n setStoppingId(\"\");\n }\n },\n [request]\n );\n\n const toggleShell = useCallback((shellId: string) => {\n setExpandedIds((current) => {\n const next = new Set(current);\n\n if (next.has(shellId)) {\n next.delete(shellId);\n } else {\n next.add(shellId);\n }\n\n return next;\n });\n }, []);\n\n if (!taskId) {\n return (\n <div className=\"shell-processes-empty\">\n <Empty description=\"No task selected\" image={Empty.PRESENTED_IMAGE_SIMPLE} />\n </div>\n );\n }\n\n return (\n <div className=\"shell-processes-panel\">\n <div className=\"shell-processes-toolbar\">\n <span className=\"shell-processes-title\">Shells</span>\n <Tooltip title=\"Refresh\">\n <Button\n aria-label=\"Refresh shells\"\n icon={<SyncOutlined spin={loading} />}\n onClick={() => {\n reconnect();\n }}\n size=\"small\"\n type=\"text\"\n />\n </Tooltip>\n </div>\n {items.length === 0 ? (\n <div className=\"shell-processes-empty\">\n <Empty description=\"No shell commands\" image={Empty.PRESENTED_IMAGE_SIMPLE} />\n </div>\n ) : (\n <div className=\"shell-processes-list\">\n {items.map((item) => {\n const isExpanded = item.status === \"running\" || expandedIds.has(item.id);\n\n return (\n <article className=\"shell-processes-item\" key={item.id}>\n <div className=\"shell-processes-item-header\">\n <button\n aria-expanded={isExpanded}\n className=\"shell-processes-item-title\"\n onClick={() => {\n toggleShell(item.id);\n }}\n type=\"button\"\n >\n {isExpanded ? <DownOutlined /> : <RightOutlined />}\n <code className=\"shell-processes-command\">{item.command}</code>\n </button>\n <Space size={4}>\n <Tag className=\"shell-processes-status\">{item.status}</Tag>\n {item.status === \"running\" ? (\n <Tooltip title=\"Stop\">\n <Button\n aria-label=\"Stop shell\"\n danger\n icon={<StopOutlined />}\n loading={stoppingId === item.id}\n onClick={() => {\n void stopShell(item.id);\n }}\n size=\"small\"\n type=\"text\"\n />\n </Tooltip>\n ) : null}\n </Space>\n </div>\n {isExpanded ? (\n <>\n <div className=\"shell-processes-meta\">{item.cwd}</div>\n <pre className=\"shell-processes-output\">\n {formatOutput(item)}\n </pre>\n </>\n ) : null}\n </article>\n );\n })}\n </div>\n )}\n </div>\n );\n}\n\nfunction formatOutput(item: ShellProcessRecord): string {\n const output = createOutputText(item);\n\n return output.trim() || \"(no output)\";\n}\n\nasync function listenForShells(\n taskId: string,\n signal: AbortSignal,\n onOpen: () => void,\n onEvent: (event: ShellProcessEvent) => void\n): Promise<void> {\n try {\n const response = await fetch(createShellStreamUrl(taskId), { signal });\n const reader = response.body?.getReader();\n onOpen();\n\n if (!response.ok || !reader) {\n return;\n }\n\n await readJsonLines(reader, signal, onEvent);\n } catch (error) {\n if (!isAbortError(error)) {\n throw error;\n }\n }\n}\n\nasync function readJsonLines(\n reader: ReadableStreamDefaultReader<Uint8Array>,\n signal: AbortSignal,\n onEvent: (event: ShellProcessEvent) => void\n): Promise<void> {\n const decoder = new TextDecoder();\n let buffer = \"\";\n\n while (!signal.aborted) {\n const result = await reader.read();\n\n if (result.done) {\n break;\n }\n\n buffer += decoder.decode(result.value, { stream: true });\n const lines = buffer.split(\"\\n\");\n buffer = lines.pop() ?? \"\";\n\n for (const line of lines) {\n if (!line.trim()) {\n continue;\n }\n\n onEvent(JSON.parse(line) as ShellProcessEvent);\n }\n }\n}\n\nfunction applyShellEvent(\n current: readonly ShellProcessRecord[],\n event: ShellProcessEvent\n): ShellProcessRecord[] {\n const next = event.record;\n const index = current.findIndex((item) => item.id === next.id);\n\n if (index === -1) {\n return sortShellProcesses([...current, next]);\n }\n\n return sortShellProcesses(\n current.map((item, itemIndex) => itemIndex === index ? next : item)\n );\n}\n\nfunction createOutputText(record: ShellProcessRecord): string {\n return [record.stdout, record.stderr].filter(Boolean).join(\"\");\n}\n\nfunction sortShellProcesses(\n items: readonly ShellProcessRecord[]\n): ShellProcessRecord[] {\n return [...items].sort((left, right) => (\n Date.parse(right.startedAt) - Date.parse(left.startedAt)\n ));\n}\n\nfunction createShellStreamUrl(taskId: string): string {\n return `/plugin/${PLUGIN_ID}/shells?taskId=${encodeURIComponent(taskId)}`;\n}\n\nfunction isAbortError(error: unknown): boolean {\n return error instanceof DOMException && error.name === \"AbortError\";\n}\n","import { CodeOutlined } from \"@ant-design/icons\";\nimport type { WebPlugin } from \"@hold-rein/plugin-web\";\n\nimport { ShellProcessesPanel } from \"./ShellProcessesPanel\";\n\ninterface CreateShellProcessesOptions {\n readonly request: WebPlugin.RuntimeContext[\"request\"];\n}\n\nexport function createShellProcesses({\n request\n}: CreateShellProcessesOptions): WebPlugin.RightPanel {\n return {\n id: \"shell-processes\",\n icon: <CodeOutlined aria-hidden=\"true\" />,\n title: \"Shell commands\",\n Render: (props) => (\n <ShellProcessesPanel\n {...props}\n request={request}\n />\n )\n };\n}\n","import type { WebPlugin } from '@hold-rein/plugin-web'\nimport {\n shellExecTool,\n callSubagentTool,\n revokeSubagentTool\n} from './web/tools'\nimport { createShellProcesses } from './web/right-panels'\nimport { PLUGIN_ID } from \"./plugin-id\";\n\nconst baseWebPlugin: WebPlugin.Plugin = {\n id: PLUGIN_ID,\n contributionResolver: ({ request }) => ({\n toolRenders: [\n shellExecTool,\n callSubagentTool,\n revokeSubagentTool\n ],\n rightPanels: [\n createShellProcesses({ request })\n ]\n })\n}\n\nexport default baseWebPlugin\n"],"names":["TerminalSvg","TerminalIcon","props","jsx","Icon","ShellExecToolRender","shellExecTool","CallSubagentToolRender","ToolOutlined","callSubagentTool","RevokeSubagentToolRender","revokeSubagentTool","PLUGIN_ID","ShellProcessesPanel","request","taskId","items","setItems","useState","expandedIds","setExpandedIds","loading","setLoading","reconnectIndex","setReconnectIndex","stoppingId","setStoppingId","reconnect","useCallback","current","useEffect","controller","active","listenForShells","event","applyShellEvent","stopShell","shellId","toggleShell","next","jsxs","Tooltip","Button","SyncOutlined","Empty","item","isExpanded","DownOutlined","RightOutlined","Space","Tag","StopOutlined","Fragment","formatOutput","createOutputText","signal","onOpen","onEvent","response","createShellStreamUrl","reader","_a","readJsonLines","error","isAbortError","decoder","buffer","result","lines","line","index","sortShellProcesses","itemIndex","record","left","right","createShellProcesses","CodeOutlined"],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@hold-rein/plugins-base",
|
|
3
|
+
"version": "0.0.0",
|
|
4
|
+
"private": false,
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/server.cjs",
|
|
7
|
+
"module": "./dist/server.js",
|
|
8
|
+
"types": "./dist/server.d.ts",
|
|
9
|
+
"exports": {
|
|
10
|
+
"./server": {
|
|
11
|
+
"types": "./dist/server.d.ts",
|
|
12
|
+
"import": "./dist/server.js",
|
|
13
|
+
"require": "./dist/server.cjs"
|
|
14
|
+
},
|
|
15
|
+
"./web": {
|
|
16
|
+
"types": "./dist/web.d.ts",
|
|
17
|
+
"style": "./dist/style.css",
|
|
18
|
+
"default": "./dist/web.umd.cjs",
|
|
19
|
+
"require": "./dist/web.umd.cjs"
|
|
20
|
+
}
|
|
21
|
+
},
|
|
22
|
+
"files": [
|
|
23
|
+
"dist"
|
|
24
|
+
],
|
|
25
|
+
"publishConfig": {
|
|
26
|
+
"access": "public"
|
|
27
|
+
},
|
|
28
|
+
"peerDependencies": {
|
|
29
|
+
"@earendil-works/pi-agent-core": "0.75.4",
|
|
30
|
+
"@earendil-works/pi-ai": "0.76.0",
|
|
31
|
+
"express": "5.2.1",
|
|
32
|
+
"@ant-design/icons": "6.2.5",
|
|
33
|
+
"@monaco-editor/react": "4.7.0",
|
|
34
|
+
"antd": "6.4.3",
|
|
35
|
+
"monaco-editor": "0.55.1",
|
|
36
|
+
"react": "19.2.6",
|
|
37
|
+
"react-dom": "19.2.6",
|
|
38
|
+
"@hold-rein/plugin-server": "^0.0.0",
|
|
39
|
+
"@hold-rein/plugin-web": "^0.0.0"
|
|
40
|
+
},
|
|
41
|
+
"devDependencies": {
|
|
42
|
+
"@earendil-works/pi-agent-core": "0.75.4",
|
|
43
|
+
"@earendil-works/pi-ai": "0.76.0",
|
|
44
|
+
"express": "5.2.1",
|
|
45
|
+
"vite": "6.3.5",
|
|
46
|
+
"@ant-design/icons": "6.2.5",
|
|
47
|
+
"@monaco-editor/react": "4.7.0",
|
|
48
|
+
"@types/react": "19.2.15",
|
|
49
|
+
"antd": "6.4.3",
|
|
50
|
+
"monaco-editor": "0.55.1",
|
|
51
|
+
"react": "19.2.6",
|
|
52
|
+
"react-dom": "19.2.6",
|
|
53
|
+
"@hold-rein/plugin-web": "^0.0.0",
|
|
54
|
+
"@hold-rein/plugin-server": "^0.0.0"
|
|
55
|
+
},
|
|
56
|
+
"scripts": {
|
|
57
|
+
"build": "vite build --config vite.config.ts && vite build --config vite.web.config.ts && tsc -p tsconfig.json --emitDeclarationOnly",
|
|
58
|
+
"typecheck": "tsc -p tsconfig.json --noEmit"
|
|
59
|
+
}
|
|
60
|
+
}
|