@myagentroam/node 0.9.62 → 0.9.65
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/LICENSE +202 -0
- package/NOTICE +4 -0
- package/dist/capabilities.js +110 -2
- package/dist/claude-agent-sdk.js +330 -2
- package/dist/claude-channel.js +44 -2
- package/dist/codex-app-server.js +510 -2
- package/dist/config.js +106 -2
- package/dist/connector/node-connector-options.js +1 -2
- package/dist/connector/node-operation-router.js +22 -2
- package/dist/connector.js +1736 -2
- package/dist/control-outbound-scheduler.js +153 -2
- package/dist/database.js +639 -2
- package/dist/fake-runner.js +129 -2
- package/dist/git-askpass.js +12 -0
- package/dist/git-execution-helper.js +266 -0
- package/dist/health.js +3 -2
- package/dist/main.js +57 -2
- package/dist/mcp-installation-model.js +1 -2
- package/dist/migrations/v004.js +55 -3
- package/dist/migrations/v005.js +13 -3
- package/dist/migrations/v006.js +90 -3
- package/dist/migrations/v007.js +22 -3
- package/dist/migrations/v008.js +18 -3
- package/dist/migrations/v009.js +70 -4
- package/dist/migrations/v010.js +43 -3
- package/dist/migrations/v011.js +20 -3
- package/dist/migrations/v012.js +8 -0
- package/dist/native-jsonl-reader.js +186 -2
- package/dist/native-session-history.js +1143 -2
- package/dist/opencode-runtime.js +80 -2
- package/dist/opencode-server.js +259 -2
- package/dist/operational.js +122 -2
- package/dist/process-tree.js +18 -2
- package/dist/ripgrep-binary.js +31 -2
- package/dist/rotating-log.js +67 -2
- package/dist/runner/abstract-runner.js +260 -2
- package/dist/runner/claude/managed-run-controller.js +355 -2
- package/dist/runner/claude/tool-normalizer.js +120 -2
- package/dist/runner/claude-code-runner.js +303 -2
- package/dist/runner/codex/composer-image-markers.js +8 -2
- package/dist/runner/codex/conversation-parser.js +913 -2
- package/dist/runner/codex/managed-run-controller.js +494 -2
- package/dist/runner/codex/tool-normalizer.js +214 -2
- package/dist/runner/codex-runner.js +585 -2
- package/dist/runner/fake-test-runner.js +47 -2
- package/dist/runner/mar-agent/conversation-normalizer.js +644 -2
- package/dist/runner/mar-agent/executor-stdio-client-transport.js +139 -2
- package/dist/runner/mar-agent/generated-images.js +41 -2
- package/dist/runner/mar-agent/history-projection.js +106 -2
- package/dist/runner/mar-agent/hosted-conversation-runtime.js +446 -2
- package/dist/runner/mar-agent/managed-run-controller.js +785 -2
- package/dist/runner/mar-agent/mcp-client-pool.js +233 -2
- package/dist/runner/mar-agent/runtime-model-factory.js +326 -2
- package/dist/runner/mar-agent-runner.js +458 -2
- package/dist/runner/opencode/conversation-parser.js +221 -2
- package/dist/runner/opencode/managed-run-controller.js +588 -2
- package/dist/runner/opencode/tool-normalizer.js +80 -2
- package/dist/runner/opencode-runner.js +426 -2
- package/dist/runner/runner-registry.js +87 -2
- package/dist/runner-command-engine.js +71 -2
- package/dist/runner-profiles.js +323 -2
- package/dist/runner-usage.js +190 -2
- package/dist/runtime-command-detector.js +73 -2
- package/dist/runtime-model.js +1 -2
- package/dist/runtime-state.js +1509 -2
- package/dist/service/attachment-domain-state.js +7 -2
- package/dist/service/bubblewrap-sandbox-executor.js +543 -2
- package/dist/service/continuous-run-coordinator.js +425 -2
- package/dist/service/conversation-history-service.js +552 -2
- package/dist/service/conversation-hosting-capability-service.js +61 -2
- package/dist/service/conversation-hosting-enablement-service.js +91 -2
- package/dist/service/conversation-hosting-maintenance-service.js +174 -2
- package/dist/service/conversation-segment-service.js +162 -2
- package/dist/service/conversation-template-node-service.js +992 -2
- package/dist/service/external-session-resume-service.js +152 -2
- package/dist/service/fake-managed-run-service.js +60 -2
- package/dist/service/git-execution-service.js +418 -0
- package/dist/service/git-operation-service.js +57 -0
- package/dist/service/hosted-conversation-node-service.js +1982 -2
- package/dist/service/hosted-conversation-store.js +1405 -2
- package/dist/service/managed-runner-session-service.js +35 -2
- package/dist/service/mar-agent-model-transport-test-service.js +88 -2
- package/dist/service/mcp-installation-verifier.js +87 -2
- package/dist/service/mcp-node-operation-service.js +90 -2
- package/dist/service/mission-mcp-server.js +124 -2
- package/dist/service/mission-mcp-stdio.js +40 -2
- package/dist/service/mission-runtime.js +142 -2
- package/dist/service/native-session-projection-service.js +274 -2
- package/dist/service/native-session-watch-service.js +683 -2
- package/dist/service/node-connection-lifecycle-service.js +88 -2
- package/dist/service/node-control-channel.js +85 -2
- package/dist/service/node-control-message-service.js +109 -2
- package/dist/service/node-request-service.js +62 -2
- package/dist/service/node-run-event-bridge.js +88 -2
- package/dist/service/node-terminal-channel.js +202 -2
- package/dist/service/node-upgrade-coordinator.js +137 -2
- package/dist/service/node-workspace-coordinator.js +97 -2
- package/dist/service/recent-run-projection-service.js +99 -2
- package/dist/service/run-attachment-service.js +321 -2
- package/dist/service/run-domain-state.js +4 -2
- package/dist/service/run-event-service.js +246 -2
- package/dist/service/run-ownership-policy.js +22 -2
- package/dist/service/run-workbench-service.js +120 -2
- package/dist/service/runner-channel-message-service.js +20 -2
- package/dist/service/runner-interaction-service.js +243 -2
- package/dist/service/runner-service.js +69 -2
- package/dist/service/runtime-credential-control-service.js +95 -2
- package/dist/service/session-catalog-service.js +404 -2
- package/dist/service/session-command-service.js +125 -2
- package/dist/service/session-context-service.js +128 -2
- package/dist/service/session-domain-state.js +9 -2
- package/dist/service/session-identity-service.js +86 -2
- package/dist/service/session-lifecycle-service.js +248 -2
- package/dist/service/session-message-service.js +270 -2
- package/dist/service/session-presentation-service.js +43 -2
- package/dist/service/session-query-service.js +82 -2
- package/dist/service/session-watch-slot-coordinator.js +21 -2
- package/dist/service/skill-directory-service.js +238 -2
- package/dist/service/skill-install-service.js +434 -2
- package/dist/service/skill-node-operation-service.js +206 -2
- package/dist/service/terminal-relay-state.js +3 -2
- package/dist/service/terminal-service.js +90 -2
- package/dist/service/web-search-error.js +40 -2
- package/dist/service/workbench-event-service.js +21 -2
- package/dist/service/workbench-manifest-service.js +69 -2
- package/dist/service/workspace-change-service.js +290 -2
- package/dist/service/workspace-content-search-service.js +457 -2
- package/dist/service/workspace-domain-state.js +41 -2
- package/dist/service/workspace-file-service.js +150 -2
- package/dist/service/workspace-git-exclude-service.js +119 -2
- package/dist/service/workspace-queue-workbench-service.js +176 -2
- package/dist/service/workspace-service.js +92 -2
- package/dist/service/workspace-session-service.js +154 -2
- package/dist/service/workspace-upload-service.js +262 -2
- package/dist/service/workspace-watch-controller.js +68 -2
- package/dist/service/workspace-watch-service.js +170 -2
- package/dist/service/workspace-watch-snapshot-service.js +218 -2
- package/dist/service/workspace-workbench-service.js +239 -2
- package/dist/service.js +91 -2
- package/dist/storage.js +32 -2
- package/dist/supervisor.js +136 -2
- package/dist/terminal.js +496 -2
- package/dist/util/git-credential-client.js +32 -0
- package/dist/util/node-operation-data.js +9 -2
- package/dist/util/node-operation-parsers.js +382 -2
- package/dist/util/personal-instructions.js +34 -2
- package/dist/util/runner-error.js +70 -2
- package/dist/util/runner-native-session-parsers.js +510 -2
- package/dist/util/safe-error.js +8 -2
- package/dist/util/secret-environment.js +25 -2
- package/dist/workspace.js +1793 -2
- package/package.json +11 -8
- package/vendor/ripgrep/darwin-arm64/rg +0 -0
- package/vendor/ripgrep/darwin-x64/rg +0 -0
- package/vendor/ripgrep/manifest.json +12 -0
- package/README.md +0 -42
- package/dist/event-buffer.js +0 -2
- package/dist/migrations/v001.js +0 -107
- package/dist/migrations/v002.js +0 -2
- package/dist/migrations/v003.js +0 -2
- package/dist/service/mcp-package-installer.js +0 -2
|
@@ -1,2 +1,206 @@
|
|
|
1
|
-
|
|
2
|
-
function _0x26e0(){const _0x2a908f=['zNjVBq','CMvWBgfJzq','Aw5ZDgfSBa','mJy4nJzHBgPIsNu','u0TjteXFq09ovevovf9jtLzbteLe','u0TjteXFvefsr0vux0XjtuLux0vyq0vfreve','zMLSzxm','C3rHDhvZ','mJy0Egr2wNne','zxHWAxjLC0f0','z2v0v29YA3nWywnL','v09ss1nqqunf','BgvUz3rO','zgvSzxrL','u0TjteWUBwq','DxbKyxrL','CMvWywLYv29YA3nWywnLr2L0rxHJBhvKzq','otbcs2PSBxK','D29YA3nWywnL','BM93','mLjhuK13qW','otiXmZK2nMHjtwrNrG','zgLYzwn0B3jPzxm','D29YA3nWywnLswq','C2v0','AgfZ','yMfZzty0','CMvJB3zLCK5VzgviB21L','C2vYDMvYvxjS','BM9KzuLK','B3bLCMf0Aw9UCW','AxnbCNjHEq','DgfYz2v0','y29UDgvUDejHC2u2na','Aw5ZDgfSBfDVCMTZCgfJzq','Bwv0ywrHDge','C2nOzw1HvMvYC2LVBG','ntiYnZHcChrtA04','u0TjteXFtKfnrv9dt05gteLdva','y29UzMLYBvrYywnRzwq','l2fWAs9ZA2LSBc1HCNrPzMfJDhmV','C2HHmJu2','zg93BMXVywq','rKfjteve','lM1HCI1ZA2LSBc1PBNn0ywXSlMPZB24','CMvTB3zLtM9KzuHVBwu','v09ss1nqqunfx0LovKfmsuq','B2jQzwn0','y29UzMLN','uLvotKLorW','Aw5ZDgfSBePVyKLK','Aw5ZDgfSBe5VzgviB21L','CgvYzM9YBuLUC3rHBgW','z2v0','C2L6zq','v09ss1nqqunfx1nlsuXmx1rsqunlrurFq09orKLstv9srvfvsvjfra','Aw5ZCgvJDfDVCMTZCgfJzq','zgf0ywjHC2u','Aw5ZCgvJDe5VzgviB21L','A2v5CW','tuvtu0fhrv9jtLzbteLe','CMvTB3zL','DMfSDwu','Agv4','BMfTzq','CMvTB3zLv29YA3nWywnL','tK9erq','mtqZndGYmJn4uuXcBKG','BwfW','nJy3ody1shz4txjR','AM9ICW','qMvHCMvYia','AM9I','AM9PBG','tK9erv9vtKfvveHftLrjq0furuq','zgLNzxn0','nZGWmti4DwfKtvP4','D29YA3nWywnLugf0Aa','BMv4Da','y3jLzgvUDgLHBa','DgLTzw91Da','Aw5ZDgfSBgvY','ywn0AxzLvgfYz2v0CW','u0TjteXFsu5tvefmtf9gquLmruq','CgfYC2u','Aw5JBhvKzunSyxvKzunVBxbHDgLIAwXPDhK','C3rYAw5N','ANnVBG','yxj0AwzHy3ruAwnRzxq','CMvJB3zLCLDVCMTZCgfJzq','v09ss1nqqunfx0jvu1K','Cgf0Aa','y29UDgvUDeHHC2G','DgLJA2v0','Dg9tDhjPBMC','zxjYB3jdB2rL','ywrK','nZzAtxryBLe','y2XLyw51CePVyNm','mJC3ntmZnu5Uyu1wra','u1vdq0vfreve'];_0x26e0=function(){return _0x2a908f;};return _0x26e0();}const _0x527373=_0x291c;(function(_0x485372,_0x35b843){const _0x5e1a82=_0x291c,_0x3dad64=_0x485372();while(!![]){try{const _0x4f6bf6=parseInt(_0x5e1a82(0xca))/(0x5d+-0xb9*-0xb+-0x84f)*(-parseInt(_0x5e1a82(0x92))/(-0x3*0x773+-0x1*-0x1efe+-0x8a3))+parseInt(_0x5e1a82(0xa3))/(-0x2d*0x50+0x140+-0x1*-0xcd3)*(parseInt(_0x5e1a82(0xdf))/(0x289*0x8+0x1df4+-0x3238))+parseInt(_0x5e1a82(0xe1))/(0x9*-0x109+0x1073+-0x71d)+-parseInt(_0x5e1a82(0x93))/(0x84*-0x10+-0xf*0xc9+0x140d)+parseInt(_0x5e1a82(0x81))/(0x151c+-0x252d*-0x1+-0x3a42)*(parseInt(_0x5e1a82(0x86))/(0x1d3*-0x9+-0xf73+0x1*0x1fe6))+parseInt(_0x5e1a82(0xc1))/(0x959*0x4+-0x1040+0x151b*-0x1)+-parseInt(_0x5e1a82(0x8f))/(-0x2f9+0x89*-0x29+0x18f4)*(-parseInt(_0x5e1a82(0xc3))/(-0x16aa+-0x33f+0x19f4));if(_0x4f6bf6===_0x35b843)break;else _0x3dad64['push'](_0x3dad64['shift']());}catch(_0x275cde){_0x3dad64['push'](_0x3dad64['shift']());}}}(_0x26e0,-0x2*-0x745df+0x12bd06+-0x148078));import{homedir}from'node:os';import{createHash,randomUUID}from'node:crypto';function _0x291c(_0x124cfa,_0x3fad68){_0x124cfa=_0x124cfa-(-0x1f7d+0x4a2+0x1b59*0x1);const _0x351c2f=_0x26e0();let _0x4f32e4=_0x351c2f[_0x124cfa];if(_0x291c['IAYqbB']===undefined){var _0xc7bc39=function(_0x52cd0c){const _0x286fe4='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/=';let _0x56be64='',_0x3d9c4a='';for(let _0x4dfc5c=-0xaa*-0x23+0x3*0x70b+-0x2c5f,_0x326281,_0x425de5,_0x31bc33=0x1c79*-0x1+0x465+-0x17*-0x10c;_0x425de5=_0x52cd0c['charAt'](_0x31bc33++);~_0x425de5&&(_0x326281=_0x4dfc5c%(-0xe9*-0x25+-0x8d1*-0x2+0x334b*-0x1)?_0x326281*(0x536+0x20*-0xa7+-0x123*-0xe)+_0x425de5:_0x425de5,_0x4dfc5c++%(-0x860+-0x423+0xc87*0x1))?_0x56be64+=String['fromCharCode'](0x23e4+-0x1*0x2413+-0x2*-0x97&_0x326281>>(-(0x7a6*0x2+-0x1*-0x26ed+-0x3637)*_0x4dfc5c&0x23d*-0x7+0x25fd+0x593*-0x4)):-0x7d*-0x1+0x1f5+-0x272){_0x425de5=_0x286fe4['indexOf'](_0x425de5);}for(let _0x1270d8=0x10c5+0xcd6*0x2+0x35*-0xcd,_0x51b2f1=_0x56be64['length'];_0x1270d8<_0x51b2f1;_0x1270d8++){_0x3d9c4a+='%'+('00'+_0x56be64['charCodeAt'](_0x1270d8)['toString'](-0x28*-0x36+0x11d8+0x68e*-0x4))['slice'](-(0xa*0x15b+-0x1127+0x39b));}return decodeURIComponent(_0x3d9c4a);};_0x291c['DNdSag']=_0xc7bc39,_0x291c['xgkLtJ']={},_0x291c['IAYqbB']=!![];}const _0x414e83=_0x351c2f[0x1738+0x1c85+-0x33bd*0x1];_0x291c['fmvIvR']!==_0x414e83&&(_0x291c['xgkLtJ']={},_0x291c['fmvIvR']=_0x414e83);const _0x3fe1ea=_0x291c['xgkLtJ'][_0x124cfa];return _0x3fe1ea===undefined?(_0x4f32e4=_0x291c['DNdSag'](_0x4f32e4),_0x291c['xgkLtJ'][_0x124cfa]=_0x4f32e4):_0x4f32e4=_0x3fe1ea,_0x4f32e4;}import{skillInstallMetadataSchema}from'@myagentroam/protocol';import{SkillDirectoryService}from'./skill-directory-service.js';import{SkillInstallService,workspaceSkillTracked}from'./skill-install-service.js';import{safeErrorCode}from'../util/safe-error.js';export class SkillNodeOperationService{[_0x527373(0xb7)];[_0x527373(0xae)];[_0x527373(0x94)]=new SkillDirectoryService();[_0x527373(0xcf)]=new SkillInstallService();[_0x527373(0xd0)]=new Set();[_0x527373(0xc4)]=new Map();constructor(_0x10e4bb,_0x1777ae){const _0x2c4086=_0x527373;this[_0x2c4086(0xb7)]=_0x10e4bb,this[_0x2c4086(0xae)]=_0x1777ae;}[_0x527373(0x9c)](){const _0x1d7fe5=_0x527373;return{'node.skills.inspect':async _0x44bd26=>{const _0x175e81=_0x291c;return await this[_0x175e81(0xcf)][_0x175e81(0x99)](homedir()),this[_0x175e81(0x94)][_0x175e81(0xb8)](homedir(),{'includeClaudeCompatibility':record(_0x44bd26)[_0x175e81(0xd3)]===!![]});},'node.skills.install':_0x5db278=>this[_0x1d7fe5(0x80)](_0x1d7fe5(0xc0),_0x5db278),'node.skills.remove':_0x156a08=>this[_0x1d7fe5(0xbb)](_0x1d7fe5(0xc0),_0x156a08),'workspace.skills.inspect':async _0x4c82a1=>{const _0x491d44=_0x1d7fe5,_0x39f848=this[_0x491d44(0xcb)](record(_0x4c82a1)[_0x491d44(0x95)]);return await this[_0x491d44(0xcf)][_0x491d44(0xd7)](_0x39f848),this[_0x491d44(0x94)][_0x491d44(0xb6)](_0x39f848);},'workspace.skills.install':_0x16746a=>this[_0x1d7fe5(0x80)](_0x1d7fe5(0x89),_0x16746a),'workspace.skills.remove':_0x401715=>this[_0x1d7fe5(0xbb)](_0x1d7fe5(0x89),_0x401715),'workspace.skills.git-exclude-repair':async _0x77601b=>{const _0x2b33d7=_0x1d7fe5,_0x1b1320=this[_0x2b33d7(0xcb)](record(_0x77601b)[_0x2b33d7(0x95)]);return await this[_0x2b33d7(0xcf)][_0x2b33d7(0xd7)](_0x1b1320),await this[_0x2b33d7(0xcf)][_0x2b33d7(0x8e)](_0x1b1320),{'repaired':!![]};},'skill.install.job.get':_0x536f16=>this[_0x1d7fe5(0xc6)](_0x536f16)};}async[_0x527373(0x80)](_0x29fb1a,_0x5cfd07){const _0x471520=_0x527373,_0x2878df=record(_0x5cfd07),_0x33a50f=text(_0x2878df[_0x471520(0xbe)],_0x471520(0xa4)),_0x3b33e8=text(_0x2878df[_0x471520(0xd6)],_0x471520(0xd1)),_0xc7ed42=skillInstallMetadataSchema[_0x471520(0xd2)](_0x2878df[_0x471520(0xa1)]),_0x381506=_0x29fb1a===_0x471520(0x89)?this[_0x471520(0xcb)](_0x2878df[_0x471520(0x95)]):undefined;if(_0x381506===undefined)await this[_0x471520(0xcf)][_0x471520(0x99)](homedir());else await this[_0x471520(0xcf)][_0x471520(0xd7)](_0x381506);if(_0x381506!==undefined&&_0x2878df[_0x471520(0xa5)]!==!![]&&await workspaceSkillTracked(_0x381506,_0x33a50f))throw new Error(_0x471520(0xb5));const _0x32fc02=_0x29fb1a+':'+(_0x381506??homedir());this[_0x471520(0xe0)]();if(this[_0x471520(0xd0)][_0x471520(0x97)](_0x32fc02))throw new Error(_0x471520(0xd8));if(this[_0x471520(0xd0)][_0x471520(0xb4)]>=0x208a+0x6f3+0x1df*-0x15)throw new Error(_0x471520(0x83));const _0x5844bc=randomUUID();return this[_0x471520(0xd0)][_0x471520(0xde)](_0x32fc02),this[_0x471520(0xc4)][_0x471520(0x96)](_0x5844bc,{'status':_0x471520(0xaf),'expiresAt':Date[_0x471520(0x91)]()+(-0x1*-0x1db7+0x9*-0x3ad+-0x121*-0x3)*(0x1acb*0x1+-0x16307*0x1+0x2329c)}),void((async()=>{const _0x51f677=_0x471520;let _0x5d69f7;try{await this[_0x51f677(0xb2)]({'target':_0x29fb1a,'name':_0x33a50f,'ticket':_0x3b33e8,'metadata':_0xc7ed42,..._0x381506===undefined?{}:{'workspace':_0x381506}}),_0x5d69f7={'status':_0x51f677(0xe2)};}catch(_0x301a2a){_0x5d69f7={'status':_0x51f677(0xa9),'errorCode':safeErrorCode(_0x301a2a,_0x51f677(0xd1))};}this[_0x51f677(0xd0)][_0x51f677(0x8b)](_0x32fc02),this[_0x51f677(0xc4)][_0x51f677(0x96)](_0x5844bc,{..._0x5d69f7,'expiresAt':Date[_0x51f677(0x91)]()+(-0x35*-0x11+0x1095+-0x1415)*(0x18f8*-0x3+-0x10fa3*0x1+0x244eb)});})()),{'accepted':!![],'installJobId':_0x5844bc};}[_0x527373(0xc6)](_0x4b4ae4){const _0x1461d4=_0x527373,_0x233e98=text(record(_0x4b4ae4)[_0x1461d4(0xb0)],_0x1461d4(0xba));this[_0x1461d4(0xe0)]();const _0x32a7fb=this[_0x1461d4(0xc4)][_0x1461d4(0xb3)](_0x233e98);if(_0x32a7fb===undefined)throw new Error(_0x1461d4(0xd1));return{'installJobId':_0x233e98,'status':_0x32a7fb[_0x1461d4(0x85)],..._0x32a7fb[_0x1461d4(0xdd)]===undefined?{}:{'errorCode':_0x32a7fb[_0x1461d4(0xdd)]}};}[_0x527373(0xe0)](){const _0x2fe235=_0x527373,_0x5d20db=Date[_0x2fe235(0x91)]();for(const [_0x134aea,_0x47bab2]of this[_0x2fe235(0xc4)])if(_0x47bab2[_0x2fe235(0x87)]<_0x5d20db)this[_0x2fe235(0xc4)][_0x2fe235(0x8b)](_0x134aea);while(this[_0x2fe235(0xc4)][_0x2fe235(0xb4)]>-0x2*-0xacf+0x28a*-0x1+0xf2c*-0x1)this[_0x2fe235(0xc4)][_0x2fe235(0x8b)](this[_0x2fe235(0xc4)][_0x2fe235(0xb9)]()[_0x2fe235(0xcc)]()[_0x2fe235(0xbc)]);}async[_0x527373(0xb2)](_0x522391){const _0x3bee44=_0x527373,_0x1a9893=await this[_0x3bee44(0xa8)](_0x522391[_0x3bee44(0xdb)],_0x522391[_0x3bee44(0xa1)][_0x3bee44(0xda)]);if(_0x522391[_0x3bee44(0x9e)]===_0x3bee44(0xc0))await this[_0x3bee44(0xcf)][_0x3bee44(0xb1)](homedir(),_0x522391[_0x3bee44(0xbe)],_0x1a9893,_0x522391[_0x3bee44(0xa1)]);else await this[_0x3bee44(0xcf)][_0x3bee44(0xa0)](_0x522391[_0x3bee44(0x90)],_0x522391[_0x3bee44(0xbe)],_0x1a9893,_0x522391[_0x3bee44(0xa1)],{'confirmTracked':!![]});}async[_0x527373(0xbb)](_0x23cc4c,_0x20753b){const _0x229998=_0x527373,_0x471768=record(_0x20753b),_0x352b8f=text(_0x471768[_0x229998(0xbe)],_0x229998(0xa4)),_0x1187c5=_0x23cc4c===_0x229998(0x89)?this[_0x229998(0xcb)](_0x471768[_0x229998(0x95)]):undefined,_0x48999a=_0x23cc4c+':'+(_0x1187c5??homedir());if(this[_0x229998(0xd0)][_0x229998(0x97)](_0x48999a))throw new Error(_0x229998(0xd8));this[_0x229998(0xd0)][_0x229998(0xde)](_0x48999a);try{_0x23cc4c===_0x229998(0xc0)?(await this[_0x229998(0xcf)][_0x229998(0x99)](homedir()),await this[_0x229998(0xcf)][_0x229998(0xab)](homedir(),_0x352b8f)):(await this[_0x229998(0xcf)][_0x229998(0xd7)](_0x1187c5),await this[_0x229998(0xcf)][_0x229998(0xbf)](_0x1187c5,_0x352b8f));}finally{this[_0x229998(0xd0)][_0x229998(0x8b)](_0x48999a);}return{'removed':!![]};}[_0x527373(0xcb)](_0x451756){const _0x5232a0=_0x527373,_0x595040=this[_0x5232a0(0xb7)]()[_0x5232a0(0x88)](text(_0x451756,_0x5232a0(0xac)));if(_0x595040===undefined)throw new Error(_0x5232a0(0xac));return _0x595040[_0x5232a0(0xd9)];}async[_0x527373(0xa8)](_0x1867f3,_0x3b43c3){const _0x4919a8=_0x527373,_0x3be75f=this[_0x4919a8(0xae)]();if(_0x3be75f[_0x4919a8(0x9b)]===undefined||_0x3be75f[_0x4919a8(0xcd)]===undefined)throw new Error(_0x4919a8(0xc8));const _0x71587a=await fetch(_0x3be75f[_0x4919a8(0x9a)][_0x4919a8(0x7f)](/\/$/u,'')+_0x4919a8(0xa6)+encodeURIComponent(_0x1867f3),{'headers':{'x-mar-node-id':_0x3be75f[_0x4919a8(0x9b)],'authorization':_0x4919a8(0xc5)+_0x3be75f[_0x4919a8(0xcd)]},'signal':AbortSignal[_0x4919a8(0xce)](0x13c6f+-0x6790+0x5*0x44d)});if(!_0x71587a['ok'])throw new Error(_0x4919a8(0xd1));const _0x5998b8=await _0x71587a[_0x4919a8(0xd5)]();return validateBundle(_0x5998b8,_0x3b43c3),_0x5998b8;}}function validateBundle(_0x3ab970,_0x2dfb95){const _0x3d857c=_0x527373;if(_0x3ab970===null||typeof _0x3ab970!==_0x3d857c(0xad)||_0x3ab970[_0x3d857c(0xa2)]!==0x8a*0x33+0x1*-0x26e7+-0xb6a*-0x1||!Array[_0x3d857c(0x9d)](_0x3ab970[_0x3d857c(0x84)])||_0x3ab970[_0x3d857c(0x84)][_0x3d857c(0x8a)]<0x1327*-0x2+-0x1163+0x37b2*0x1||_0x3ab970[_0x3d857c(0x84)][_0x3d857c(0x8a)]>0x2b*0x45+-0x32*-0x5f+-0x1a3d)throw new Error(_0x3d857c(0x82));let _0x1cba6f=-0x7*-0x3a1+0x41*0x6d+-0x3514;const _0x54ca07=new Set();for(const _0x37fefc of _0x3ab970[_0x3d857c(0x84)]){if(_0x37fefc===null||typeof _0x37fefc!==_0x3d857c(0xad)||typeof _0x37fefc[_0x3d857c(0xd9)]!==_0x3d857c(0xd4)||typeof _0x37fefc[_0x3d857c(0x9f)]!==_0x3d857c(0xd4)||_0x54ca07[_0x3d857c(0x97)](_0x37fefc[_0x3d857c(0xd9)]))throw new Error(_0x3d857c(0x82));_0x54ca07[_0x3d857c(0xde)](_0x37fefc[_0x3d857c(0xd9)]);const _0x24201f=Buffer[_0x3d857c(0x7e)](_0x37fefc[_0x3d857c(0x9f)],_0x3d857c(0x98));if(_0x24201f[_0x3d857c(0xdc)](_0x3d857c(0x98))!==_0x37fefc[_0x3d857c(0x9f)]||_0x24201f[_0x3d857c(0x8a)]>(-0xf*0xf9+0x1738+-0x44e*0x2)*(-0x1814+-0x102*-0xd+0xefa)*(0xd45+0x5*0x5c1+0x1*-0x260a))throw new Error(_0x3d857c(0x82));_0x1cba6f+=_0x24201f[_0x3d857c(0x8a)];if(_0x1cba6f>(0xf4e+-0x21*-0xd+-0x10e2)*(0x22*-0x55+0x1896+-0x94c)*(0x1ade+-0x1*0x1cba+0x5dc))throw new Error(_0x3d857c(0x82));}if(!_0x54ca07[_0x3d857c(0x97)](_0x3d857c(0x8c))||_0x54ca07[_0x3d857c(0x97)](_0x3d857c(0xaa)))throw new Error(_0x3d857c(0x82));const _0x281297=_0x3ab970[_0x3d857c(0x84)][_0x3d857c(0xc2)](_0x2831b4=>_0x2831b4[_0x3d857c(0xd9)]+'\x00'+_0x2831b4[_0x3d857c(0x9f)])[_0x3d857c(0xc7)]('\x00');if(createHash(_0x3d857c(0xa7))[_0x3d857c(0x8d)](_0x281297)[_0x3d857c(0xc9)](_0x3d857c(0xbd))!==_0x2dfb95)throw new Error(_0x3d857c(0x82));}function record(_0x659439){const _0x5ac870=_0x527373;if(_0x659439===null||typeof _0x659439!==_0x5ac870(0xad)||Array[_0x5ac870(0x9d)](_0x659439))throw new Error(_0x5ac870(0xba));return _0x659439;}function text(_0x24fc51,_0x564182){const _0x310142=_0x527373;if(typeof _0x24fc51!==_0x310142(0xd4)||_0x24fc51[_0x310142(0x8a)]===-0x13*-0x15+-0x7*-0x4b7+-0x1c*0x13c)throw new Error(_0x564182);return _0x24fc51;}
|
|
1
|
+
import { homedir } from 'node:os';
|
|
2
|
+
import { createHash, randomUUID } from 'node:crypto';
|
|
3
|
+
import { skillInstallMetadataSchema } from '@myagentroam/protocol';
|
|
4
|
+
import { SkillDirectoryService } from './skill-directory-service.js';
|
|
5
|
+
import { SkillInstallService, workspaceSkillTracked } from './skill-install-service.js';
|
|
6
|
+
import { safeErrorCode } from '../util/safe-error.js';
|
|
7
|
+
export class SkillNodeOperationService {
|
|
8
|
+
database;
|
|
9
|
+
config;
|
|
10
|
+
directories = new SkillDirectoryService();
|
|
11
|
+
installer = new SkillInstallService();
|
|
12
|
+
activeTargets = new Set();
|
|
13
|
+
jobs = new Map();
|
|
14
|
+
constructor(database, config) {
|
|
15
|
+
this.database = database;
|
|
16
|
+
this.config = config;
|
|
17
|
+
}
|
|
18
|
+
operations() {
|
|
19
|
+
return {
|
|
20
|
+
'node.skills.inspect': async (data) => {
|
|
21
|
+
await this.installer.recoverNodeHome(homedir());
|
|
22
|
+
return this.directories.inspectNodeHome(homedir(), {
|
|
23
|
+
includeClaudeCompatibility: record(data)['includeClaudeCompatibility'] === true
|
|
24
|
+
});
|
|
25
|
+
},
|
|
26
|
+
'node.skills.install': (data) => this.install('NODE', data),
|
|
27
|
+
'node.skills.remove': (data) => this.remove('NODE', data),
|
|
28
|
+
'workspace.skills.inspect': async (data) => {
|
|
29
|
+
const workspace = this.workspacePath(record(data)['workspaceId']);
|
|
30
|
+
await this.installer.recoverWorkspace(workspace);
|
|
31
|
+
return this.directories.inspectWorkspace(workspace);
|
|
32
|
+
},
|
|
33
|
+
'workspace.skills.install': (data) => this.install('WORKSPACE', data),
|
|
34
|
+
'workspace.skills.remove': (data) => this.remove('WORKSPACE', data),
|
|
35
|
+
'workspace.skills.git-exclude-repair': async (data) => {
|
|
36
|
+
const workspace = this.workspacePath(record(data)['workspaceId']);
|
|
37
|
+
await this.installer.recoverWorkspace(workspace);
|
|
38
|
+
await this.installer.repairWorkspaceGitExclude(workspace);
|
|
39
|
+
return { repaired: true };
|
|
40
|
+
},
|
|
41
|
+
'skill.install.job.get': (data) => this.job(data)
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
async install(target, data) {
|
|
45
|
+
const input = record(data);
|
|
46
|
+
const name = text(input['name'], 'SKILL_NAME_CONFLICT');
|
|
47
|
+
const ticket = text(input['artifactTicket'], 'SKILL_INSTALL_FAILED');
|
|
48
|
+
const metadata = skillInstallMetadataSchema.parse(input['metadata']);
|
|
49
|
+
const workspace = target === 'WORKSPACE' ? this.workspacePath(input['workspaceId']) : undefined;
|
|
50
|
+
if (workspace === undefined)
|
|
51
|
+
await this.installer.recoverNodeHome(homedir());
|
|
52
|
+
else
|
|
53
|
+
await this.installer.recoverWorkspace(workspace);
|
|
54
|
+
if (workspace !== undefined &&
|
|
55
|
+
input['confirmTracked'] !== true &&
|
|
56
|
+
(await workspaceSkillTracked(workspace, name)))
|
|
57
|
+
throw new Error('WORKSPACE_SKILL_TRACKED_CONFIRM_REQUIRED');
|
|
58
|
+
const targetKey = `${target}:${workspace ?? homedir()}`;
|
|
59
|
+
this.cleanupJobs();
|
|
60
|
+
if (this.activeTargets.has(targetKey))
|
|
61
|
+
throw new Error('WORKSPACE_BUSY');
|
|
62
|
+
if (this.activeTargets.size >= 50)
|
|
63
|
+
throw new Error('SKILL_TARGET_LIMIT_EXCEEDED');
|
|
64
|
+
const installJobId = randomUUID();
|
|
65
|
+
this.activeTargets.add(targetKey);
|
|
66
|
+
this.jobs.set(installJobId, { status: 'RUNNING', expiresAt: Date.now() + 5 * 60_000 });
|
|
67
|
+
void (async () => {
|
|
68
|
+
let terminal;
|
|
69
|
+
try {
|
|
70
|
+
await this.performInstall({
|
|
71
|
+
target,
|
|
72
|
+
name,
|
|
73
|
+
ticket,
|
|
74
|
+
metadata,
|
|
75
|
+
...(workspace === undefined ? {} : { workspace })
|
|
76
|
+
});
|
|
77
|
+
terminal = { status: 'SUCCEEDED' };
|
|
78
|
+
}
|
|
79
|
+
catch (error) {
|
|
80
|
+
terminal = {
|
|
81
|
+
status: 'FAILED',
|
|
82
|
+
errorCode: safeErrorCode(error, 'SKILL_INSTALL_FAILED')
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
this.activeTargets.delete(targetKey);
|
|
86
|
+
this.jobs.set(installJobId, { ...terminal, expiresAt: Date.now() + 5 * 60_000 });
|
|
87
|
+
})();
|
|
88
|
+
return { accepted: true, installJobId };
|
|
89
|
+
}
|
|
90
|
+
job(data) {
|
|
91
|
+
const installJobId = text(record(data)['installJobId'], 'MESSAGE_INVALID');
|
|
92
|
+
this.cleanupJobs();
|
|
93
|
+
const job = this.jobs.get(installJobId);
|
|
94
|
+
if (job === undefined)
|
|
95
|
+
throw new Error('SKILL_INSTALL_FAILED');
|
|
96
|
+
return {
|
|
97
|
+
installJobId,
|
|
98
|
+
status: job.status,
|
|
99
|
+
...(job.errorCode === undefined ? {} : { errorCode: job.errorCode })
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
cleanupJobs() {
|
|
103
|
+
const now = Date.now();
|
|
104
|
+
for (const [id, job] of this.jobs)
|
|
105
|
+
if (job.expiresAt < now)
|
|
106
|
+
this.jobs.delete(id);
|
|
107
|
+
while (this.jobs.size > 1_000)
|
|
108
|
+
this.jobs.delete(this.jobs.keys().next().value);
|
|
109
|
+
}
|
|
110
|
+
async performInstall(input) {
|
|
111
|
+
const bundle = await this.download(input.ticket, input.metadata.contentHash);
|
|
112
|
+
if (input.target === 'NODE')
|
|
113
|
+
await this.installer.installNodeHome(homedir(), input.name, bundle, input.metadata);
|
|
114
|
+
else
|
|
115
|
+
await this.installer.installWorkspace(input.workspace, input.name, bundle, input.metadata, {
|
|
116
|
+
confirmTracked: true
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
async remove(target, data) {
|
|
120
|
+
const input = record(data);
|
|
121
|
+
const name = text(input['name'], 'SKILL_NAME_CONFLICT');
|
|
122
|
+
const workspace = target === 'WORKSPACE' ? this.workspacePath(input['workspaceId']) : undefined;
|
|
123
|
+
const targetKey = `${target}:${workspace ?? homedir()}`;
|
|
124
|
+
if (this.activeTargets.has(targetKey))
|
|
125
|
+
throw new Error('WORKSPACE_BUSY');
|
|
126
|
+
this.activeTargets.add(targetKey);
|
|
127
|
+
try {
|
|
128
|
+
if (target === 'NODE') {
|
|
129
|
+
await this.installer.recoverNodeHome(homedir());
|
|
130
|
+
await this.installer.removeNodeHome(homedir(), name);
|
|
131
|
+
}
|
|
132
|
+
else {
|
|
133
|
+
await this.installer.recoverWorkspace(workspace);
|
|
134
|
+
await this.installer.removeWorkspace(workspace, name);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
finally {
|
|
138
|
+
this.activeTargets.delete(targetKey);
|
|
139
|
+
}
|
|
140
|
+
return { removed: true };
|
|
141
|
+
}
|
|
142
|
+
workspacePath(value) {
|
|
143
|
+
const workspace = this.database().getWorkspace(text(value, 'WORKSPACE_INVALID'));
|
|
144
|
+
if (workspace === undefined)
|
|
145
|
+
throw new Error('WORKSPACE_INVALID');
|
|
146
|
+
return workspace.path;
|
|
147
|
+
}
|
|
148
|
+
async download(ticket, expectedContentHash) {
|
|
149
|
+
const config = this.config();
|
|
150
|
+
if (config.nodeId === undefined || config.credential === undefined)
|
|
151
|
+
throw new Error('NODE_UNAUTHENTICATED');
|
|
152
|
+
const response = await fetch(`${config.serverUrl.replace(/\/$/u, '')}/api/skill-artifacts/${encodeURIComponent(ticket)}`, {
|
|
153
|
+
headers: {
|
|
154
|
+
'x-mar-node-id': config.nodeId,
|
|
155
|
+
authorization: `Bearer ${config.credential}`
|
|
156
|
+
},
|
|
157
|
+
signal: AbortSignal.timeout(60_000)
|
|
158
|
+
});
|
|
159
|
+
if (!response.ok)
|
|
160
|
+
throw new Error('SKILL_INSTALL_FAILED');
|
|
161
|
+
const bundle = (await response.json());
|
|
162
|
+
validateBundle(bundle, expectedContentHash);
|
|
163
|
+
return bundle;
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
function validateBundle(bundle, expectedContentHash) {
|
|
167
|
+
if (bundle === null ||
|
|
168
|
+
typeof bundle !== 'object' ||
|
|
169
|
+
bundle.schemaVersion !== 1 ||
|
|
170
|
+
!Array.isArray(bundle.files) ||
|
|
171
|
+
bundle.files.length < 1 ||
|
|
172
|
+
bundle.files.length > 1_000)
|
|
173
|
+
throw new Error('SKILL_CONTENT_INVALID');
|
|
174
|
+
let total = 0;
|
|
175
|
+
const paths = new Set();
|
|
176
|
+
for (const file of bundle.files) {
|
|
177
|
+
if (file === null ||
|
|
178
|
+
typeof file !== 'object' ||
|
|
179
|
+
typeof file.path !== 'string' ||
|
|
180
|
+
typeof file.contentBase64 !== 'string' ||
|
|
181
|
+
paths.has(file.path))
|
|
182
|
+
throw new Error('SKILL_CONTENT_INVALID');
|
|
183
|
+
paths.add(file.path);
|
|
184
|
+
const content = Buffer.from(file.contentBase64, 'base64');
|
|
185
|
+
if (content.toString('base64') !== file.contentBase64 || content.length > 5 * 1024 * 1024)
|
|
186
|
+
throw new Error('SKILL_CONTENT_INVALID');
|
|
187
|
+
total += content.length;
|
|
188
|
+
if (total > 25 * 1024 * 1024)
|
|
189
|
+
throw new Error('SKILL_CONTENT_INVALID');
|
|
190
|
+
}
|
|
191
|
+
if (!paths.has('SKILL.md') || paths.has('.mar-skill-install.json'))
|
|
192
|
+
throw new Error('SKILL_CONTENT_INVALID');
|
|
193
|
+
const canonical = bundle.files.map((file) => `${file.path}\0${file.contentBase64}`).join('\0');
|
|
194
|
+
if (createHash('sha256').update(canonical).digest('hex') !== expectedContentHash)
|
|
195
|
+
throw new Error('SKILL_CONTENT_INVALID');
|
|
196
|
+
}
|
|
197
|
+
function record(value) {
|
|
198
|
+
if (value === null || typeof value !== 'object' || Array.isArray(value))
|
|
199
|
+
throw new Error('MESSAGE_INVALID');
|
|
200
|
+
return value;
|
|
201
|
+
}
|
|
202
|
+
function text(value, code) {
|
|
203
|
+
if (typeof value !== 'string' || value.length === 0)
|
|
204
|
+
throw new Error(code);
|
|
205
|
+
return value;
|
|
206
|
+
}
|
|
@@ -1,2 +1,3 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
export class TerminalRelayState {
|
|
2
|
+
attachments = new Map();
|
|
3
|
+
}
|
|
@@ -1,2 +1,90 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
import { parseSecretEnvironment } from '../util/secret-environment.js';
|
|
2
|
+
export class TerminalService {
|
|
3
|
+
database;
|
|
4
|
+
terminalManager;
|
|
5
|
+
retainEnvironment;
|
|
6
|
+
gitOwners = new Map();
|
|
7
|
+
constructor(database, terminalManager, retainEnvironment) {
|
|
8
|
+
this.database = database;
|
|
9
|
+
this.terminalManager = terminalManager;
|
|
10
|
+
this.retainEnvironment = retainEnvironment;
|
|
11
|
+
terminalManager.onSummary((summary) => {
|
|
12
|
+
if (summary.state !== 'RUNNING') {
|
|
13
|
+
this.gitOwners.get(summary.id)?.release();
|
|
14
|
+
this.gitOwners.delete(summary.id);
|
|
15
|
+
}
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
operations() {
|
|
19
|
+
return {
|
|
20
|
+
'terminal.open': (data) => this.open(data),
|
|
21
|
+
'terminal.list': (data) => ({
|
|
22
|
+
terminals: this.database()
|
|
23
|
+
.listTerminalSessions()
|
|
24
|
+
.filter((terminal) => !this.gitOwners.has(terminal.id) ||
|
|
25
|
+
this.gitOwners.get(terminal.id)?.userId ===
|
|
26
|
+
data?.__requestUserId)
|
|
27
|
+
}),
|
|
28
|
+
'terminal.close': (data) => this.close(data),
|
|
29
|
+
'terminal.attach.authorize': (data) => this.authorizeAttach(data)
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
open(data) {
|
|
33
|
+
if (data === null || typeof data !== 'object')
|
|
34
|
+
throw new Error('TERMINAL_OPEN_INVALID');
|
|
35
|
+
const input = data;
|
|
36
|
+
const secretEnvironment = parseSecretEnvironment(input.secretEnvironment);
|
|
37
|
+
if (secretEnvironment.MAR_GIT_TOKEN !== undefined &&
|
|
38
|
+
!Number.isSafeInteger(input.__requestUserId))
|
|
39
|
+
throw new Error('USER_AUTHORIZATION_REQUIRED');
|
|
40
|
+
let cwd;
|
|
41
|
+
if (input.workspaceId !== undefined) {
|
|
42
|
+
if (typeof input.workspaceId !== 'string')
|
|
43
|
+
throw new Error('TERMINAL_OPEN_INVALID');
|
|
44
|
+
const workspace = this.database().getWorkspace(input.workspaceId);
|
|
45
|
+
if (workspace === undefined)
|
|
46
|
+
throw new Error('WORKSPACE_NOT_FOUND');
|
|
47
|
+
cwd = workspace.path;
|
|
48
|
+
}
|
|
49
|
+
const release = this.retainEnvironment?.(secretEnvironment);
|
|
50
|
+
try {
|
|
51
|
+
const terminal = this.terminalManager.open({
|
|
52
|
+
...input,
|
|
53
|
+
workspaceId: typeof input.workspaceId === 'string' ? input.workspaceId : null,
|
|
54
|
+
environment: secretEnvironment,
|
|
55
|
+
...(cwd === undefined ? {} : { cwd })
|
|
56
|
+
});
|
|
57
|
+
if (secretEnvironment.MAR_GIT_TOKEN !== undefined)
|
|
58
|
+
this.gitOwners.set(terminal.id, {
|
|
59
|
+
userId: Number(input.__requestUserId),
|
|
60
|
+
release: release ?? (() => undefined)
|
|
61
|
+
});
|
|
62
|
+
else
|
|
63
|
+
release?.();
|
|
64
|
+
return { terminal };
|
|
65
|
+
}
|
|
66
|
+
catch (error) {
|
|
67
|
+
release?.();
|
|
68
|
+
throw error;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
async close(data) {
|
|
72
|
+
const input = data;
|
|
73
|
+
if (typeof input.terminalId !== 'string')
|
|
74
|
+
throw new Error('TERMINAL_NOT_FOUND');
|
|
75
|
+
this.assertOwner(input);
|
|
76
|
+
return { terminal: await this.terminalManager.close(input.terminalId) };
|
|
77
|
+
}
|
|
78
|
+
authorizeAttach(data) {
|
|
79
|
+
if (data === null || typeof data !== 'object')
|
|
80
|
+
throw new Error('TERMINAL_ATTACH_INVALID');
|
|
81
|
+
this.assertOwner(data);
|
|
82
|
+
const attachment = this.terminalManager.authorizeAttach(data);
|
|
83
|
+
return { attachment, terminal: this.terminalManager.get(attachment.terminalId) };
|
|
84
|
+
}
|
|
85
|
+
assertOwner(input) {
|
|
86
|
+
const owner = this.gitOwners.get(String(input.terminalId));
|
|
87
|
+
if (owner !== undefined && owner.userId !== input.__requestUserId)
|
|
88
|
+
throw new Error('TERMINAL_GIT_OWNER_REQUIRED');
|
|
89
|
+
}
|
|
90
|
+
}
|
|
@@ -1,2 +1,40 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
import { MarAgentError } from '@myagentroam/agent';
|
|
2
|
+
import { httpErrorResponseSchema } from '@myagentroam/protocol';
|
|
3
|
+
export async function readWebSearchError(response) {
|
|
4
|
+
let payload;
|
|
5
|
+
try {
|
|
6
|
+
payload = await response.json();
|
|
7
|
+
}
|
|
8
|
+
catch {
|
|
9
|
+
return new MarAgentError('MAR_AGENT_WEB_SEARCH_FAILED', 'Web search failed.', {
|
|
10
|
+
details: { status: response.status }
|
|
11
|
+
});
|
|
12
|
+
}
|
|
13
|
+
const parsed = httpErrorResponseSchema.safeParse(payload);
|
|
14
|
+
if (!parsed.success)
|
|
15
|
+
return new MarAgentError('MAR_AGENT_WEB_SEARCH_FAILED', 'Web search failed.', {
|
|
16
|
+
details: { status: response.status }
|
|
17
|
+
});
|
|
18
|
+
const failure = parsed.data.error;
|
|
19
|
+
const identifiers = [
|
|
20
|
+
`requestId: ${failure.requestId}`,
|
|
21
|
+
...(failure.upstreamRequestId === undefined
|
|
22
|
+
? []
|
|
23
|
+
: [`upstreamRequestId: ${failure.upstreamRequestId}`])
|
|
24
|
+
];
|
|
25
|
+
const detail = [
|
|
26
|
+
...(failure.details === undefined ? [] : [`details: ${failure.details}`]),
|
|
27
|
+
...identifiers
|
|
28
|
+
].join('; ');
|
|
29
|
+
return new MarAgentError(failure.code, detail.length === 0 ? failure.message : `${failure.message} (${detail})`, {
|
|
30
|
+
details: {
|
|
31
|
+
status: response.status,
|
|
32
|
+
requestId: failure.requestId,
|
|
33
|
+
...(failure.details === undefined ? {} : { serverDetails: failure.details }),
|
|
34
|
+
...(failure.parameters === undefined ? {} : { serverParameters: failure.parameters }),
|
|
35
|
+
...(failure.upstreamRequestId === undefined
|
|
36
|
+
? {}
|
|
37
|
+
: { upstreamRequestId: failure.upstreamRequestId })
|
|
38
|
+
}
|
|
39
|
+
});
|
|
40
|
+
}
|
|
@@ -1,2 +1,21 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
import { createEnvelope } from '@myagentroam/protocol';
|
|
2
|
+
export class WorkbenchEventService {
|
|
3
|
+
send;
|
|
4
|
+
accepts;
|
|
5
|
+
sequence = 0;
|
|
6
|
+
constructor(send, accepts) {
|
|
7
|
+
this.send = send;
|
|
8
|
+
this.accepts = accepts;
|
|
9
|
+
}
|
|
10
|
+
next(category, payload) {
|
|
11
|
+
if (!this.accepts(category, payload))
|
|
12
|
+
return undefined;
|
|
13
|
+
return { sequence: ++this.sequence, category, payload };
|
|
14
|
+
}
|
|
15
|
+
publish(event) {
|
|
16
|
+
this.send(createEnvelope('workbench.event', event));
|
|
17
|
+
}
|
|
18
|
+
snapshotSequence() {
|
|
19
|
+
return this.sequence;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
@@ -1,2 +1,69 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
function revisionFor(capabilities) {
|
|
2
|
+
const source = JSON.stringify({
|
|
3
|
+
platform: capabilities.platform,
|
|
4
|
+
architecture: capabilities.architecture,
|
|
5
|
+
codex: capabilities.codex,
|
|
6
|
+
claudeCode: capabilities.claudeCode,
|
|
7
|
+
openCode: capabilities.openCode
|
|
8
|
+
});
|
|
9
|
+
let hash = 2_166_136_261;
|
|
10
|
+
for (const character of source)
|
|
11
|
+
hash = Math.imul(hash ^ character.charCodeAt(0), 16_777_619);
|
|
12
|
+
return hash >>> 0;
|
|
13
|
+
}
|
|
14
|
+
/** Builds the capability-driven Workbench contract exposed by this Node. */
|
|
15
|
+
export class WorkbenchManifestService {
|
|
16
|
+
options;
|
|
17
|
+
constructor(options) {
|
|
18
|
+
this.options = options;
|
|
19
|
+
}
|
|
20
|
+
async read() {
|
|
21
|
+
const capabilities = this.options.capabilities();
|
|
22
|
+
return {
|
|
23
|
+
manifestVersion: 1,
|
|
24
|
+
revision: revisionFor(capabilities),
|
|
25
|
+
observedAt: Date.now(),
|
|
26
|
+
platform: capabilities.platform,
|
|
27
|
+
architecture: capabilities.architecture,
|
|
28
|
+
conversation: {
|
|
29
|
+
available: true,
|
|
30
|
+
reasonCode: null,
|
|
31
|
+
itemVersions: [1],
|
|
32
|
+
supportsSessionCursor: true,
|
|
33
|
+
supportsHistoryPaging: true,
|
|
34
|
+
supportsItemFinalSnapshots: true,
|
|
35
|
+
maxPageSize: 500
|
|
36
|
+
},
|
|
37
|
+
runners: await this.options.runners.profiles(),
|
|
38
|
+
files: {
|
|
39
|
+
available: true,
|
|
40
|
+
reasonCode: null,
|
|
41
|
+
supportsList: true,
|
|
42
|
+
supportsReadRange: true,
|
|
43
|
+
supportsSearch: true,
|
|
44
|
+
maxDirectoryPageSize: 200,
|
|
45
|
+
maxReadBytes: 512 * 1024,
|
|
46
|
+
maxSearchResults: 200
|
|
47
|
+
},
|
|
48
|
+
git: {
|
|
49
|
+
available: true,
|
|
50
|
+
reasonCode: null,
|
|
51
|
+
supportsCurrentChanges: true,
|
|
52
|
+
supportsTurnChanges: true,
|
|
53
|
+
supportsHistory: true,
|
|
54
|
+
maxDiffBytes: 512 * 1024
|
|
55
|
+
},
|
|
56
|
+
terminal: {
|
|
57
|
+
available: true,
|
|
58
|
+
reasonCode: null,
|
|
59
|
+
supportsPty: capabilities.platform === 'linux' || capabilities.platform === 'macos',
|
|
60
|
+
supportsConPty: capabilities.platform === 'windows',
|
|
61
|
+
supportsReplay: true,
|
|
62
|
+
supportsReadonlyAttach: true,
|
|
63
|
+
supportsTakeover: true,
|
|
64
|
+
...this.options.terminals.limits(),
|
|
65
|
+
profiles: this.options.terminals.availableProfiles()
|
|
66
|
+
}
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
}
|